File indexing completed on 2024-05-05 04:22:02

0001 // SPDX-FileCopyrightText: 2003-2020 Jesper K. Pedersen <blackie@kde.org>
0002 // SPDX-FileCopyrightText: 2021 Johannes Zarl-Zierl <johannes@zarl-zierl.at>
0003 //
0004 // SPDX-License-Identifier: GPL-2.0-or-later
0005 
0006 #include "MD5CheckPage.h"
0007 
0008 #include <DB/ImageDB.h>
0009 #include <DB/MD5Map.h>
0010 
0011 #include <KLocalizedString>
0012 #include <QButtonGroup>
0013 #include <QFrame>
0014 #include <QLabel>
0015 #include <QRadioButton>
0016 #include <QVBoxLayout>
0017 
0018 ImportExport::ClashInfo::ClashInfo(const QStringList &categories)
0019     : label(false)
0020     , description(false)
0021     , orientation(false)
0022     , date(false)
0023 {
0024     for (const QString &category : categories)
0025         this->categories[category] = false;
0026 }
0027 
0028 bool ImportExport::MD5CheckPage::pageNeeded(const ImportSettings &settings)
0029 {
0030     if (countOfMD5Matches(settings) != 0 && clashes(settings).anyClashes())
0031         return true;
0032 
0033     return false;
0034 }
0035 
0036 ImportExport::MD5CheckPage::MD5CheckPage(const ImportSettings &settings)
0037 {
0038     QVBoxLayout *vlay = new QVBoxLayout(this);
0039 
0040     const QString txt = i18np("One image from the import file, has the same MD5 sum as an image in the Database, how should that be resolved?",
0041                               "%1 images from the import file, have the same MD5 sum as images in the Database, how should that be resolved?",
0042                               countOfMD5Matches(settings));
0043     QLabel *label = new QLabel(txt);
0044     label->setWordWrap(true);
0045 
0046     vlay->addWidget(label);
0047 
0048     QGridLayout *grid = new QGridLayout;
0049     grid->setHorizontalSpacing(0);
0050     vlay->addLayout(grid);
0051 
0052     int row = -1;
0053 
0054     // Titles
0055     label = new QLabel(i18n("Use data from\nImport File"));
0056     grid->addWidget(label, ++row, 1);
0057 
0058     label = new QLabel(i18n("Use data from\nDatabase"));
0059     grid->addWidget(label, row, 2);
0060 
0061     label = new QLabel(i18n("Merge data"));
0062     grid->addWidget(label, row, 3);
0063 
0064     ClashInfo clashes = this->clashes(settings);
0065     createRow(grid, row, QString::fromLatin1("*Label*"), i18n("Label"), clashes.label, false);
0066     createRow(grid, row, QString::fromLatin1("*Description*"), i18n("Description"), clashes.description, true);
0067     createRow(grid, row, QString::fromLatin1("*Orientation*"), i18n("Orientation"), clashes.orientation, false);
0068     createRow(grid, row, QString::fromLatin1("*Date*"), i18n("Date and Time"), clashes.date, false);
0069     for (QMap<QString, bool>::const_iterator it = clashes.categories.constBegin(); it != clashes.categories.constEnd(); ++it) {
0070         createRow(grid, row, it.key(), it.key(), *it, true);
0071     }
0072 
0073     vlay->addStretch(1);
0074 }
0075 
0076 /**
0077  * Return the number of images in the import set which has the same MD5 sum as those from the DB.
0078  */
0079 int ImportExport::MD5CheckPage::countOfMD5Matches(const ImportSettings &settings)
0080 {
0081     int count = 0;
0082     DB::ImageInfoList list = settings.selectedImages();
0083     for (DB::ImageInfoPtr info : list) {
0084         if (DB::ImageDB::instance()->md5Map()->contains(info->MD5Sum()))
0085             ++count;
0086     }
0087     return count;
0088 }
0089 
0090 ImportExport::ClashInfo ImportExport::MD5CheckPage::clashes(const ImportSettings &settings)
0091 {
0092     QStringList myCategories;
0093     const auto categoryMatchSettings = settings.categoryMatchSetting();
0094     for (const CategoryMatchSetting &matcher : categoryMatchSettings) {
0095         myCategories.append(matcher.DBCategoryName());
0096     }
0097 
0098     ClashInfo res(myCategories);
0099     const DB::ImageInfoList list = settings.selectedImages();
0100     for (const DB::ImageInfoPtr &info : list) {
0101         if (!DB::ImageDB::instance()->md5Map()->contains(info->MD5Sum()))
0102             continue;
0103 
0104         const DB::FileName name = DB::ImageDB::instance()->md5Map()->lookup(info->MD5Sum());
0105         const DB::ImageInfoPtr other = DB::ImageDB::instance()->info(name);
0106         if (other->isNull())
0107             continue;
0108         if (info->label() != other->label())
0109             res.label = true;
0110         if (info->description() != other->description())
0111             res.description = true;
0112 
0113         if (info->angle() != other->angle())
0114             res.orientation = true;
0115 
0116         if (info->date() != other->date())
0117             res.date = true;
0118 
0119         const auto categoryMatchSettings = settings.categoryMatchSetting();
0120         for (const CategoryMatchSetting &matcher : categoryMatchSettings) {
0121             const QString XMLFileCategory = matcher.XMLCategoryName();
0122             const QString DBCategory = matcher.DBCategoryName();
0123             if (mapCategoriesToDB(matcher, info->itemsOfCategory(XMLFileCategory)) != other->itemsOfCategory(DBCategory))
0124                 res.categories[DBCategory] = true;
0125         }
0126     }
0127     return res;
0128 }
0129 
0130 bool ImportExport::ClashInfo::anyClashes()
0131 {
0132     if (label || description || orientation || date)
0133         return true;
0134 
0135     for (QMap<QString, bool>::ConstIterator categoryIt = categories.constBegin(); categoryIt != categories.constEnd(); ++categoryIt) {
0136         if (categoryIt.value())
0137             return true;
0138     }
0139 
0140     return false;
0141 }
0142 
0143 void ImportExport::MD5CheckPage::createRow(QGridLayout *layout, int &row, const QString &name, const QString &title, bool anyClashes, bool allowMerge)
0144 {
0145     if (row % 3 == 0) {
0146         QFrame *line = new QFrame;
0147         line->setFrameShape(QFrame::HLine);
0148         layout->addWidget(line, ++row, 0, 1, 4);
0149     }
0150 
0151     QLabel *label = new QLabel(title);
0152     label->setEnabled(anyClashes);
0153     layout->addWidget(label, ++row, 0);
0154 
0155     QButtonGroup *group = new QButtonGroup(this);
0156     m_groups[name] = group;
0157 
0158     for (int i = 1; i < 4; ++i) {
0159         if (i == 3 && !allowMerge)
0160             continue;
0161 
0162         QRadioButton *rb = new QRadioButton;
0163         layout->addWidget(rb, row, i);
0164         group->addButton(rb, i);
0165         rb->setEnabled(anyClashes);
0166         if (i == 1)
0167             rb->setChecked(true);
0168     }
0169 }
0170 
0171 Utilities::StringSet ImportExport::MD5CheckPage::mapCategoriesToDB(const CategoryMatchSetting &matcher, const Utilities::StringSet &items)
0172 {
0173     Utilities::StringSet res;
0174 
0175     for (const QString &item : items) {
0176         if (matcher.XMLtoDB().contains(item))
0177             res.insert(matcher.XMLtoDB()[item]);
0178     }
0179     return res;
0180 }
0181 
0182 QMap<QString, ImportExport::ImportSettings::ImportAction> ImportExport::MD5CheckPage::settings()
0183 {
0184     QMap<QString, ImportSettings::ImportAction> res;
0185     for (QMap<QString, QButtonGroup *>::iterator it = m_groups.begin(); it != m_groups.end(); ++it) {
0186         res.insert(it.key(), static_cast<ImportSettings::ImportAction>(it.value()->checkedId()));
0187     }
0188     return res;
0189 }
0190 
0191 // vi:expandtab:tabstop=4 shiftwidth=4: