diff --git a/core/utilities/setup/metadata/namespaceeditdlg.cpp b/core/utilities/setup/metadata/namespaceeditdlg.cpp
index 1694b99dca..9b88a4ea2b 100644
--- a/core/utilities/setup/metadata/namespaceeditdlg.cpp
+++ b/core/utilities/setup/metadata/namespaceeditdlg.cpp
@@ -1,683 +1,683 @@
/* ============================================================
*
* This file is a part of digiKam project
* https://www.digikam.org
*
* Date : 2015-07-03
* Description : dialog to edit and create digiKam xmp namespaces
*
* Copyright (C) 2015 by Veaceslav Munteanu
*
* This program is free software; you can redistribute it
* and/or modify it under the terms of the GNU General
* Public License as published by the Free Software Foundation;
* either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* ============================================================ */
#include "namespaceeditdlg.h"
// Qt includes
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
// KDE includes
#include
// Local includes
#include "dxmlguiwindow.h"
#include "digikam_debug.h"
namespace Digikam
{
class Q_DECL_HIDDEN NamespaceEditDlg::Private
{
public:
explicit Private()
: buttons(nullptr),
create(0),
topLabel(nullptr),
logo(nullptr),
gridLayout(nullptr),
page(nullptr),
- subspaceCombo(nullptr), // NamespaceEntry variables
+ subspaceCombo(nullptr), ///< NamespaceEntry variables
specialOptsCombo(nullptr),
altSpecialOptsCombo(nullptr),
namespaceName(nullptr),
alternativeName(nullptr),
nameSpaceSeparator(nullptr),
isPath(nullptr),
ratingMappings(nullptr),
zeroStars(nullptr),
oneStar(nullptr),
twoStars(nullptr),
threeStars(nullptr),
fourStars(nullptr),
fiveStars(nullptr),
- tagTipLabel(nullptr), // Labels
+ tagTipLabel(nullptr), ///< Labels
ratingTipLabel(nullptr),
commentTipLabel(nullptr),
subspaceLabel(nullptr),
titleLabel(nullptr),
specialOptsLabel(nullptr),
alternativeNameLabel(nullptr),
altspecialOptsLabel(nullptr),
isTagLabel(nullptr),
separatorLabel(nullptr),
tipLabel2(nullptr),
nsType(NamespaceEntry::TAGS)
{
}
QDialogButtonBox* buttons;
bool create;
QLabel* topLabel;
QLabel* logo;
QGridLayout* gridLayout;
QWidget* page;
- // NamespaceEntry variables
+ /// NamespaceEntry variables
QComboBox* subspaceCombo;
QComboBox* specialOptsCombo;
QComboBox* altSpecialOptsCombo;
QLineEdit* namespaceName;
QLineEdit* alternativeName;
QLineEdit* nameSpaceSeparator;
QCheckBox* isPath;
QGroupBox* ratingMappings;
QSpinBox* zeroStars;
QSpinBox* oneStar;
QSpinBox* twoStars;
QSpinBox* threeStars;
QSpinBox* fourStars;
QSpinBox* fiveStars;
- // Labels
+ /// Labels
QLabel* tagTipLabel;
QLabel* ratingTipLabel;
QLabel* commentTipLabel;
QLabel* subspaceLabel;
QLabel* titleLabel;
QLabel* specialOptsLabel;
QLabel* alternativeNameLabel;
QLabel* altspecialOptsLabel;
QLabel* isTagLabel;
QLabel* separatorLabel;
QLabel* tipLabel2;
NamespaceEntry::NamespaceType nsType;
};
NamespaceEditDlg::NamespaceEditDlg(bool create,
NamespaceEntry& entry,
QWidget* const parent)
: QDialog(parent),
d(new Private())
{
setModal(true);
d->buttons = new QDialogButtonBox(QDialogButtonBox::Help |
QDialogButtonBox::Ok |
QDialogButtonBox::Cancel, this);
d->buttons->button(QDialogButtonBox::Ok)->setDefault(true);
if (create)
{
setWindowTitle(i18n("New Xmp Namespace"));
}
else
{
setWindowTitle(i18n("Edit Xmp Namespace"));
}
d->create = create;
d->nsType = entry.nsType;
setupTagGui(entry);
// --- NOTE: use dynamic binding as slots below are virtual method which can be re-implemented in derived classes.
connect(d->buttons->button(QDialogButtonBox::Ok), &QPushButton::clicked,
this, &NamespaceEditDlg::accept);
connect(d->buttons->button(QDialogButtonBox::Cancel), &QPushButton::clicked,
this, &NamespaceEditDlg::reject);
connect(d->buttons->button(QDialogButtonBox::Help), &QPushButton::clicked,
this, &NamespaceEditDlg::slotHelp);
// --------------------------------------------------------
if (!d->create)
{
populateFields(entry);
}
setType(entry.nsType);
if (entry.isDefault)
{
makeReadOnly();
}
qCDebug(DIGIKAM_GENERAL_LOG) << "Entry type" << entry.nsType
<< "subspace" << entry.subspace
<< entry.isDefault;
adjustSize();
}
NamespaceEditDlg::~NamespaceEditDlg()
{
delete d;
}
bool NamespaceEditDlg::create(QWidget* const parent, NamespaceEntry& entry)
{
QPointer dlg = new NamespaceEditDlg(true,entry,parent);
qCDebug(DIGIKAM_GENERAL_LOG) << "Name before save: " << entry.namespaceName;
bool valRet = dlg->exec();
if (valRet == QDialog::Accepted)
{
dlg->saveData(entry);
}
qCDebug(DIGIKAM_GENERAL_LOG) << "Name after save: " << entry.namespaceName;
delete dlg;
return valRet;
}
bool NamespaceEditDlg::edit(QWidget* const parent, NamespaceEntry& entry)
{
QPointer dlg = new NamespaceEditDlg(false, entry, parent);
qCDebug(DIGIKAM_GENERAL_LOG) << "Name before save: " << entry.namespaceName;
bool valRet = dlg->exec();
if (valRet == QDialog::Accepted && !entry.isDefault)
{
dlg->saveData(entry);
}
qCDebug(DIGIKAM_GENERAL_LOG) << "Name before save: " << entry.namespaceName;
delete dlg;
return valRet;
}
void NamespaceEditDlg::setupTagGui(NamespaceEntry& entry)
{
d->page = new QWidget(this);
d->gridLayout = new QGridLayout(d->page);
d->logo = new QLabel(d->page);
d->logo->setPixmap(QIcon::fromTheme(QLatin1String("digikam")).pixmap(QSize(48,48)));
d->topLabel = new QLabel(d->page);
d->topLabel->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
d->topLabel->setWordWrap(false);
d->topLabel->setText(i18n("Add metadata namespace"));
d->subspaceCombo = new QComboBox(this);
d->subspaceLabel = new QLabel(d->page);
d->subspaceLabel->setText(i18n("Metadata Subspace"));
d->subspaceCombo->addItem(QLatin1String("EXIF"), (int)NamespaceEntry::EXIF);
d->subspaceCombo->addItem(QLatin1String("IPTC"), (int)NamespaceEntry::IPTC);
d->subspaceCombo->addItem(QLatin1String("XMP"), (int)NamespaceEntry::XMP);
d->subspaceCombo->setCurrentIndex((int)entry.subspace);
qCDebug(DIGIKAM_GENERAL_LOG) << "Entry subspace" << (int)entry.subspace;
// -------------------Tag Elements---------------------------------
d->titleLabel = new QLabel(d->page);
d->titleLabel->setText(i18n("Name:"));
d->namespaceName = new QLineEdit(this);
//----------------- Tip Labels --------------------------------------
d->tagTipLabel = new QLabel(d->page);
d->tagTipLabel->setTextFormat(Qt::RichText);
d->tagTipLabel->setWordWrap(true);
d->tagTipLabel->setText(i18n("To create new namespaces, you need to specify parameters:
"
"- Namespace name with dots.
"
"Ex.: \"Xmp.digiKam.TagsList\" "
"- Separator parameter, used by tag paths
"
"Ex.: \"City/Paris\" or \"City|Paris\" "
"- Specify if only keyword or the whole path must be written.
"
));
d->ratingTipLabel = new QLabel(d->page);
d->ratingTipLabel->setTextFormat(Qt::RichText);
d->ratingTipLabel->setWordWrap(true);
d->ratingTipLabel->setText(i18n("To create new rating namespaces, you need to specify parameters:
"
"- Namespace name with dots.
"
"Ex.: \"Xmp.xmp.Rating\" "
"- Rating mappings, if namespace need other values than 0-5
"
"Ex.: Microsoft uses 0 1 25 50 75 99 "
"- Select the correct namespace option from list.
"
));
d->commentTipLabel = new QLabel(d->page);
d->commentTipLabel->setTextFormat(Qt::RichText);
d->commentTipLabel->setWordWrap(true);
d->commentTipLabel->setText(i18n("To create new comment namespaces, you need to specify parameters:
"
"- Namespace name with dots.
"
"Ex.: \"Xmp.xmp.Rating\" "
"- Select the correct namespace option from list.
"
));
// -------------------------------------------------------
d->specialOptsLabel = new QLabel(d->page);
d->specialOptsLabel->setText(i18n("Special Options"));
d->specialOptsCombo = new QComboBox(d->page);
d->specialOptsCombo->addItem(QLatin1String("NO_OPTS"), (int)NamespaceEntry::NO_OPTS);
if (entry.nsType == NamespaceEntry::COMMENT)
{
d->specialOptsCombo->addItem(QLatin1String("COMMENT_ALTLANG"), NamespaceEntry::COMMENT_ALTLANG);
d->specialOptsCombo->addItem(QLatin1String("COMMENT_ALTLANGLIST"), NamespaceEntry::COMMENT_ATLLANGLIST);
d->specialOptsCombo->addItem(QLatin1String("COMMENT_XMP"), NamespaceEntry::COMMENT_XMP);
d->specialOptsCombo->addItem(QLatin1String("COMMENT_JPEG"), NamespaceEntry::COMMENT_JPEG);
}
if (entry.nsType == NamespaceEntry::TAGS)
{
d->specialOptsCombo->addItem(QLatin1String("TAG_XMPBAG"), NamespaceEntry::TAG_XMPBAG);
d->specialOptsCombo->addItem(QLatin1String("TAG_XMPSEQ"), NamespaceEntry::TAG_XMPSEQ);
d->specialOptsCombo->addItem(QLatin1String("TAG_ACDSEE"), NamespaceEntry::TAG_ACDSEE);
}
d->alternativeNameLabel = new QLabel(d->page);
d->alternativeNameLabel->setText(i18n("Alternative name"));
d->alternativeName = new QLineEdit(d->page);
d->altspecialOptsLabel = new QLabel(d->page);
d->altspecialOptsLabel->setText(i18n("Alternative special options"));
d->altSpecialOptsCombo = new QComboBox(d->page);
d->altSpecialOptsCombo->addItem(QLatin1String("NO_OPTS"), (int)NamespaceEntry::NO_OPTS);
if (entry.nsType == NamespaceEntry::COMMENT)
{
d->altSpecialOptsCombo->addItem(QLatin1String("COMMENT_ALTLANG"), NamespaceEntry::COMMENT_ALTLANG);
d->altSpecialOptsCombo->addItem(QLatin1String("COMMENT_ALTLANGLIST"), NamespaceEntry::COMMENT_ATLLANGLIST);
d->altSpecialOptsCombo->addItem(QLatin1String("COMMENT_XMP"), NamespaceEntry::COMMENT_XMP);
d->altSpecialOptsCombo->addItem(QLatin1String("COMMENT_JPEG"), NamespaceEntry::COMMENT_JPEG);
}
if (entry.nsType == NamespaceEntry::TAGS)
{
d->altSpecialOptsCombo->addItem(QLatin1String("TAG_XMPBAG"), NamespaceEntry::TAG_XMPBAG);
d->altSpecialOptsCombo->addItem(QLatin1String("TAG_XMPSEQ"), NamespaceEntry::TAG_XMPSEQ);
d->altSpecialOptsCombo->addItem(QLatin1String("TAG_ACDSEE"), NamespaceEntry::TAG_ACDSEE);
}
// --------------------------------------------------------
d->separatorLabel = new QLabel(d->page);
d->separatorLabel->setText(i18n("Separator:"));
d->nameSpaceSeparator = new QLineEdit(this);
// --------------------------------------------------------
d->isTagLabel = new QLabel(d->page);
d->isTagLabel->setText(i18n("Set Tags Path:"));
d->isPath = new QCheckBox(this);
d->tipLabel2 = new QLabel(d->page);
d->tipLabel2->setTextFormat(Qt::RichText);
d->tipLabel2->setWordWrap(true);
QPalette sample_palette;
sample_palette.setColor(QPalette::Window, QColor(255, 51, 51, 150));
sample_palette.setColor(QPalette::WindowText, Qt::black);
d->tipLabel2->setAutoFillBackground(true);
d->tipLabel2->setPalette(sample_palette);
d->tipLabel2->hide();
// ----------------------Rating Elements----------------------------------
d->ratingMappings = new QGroupBox(this);
d->ratingMappings->setFlat(true);
QGridLayout* const ratingMappingsLayout = new QGridLayout(d->ratingMappings);
QLabel* const ratingLabel = new QLabel(d->page);
ratingLabel->setText(i18n("Rating Mapping:"));
d->zeroStars = new QSpinBox(this);
d->zeroStars->setValue(0);
d->oneStar = new QSpinBox(this);
d->oneStar->setValue(1);
d->twoStars = new QSpinBox(this);
d->twoStars->setValue(2);
d->threeStars = new QSpinBox(this);
d->threeStars->setValue(3);
d->fourStars = new QSpinBox(this);
d->fourStars->setValue(4);
d->fiveStars = new QSpinBox(this);
d->fiveStars->setValue(5);
const int spacing = QApplication::style()->pixelMetric(QStyle::PM_DefaultLayoutSpacing);
const int cmargin = QApplication::style()->pixelMetric(QStyle::PM_DefaultChildMargin);
ratingMappingsLayout->addWidget(ratingLabel, 0, 0, 1, 2);
ratingMappingsLayout->addWidget(d->zeroStars, 1, 0, 1, 1);
ratingMappingsLayout->addWidget(d->oneStar, 1, 1, 1, 1);
ratingMappingsLayout->addWidget(d->twoStars, 1, 2, 1, 1);
ratingMappingsLayout->addWidget(d->threeStars, 1, 3, 1, 1);
ratingMappingsLayout->addWidget(d->fourStars, 1, 4, 1, 1);
ratingMappingsLayout->addWidget(d->fiveStars, 1, 5, 1, 1);
d->gridLayout->addWidget(d->logo, 0, 0, 1, 2);
d->gridLayout->addWidget(d->topLabel, 0, 1, 1, 4);
d->gridLayout->addWidget(d->tagTipLabel, 1, 0, 1, 6);
d->gridLayout->addWidget(d->ratingTipLabel, 2, 0, 1, 6);
d->gridLayout->addWidget(d->commentTipLabel, 3, 0, 1, 6);
d->gridLayout->addWidget(d->subspaceLabel, 5, 0, 1, 2);
d->gridLayout->addWidget(d->subspaceCombo, 5, 2, 1, 4);
d->gridLayout->addWidget(d->titleLabel, 6, 0, 1, 2);
d->gridLayout->addWidget(d->namespaceName, 6, 2, 1, 4);
d->gridLayout->addWidget(d->specialOptsLabel, 7, 0, 1, 2);
d->gridLayout->addWidget(d->specialOptsCombo, 7, 2, 1, 4);
d->gridLayout->addWidget(d->alternativeNameLabel, 8, 0, 1, 2);
d->gridLayout->addWidget(d->alternativeName, 8, 2, 1, 4);
d->gridLayout->addWidget(d->altspecialOptsLabel, 9, 0, 1, 2);
d->gridLayout->addWidget(d->altSpecialOptsCombo, 9, 2, 1, 4);
- d->gridLayout->addWidget(d->separatorLabel, 10, 0, 1, 2);
- d->gridLayout->addWidget(d->nameSpaceSeparator, 10, 2, 1, 4);
- d->gridLayout->addWidget(d->isTagLabel, 11, 0, 1, 2);
- d->gridLayout->addWidget(d->isPath, 11, 2, 1, 3);
+ d->gridLayout->addWidget(d->separatorLabel, 10, 0, 1, 2);
+ d->gridLayout->addWidget(d->nameSpaceSeparator, 10, 2, 1, 4);
+ d->gridLayout->addWidget(d->isTagLabel, 11, 0, 1, 2);
+ d->gridLayout->addWidget(d->isPath, 11, 2, 1, 3);
- d->gridLayout->addWidget(d->ratingMappings, 12, 0, 2, 6);
- d->gridLayout->addWidget(d->tipLabel2, 14, 0, 1, 6);
+ d->gridLayout->addWidget(d->ratingMappings, 12, 0, 2, 6);
+ d->gridLayout->addWidget(d->tipLabel2, 14, 0, 1, 6);
d->gridLayout->setContentsMargins(cmargin, cmargin, cmargin, cmargin);
d->gridLayout->setSpacing(spacing);
QVBoxLayout* const vbx = new QVBoxLayout(this);
vbx->addWidget(d->page);
vbx->addWidget(d->buttons);
}
void NamespaceEditDlg::populateFields(NamespaceEntry& entry)
{
d->namespaceName->setText(entry.namespaceName);
d->nameSpaceSeparator->setText(entry.separator);
if (entry.tagPaths == NamespaceEntry::TAGPATH)
{
d->isPath->setChecked(true);
}
else
{
d->isPath->setChecked(false);
}
d->alternativeName->setText(entry.alternativeName);
d->specialOptsCombo->setCurrentIndex(d->specialOptsCombo->findData(entry.specialOpts));
d->altSpecialOptsCombo->setCurrentIndex(d->altSpecialOptsCombo->findData(entry.secondNameOpts));
if (entry.convertRatio.size() == 6)
{
d->zeroStars->setValue(entry.convertRatio.at(0));
d->oneStar->setValue(entry.convertRatio.at(1));
d->twoStars->setValue(entry.convertRatio.at(2));
d->threeStars->setValue(entry.convertRatio.at(3));
d->fourStars->setValue(entry.convertRatio.at(4));
d->fiveStars->setValue(entry.convertRatio.at(5));
}
}
void NamespaceEditDlg::setType(NamespaceEntry::NamespaceType type)
{
switch (type)
{
case NamespaceEntry::TAGS:
qCDebug(DIGIKAM_GENERAL_LOG) << "Setting up tags";
d->ratingTipLabel->hide();
d->commentTipLabel->hide();
d->ratingMappings->hide();
- // disable IPTC and EXIV for tags
+ // disable IPTC and EXIF for tags
d->subspaceCombo->setItemData(0, 0, Qt::UserRole -1);
d->subspaceCombo->setItemData(1, 0, Qt::UserRole -1);
break;
case NamespaceEntry::RATING:
d->tagTipLabel->hide();
d->commentTipLabel->hide();
d->isPath->hide();
d->isTagLabel->hide();
d->separatorLabel->hide();
d->nameSpaceSeparator->hide();
break;
case NamespaceEntry::COMMENT:
d->tagTipLabel->hide();
d->ratingTipLabel->hide();
d->isPath->hide();
d->isTagLabel->hide();
d->separatorLabel->hide();
d->nameSpaceSeparator->hide();
d->ratingMappings->hide();
break;
default:
break;
}
}
void NamespaceEditDlg::makeReadOnly()
{
QString txt = i18n("This is a default namespace. Default namespaces can only be disabled");
d->tipLabel2->setText(txt);
d->tipLabel2->show();
d->subspaceCombo->setDisabled(true);
d->specialOptsCombo->setDisabled(true);
d->altSpecialOptsCombo->setDisabled(true);
d->namespaceName->setDisabled(true);
d->alternativeName->setDisabled(true);
d->nameSpaceSeparator->setDisabled(true);
d->isPath->setDisabled(true);
d->ratingMappings->setDisabled(true);
d->zeroStars->setDisabled(true);
d->oneStar->setDisabled(true);
d->twoStars->setDisabled(true);
d->threeStars->setDisabled(true);
d->fourStars->setDisabled(true);
d->fiveStars->setDisabled(true);
}
bool NamespaceEditDlg::validifyCheck(QString& errMsg)
{
// bool result = true; NOT USED
if (d->namespaceName->text().isEmpty())
{
errMsg = i18n("The namespace name is required");
return false;
}
switch (d->subspaceCombo->currentData().toInt())
{
case NamespaceEntry::EXIF:
if (d->namespaceName->text().split(QLatin1Char('.')).first() != QLatin1String("Exif"))
{
errMsg = i18n("EXIF namespace name must start with \"Exif\".");
return false;
}
if (!d->alternativeName->text().isEmpty() &&
- d->alternativeName->text().split(QLatin1Char('.')).first() != QLatin1String("Exif"))
+ (d->alternativeName->text().split(QLatin1Char('.')).first() != QLatin1String("Exif")))
{
errMsg = i18n("EXIF alternative namespace name must start with \"Exif\".");
return false;
}
break;
case NamespaceEntry::IPTC:
if (d->namespaceName->text().split(QLatin1Char('.')).first() != QLatin1String("Iptc"))
{
errMsg = i18n("IPTC namespace name must start with \"Iptc\".");
return false;
}
if (!d->alternativeName->text().isEmpty() &&
- d->alternativeName->text().split(QLatin1Char('.')).first() != QLatin1String("Iptc"))
+ (d->alternativeName->text().split(QLatin1Char('.')).first() != QLatin1String("Iptc")))
{
errMsg = i18n("IPTC alternative namespace name must start with \"Iptc\".");
return false;
}
break;
case NamespaceEntry::XMP:
if (d->namespaceName->text().split(QLatin1Char('.')).first() != QLatin1String("Xmp"))
{
errMsg = i18n("XMP namespace name must start with \"Xmp\".");
return false;
}
if (!d->alternativeName->text().isEmpty() &&
- d->alternativeName->text().split(QLatin1Char('.')).first() != QLatin1String("Xmp"))
+ (d->alternativeName->text().split(QLatin1Char('.')).first() != QLatin1String("Xmp")))
{
errMsg = i18n("XMP alternative namespace name must start with \"Xmp\".");
return false;
}
break;
default:
break;
}
switch (d->nsType)
{
case NamespaceEntry::TAGS:
if (d->nameSpaceSeparator->text().isEmpty())
{
errMsg = i18n("Tag Path separator is required");
return false;
}
if (d->nameSpaceSeparator->text().size() > 1)
{
errMsg = i18n("Only one character is now supported as tag path separator");
return false;
}
break;
case NamespaceEntry::RATING:
break;
case NamespaceEntry::COMMENT:
break;
default:
break;
}
return true;
}
void NamespaceEditDlg::saveData(NamespaceEntry& entry)
{
entry.namespaceName = d->namespaceName->text();
entry.separator = d->nameSpaceSeparator->text();
if (d->isPath->isChecked())
{
entry.tagPaths = NamespaceEntry::TAGPATH;
}
else
{
entry.tagPaths = NamespaceEntry::TAG;
}
entry.alternativeName = d->alternativeName->text();
entry.specialOpts = (NamespaceEntry::SpecialOptions)d->specialOptsCombo->currentData().toInt();
entry.secondNameOpts = (NamespaceEntry::SpecialOptions)d->altSpecialOptsCombo->currentData().toInt();
entry.subspace = (NamespaceEntry::NsSubspace)d->subspaceCombo->currentData().toInt();
entry.convertRatio.clear();
entry.convertRatio.append(d->zeroStars->value());
entry.convertRatio.append(d->oneStar->value());
entry.convertRatio.append(d->twoStars->value());
entry.convertRatio.append(d->threeStars->value());
entry.convertRatio.append(d->fourStars->value());
entry.convertRatio.append(d->fiveStars->value());
}
void NamespaceEditDlg::accept()
{
QString errMsg;
if (validifyCheck(errMsg))
{
QDialog::accept();
}
else
{
d->tipLabel2->setText(errMsg);
d->tipLabel2->show();
}
}
void NamespaceEditDlg::slotHelp()
{
DXmlGuiWindow::openHandbook();
}
} // namespace Digikam
diff --git a/core/utilities/setup/metadata/namespacelistview.cpp b/core/utilities/setup/metadata/namespacelistview.cpp
index 5bd0322f7b..e7064b043a 100644
--- a/core/utilities/setup/metadata/namespacelistview.cpp
+++ b/core/utilities/setup/metadata/namespacelistview.cpp
@@ -1,180 +1,180 @@
/* ============================================================
*
* This file is a part of digiKam project
* https://www.digikam.org
*
* Date : 2013-08-22
* Description : Reimplemented QListView for metadata setup, with support for
* drag-n-drop
*
* Copyright (C) 2013-2015 by Veaceslav Munteanu
*
* This program is free software; you can redistribute it
* and/or modify it under the terms of the GNU General
* Public License as published by the Free Software Foundation;
* either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* ============================================================ */
#include "namespacelistview.h"
// Qt includes
#include
#include
#include
#include
#include
#include
#include
#include
#include
// KDE includes
#include
// Local includes
#include "digikam_debug.h"
namespace Digikam
{
NamespaceListView::NamespaceListView(QWidget* const parent)
: QListView(parent)
{
setAlternatingRowColors(true);
setAcceptDrops(true);
setDragEnabled(true);
setDragDropMode(QAbstractItemView::InternalMove);
setSelectionMode(QAbstractItemView::SingleSelection);
}
void NamespaceListView::startDrag(Qt::DropActions supportedActions)
{
QListView::startDrag(supportedActions);
}
QModelIndexList NamespaceListView::mySelectedIndexes()
{
return selectedIndexes();
}
void NamespaceListView::dropEvent(QDropEvent* e)
{
QListView::dropEvent(e);
emit signalItemsChanged();
}
QModelIndex NamespaceListView::indexVisuallyAt(const QPoint& p)
{
if (viewport()->rect().contains(p))
{
QModelIndex index = indexAt(p);
if (index.isValid() && visualRect(index).contains(p))
{
return index;
}
}
return QModelIndex();
}
void NamespaceListView::slotDeleteSelected()
{
QModelIndexList sel = selectionModel()->selectedIndexes();
if (sel.isEmpty())
{
return;
}
QStandardItemModel* const model = dynamic_cast(this->model());
if (!model)
{
qCDebug(DIGIKAM_GENERAL_LOG) << "Error! no model available!";
return;
}
foreach (const QModelIndex& index, sel)
{
QStandardItem* const root = model->invisibleRootItem();
root->removeRow(index.row());
}
emit signalItemsChanged();
}
void NamespaceListView::slotMoveItemDown()
{
QModelIndexList sel = selectionModel()->selectedIndexes();
if (sel.isEmpty())
{
return;
}
QStandardItemModel* const model = dynamic_cast(this->model());
if (!model)
{
qCDebug(DIGIKAM_GENERAL_LOG) << "Error! no model available!";
return;
}
QModelIndex index = sel.first();
QStandardItem* const root = model->invisibleRootItem();
- if (index.row() == root->rowCount() - 1)
+ if (index.row() == (root->rowCount() - 1))
{
return;
}
root->insertRow(index.row() + 1, root->takeRow(index.row()));
setCurrentIndex(model->index(index.row() + 1, index.column(), index.parent()));
emit signalItemsChanged();
}
void NamespaceListView::slotMoveItemUp()
{
QModelIndexList sel = selectionModel()->selectedIndexes();
if (sel.isEmpty())
{
return;
}
QStandardItemModel* const model = dynamic_cast(this->model());
if (!model)
{
qCDebug(DIGIKAM_GENERAL_LOG) << "Error! no model available!";
return;
}
QModelIndex index = sel.first();
QStandardItem* const root = model->invisibleRootItem();
if (index.row() == 0)
{
return;
}
root->insertRow(index.row() - 1, root->takeRow(index.row()));
setCurrentIndex(model->index(index.row() - 1, index.column(), index.parent()));
emit signalItemsChanged();
}
} // namespace Digikam
diff --git a/core/utilities/setup/metadata/setupmetadata.cpp b/core/utilities/setup/metadata/setupmetadata.cpp
index f65da440b3..877526c386 100644
--- a/core/utilities/setup/metadata/setupmetadata.cpp
+++ b/core/utilities/setup/metadata/setupmetadata.cpp
@@ -1,919 +1,921 @@
/* ============================================================
*
* This file is a part of digiKam project
* https://www.digikam.org
*
* Date : 2003-08-03
* Description : setup Metadata tab.
*
* Copyright (C) 2003-2004 by Ralf Holzer
* Copyright (C) 2003-2020 by Gilles Caulier
* Copyright (C) 2009-2012 by Marcel Wiesweg
* Copyright (C) 2017 by Simon Frei
*
* This program is free software; you can redistribute it
* and/or modify it under the terms of the GNU General
* Public License as published by the Free Software Foundation;
* either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* ============================================================ */
#include "setupmetadata.h"
// Qt includes
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
// KDE includes
#include
// Local includes
#include "advancedmetadatatab.h"
#include "applicationsettings.h"
#include "dactivelabel.h"
#include "digikam_config.h"
#include "digikam_debug.h"
#include "metaengine.h"
#include "metadatapanel.h"
#include "metaenginesettings.h"
#include "setuputils.h"
namespace Digikam
{
class Q_DECL_HIDDEN SetupMetadata::Private
{
public:
explicit Private()
: exifAutoRotateOriginal(false),
exifAutoRotateShowedInfo(false),
clearMetadataShowedInfo(false),
fieldsGroup(nullptr),
readWriteGroup(nullptr),
rotationGroup(nullptr),
rotationAdvGroup(nullptr),
saveTagsBox(nullptr),
saveCommentsBox(nullptr),
saveRatingBox(nullptr),
savePickLabelBox(nullptr),
saveColorLabelBox(nullptr),
saveDateTimeBox(nullptr),
saveTemplateBox(nullptr),
saveFaceTags(nullptr),
useLazySync(nullptr),
writeRawFilesBox(nullptr),
writeXMPSidecarBox(nullptr),
readXMPSidecarBox(nullptr),
sidecarFileNameBox(nullptr),
updateFileTimeStampBox(nullptr),
rescanImageIfModifiedBox(nullptr),
clearMetadataIfRescanBox(nullptr),
writingModeCombo(nullptr),
rotateByFlag(nullptr),
rotateByContents(nullptr),
allowRotateByMetadata(nullptr),
allowLossyRotate(nullptr),
exifRotateBox(nullptr),
exifSetOrientationBox(nullptr),
saveToBalooBox(nullptr),
readFromBalooBox(nullptr),
tab(nullptr),
displaySubTab(nullptr),
tagsCfgPanel(nullptr),
advTab(nullptr),
extensionsEdit(nullptr)
{
}
bool exifAutoRotateOriginal;
bool exifAutoRotateShowedInfo;
bool clearMetadataShowedInfo;
QGroupBox* fieldsGroup;
QGroupBox* readWriteGroup;
QGroupBox* rotationGroup;
QGroupBox* rotationAdvGroup;
QCheckBox* saveTagsBox;
QCheckBox* saveCommentsBox;
QCheckBox* saveRatingBox;
QCheckBox* savePickLabelBox;
QCheckBox* saveColorLabelBox;
QCheckBox* saveDateTimeBox;
QCheckBox* saveTemplateBox;
QCheckBox* saveFaceTags;
QCheckBox* useLazySync;
QCheckBox* writeRawFilesBox;
QCheckBox* writeXMPSidecarBox;
QCheckBox* readXMPSidecarBox;
QCheckBox* sidecarFileNameBox;
QCheckBox* updateFileTimeStampBox;
QCheckBox* rescanImageIfModifiedBox;
QCheckBox* clearMetadataIfRescanBox;
QComboBox* writingModeCombo;
QRadioButton* rotateByFlag;
QRadioButton* rotateByContents;
QCheckBox* allowRotateByMetadata;
QCheckBox* allowLossyRotate;
QCheckBox* exifRotateBox;
QCheckBox* exifSetOrientationBox;
QCheckBox* saveToBalooBox;
QCheckBox* readFromBalooBox;
QTabWidget* tab;
QTabWidget* displaySubTab;
MetadataPanel* tagsCfgPanel;
AdvancedMetadataTab* advTab;
QLineEdit* extensionsEdit;
};
SetupMetadata::SetupMetadata(QWidget* const parent)
: QScrollArea(parent),
d(new Private)
{
d->tab = new QTabWidget(viewport());
setWidget(d->tab);
setWidgetResizable(true);
QWidget* const panel = new QWidget;
QVBoxLayout* const mainLayout = new QVBoxLayout;
// --------------------------------------------------------
d->fieldsGroup = new QGroupBox;
QGridLayout* const fieldsLayout = new QGridLayout;
d->fieldsGroup->setWhatsThis(xi18nc("@info:whatsthis",
"In addition to the pixel content, image files usually "
"contain a variety of metadata. A lot of the parameters you can use "
"in digiKam to manage files, such as rating or comment, can be written "
"to the files' metadata. "
"Storing in metadata allows one to preserve this information "
"when moving or sending the files to different systems."));
QLabel* const fieldsIconLabel = new QLabel;
fieldsIconLabel->setPixmap(QIcon::fromTheme(QLatin1String("format-list-unordered")).pixmap(32));
QLabel* const fieldsLabel = new QLabel(i18nc("@label", "Write This Information to the Metadata"));
- d->saveTagsBox = new QCheckBox;
+ d->saveTagsBox = new QCheckBox;
d->saveTagsBox->setText(i18nc("@option:check", "Image tags"));
d->saveTagsBox->setWhatsThis(i18nc("@info:whatsthis", "Turn on this option to store the item tags "
"in the XMP and IPTC tags."));
- d->saveCommentsBox = new QCheckBox;
+ d->saveCommentsBox = new QCheckBox;
d->saveCommentsBox->setText(i18nc("@option:check", "Captions and title"));
d->saveCommentsBox->setWhatsThis(i18nc("@info:whatsthis", "Turn on this option to store item caption and title "
"in the JFIF Comment section, the EXIF tag, the XMP tag, "
"and the IPTC tag."));
- d->saveRatingBox = new QCheckBox;
+ d->saveRatingBox = new QCheckBox;
d->saveRatingBox->setText(i18nc("@option:check", "Rating"));
d->saveRatingBox->setWhatsThis(i18nc("@info:whatsthis", "Turn on this option to store the item rating "
"in the EXIF tag and the XMP tags."));
- d->savePickLabelBox = new QCheckBox;
+ d->savePickLabelBox = new QCheckBox;
d->savePickLabelBox->setText(i18nc("@option:check", "Pick label"));
d->savePickLabelBox->setWhatsThis(i18nc("@info:whatsthis", "Turn on this option to store the item pick label "
"in the XMP tags."));
d->saveColorLabelBox = new QCheckBox;
d->saveColorLabelBox->setText(i18nc("@option:check", "Color label"));
d->saveColorLabelBox->setWhatsThis(i18nc("@info:whatsthis", "Turn on this option to store the item color label "
"in the XMP tags."));
d->saveDateTimeBox = new QCheckBox;
d->saveDateTimeBox->setText(i18nc("@option:check", "Timestamps"));
d->saveDateTimeBox->setWhatsThis(i18nc("@info:whatsthis", "Turn on this option to store the item date and time "
"in the EXIF, XMP, and IPTC tags."));
d->saveTemplateBox = new QCheckBox;
d->saveTemplateBox->setText(i18nc("@option:check", "Metadata templates (Copyright etc.)"));
d->saveTemplateBox->setWhatsThis(i18nc("@info:whatsthis", "Turn on this option to store the metadata "
"template in the XMP and the IPTC tags. "
"You can set template values to Template setup page."));
- d->saveFaceTags = new QCheckBox;
+ d->saveFaceTags = new QCheckBox;
d->saveFaceTags->setText(i18nc("@option:check", "Face Tags (including face areas)"));
d->saveFaceTags->setWhatsThis(i18nc("@info:whatsthis", "Turn on this option to store face tags "
"with face rectangles in the XMP tags."));
fieldsLayout->addWidget(fieldsIconLabel, 0, 0, 2, 3);
fieldsLayout->addWidget(fieldsLabel, 0, 1, 2, 3);
fieldsLayout->addWidget(d->saveTagsBox, 2, 0, 1, 3);
fieldsLayout->addWidget(d->saveCommentsBox, 3, 0, 1, 3);
fieldsLayout->addWidget(d->saveRatingBox, 4, 0, 1, 3);
fieldsLayout->addWidget(d->savePickLabelBox, 5, 0, 1, 3);
fieldsLayout->addWidget(d->saveColorLabelBox, 6, 0, 1, 3);
fieldsLayout->addWidget(d->saveDateTimeBox, 7, 0, 1, 3);
fieldsLayout->addWidget(d->saveTemplateBox, 8, 0, 1, 3);
fieldsLayout->addWidget(d->saveFaceTags, 9 ,0, 1, 3);
fieldsLayout->setColumnStretch(3, 10);
d->fieldsGroup->setLayout(fieldsLayout);
// --------------------------------------------------------
d->readWriteGroup = new QGroupBox;
QGridLayout* const readWriteLayout = new QGridLayout;
QLabel* const readWriteIconLabel = new QLabel;
readWriteIconLabel->setPixmap(QIcon::fromTheme(QLatin1String("document-open")).pixmap(32));
QLabel* const readWriteLabel = new QLabel(i18nc("@label", "Reading and Writing Metadata"));
d->useLazySync = new QCheckBox;
d->useLazySync->setText(i18nc("@option:check", "Use lazy synchronization"));
d->useLazySync->setWhatsThis(i18nc("@info:whatsthis",
"Instead of synchronizing metadata, just schedule it for synchronization."
"Synchronization can be done later by triggering the apply pending, or at digikam exit"));
- d->writeRawFilesBox = new QCheckBox;
+ d->writeRawFilesBox = new QCheckBox;
d->writeRawFilesBox->setText(i18nc("@option:check", "If possible write Metadata to RAW files (experimental)"));
d->writeRawFilesBox->setWhatsThis(i18nc("@info:whatsthis", "Turn on this option to write metadata into RAW TIFF/EP files. "
"This feature requires the Exiv2 shared library, version >= 0.18.0. It is still "
"experimental, and is disabled by default."));
d->writeRawFilesBox->setEnabled(MetaEngine::supportMetadataWritting(QLatin1String("image/x-raw")));
d->updateFileTimeStampBox = new QCheckBox;
d->updateFileTimeStampBox->setText(i18nc("@option:check", "&Update file modification timestamp when files are modified"));
d->updateFileTimeStampBox->setWhatsThis(i18nc("@info:whatsthis",
"Turn off this option to not update file timestamps when files are changed as "
"when you update metadata or image data. Note: disabling this option can "
"introduce some dysfunctions with applications which use file timestamps "
"properties to detect file modifications automatically."));
d->rescanImageIfModifiedBox = new QCheckBox;
d->rescanImageIfModifiedBox->setText(i18nc("@option:check", "&Rescan file when files are modified"));
d->rescanImageIfModifiedBox->setWhatsThis(i18nc("@info:whatsthis",
"Turning this option on, will force digiKam to rescan files that has been "
"modified outside digiKam. If a file has changed it is file size or if "
"the last modified timestamp has changed, a rescan of that "
"file will be performed when digiKam starts."));
d->clearMetadataIfRescanBox = new QCheckBox;
d->clearMetadataIfRescanBox->setText(i18nc("@option:check", "&Clean up the metadata from the database when rescan files"));
d->clearMetadataIfRescanBox->setWhatsThis(i18nc("@info:whatsthis",
"Turning this option on, will force digiKam to delete the file metadata "
"contained in the database before the file is rescanned. WARNING: "
"if your metadata has been written to the database only and not "
"to the file or sidecar, you will be able to lose inserted "
"metadata such as tags, keywords, or geographic coordinates."));
readWriteLayout->addWidget(readWriteIconLabel, 0, 0, 2, 3);
readWriteLayout->addWidget(readWriteLabel, 0, 1, 2, 3);
readWriteLayout->addWidget(d->useLazySync, 2, 0, 1, 3);
readWriteLayout->addWidget(d->writeRawFilesBox, 3, 0, 1, 3);
readWriteLayout->addWidget(d->updateFileTimeStampBox, 4, 0, 1, 3);
readWriteLayout->addWidget(d->rescanImageIfModifiedBox, 5, 0, 1, 3);
readWriteLayout->addWidget(d->clearMetadataIfRescanBox, 6, 0, 1, 3);
readWriteLayout->setColumnStretch(3, 10);
d->readWriteGroup->setLayout(readWriteLayout);
// --------------------------------------------------------
QFrame* const infoBox = new QFrame;
QGridLayout* const infoBoxGrid = new QGridLayout;
infoBox->setFrameStyle(QFrame::StyledPanel | QFrame::Raised);
DActiveLabel* const exiv2LogoLabel = new DActiveLabel(QUrl(QLatin1String("https://www.exiv2.org")),
QStandardPaths::locate(QStandardPaths::GenericDataLocation, QLatin1String("digikam/data/logo-exiv2.png")),
infoBox);
exiv2LogoLabel->setWhatsThis(i18n("Visit Exiv2 project website"));
QLabel* const explanation = new QLabel(infoBox);
explanation->setOpenExternalLinks(true);
explanation->setWordWrap(true);
QString txt;
txt.append(i18n("EXIF - "
"a standard used by most digital cameras today to store technical "
"information (like aperture and shutter speed) about an image.
"));
txt.append(i18n("IPTC - "
"an older standard used in digital photography to store "
"photographer information in images.
"));
if (MetaEngine::supportXmp())
+ {
txt.append(i18n("XMP - "
"a new standard used in digital photography, designed to replace IPTC.
"));
+ }
explanation->setText(txt);
infoBoxGrid->addWidget(exiv2LogoLabel, 0, 0, 1, 1);
infoBoxGrid->addWidget(explanation, 0, 1, 1, 2);
infoBoxGrid->setColumnStretch(1, 10);
infoBoxGrid->setRowStretch(1, 10);
infoBoxGrid->setSpacing(0);
infoBox->setLayout(infoBoxGrid);
// --------------------------------------------------------
mainLayout->addWidget(d->fieldsGroup);
mainLayout->addWidget(d->readWriteGroup);
mainLayout->addWidget(infoBox);
panel->setLayout(mainLayout);
d->tab->insertTab(Behavior, panel, i18nc("@title:tab", "Behavior"));
// --------------------------------------------------------
QWidget* const rotationPanel = new QWidget(d->tab);
QVBoxLayout* const rotationLayout = new QVBoxLayout;
d->rotationGroup = new QGroupBox;
QGridLayout* const rotationGroupLayout = new QGridLayout;
QLabel* const rotationExplanation = new QLabel(i18nc("@label", "When rotating a file"));
QLabel* const rotationIcon = new QLabel;
rotationIcon->setPixmap(QIcon::fromTheme(QLatin1String("transform-rotate")).pixmap(32));
d->rotateByFlag = new QRadioButton(i18nc("@option:radio", "Rotate by only setting a flag"));
d->rotateByContents = new QRadioButton(i18nc("@option:radio", "Rotate by changing the content if possible"));
d->allowLossyRotate = new QCheckBox(i18nc("@option:check", "Even allow lossy rotation if necessary"));
d->allowRotateByMetadata = new QCheckBox(i18nc("@option:check", "Write flag to metadata if possible"));
connect(d->rotateByContents, SIGNAL(toggled(bool)),
d->allowLossyRotate, SLOT(setEnabled(bool)));
d->rotateByFlag->setChecked(false);
d->rotateByContents->setChecked(false);
d->allowLossyRotate->setEnabled(false);
d->allowLossyRotate->setChecked(false);
d->allowRotateByMetadata->setChecked(true);
d->rotateByFlag->setToolTip(i18nc("@info:tooltip",
"Rotate files only by changing a flag, not touching the pixel data"));
d->rotateByFlag->setWhatsThis(xi18nc("@info:whatsthis",
"A file can be rotated in two ways: "
"You can change the contents, rearranging the individual pixels of the image data. "
"Or you can set a flag that the file is to be rotated before it is shown. "
"Select this option if you always want to set only a flag. "
"This is less obtrusive, but requires support if the file is accessed with another software. "
"Ensure to allow setting the flag in the metadata if you want to share your files "
"outside digiKam."));
d->rotateByContents->setToolTip(i18nc("@info:tooltip",
"If possible rotate files by changing the pixel data"));
d->rotateByContents->setWhatsThis(xi18nc("@info:whatsthis",
"A file can be rotated in two ways: "
"You can change the contents, rearranging the individual pixels of the image data. "
"Or you can set a flag that the file is to be rotated before it is shown. "
"Select this option if you want the file to be rotated by changing the content. "
"This is a lossless operation for JPEG files. For other formats it is a lossy operation, "
"which you need to enable explicitly. "
"It is not support for RAW and other read-only formats, "
"which will be rotated by flag only."));
d->allowLossyRotate->setToolTip(i18nc("@info:tooltip",
"Rotate files by changing the pixel data even if the operation will incur quality loss"));
d->allowLossyRotate->setWhatsThis(i18nc("@info:whatsthis",
"For some file formats which apply lossy compression, "
"data will be lost each time the content is rotated. "
"Check this option to allow lossy rotation. "
"If not enabled, these files will be rotated by flag."));
d->allowRotateByMetadata->setToolTip(i18nc("@info:tooltip",
"When rotating a file by setting a flag, also change this flag in the file's metadata"));
d->allowRotateByMetadata->setWhatsThis(i18nc("@info:whatsthis",
"File metadata typically contains a flag describing "
"that a file shall be shown rotated. "
"Enable this option to allow editing this field. "));
rotationGroupLayout->addWidget(rotationIcon, 0, 0, 1, 1);
rotationGroupLayout->addWidget(rotationExplanation, 0, 1, 1, 2);
rotationGroupLayout->addWidget(d->rotateByFlag, 1, 0, 1, 3);
rotationGroupLayout->addWidget(d->rotateByContents, 2, 0, 1, 3);
rotationGroupLayout->addWidget(d->allowLossyRotate, 3, 2, 1, 1);
rotationGroupLayout->addWidget(d->allowRotateByMetadata, 4, 0, 1, 3);
rotationGroupLayout->setColumnStretch(3, 10);
d->rotationGroup->setLayout(rotationGroupLayout);
// --------------------------------------------------------
d->rotationAdvGroup = new QGroupBox;
QGridLayout* const rotationAdvLayout = new QGridLayout;
QLabel* const rotationAdvExpl = new QLabel(i18nc("@label", "Rotate actions"));
QLabel* const rotationAdvIcon = new QLabel;
rotationAdvIcon->setPixmap(QIcon::fromTheme(QLatin1String("configure")).pixmap(32));
d->exifRotateBox = new QCheckBox;
d->exifRotateBox->setText(i18n("Show images/thumbnails &rotated according to orientation tag."));
d->exifSetOrientationBox = new QCheckBox;
d->exifSetOrientationBox->setText(i18n("Set orientation tag to normal after rotate/flip."));
rotationAdvLayout->addWidget(rotationAdvIcon, 0, 0, 1, 1);
rotationAdvLayout->addWidget(rotationAdvExpl, 0, 1, 1, 1);
rotationAdvLayout->addWidget(d->exifRotateBox, 1, 0, 1, 3);
rotationAdvLayout->addWidget(d->exifSetOrientationBox, 2, 0, 1, 3);
rotationAdvLayout->setColumnStretch(2, 10);
d->rotationAdvGroup->setLayout(rotationAdvLayout);
// --------------------------------------------------------
QLabel* const rotationNote = new QLabel(i18n("Note: These settings affect the album view "
"and not the image editor. The image editor always "
"changes the image data during the rotation."));
rotationNote->setWordWrap(true);
rotationNote->setFrameStyle(QFrame::StyledPanel | QFrame::Raised);
// --------------------------------------------------------
rotationLayout->addWidget(d->rotationGroup);
rotationLayout->addWidget(d->rotationAdvGroup);
rotationLayout->addWidget(rotationNote);
rotationLayout->addStretch();
rotationPanel->setLayout(rotationLayout);
d->tab->insertTab(Rotation, rotationPanel, i18nc("@title:tab", "Rotation"));
// --------------------------------------------------------
QWidget* const displayPanel = new QWidget;
QGridLayout* const displayLayout = new QGridLayout;
QLabel* const displayLabel = new QLabel(i18nc("@info:label", "Select Metadata Fields to Be Displayed"));
QLabel* const displayIcon = new QLabel;
displayIcon->setPixmap(QIcon::fromTheme(QLatin1String("view-list-tree")).pixmap(32));
d->displaySubTab = new QTabWidget;
d->tagsCfgPanel = new MetadataPanel(d->displaySubTab);
displayLayout->addWidget(displayIcon, 0, 0);
displayLayout->addWidget(displayLabel, 0, 1);
displayLayout->addWidget(d->displaySubTab, 1, 0, 1, 3);
displayLayout->setColumnStretch(2, 1);
displayPanel->setLayout(displayLayout);
d->tab->insertTab(Display, displayPanel, i18nc("@title:tab", "Views"));
// --------------------------------------------------------
#ifdef HAVE_KFILEMETADATA
QWidget* const balooPanel = new QWidget(d->tab);
QVBoxLayout* const balooLayout = new QVBoxLayout(balooPanel);
QGroupBox* const balooGroup = new QGroupBox(i18n("Baloo Desktop Search"), balooPanel);
QVBoxLayout* const gLayout3 = new QVBoxLayout(balooGroup);
d->saveToBalooBox = new QCheckBox;
d->saveToBalooBox->setText(i18n("Store metadata from digiKam in Baloo"));
d->saveToBalooBox->setWhatsThis(i18n("Turn on this option to push rating, comments and tags "
"from digiKam into the Baloo storage"));
d->readFromBalooBox = new QCheckBox;
d->readFromBalooBox->setText(i18n("Read metadata from Baloo"));
d->readFromBalooBox->setWhatsThis(i18n("Turn on this option if you want to apply changes to "
"rating, comments and tags made in Baloo to digiKam's metadata storage. "
"Please note that image metadata will not be edited automatically."));
gLayout3->addWidget(d->saveToBalooBox);
gLayout3->addWidget(d->readFromBalooBox);
d->tab->insertTab(Baloo, balooPanel, i18nc("@title:tab", "Baloo"));
// --------------------------------------------------------
QFrame* const balooBox = new QFrame(balooPanel);
QGridLayout* const balooGrid = new QGridLayout(balooBox);
balooBox->setFrameStyle(QFrame::StyledPanel | QFrame::Raised);
QLabel* const balooLogoLabel = new QLabel;
balooLogoLabel->setPixmap(QIcon::fromTheme(QLatin1String("baloo")).pixmap(48));
QLabel* const balooExplanation = new QLabel(balooBox);
balooExplanation->setOpenExternalLinks(true);
balooExplanation->setWordWrap(true);
QString balootxt;
balootxt.append(i18n("Baloo "
"provides the basis to handle all kinds of metadata on the KDE desktop in a generic fashion. "
"It allows you to tag, rate and comment your files in KDE applications like Dolphin.
"
"Please set here if you want to synchronize the metadata stored by digiKam desktop-wide with the "
"Baloo Desktop Search.
"));
balooExplanation->setText(balootxt);
balooGrid->addWidget(balooLogoLabel, 0, 0, 1, 1);
balooGrid->addWidget(balooExplanation, 0, 1, 1, 2);
balooGrid->setColumnStretch(1, 10);
balooGrid->setSpacing(0);
// --------------------------------------------------------
balooLayout->addWidget(balooGroup);
balooLayout->addWidget(balooBox);
/*
balooLayout->addWidget(d->resyncButton, 0, Qt::AlignRight);
*/
balooLayout->addStretch();
#endif // HAVE_KFILEMETADATA
//--------------Advanced Metadata Configuration --------------
d->advTab = new AdvancedMetadataTab(this);
d->tab->insertTab(AdvancedConfig, d->advTab, i18nc("@title:tab", "Advanced"));
//------------------------Sidecars-------------------------
QWidget* const sidecarsPanel = new QWidget(d->tab);
QVBoxLayout* const sidecarsLayout = new QVBoxLayout(sidecarsPanel);
// --------------------------------------------------------
QGroupBox* rwSidecarsGroup = new QGroupBox;
QGridLayout* const rwSidecarsLayout = new QGridLayout;
QLabel* const rwSidecarsLabel = new QLabel(i18nc("@label", "Reading and Writing to Sidecars"));
d->readXMPSidecarBox = new QCheckBox;
d->readXMPSidecarBox->setText(i18nc("@option:check", "Read from sidecar files"));
d->readXMPSidecarBox->setWhatsThis(i18nc("@info:whatsthis",
"Turn on this option to read metadata from XMP sidecar files when reading metadata."));
d->readXMPSidecarBox->setEnabled(MetaEngine::supportXmp());
d->writeXMPSidecarBox = new QCheckBox;
d->writeXMPSidecarBox->setText(i18nc("@option:check", "Write to sidecar files"));
d->writeXMPSidecarBox->setWhatsThis(i18nc("@info:whatsthis",
"Turn on this option to save, as specified, metadata to XMP sidecar files."));
d->writeXMPSidecarBox->setEnabled(MetaEngine::supportXmp());
d->writingModeCombo = new QComboBox;
d->writingModeCombo->addItem(i18n("Write to XMP sidecar for read-only item only"), MetaEngine::WRITE_TO_SIDECAR_ONLY_FOR_READ_ONLY_FILES);
d->writingModeCombo->addItem(i18n("Write to XMP sidecar only"), MetaEngine::WRITE_TO_SIDECAR_ONLY);
d->writingModeCombo->addItem(i18n("Write to item and XMP Sidecar"), MetaEngine::WRITE_TO_SIDECAR_AND_FILE);
d->writingModeCombo->setToolTip(i18nc("@info:tooltip", "Specify the exact mode of XMP sidecar writing"));
d->writingModeCombo->setEnabled(false);
d->sidecarFileNameBox = new QCheckBox;
d->sidecarFileNameBox->setText(i18nc("@option:check", "Sidecar file names are compatible with commercial programs"));
d->sidecarFileNameBox->setWhatsThis(i18nc("@info:whatsthis",
"Turn on this option to create the XMP sidecar files with a compatible "
"file name (BASENAME.xmp) used by many commercial programs. "
"For Darktable do not enable this option."));
d->sidecarFileNameBox->setEnabled(false);
connect(d->writeXMPSidecarBox, SIGNAL(toggled(bool)),
d->writingModeCombo, SLOT(setEnabled(bool)));
connect(d->writeXMPSidecarBox, SIGNAL(toggled(bool)),
d->sidecarFileNameBox, SLOT(setEnabled(bool)));
rwSidecarsLayout->addWidget(rwSidecarsLabel, 0, 0, 1, 3);
rwSidecarsLayout->addWidget(d->readXMPSidecarBox, 1, 0, 1, 3);
rwSidecarsLayout->addWidget(d->writeXMPSidecarBox, 2, 0, 1, 3);
rwSidecarsLayout->addWidget(d->writingModeCombo, 3, 1, 1, 2);
rwSidecarsLayout->addWidget(d->sidecarFileNameBox, 4, 0, 1, 3);
rwSidecarsLayout->setColumnStretch(3, 10);
rwSidecarsGroup->setLayout(rwSidecarsLayout);
// --------------------------------------------------------
QGroupBox* const extensionsGroup = new QGroupBox(sidecarsPanel);
QGridLayout* const extensionsGrid = new QGridLayout(extensionsGroup);
QLabel* extensionsGroupLabel = new QLabel(
i18n("Add file types to be recognised as sidecars.
"
"digiKam (optionally) writes metadata to *.xmp sidecar "
"files. Other programs might use different types, which "
"can be specified below. digiKam will neither display these "
"nor read from or write to them. But whenever a matching album "
"item (e.g. \"image.dng\" for \"image.dng.pp3\") is renamed, "
"moved, copied or deleted, the same operation will be done "
"on these sidecar files.
"
"Multiple extensions must be separated by a semicolon "
"or a space.
"));
extensionsGroupLabel->setWordWrap(true);
QLabel* const extensionsLogo = new QLabel(extensionsGroup);
extensionsLogo->setPixmap(QIcon::fromTheme(QLatin1String("text-x-texinfo")).pixmap(48));
- d->extensionsEdit = new QLineEdit(extensionsGroup);
+ d->extensionsEdit = new QLineEdit(extensionsGroup);
d->extensionsEdit->setWhatsThis(i18n("Here you can add extra extensions "
"of sidecars files to be processed alongside "
"regular items. These files will not be visible, "
"but regarded as an extension of the main file. "
"Just write \"xyz abc\" to support files with "
"the *.xyz and *.abc extensions. The internally "
"used sidecars type *.xmp is always included.
"));
d->extensionsEdit->setClearButtonEnabled(true);
d->extensionsEdit->setPlaceholderText(i18n("Enter additional sidecars file extensions."));
QLabel* const extensionsLabel = new QLabel(extensionsGroup);
extensionsLabel->setText(i18n("Additional &sidecar file extensions"));
extensionsLabel->setBuddy(d->extensionsEdit);
extensionsGrid->addWidget(extensionsGroupLabel, 0, 0, 1, -1);
extensionsGrid->addWidget(extensionsLogo, 1, 0, 2, 1);
extensionsGrid->addWidget(extensionsLabel, 1, 1, 1, -1);
extensionsGrid->addWidget(d->extensionsEdit, 2, 1, 1, -1);
extensionsGrid->setColumnStretch(1, 10);
// --------------------------------------------------------
sidecarsLayout->addWidget(rwSidecarsGroup);
sidecarsLayout->addWidget(extensionsGroup);
sidecarsLayout->addStretch();
d->tab->insertTab(Sidecars, sidecarsPanel, i18nc("@title:tab", "Sidecars"));
// --------------------------------------------------------
readSettings();
connect(d->exifRotateBox, SIGNAL(toggled(bool)),
this, SLOT(slotExifAutoRotateToggled(bool)));
connect(d->clearMetadataIfRescanBox, SIGNAL(toggled(bool)),
this, SLOT(slotClearMetadataToggled(bool)));
connect(d->writeRawFilesBox, SIGNAL(toggled(bool)),
this, SLOT(slotWriteRawFilesToggled(bool)));
}
SetupMetadata::~SetupMetadata()
{
delete d;
}
void SetupMetadata::setActiveMainTab(MetadataTab tab)
{
d->tab->setCurrentIndex(tab);
}
void SetupMetadata::setActiveSubTab(int tab)
{
d->displaySubTab->setCurrentIndex(tab);
}
void SetupMetadata::applySettings()
{
MetaEngineSettings* const mSettings = MetaEngineSettings::instance();
if (!mSettings)
{
return;
}
MetaEngineSettingsContainer set;
set.rotationBehavior = MetaEngineSettingsContainer::RotateByInternalFlag;
if (d->allowRotateByMetadata->isChecked())
{
set.rotationBehavior |= MetaEngineSettingsContainer::RotateByMetadataFlag;
}
if (d->rotateByContents->isChecked())
{
set.rotationBehavior |= MetaEngineSettingsContainer::RotateByLosslessRotation;
if (d->allowLossyRotate->isChecked())
{
set.rotationBehavior |= MetaEngineSettingsContainer::RotateByLossyRotation;
}
}
set.exifRotate = d->exifRotateBox->isChecked();
set.exifSetOrientation = d->exifSetOrientationBox->isChecked();
set.saveComments = d->saveCommentsBox->isChecked();
set.saveDateTime = d->saveDateTimeBox->isChecked();
set.savePickLabel = d->savePickLabelBox->isChecked();
set.saveColorLabel = d->saveColorLabelBox->isChecked();
set.saveRating = d->saveRatingBox->isChecked();
set.saveTags = d->saveTagsBox->isChecked();
set.saveTemplate = d->saveTemplateBox->isChecked();
set.saveFaceTags = d->saveFaceTags->isChecked();
set.useLazySync = d->useLazySync->isChecked();
set.writeRawFiles = d->writeRawFilesBox->isChecked();
set.useXMPSidecar4Reading = d->readXMPSidecarBox->isChecked();
set.useCompatibleFileName = d->sidecarFileNameBox->isChecked();
if (d->writeXMPSidecarBox->isChecked())
{
set.metadataWritingMode = (MetaEngine::MetadataWritingMode)
d->writingModeCombo->itemData(d->writingModeCombo->currentIndex()).toInt();
}
else
{
set.metadataWritingMode = MetaEngine::WRITE_TO_FILE_ONLY;
}
set.updateFileTimeStamp = d->updateFileTimeStampBox->isChecked();
set.rescanImageIfModified = d->rescanImageIfModifiedBox->isChecked();
set.clearMetadataIfRescan = d->clearMetadataIfRescanBox->isChecked();
set.sidecarExtensions = cleanUserFilterString(d->extensionsEdit->text());
set.sidecarExtensions.removeAll(QLatin1String("xmp"));
set.sidecarExtensions.removeDuplicates();
mSettings->setSettings(set);
#ifdef HAVE_KFILEMETADATA
ApplicationSettings* const aSettings = ApplicationSettings::instance();
if (!aSettings)
{
return;
}
aSettings->setSyncDigikamToBaloo(d->saveToBalooBox->isChecked());
aSettings->setSyncBalooToDigikam(d->readFromBalooBox->isChecked());
aSettings->saveSettings();
#endif // HAVE_KFILEMETADATA
d->tagsCfgPanel->applySettings();
d->advTab->applySettings();
}
void SetupMetadata::readSettings()
{
MetaEngineSettings* const mSettings = MetaEngineSettings::instance();
if (!mSettings)
{
return;
}
MetaEngineSettingsContainer set = mSettings->settings();
if (set.rotationBehavior & MetaEngineSettingsContainer::RotatingPixels)
{
d->rotateByContents->setChecked(true);
}
else
{
d->rotateByFlag->setChecked(true);
}
d->allowRotateByMetadata->setChecked(set.rotationBehavior & MetaEngineSettingsContainer::RotateByMetadataFlag);
d->allowLossyRotate->setChecked(set.rotationBehavior & MetaEngineSettingsContainer::RotateByLossyRotation);
- d->exifAutoRotateOriginal = set.exifRotate;
+ d->exifAutoRotateOriginal = set.exifRotate;
d->exifRotateBox->setChecked(d->exifAutoRotateOriginal);
d->exifSetOrientationBox->setChecked(set.exifSetOrientation);
d->saveTagsBox->setChecked(set.saveTags);
d->saveCommentsBox->setChecked(set.saveComments);
d->saveRatingBox->setChecked(set.saveRating);
d->savePickLabelBox->setChecked(set.savePickLabel);
d->saveColorLabelBox->setChecked(set.saveColorLabel);
d->saveDateTimeBox->setChecked(set.saveDateTime);
d->saveTemplateBox->setChecked(set.saveTemplate);
d->saveFaceTags->setChecked(set.saveFaceTags);
d->useLazySync->setChecked(set.useLazySync);
d->writeRawFilesBox->setChecked(set.writeRawFiles);
d->readXMPSidecarBox->setChecked(set.useXMPSidecar4Reading);
d->sidecarFileNameBox->setChecked(set.useCompatibleFileName);
d->updateFileTimeStampBox->setChecked(set.updateFileTimeStamp);
d->rescanImageIfModifiedBox->setChecked(set.rescanImageIfModified);
d->clearMetadataIfRescanBox->setChecked(set.clearMetadataIfRescan);
if (set.metadataWritingMode == MetaEngine::WRITE_TO_FILE_ONLY)
{
d->writeXMPSidecarBox->setChecked(false);
}
else
{
d->writeXMPSidecarBox->setChecked(true);
d->writingModeCombo->setCurrentIndex(d->writingModeCombo->findData(set.metadataWritingMode));
}
d->extensionsEdit->setText(set.sidecarExtensions.join(QLatin1Char(' ')));
#ifdef HAVE_KFILEMETADATA
ApplicationSettings* const aSettings = ApplicationSettings::instance();
if (!aSettings)
{
return;
}
d->saveToBalooBox->setChecked(aSettings->getSyncDigikamToBaloo());
d->readFromBalooBox->setChecked(aSettings->getSyncBalooToDigikam());
#endif // HAVE_KFILEMETADATA
}
bool SetupMetadata::exifAutoRotateHasChanged() const
{
return (d->exifAutoRotateOriginal != d->exifRotateBox->isChecked());
}
void SetupMetadata::slotExifAutoRotateToggled(bool b)
{
// Show info if rotation was switched off, and only once.
if (!b && !d->exifAutoRotateShowedInfo && exifAutoRotateHasChanged())
{
d->exifAutoRotateShowedInfo = true;
QMessageBox::information(this, qApp->applicationName(),
i18nc("@info",
"Switching off exif auto rotation will most probably show "
"your images in a wrong orientation, so only change this "
"option if you explicitly require this."));
}
}
void SetupMetadata::slotClearMetadataToggled(bool b)
{
// Show info if delete metadata from the database was switched on, and only once.
if (b && !d->clearMetadataShowedInfo)
{
d->clearMetadataShowedInfo = true;
QMessageBox::information(this, qApp->applicationName(),
i18nc("@info",
"Switching on this option and your metadata has been written to the "
"database only and not to the file or sidecar, you will be able to "
"lose inserted metadata such as tags, keywords, or geographic "
"coordinates."));
}
}
void SetupMetadata::slotWriteRawFilesToggled(bool b)
{
// Show info if write metadata to raw files was switched on
if (b)
{
QApplication::beep();
QPointer msgBox = new QMessageBox(QMessageBox::Warning,
qApp->applicationName(),
i18n("Do you really want to enable metadata writing to RAW files?
"
"DigiKam delegates this task to the Exiv2 library. With different RAW "
"formats, problems are known which can lead to the destruction of RAW "
"files. If you decide to do so, make a backup of your RAW files.
"
"We strongly recommend not to enable this option.
"),
QMessageBox::Yes | QMessageBox::No, this);
msgBox->button(QMessageBox::Yes)->setText(i18n("Yes I understand"));
msgBox->setDefaultButton(QMessageBox::No);
- int result = msgBox->exec();
+ int result1 = msgBox->exec();
delete msgBox;
- if (result == QMessageBox::Yes)
+ if (result1 == QMessageBox::Yes)
{
QPointer msgBox = new QMessageBox(QMessageBox::Warning,
qApp->applicationName(),
i18n("You would rather disable writing metadata to RAW files?"),
QMessageBox::Yes | QMessageBox::No, this);
- int result = msgBox->exec();
+ int result2 = msgBox->exec();
delete msgBox;
- if (result == QMessageBox::No)
+ if (result2 == QMessageBox::No)
{
return;
}
}
d->writeRawFilesBox->setChecked(false);
}
}
} // namespace Digikam