Allow opening HTML file info in browser

This commit is contained in:
Martchus 2017-09-20 19:37:49 +02:00
parent 5c5db1574f
commit 25d570d394
4 changed files with 113 additions and 49 deletions

View File

@ -130,7 +130,7 @@ MainWindow::MainWindow(QWidget *parent) :
connect(m_ui->actionSave, &QAction::triggered, m_ui->tagEditorWidget, &TagEditorWidget::applyEntriesAndSaveChangings);
connect(m_ui->actionSave_as, &QAction::triggered, this, &MainWindow::showSaveAsDlg);
connect(m_ui->actionDelete_all_tags, &QAction::triggered, m_ui->tagEditorWidget, &TagEditorWidget::deleteAllTagsAndSave);
connect(m_ui->actionSave_file_information, &QAction::triggered, this, &MainWindow::saveFileInformation);
connect(m_ui->actionSave_file_information, &QAction::triggered, m_ui->tagEditorWidget, &TagEditorWidget::saveFileInfo);
connect(m_ui->actionClose, &QAction::triggered, m_ui->tagEditorWidget, &TagEditorWidget::closeFile);
connect(m_ui->actionReload, &QAction::triggered, m_ui->tagEditorWidget, &TagEditorWidget::reparseFile);
connect(m_ui->actionExternalPlayer, &QAction::triggered, this, &MainWindow::spawnExternalPlayer);
@ -509,49 +509,6 @@ void MainWindow::showSaveAsDlg()
}
}
/*!
* \brief Saves the file information generated to be displayed in the info web view in a file.
*/
void MainWindow::saveFileInformation()
{
if(fileOperationOngoing()) {
m_ui->statusBar->showMessage(tr("Unable to save file information because the current process hasn't been finished yet."));
return;
}
if(!fileInfo().isOpen()) {
QMessageBox::information(this, QApplication::applicationName(), tr("No file is opened."));
return;
}
const QByteArray htmlData =
#ifndef TAGEDITOR_NO_WEBVIEW
!m_ui->tagEditorWidget->fileInfoHtml().isEmpty() ?
m_ui->tagEditorWidget->fileInfoHtml() :
#endif
HtmlInfo::generateInfo(fileInfo(), m_ui->tagEditorWidget->originalNotifications());
if(htmlData.isEmpty()) {
QMessageBox::information(this, QApplication::applicationName(), tr("No file information available."));
return;
}
const QString path = QFileDialog::getSaveFileName(this, tr("Save file information - ") + QCoreApplication::applicationName());
if(path.isEmpty()) {
QMessageBox::critical(this, QApplication::applicationName(), tr("Unable to open file."));
return;
}
QFile file(path);
if(file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
QTextStream stream(&file);
stream.setCodec(QTextCodec::codecForName("UTF-8"));
stream << htmlData;
file.close();
if(file.error() != QFileDevice::NoError) {
QMessageBox::critical(this, QApplication::applicationName(), tr("Unable to write to file.\n%1").arg(file.errorString()));
}
}
}
/*!
* \brief Applies settings from Settings namespace. Only settings configurable through the SettingsDialog
* will be applied and not settings like the main window's geometry and state.

View File

@ -64,7 +64,6 @@ private slots:
void showNextFileNotFound();
void showOpenFileDlg();
void showSaveAsDlg();
void saveFileInformation();
void handleFileStatusChange(bool opened, bool hasTag);
void handleCurrentPathChanged(const QString &newPath);

View File

@ -12,6 +12,7 @@
#include "../misc/utility.h"
#include "ui_tageditorwidget.h"
#include "resources/config.h"
#include <tagparser/exceptions.h>
#include <tagparser/signature.h>
@ -30,13 +31,17 @@
#include <c++utilities/io/path.h>
#include <c++utilities/io/catchiofailure.h>
#include <QDesktopServices>
#include <QMessageBox>
#include <QKeyEvent>
#include <QClipboard>
#include <QFileSystemModel>
#include <QFileInfo>
#include <QTemporaryFile>
#include <QDir>
#include <QPlainTextEdit>
#include <QMimeData>
#include <QFileDialog>
#include <QFileSystemWatcher>
#include <QMenu>
#include <QCheckBox>
@ -152,6 +157,18 @@ TagEditorWidget::TagEditorWidget(QWidget *parent) :
TagEditorWidget::~TagEditorWidget()
{}
/*!
* \brief Returns the HTML source of the info website.
* \remarks In contrast to fileInfoHtml(), this method will generate file info if not available yet.
*/
const QByteArray &TagEditorWidget::generateFileInfoHtml()
{
if(m_fileInfoHtml.isEmpty()) {
m_fileInfoHtml = HtmlInfo::generateInfo(m_fileInfo, m_originalNotifications);
}
return m_fileInfoHtml;
}
/*!
* \brief Returns whether the file name is visible at the top of the widget.
*/
@ -621,21 +638,25 @@ void TagEditorWidget::initInfoView()
}
/*!
* \brief Updates the info web view to show information about the
* currently opened file.
* \brief Updates the info web view to show information about the currently opened file.
*/
void TagEditorWidget::updateInfoView()
{
// ensure previous file info HTML is cleared in any case
m_fileInfoHtml.clear();
// update webview if present
#ifndef TAGEDITOR_NO_WEBVIEW
if(m_infoWebView) {
if(m_fileInfo.isOpen()) {
m_fileInfoHtml = HtmlInfo::generateInfo(m_fileInfo, m_originalNotifications);
m_infoWebView->setContent(m_fileInfoHtml, QStringLiteral("application/xhtml+xml"));
m_infoWebView->setContent(generateFileInfoHtml(), QStringLiteral("application/xhtml+xml"));
} else {
m_infoWebView->setUrl(QStringLiteral("about:blank"));
}
}
#endif
// update info model if present
if(m_infoModel) {
m_infoModel->setFileInfo(m_fileInfo.isOpen() ? &m_fileInfo : nullptr); // resets the model
}
@ -680,8 +701,16 @@ void TagEditorWidget::showInfoWebViewContextMenu(const QPoint &)
connect(&copyAction, &QAction::triggered, [this] {
QApplication::clipboard()->setText(m_infoWebView->selectedText());
});
QAction saveAction(QIcon::fromTheme(QStringLiteral("document-save")), tr("Save ..."), nullptr);
saveAction.setDisabled(m_fileInfoHtml.isEmpty());
connect(&saveAction, &QAction::triggered, this, &TagEditorWidget::saveFileInfo);
QAction openAction(QIcon::fromTheme(QStringLiteral("internet-web-browser")), tr("Open in browser"), nullptr);
openAction.setDisabled(m_fileInfoHtml.isEmpty());
connect(&openAction, &QAction::triggered, this, &TagEditorWidget::openFileInfoInBrowser);
QMenu menu;
menu.addAction(&copyAction);
menu.addAction(&saveAction);
menu.addAction(&openAction);
menu.exec(QCursor::pos());
}
#endif
@ -1233,6 +1262,75 @@ void TagEditorWidget::closeFile()
updateFileStatusStatus();
}
bool TagEditorWidget::handleFileInfoUnavailable()
{
if(fileOperationOngoing()) {
emit statusMessage(tr("Unable to save file information because the current process hasn't been finished yet."));
return true;
}
if(!fileInfo().isOpen()) {
QMessageBox::information(this, QApplication::applicationName(), tr("No file is opened."));
return true;
}
if(generateFileInfoHtml().isEmpty()) {
QMessageBox::information(this, QApplication::applicationName(), tr("No file information available."));
return true;
}
return false;
}
bool TagEditorWidget::writeFileInfoToFile(QFile &file)
{
if(!file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
QMessageBox::critical(this, QApplication::applicationName(), tr("Unable to open file \"%1\".").arg(file.fileName()));
return false;
}
QTextStream stream(&file);
stream.setCodec(QTextCodec::codecForName("UTF-8"));
stream << fileInfoHtml();
file.close();
if(file.error() != QFileDevice::NoError) {
QMessageBox::critical(this, QApplication::applicationName(), tr("Unable to write to file \"%1\".\n%2").arg(file.fileName(), file.errorString()));
return false;
}
return true;
}
/*!
* \brief Saves the file information generated to be displayed in the info web view in a file.
*/
void TagEditorWidget::saveFileInfo()
{
if(handleFileInfoUnavailable()) {
return;
}
const QString path(QFileDialog::getSaveFileName(this, tr("Save file information - ") + QCoreApplication::applicationName()));
if(path.isEmpty()) {
QMessageBox::critical(this, QApplication::applicationName(), tr("Unable to open file."));
return;
}
QFile file(path);
writeFileInfoToFile(file);
}
void TagEditorWidget::openFileInfoInBrowser()
{
if(handleFileInfoUnavailable()) {
return;
}
m_temporaryInfoFile = make_unique<QTemporaryFile>(QDir::tempPath() + QStringLiteral("/" PROJECT_NAME "-fileinfo-XXXXXX.xhtml"));
if(!writeFileInfoToFile(*m_temporaryInfoFile)) {
return;
}
QDesktopServices::openUrl(QStringLiteral("file://") + m_temporaryInfoFile->fileName());
}
/*!
* \brief This private slot is invoked the the return key has been pressed in a tag edit.
*

View File

@ -14,6 +14,8 @@
QT_FORWARD_DECLARE_CLASS(QFileSystemWatcher)
QT_FORWARD_DECLARE_CLASS(QMenu)
QT_FORWARD_DECLARE_CLASS(QTreeView)
QT_FORWARD_DECLARE_CLASS(QFile)
QT_FORWARD_DECLARE_CLASS(QTemporaryFile)
namespace Media {
DECLARE_ENUM_CLASS(TagType, unsigned int);
@ -50,6 +52,7 @@ public:
Media::NotificationList &originalNotifications();
bool isTagEditShown() const;
const QByteArray &fileInfoHtml() const;
const QByteArray &generateFileInfoHtml();
bool isFileNameVisible() const;
void setFileNameVisible(bool visible);
bool areButtonsVisible() const;
@ -66,6 +69,8 @@ public slots:
bool applyEntriesAndSaveChangings();
bool deleteAllTagsAndSave();
void closeFile();
void saveFileInfo();
void openFileInfoInBrowser();
// misc
void applySettingsFromDialog();
@ -108,6 +113,8 @@ private slots:
#ifndef TAGEDITOR_NO_WEBVIEW
void showInfoWebViewContextMenu(const QPoint &);
#endif
bool handleFileInfoUnavailable();
bool writeFileInfoToFile(QFile &file);
private:
void updateDocumentTitleEdits();
@ -130,6 +137,7 @@ private:
#endif
FileInfoModel *m_infoModel;
QTreeView *m_infoTreeView;
std::unique_ptr<QTemporaryFile> m_temporaryInfoFile;
// tag, file, directory management
QString m_currentPath;
QFileSystemWatcher *m_fileWatcher;
@ -192,6 +200,8 @@ inline Media::NotificationList &TagEditorWidget::originalNotifications()
/*!
* \brief Returns the HTML source of the info website.
* \remarks Returns an empty string if no file info has been generated yet. See generateFileInfoHtml() for a method which will ensure
* the file info has been generated.
*/
inline const QByteArray &TagEditorWidget::fileInfoHtml() const
{