Add info about auto-correction when opening file

This commit is contained in:
Martchus 2019-06-01 12:53:44 +02:00
parent ef82a88a97
commit cf71ac5dca
8 changed files with 115 additions and 52 deletions

View File

@ -92,16 +92,19 @@ PicturePreviewSelection::~PicturePreviewSelection()
*
* Used for editing tags programmatically, eg. in TagEditorWidget::insertTitleFromFilename() and DbQueryWidget::applyResults().
*/
void PicturePreviewSelection::setValue(const TagValue &value, PreviousValueHandling previousValueHandling)
bool PicturePreviewSelection::setValue(const TagValue &value, PreviousValueHandling previousValueHandling)
{
assert(m_currentTypeIndex < m_values.size());
TagValue &currentValue = m_values[m_currentTypeIndex];
bool updated = false;
if ((previousValueHandling == PreviousValueHandling::Clear || !value.isEmpty())
&& (previousValueHandling != PreviousValueHandling::Keep || currentValue.isEmpty())) {
currentValue = value; // TODO: move(value);
updated = true;
emit pictureChanged();
}
updatePreview(m_currentTypeIndex);
return updated;
}
/*!
@ -153,7 +156,7 @@ int fetchId3v2CoverValues(
/*!
* \brief Sets the widget up.
*/
void PicturePreviewSelection::setup(PreviousValueHandling previousValueHandling)
bool PicturePreviewSelection::setup(PreviousValueHandling previousValueHandling)
{
if (previousValueHandling == PreviousValueHandling::Auto) {
previousValueHandling = PreviousValueHandling::Update;
@ -161,7 +164,7 @@ void PicturePreviewSelection::setup(PreviousValueHandling previousValueHandling)
m_currentTypeIndex = 0;
if (!m_tag) {
setEnabled(false);
return;
return false;
}
if (m_field == KnownField::Cover && (m_tag->type() == TagType::Id3v2Tag || m_tag->type() == TagType::VorbisComment)) {
m_ui->switchTypeComboBox->setHidden(false);
@ -219,6 +222,7 @@ void PicturePreviewSelection::setup(PreviousValueHandling previousValueHandling)
updatePreview(m_currentTypeIndex);
updateDescription(m_currentTypeIndex);
setEnabled(true);
return true;
}
/*!

View File

@ -42,8 +42,8 @@ public:
TagParser::KnownField field() const;
public slots:
void setTagField(TagParser::Tag *tag, TagParser::KnownField field, PreviousValueHandling previousValueHandling = PreviousValueHandling::Clear);
void setValue(const TagParser::TagValue &value, PreviousValueHandling previousValueHandling = PreviousValueHandling::Clear);
bool setTagField(TagParser::Tag *tag, TagParser::KnownField field, PreviousValueHandling previousValueHandling = PreviousValueHandling::Clear);
bool setValue(const TagParser::TagValue &value, PreviousValueHandling previousValueHandling = PreviousValueHandling::Clear);
void apply();
void clear();
@ -77,7 +77,7 @@ private slots:
void showContextMenu();
private:
void setup(PreviousValueHandling previousValueHandling = PreviousValueHandling::Clear);
bool setup(PreviousValueHandling previousValueHandling = PreviousValueHandling::Clear);
void updateSizeAndMimeType(std::size_t fileSize, const QSize &resolution, const QString &mimeType);
std::unique_ptr<Ui::PicturePreviewSelection> m_ui;
@ -118,11 +118,11 @@ inline TagParser::KnownField PicturePreviewSelection::field() const
*
* If \a tag is nullptr the widget is disabled. The widget will be re-setup.
*/
inline void PicturePreviewSelection::setTagField(TagParser::Tag *tag, TagParser::KnownField field, PreviousValueHandling previousValueHandling)
inline bool PicturePreviewSelection::setTagField(TagParser::Tag *tag, TagParser::KnownField field, PreviousValueHandling previousValueHandling)
{
m_tag = tag;
m_field = field;
setup(previousValueHandling);
return setup(previousValueHandling);
}
} // namespace QtGui

View File

@ -174,6 +174,16 @@ bool TagEdit::hasField(KnownField field) const
return false;
}
bool TagEdit::hasAutoCorrectionBeenApplied() const
{
for (auto i = m_widgets.constBegin(), end = m_widgets.constEnd(); i != end; ++i) {
if (i.value()->hasAutoCorrectionBeenApplied()) {
return true;
}
}
return false;
}
/*!
* \brief Generates a label for the currently assigned tags.
*

View File

@ -44,6 +44,7 @@ public:
void setPreviousValueHandling(PreviousValueHandling previousValueHandling);
TagFieldEdit *tagFieldEdit(TagParser::KnownField field) const;
QString generateLabel() const;
bool hasAutoCorrectionBeenApplied() const;
public slots:
void clear();

View File

@ -262,6 +262,7 @@ bool TagEditorWidget::event(QEvent *event)
return true;
}
}
break;
}
default:;
}
@ -332,6 +333,7 @@ void TagEditorWidget::updateTagEditsAndAttachmentEdits(bool updateUi, PreviousVa
break;
default:;
}
// define helper function to fetch next edit
TagEdit *edit; // holds current edit
int widgetIndex = 0; // holds index of current edit in the stacked widget
@ -348,6 +350,7 @@ void TagEditorWidget::updateTagEditsAndAttachmentEdits(bool updateUi, PreviousVa
// apply settings
edit->setPreviousValueHandling(previousValueHandling);
};
// add/update TagEdit widgets
if (m_tags.size()) {
// create a lists of the targets and tags
@ -364,12 +367,16 @@ void TagEditorWidget::updateTagEditsAndAttachmentEdits(bool updateUi, PreviousVa
}
}
// create a singe editor per target or seperate editors for each tag depending on the settings
bool hasAutoCorrectionBeenApplied = false;
switch (Settings::values().editor.multipleTagHandling) {
case Settings::MultipleTagHandling::SingleEditorPerTarget:
// iterate through all targets in both cases
for (int targetIndex = 0, targetCount = targets.size(); targetIndex < targetCount; ++targetIndex) {
fetchNextEdit();
edit->setTags(tagsByTarget.at(targetIndex), updateUi); // set all tags with the same target to a single edit
if (!hasAutoCorrectionBeenApplied) {
hasAutoCorrectionBeenApplied = edit->hasAutoCorrectionBeenApplied();
}
++widgetIndex;
}
break;
@ -379,17 +386,24 @@ void TagEditorWidget::updateTagEditsAndAttachmentEdits(bool updateUi, PreviousVa
for (Tag *tag : tagsByTarget.at(targetIndex)) {
fetchNextEdit();
edit->setTag(tag, updateUi); // use a separate edit for each tag
if (!hasAutoCorrectionBeenApplied) {
hasAutoCorrectionBeenApplied = edit->hasAutoCorrectionBeenApplied();
}
++widgetIndex;
}
}
break;
}
if (hasAutoCorrectionBeenApplied) {
addParsingNotificationLine(tr("Some values have been changed by the auto-correction."));
}
} else {
// there are no tags -> leave one edit existend but ensure no tags are assigned
fetchNextEdit();
edit->setTag(nullptr, false);
++widgetIndex;
}
// add/update AttachmentsEdit widget
if (m_fileInfo.areAttachmentsSupported()) {
AttachmentsEdit *edit;
@ -406,6 +420,7 @@ void TagEditorWidget::updateTagEditsAndAttachmentEdits(bool updateUi, PreviousVa
}
++widgetIndex;
}
// remove surplus edits
while (widgetIndex < m_ui->stackedWidget->count()) {
QWidget *toRemove = m_ui->stackedWidget->widget(widgetIndex);
@ -609,19 +624,26 @@ void TagEditorWidget::updateKeepPreviousValuesButton()
*/
void TagEditorWidget::insertTitleFromFilename()
{
if (!m_tags.empty() && Settings::values().editor.autoCompletition.insertTitleFromFilename) {
QString title;
int trackNum;
parseFileName(m_fileName, title, trackNum);
const TagValue titleValue = qstringToTagValue(title, TagTextEncoding::Utf16LittleEndian);
foreachTagEdit([&titleValue](TagEdit *edit) {
for (const Tag *tag : edit->tags()) {
if (tag->supportsTarget() && tag->isTargetingLevel(TagTargetLevel::Part)) {
return;
}
if (m_tags.empty() || !Settings::values().editor.autoCompletition.insertTitleFromFilename) {
return;
}
QString title;
int trackNum;
parseFileName(m_fileName, title, trackNum);
const auto titleValue = qstringToTagValue(title, TagTextEncoding::Utf16LittleEndian);
auto updated = false;
foreachTagEdit([&titleValue, &updated](TagEdit *const edit) {
for (const auto *const tag : edit->tags()) {
if (tag->supportsTarget() && tag->isTargetingLevel(TagTargetLevel::Part)) {
return;
}
edit->setValue(KnownField::Title, titleValue, PreviousValueHandling::Keep);
});
}
if (edit->setValue(KnownField::Title, titleValue, PreviousValueHandling::Keep)) {
updated = true;
}
});
if (updated) {
addParsingNotificationLine(tr("Inserted title from filename."));
}
}
@ -1414,6 +1436,11 @@ void TagEditorWidget::applySettingsFromDialog()
updateInfoView();
}
void TagEditorWidget::addParsingNotificationLine(const QString &line)
{
m_ui->parsingNotificationWidget->appendLine(line);
}
/*!
* \brief Adds a tag (using the specified \a createTag function) to the currently opened file.
*

View File

@ -75,6 +75,7 @@ public slots:
void openFileInfoInBrowser();
// misc
void applySettingsFromDialog();
void addParsingNotificationLine(const QString &line);
signals:
/// \brief Emitted when loading the next file has been triggered.

View File

@ -170,11 +170,11 @@ TagValue TagFieldEdit::value(TagTextEncoding encoding, bool includeDescription)
*/
bool TagFieldEdit::setValue(const TagValue &value, PreviousValueHandling previousValueHandling)
{
updateValue(value, previousValueHandling, false);
bool updated = updateValue(value, previousValueHandling, false);
if (m_pictureSelection) {
m_pictureSelection->setValue(value, previousValueHandling);
updated = m_pictureSelection->setValue(value, previousValueHandling) || updated;
}
return true;
return updated;
}
/*!
@ -510,7 +510,7 @@ QLabel *TagFieldEdit::setupTypeNotSupportedLabel()
*
* The new value is read from the assigned tag(s).
*/
void TagFieldEdit::updateValue(PreviousValueHandling previousValueHandling)
bool TagFieldEdit::updateValue(PreviousValueHandling previousValueHandling)
{
// use the values from the last tag which has the specified field
for (auto i = tags().crbegin(), end = tags().crend(); i != end; ++i) {
@ -521,19 +521,20 @@ void TagFieldEdit::updateValue(PreviousValueHandling previousValueHandling)
continue;
}
updateValue(value, previousValueHandling);
bool updated = updateValue(value, previousValueHandling);
if (m_pictureSelection) {
m_pictureSelection->setTagField(tag, m_field, previousValueHandling);
updated = m_pictureSelection->setTagField(tag, m_field, previousValueHandling) || updated;
}
return;
return updated;
}
// set an empty value
updateValue(TagValue(), previousValueHandling);
bool updated = updateValue(TagValue(), previousValueHandling);
if (m_pictureSelection) {
// pass the last tag if present so the picture selection can operate on that tag instance and won't be disabled
m_pictureSelection->setTagField(m_tags->isEmpty() ? nullptr : m_tags->back(), m_field, previousValueHandling);
updated = m_pictureSelection->setTagField(m_tags->isEmpty() ? nullptr : m_tags->back(), m_field, previousValueHandling) || updated;
}
return updated;
}
/*!
@ -542,12 +543,13 @@ void TagFieldEdit::updateValue(PreviousValueHandling previousValueHandling)
* \param previousValueHandling Specifies how to deal with the previous value.
* \remarks If \a tag is nullptr, the new value is empty.
*/
void TagFieldEdit::updateValue(Tag *tag, PreviousValueHandling previousValueHandling)
bool TagFieldEdit::updateValue(Tag *tag, PreviousValueHandling previousValueHandling)
{
updateValue(tag ? tag->value(m_field) : TagValue::empty(), previousValueHandling);
bool updated = updateValue(tag ? tag->value(m_field) : TagValue::empty(), previousValueHandling);
if (m_pictureSelection) {
m_pictureSelection->setTagField(tag, m_field, previousValueHandling);
updated = m_pictureSelection->setTagField(tag, m_field, previousValueHandling) || updated;
}
return updated;
}
/*!
@ -557,8 +559,9 @@ void TagFieldEdit::updateValue(Tag *tag, PreviousValueHandling previousValueHand
* \param updateRestoreButton Specifies whether the "restore button" should be updated.
* \remarks Does not update the picture preview selection.
*/
void TagFieldEdit::updateValue(const TagValue &value, PreviousValueHandling previousValueHandling, bool updateRestoreButton)
bool TagFieldEdit::updateValue(const TagValue &value, PreviousValueHandling previousValueHandling, bool updateRestoreButton)
{
bool autoCorrectionApplied = false;
bool conversionError = false;
bool updated = false;
concretizePreviousValueHandling(previousValueHandling);
@ -567,9 +570,12 @@ void TagFieldEdit::updateValue(const TagValue &value, PreviousValueHandling prev
if (m_lineEdit || m_comboBox || m_plainTextEdit) {
const auto text([&] {
try {
auto text(Utility::tagValueToQString(value));
applyAutoCorrection(text);
return text;
const auto text(Utility::tagValueToQString(value));
const auto correctedText = applyAutoCorrection(text);
if (correctedText != text) {
autoCorrectionApplied = true;
}
return correctedText;
} catch (const ConversionException &) {
conversionError = true;
return QString();
@ -651,10 +657,13 @@ void TagFieldEdit::updateValue(const TagValue &value, PreviousValueHandling prev
m_descriptionLineEdit->setEnabled(true);
if (previousValueHandling != PreviousValueHandling::Keep || m_descriptionLineEdit->isCleared()) {
try {
auto desc = Utility::stringToQString(value.description(), value.descriptionEncoding());
applyAutoCorrection(desc);
if (!m_isLocked || desc.isEmpty()) {
m_descriptionLineEdit->setText(desc);
const auto desc = Utility::stringToQString(value.description(), value.descriptionEncoding());
const auto correctedDesc = applyAutoCorrection(desc);
if (correctedDesc != desc) {
autoCorrectionApplied = true;
}
if (!m_isLocked || correctedDesc.isEmpty()) {
m_descriptionLineEdit->setText(correctedDesc);
}
} catch (const ConversionException &) {
conversionError = true;
@ -673,6 +682,7 @@ void TagFieldEdit::updateValue(const TagValue &value, PreviousValueHandling prev
if (updated) {
setLocked(false);
}
m_autoCorrectionApplied = updated && autoCorrectionApplied;
// setup info button
const auto widgets = initializer_list<ButtonOverlay *>{ m_lineEdit, m_comboBox, m_spinBoxes.first, m_spinBoxes.second };
@ -683,7 +693,7 @@ void TagFieldEdit::updateValue(const TagValue &value, PreviousValueHandling prev
overlay->disableInfoButton();
}
}
return;
return updated;
}
const auto pixmap(
QIcon::fromTheme(QStringLiteral("emblem-error"), QIcon(QStringLiteral(":/qtutilities/icons/hicolor/48x48/actions/edit-error.png")))
@ -706,6 +716,7 @@ void TagFieldEdit::updateValue(const TagValue &value, PreviousValueHandling prev
overlay->enableInfoButton(pixmap, text);
}
}
return updated;
}
/*!
@ -756,8 +767,9 @@ void TagFieldEdit::showRestoreButton()
/*!
* \brief Applies auto correction (according to the settings) for the specified \a textValue.
*/
void TagFieldEdit::applyAutoCorrection(QString &textValue)
QString TagFieldEdit::applyAutoCorrection(const QString &textValue)
{
QString correctedValue = textValue;
const auto &settings = Settings::values().editor.autoCompletition;
auto &fields = settings.fields.items();
auto i = find_if(fields.constBegin(), fields.constEnd(), [this](const ChecklistItem &item) {
@ -766,17 +778,18 @@ void TagFieldEdit::applyAutoCorrection(QString &textValue)
});
// if current field is in the list of auto correction fields and auto correction should be applied
if (i == fields.constEnd() || !i->isChecked()) {
return;
return correctedValue;
}
if (settings.trimWhitespaces) {
textValue = textValue.trimmed();
}
if (settings.fixUmlauts) {
textValue = Utility::fixUmlauts(textValue);
correctedValue = correctedValue.trimmed();
}
if (settings.formatNames) {
textValue = Utility::formatName(textValue);
correctedValue = Utility::formatName(correctedValue);
}
if (settings.fixUmlauts) {
correctedValue = Utility::fixUmlauts(correctedValue);
}
return correctedValue;
}
/*!

View File

@ -49,6 +49,7 @@ public:
bool isLocked() const;
void setLocked(bool locked);
void toggleLocked();
bool hasAutoCorrectionBeenApplied() const;
public slots:
void clear();
@ -79,14 +80,14 @@ private:
QWidget *setupFileSelection();
Widgets::ClearLineEdit *setupDescriptionLineEdit();
QLabel *setupTypeNotSupportedLabel();
void updateValue(PreviousValueHandling previousValueHandling = PreviousValueHandling::Clear);
void updateValue(TagParser::Tag *tag, PreviousValueHandling previousValueHandling = PreviousValueHandling::Clear);
void updateValue(
bool updateValue(PreviousValueHandling previousValueHandling = PreviousValueHandling::Clear);
bool updateValue(TagParser::Tag *tag, PreviousValueHandling previousValueHandling = PreviousValueHandling::Clear);
bool updateValue(
const TagParser::TagValue &value, PreviousValueHandling previousValueHandling = PreviousValueHandling::Clear, bool resetRestoreButton = true);
Widgets::IconButton *setupRestoreButton();
Widgets::IconButton *setupLockButton();
void showRestoreButton();
void applyAutoCorrection(QString &textValue);
QString applyAutoCorrection(const QString &textValue);
void concretizePreviousValueHandling(PreviousValueHandling &previousValueHandling);
QVBoxLayout *m_layout;
@ -103,6 +104,7 @@ private:
Widgets::IconButton *m_restoreButton;
Widgets::IconButton *m_lockButton;
bool m_isLocked;
bool m_autoCorrectionApplied;
};
inline const QList<TagParser::Tag *> &TagFieldEdit::tags() const
@ -125,6 +127,11 @@ inline void TagFieldEdit::toggleLocked()
setLocked(!isLocked());
}
inline bool TagFieldEdit::hasAutoCorrectionBeenApplied() const
{
return m_autoCorrectionApplied;
}
} // namespace QtGui
#endif // QTGUI_TAGFIELDLINEEDIT_H