diff --git a/application/settings.cpp b/application/settings.cpp index 48aa685..e58638e 100644 --- a/application/settings.cpp +++ b/application/settings.cpp @@ -107,6 +107,37 @@ bool &mergeMultipleSuccessiveId3v2Tags() return v; } +// file layout +TagPosition &preferredTagPosition() +{ + static TagPosition v = TagPosition::BeforeData; + return v; +} + +bool &forceTagPosition() +{ + static bool v = true; + return v; +} + +size_t &minPadding() +{ + static size_t v = 0; + return v; +} + +size_t &maxPadding() +{ + static size_t v = 0; + return v; +} + +size_t &preferredPadding() +{ + static size_t v = 0; + return v; +} + // fields KnownFieldModel &selectedFieldsModel() { @@ -263,6 +294,20 @@ void restore() keepVersionOfExistingId3v2Tag() = settings.value(QStringLiteral("keepversionofexistingtag"), true).toBool(); mergeMultipleSuccessiveId3v2Tags() = settings.value(QStringLiteral("mergemultiplesuccessivetags"), true).toBool(); settings.endGroup(); + settings.beginGroup(QStringLiteral("filelayout")); + switch(settings.value(QStringLiteral("tagpos")).toInt()) { + case 0: + preferredTagPosition() = TagPosition::BeforeData; + break; + case 1: + preferredTagPosition() = TagPosition::AfterData; + break; + } + forceTagPosition() = settings.value(QStringLiteral("forcetagpos"), true).toBool(); + minPadding() = settings.value(QStringLiteral("minpad"), 0).toInt(); + maxPadding() = settings.value(QStringLiteral("maxpad"), 0).toInt(); + preferredPadding() = settings.value(QStringLiteral("prefpad"), 0).toInt(); + settings.endGroup(); settings.endGroup(); settings.beginGroup(QStringLiteral("mainwindow")); @@ -317,6 +362,13 @@ void save() settings.setValue(QStringLiteral("keepversionofexistingtag"), keepVersionOfExistingId3v2Tag()); settings.setValue(QStringLiteral("mergemultiplesuccessivetags"), mergeMultipleSuccessiveId3v2Tags()); settings.endGroup(); + settings.beginGroup(QStringLiteral("filelayout")); + settings.setValue(QStringLiteral("tagpos"), static_cast(preferredTagPosition())); + settings.setValue(QStringLiteral("forcetagpos"), forceTagPosition()); + settings.setValue(QStringLiteral("minpad"), QVariant::fromValue(minPadding())); + settings.setValue(QStringLiteral("maxpad"), QVariant::fromValue(maxPadding())); + settings.setValue(QStringLiteral("prefpad"), QVariant::fromValue(preferredPadding())); + settings.endGroup(); settings.endGroup(); settings.beginGroup(QStringLiteral("mainwindow")); diff --git a/application/settings.h b/application/settings.h index 449189a..e5d38ad 100644 --- a/application/settings.h +++ b/application/settings.h @@ -7,13 +7,12 @@ #include -QT_BEGIN_NAMESPACE -class QByteArray; -class QString; -QT_END_NAMESPACE +QT_FORWARD_DECLARE_CLASS(QByteArray) +QT_FORWARD_DECLARE_CLASS(QString) namespace Media { enum class TagUsage; +enum class TagPosition; } namespace Settings { @@ -66,6 +65,13 @@ uint32 &id3v2versionToBeUsed(); bool &keepVersionOfExistingId3v2Tag(); bool &mergeMultipleSuccessiveId3v2Tags(); +// file layout +Media::TagPosition &preferredTagPosition(); +bool &forceTagPosition(); +size_t &minPadding(); +size_t &maxPadding(); +size_t &preferredPadding(); + // fields class KnownFieldModel; KnownFieldModel &selectedFieldsModel(); diff --git a/gui/filelayout.ui b/gui/filelayout.ui new file mode 100644 index 0000000..8461496 --- /dev/null +++ b/gui/filelayout.ui @@ -0,0 +1,191 @@ + + + QtGui::FileLayoutPage + + + + 0 + 0 + 325 + 311 + + + + Form + + + QGroupBox { font-weight: bold }; + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Padding + + + + + + + + minimum padding + + + + + + + + 150 + 0 + + + + byte + + + 0 + + + + + + + maximum padding + + + + + + + + 150 + 0 + + + + byte + + + 0 + + + 429496729 + + + 0 + + + + + + + preferred padding + + + + + + + + 150 + 0 + + + + byte + + + 0 + + + 429496729 + + + 0 + + + + + + + + + + + + Preferred tag position + + + + + + befo&re (media) data / at the beginning of the file + + + + + + + after (&media) data / at the end of the file + + + + + + + Use preferred position event if putting the tags at +another position would prevent rewriting the entire file + + + + + + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + NotificationLabel + QWidget +
gui/notificationlabel.h
+ 1 +
+
+ + +
diff --git a/gui/mainwindow.cpp b/gui/mainwindow.cpp index 4a0c2b8..b09568b 100644 --- a/gui/mainwindow.cpp +++ b/gui/mainwindow.cpp @@ -636,7 +636,7 @@ void MainWindow::updateInfoWebView() { if(m_fileInfo.isOpen()) { m_fileInfoHtml = HtmlInfo::generateInfo(m_fileInfo, m_originalNotifications); - m_infoWebView->setHtml(m_fileInfoHtml); + m_infoWebView->setContent(m_fileInfoHtml, QStringLiteral("application/xhtml+xml")); } else { m_infoWebView->setUrl(QStringLiteral("about:blank")); } @@ -987,11 +987,18 @@ bool MainWindow::startSaving() // tags might get invalidated m_tags.clear(); foreachTagEdit([] (TagEdit *edit) { edit->setTag(nullptr, false); }); + // show abort button m_ui->abortButton->setHidden(false); m_ui->abortButton->setEnabled(true); m_abortClicked = false; // remove current path from file watcher m_fileWatcher->removePath(m_currentPath); + // use current configuration + m_fileInfo.setTagPosition(Settings::preferredTagPosition()); + m_fileInfo.setForceTagPosition(Settings::forceTagPosition()); + m_fileInfo.setMinPadding(Settings::minPadding()); + m_fileInfo.setMaxPadding(Settings::maxPadding()); + m_fileInfo.setPreferredPadding(Settings::preferredPadding()); // define functions to show the saving progress and to actually applying the changes auto showProgress = [this] (StatusProvider &sender) -> void { QMetaObject::invokeMethod(m_ui->makingNotificationWidget, "setPercentage", Qt::QueuedConnection, Q_ARG(int, static_cast(sender.currentPercentage() * 100.0))); diff --git a/gui/settingsdialog.cpp b/gui/settingsdialog.cpp index 131ac4a..d706388 100644 --- a/gui/settingsdialog.cpp +++ b/gui/settingsdialog.cpp @@ -12,6 +12,10 @@ #include +#include + +using namespace std; +using namespace std::placeholders; using namespace Settings; using namespace Media; @@ -138,7 +142,7 @@ void EditorTempOptionPage::reset() QWidget *EditorTempOptionPage::setupWidget() { - QWidget *widget = UiFileBasedOptionPage::setupWidget(); + auto *widget = UiFileBasedOptionPage::setupWidget(); QObject::connect(ui()->selectPushButton, &QPushButton::clicked, std::bind(&EditorTempOptionPage::showDirectorySelection, this)); return widget; } @@ -185,7 +189,7 @@ void EditorFieldsOptionPage::reset() QWidget *EditorFieldsOptionPage::setupWidget() { - QWidget *w = UiFileBasedOptionPage::setupWidget(); + auto *w = UiFileBasedOptionPage::setupWidget(); if(!m_model) { m_model = new KnownFieldModel(w); } @@ -203,7 +207,7 @@ EditorAutoCorrectionOptionPage::~EditorAutoCorrectionOptionPage() QString EditorAutoCorrectionOptionPage::displayName() const { - return QApplication::translate("QtGui::EditorAutoCorrectionOptionPage", "Auto correction/completition"); + return QApplication::translate("QtGui::EditorAutoCorrectionOptionPage", "Auto correction/completion"); } bool EditorAutoCorrectionOptionPage::apply() @@ -235,7 +239,7 @@ void EditorAutoCorrectionOptionPage::reset() QWidget *EditorAutoCorrectionOptionPage::setupWidget() { - QWidget *w = UiFileBasedOptionPage::setupWidget(); + auto *w = UiFileBasedOptionPage::setupWidget(); if(!m_model) { m_model = new KnownFieldModel(w); } @@ -451,6 +455,67 @@ void Id3v2OptionPage::reset() } } +// FileLayoutPage +FileLayoutPage::FileLayoutPage() +{} + +FileLayoutPage::~FileLayoutPage() +{} + +QString FileLayoutPage::displayName() const +{ + return QApplication::translate("QtGui::FileLayoutPage", "File layout"); +} + +bool FileLayoutPage::apply() +{ + if(hasBeenShown()) { + if(ui()->minPaddingSpinBox->value() > ui()->maxPaddingSpinBox->value()) { + return false; + } + Settings::maxPadding() = static_cast(ui()->maxPaddingSpinBox->value()); + Settings::minPadding() = static_cast(ui()->minPaddingSpinBox->value()); + Settings::preferredPadding() = static_cast(ui()->preferredPaddingSpinBox->value()); + if(ui()->beforeDataRadioButton->isChecked()) { + preferredTagPosition() = TagPosition::BeforeData; + } else if(ui()->afterDataRadioButton->isChecked()) { + preferredTagPosition() = TagPosition::AfterData; + } + forceTagPosition() = ui()->forcePositionCheckBox->isChecked(); + } + return true; +} + +void FileLayoutPage::reset() +{ + if(hasBeenShown()) { + ui()->maxPaddingSpinBox->setValue(static_cast(Settings::maxPadding())); + ui()->minPaddingSpinBox->setValue(static_cast(Settings::minPadding())); + ui()->preferredPaddingSpinBox->setValue(static_cast(Settings::preferredPadding())); + switch(preferredTagPosition()) { + case TagPosition::BeforeData: + ui()->beforeDataRadioButton->setChecked(true); + break; + case TagPosition::AfterData: + ui()->afterDataRadioButton->setChecked(true); + break; + } + ui()->forcePositionCheckBox->setChecked(forceTagPosition()); + } +} + +QWidget *FileLayoutPage::setupWidget() +{ + auto *widget = Dialogs::UiFileBasedOptionPage::setupWidget(); + ui()->preferredTagPosLabel->setNotificationType(NotificationType::Warning); + ui()->preferredTagPosLabel->setText(QApplication::translate("QtGui::FileLayoutPage", "These options might be ignored if not supported by either the format or the implementation.")); + QObject::connect(ui()->minPaddingSpinBox, static_cast(&QSpinBox::valueChanged), ui()->maxPaddingSpinBox, &QSpinBox::setMinimum); + QObject::connect(ui()->minPaddingSpinBox, static_cast(&QSpinBox::valueChanged), ui()->preferredPaddingSpinBox, &QSpinBox::setMinimum); + QObject::connect(ui()->maxPaddingSpinBox, static_cast(&QSpinBox::valueChanged), ui()->minPaddingSpinBox, &QSpinBox::setMaximum); + QObject::connect(ui()->maxPaddingSpinBox, static_cast(&QSpinBox::valueChanged), ui()->preferredPaddingSpinBox, &QSpinBox::setMaximum); + return widget; +} + /* TRANSLATOR QtGui::SettingsDialog Necessary for lupdate. @@ -467,7 +532,7 @@ SettingsDialog::SettingsDialog(QWidget *parent) : category->setDisplayName(tr("Tag processing")); category->assignPages(QList() << new TagProcessingGeneralOptionPage << - new Id3v1OptionPage << new Id3v2OptionPage); + new Id3v1OptionPage << new Id3v2OptionPage << new FileLayoutPage); category->setIcon(QIcon(QStringLiteral(":/tageditor/icons/hicolor/32x32/settingscategories/tag.png"))); categories << category; diff --git a/gui/settingsdialog.h b/gui/settingsdialog.h index 2603725..da85c86 100644 --- a/gui/settingsdialog.h +++ b/gui/settingsdialog.h @@ -10,6 +10,7 @@ #include "gui/ui_tagprocessinggeneraloptionpage.h" #include "gui/ui_id3v1optionpage.h" #include "gui/ui_id3v2optionpage.h" +#include "gui/ui_filelayout.h" #include #include @@ -179,6 +180,25 @@ public: void reset(); }; +// FileLayoutPage +namespace Ui { +class FileLayoutPage; +} + +class FileLayoutPage : public Dialogs::UiFileBasedOptionPage +{ +public: + explicit FileLayoutPage(); + ~FileLayoutPage(); + + QString displayName() const; + bool apply(); + void reset(); + +private: + QWidget *setupWidget(); +}; + class SettingsDialog : public Dialogs::SettingsDialog { Q_OBJECT