File indexing completed on 2025-04-27 03:57:27

0001 /* ============================================================
0002  *
0003  * This file is a part of digiKam project
0004  * https://www.digikam.org
0005  *
0006  * Date        : 2003-03-09
0007  * Description : Captions, Tags, and Rating properties editor - private container
0008  *
0009  * SPDX-FileCopyrightText: 2003-2005 by Renchi Raju <renchi dot raju at gmail dot com>
0010  * SPDX-FileCopyrightText: 2003-2024 by Gilles Caulier <caulier dot gilles at gmail dot com>
0011  * SPDX-FileCopyrightText: 2006-2011 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
0012  * SPDX-FileCopyrightText: 2009-2011 by Andi Clemens <andi dot clemens at gmail dot com>
0013  * SPDX-FileCopyrightText: 2009-2011 by Johannes Wienke <languitar at semipol dot de>
0014  * SPDX-FileCopyrightText: 2015      by Veaceslav Munteanu <veaceslav dot munteanu90 at gmail dot com>
0015  *
0016  * SPDX-License-Identifier: GPL-2.0-or-later
0017  *
0018  * ============================================================ */
0019 
0020 #include "itemdescedittab_p.h"
0021 
0022 namespace Digikam
0023 {
0024 
0025 ItemDescEditTab::Private::Private(ItemDescEditTab* const tab)
0026     : modified                    (false),
0027       ignoreItemAttributesWatch   (false),
0028       revertBtn                   (nullptr),
0029       moreMenu                    (nullptr),
0030       applyBtn                    (nullptr),
0031       moreButton                  (nullptr),
0032       applyToAllVersionsButton    (nullptr),
0033       lastSelectedWidget          (nullptr),
0034       titleEdit                   (nullptr),
0035       captionsEdit                (nullptr),
0036       dateTimeEdit                (nullptr),
0037       tabWidget                   (nullptr),
0038       templateSelector            (nullptr),
0039       templateViewer              (nullptr),
0040       ratingWidget                (nullptr),
0041       colorLabelSelector          (nullptr),
0042       pickLabelSelector           (nullptr),
0043       hub                         (nullptr),
0044       metadataChangeTimer         (nullptr),
0045       togglingTagsSearchSettings  (false),
0046       ignoreTagChanges            (false),
0047       recentTagsBtn               (nullptr),
0048       assignedTagsBtn             (nullptr),
0049       openTagMngr                 (nullptr),
0050       tagsSearchBar               (nullptr),
0051       newTagEdit                  (nullptr),
0052       tagCheckView                (nullptr),
0053       tagModel                    (nullptr),
0054       q                           (tab)
0055 {
0056     spacing = qMin(QApplication::style()->pixelMetric(QStyle::PM_LayoutHorizontalSpacing),
0057                    QApplication::style()->pixelMetric(QStyle::PM_LayoutVerticalSpacing));
0058 }
0059 
0060 void ItemDescEditTab::Private::setupConnections()
0061 {
0062     QObject::connect(titleEdit, SIGNAL(signalModified(QString,QString)),
0063                      q, SLOT(slotTitleChanged()));
0064 
0065     QObject::connect(titleEdit, SIGNAL(signalValueAdded(QString,QString)),
0066                      q, SLOT(slotTitleChanged()));
0067 
0068     QObject::connect(titleEdit, SIGNAL(signalValueDeleted(QString)),
0069                      q, SLOT(slotTitleChanged()));
0070 
0071     QObject::connect(captionsEdit, SIGNAL(signalModified()),
0072                      q, SLOT(slotCommentChanged()));
0073 
0074     QObject::connect(dateTimeEdit, SIGNAL(dateTimeChanged(QDateTime)),
0075                      q, SLOT(slotDateTimeChanged(QDateTime)));
0076 
0077     QObject::connect(pickLabelSelector, SIGNAL(signalPickLabelChanged(int)),
0078                      q, SLOT(slotPickLabelChanged(int)));
0079 
0080     QObject::connect(colorLabelSelector, SIGNAL(signalColorLabelChanged(int)),
0081                      q, SLOT(slotColorLabelChanged(int)));
0082 
0083     QObject::connect(ratingWidget, SIGNAL(signalRatingChanged(int)),
0084                      q, SLOT(slotRatingChanged(int)));
0085 
0086     QObject::connect(templateSelector, SIGNAL(signalTemplateSelected()),
0087                      q, SLOT(slotTemplateSelected()));
0088 
0089     QObject::connect(applyBtn, SIGNAL(clicked()),
0090                      q, SLOT(slotApplyAllChanges()));
0091 
0092     QObject::connect(applyToAllVersionsButton, SIGNAL(clicked()),
0093                      q, SLOT(slotApplyChangesToAllVersions()));
0094 
0095     QObject::connect(revertBtn, SIGNAL(clicked()),
0096                      q, SLOT(slotRevertAllChanges()));
0097 
0098     QObject::connect(moreMenu, SIGNAL(aboutToShow()),
0099                      q, SLOT(slotMoreMenu()));
0100 
0101     QObject::connect(metadataChangeTimer, SIGNAL(timeout()),
0102                      q, SLOT(slotReloadForMetadataChange()));
0103 
0104     QObject::connect(q, SIGNAL(signalAskToApplyChanges(QList<ItemInfo>,DisjointMetadata*)),
0105                      q, SLOT(slotAskToApplyChanges(QList<ItemInfo>,DisjointMetadata*)),
0106                      Qt::QueuedConnection);
0107 
0108     ItemAttributesWatch* const watch = ItemAttributesWatch::instance();
0109 
0110     QObject::connect(watch, SIGNAL(signalImagesChanged(int)),
0111                      q, SLOT(slotImagesChanged(int)));
0112 
0113     QObject::connect(watch, SIGNAL(signalImageRatingChanged(qlonglong)),
0114                      q, SLOT(slotImageRatingChanged(qlonglong)));
0115 
0116     QObject::connect(watch, SIGNAL(signalImageDateChanged(qlonglong)),
0117                      q, SLOT(slotImageDateChanged(qlonglong)));
0118 
0119     QObject::connect(watch, SIGNAL(signalImageCaptionChanged(qlonglong)),
0120                      q, SLOT(slotImageCaptionChanged(qlonglong)));
0121 }
0122 
0123 void ItemDescEditTab::Private::setupEventFilters()
0124 {
0125     titleEdit->textEdit()->installEventFilter(q);
0126     captionsEdit->altLangStrEdit()->textEdit()->installEventFilter(q);
0127 
0128     dateTimeEdit->installEventFilter(q);
0129     pickLabelSelector->installEventFilter(q);
0130     colorLabelSelector->installEventFilter(q);
0131     ratingWidget->installEventFilter(q);
0132 
0133     // TODO update, what does this filter?
0134 
0135     tagCheckView->installEventFilter(q);
0136     newTagEdit->installEventFilter(q);
0137 }
0138 
0139 void ItemDescEditTab::Private::reset()
0140 {
0141     modified = false;
0142     hub->resetChanged();
0143     applyBtn->setEnabled(false);
0144     revertBtn->setEnabled(false);
0145     applyToAllVersionsButton->setEnabled(false);
0146 }
0147 
0148 void ItemDescEditTab::Private::setInfos(const ItemInfoList& infos)
0149 {
0150     if (infos.isEmpty())
0151     {
0152         hub->reset();
0153         captionsEdit->blockSignals(true);
0154         captionsEdit->reset();
0155         q->resetCaptionEditPlaceholderText();
0156         captionsEdit->blockSignals(false);
0157         titleEdit->blockSignals(true);
0158         titleEdit->reset();
0159         q->resetTitleEditPlaceholderText();
0160         titleEdit->blockSignals(false);
0161         currInfos.clear();
0162         resetMetadataChangeInfo();
0163         q->setEnabled(false);
0164 
0165         return;
0166     }
0167 
0168     q->setEnabled(true);
0169     currInfos = infos;
0170     modified  = false;
0171     resetMetadataChangeInfo();
0172     hub->reset();
0173     applyBtn->setEnabled(false);
0174     revertBtn->setEnabled(false);
0175 
0176     if (currInfos.count() > 1000)
0177     {
0178         QApplication::setOverrideCursor(Qt::WaitCursor);
0179     }
0180 
0181     // First, we read all tags of the items into the cache with one SQL query.
0182     // This is faster than each item individually.
0183 
0184     currInfos.loadTagIds();
0185 
0186     Q_FOREACH (const ItemInfo& info, currInfos)
0187     {
0188         hub->load(info);
0189     }
0190 
0191     q->updateComments();
0192     q->updatePickLabel();
0193     q->updateColorLabel();
0194     q->updateRating();
0195     q->updateDate();
0196     q->updateTemplate();
0197     q->updateTagsView();
0198     q->updateRecentTags();
0199     setFocusToLastSelectedWidget();
0200 
0201     if (currInfos.count() > 1000)
0202     {
0203         QApplication::restoreOverrideCursor();
0204     }
0205 }
0206 
0207 void ItemDescEditTab::Private::resetMetadataChangeInfo()
0208 {
0209     metadataChangeTimer->stop();
0210     metadataChangeIds.clear();
0211 }
0212 
0213 void ItemDescEditTab::Private::setFocusToLastSelectedWidget()
0214 {
0215     if (lastSelectedWidget)
0216     {
0217         lastSelectedWidget->setFocus();
0218     }
0219 
0220     lastSelectedWidget = nullptr;
0221 }
0222 
0223 bool ItemDescEditTab::Private::singleSelection() const
0224 {
0225     return (currInfos.count() == 1);
0226 }
0227 
0228 void ItemDescEditTab::Private::setMetadataWidgetStatus(int status, QWidget* const widget)
0229 {
0230     if (status == DisjointMetadataDataFields::MetadataDisjoint)
0231     {
0232         // For text widgets: Set text color to color of disabled text.
0233 
0234         QPalette palette = widget->palette();
0235         palette.setColor(QPalette::Text, palette.color(QPalette::Disabled, QPalette::Text));
0236         widget->setPalette(palette);
0237 
0238         QString msg = i18nc("@info", "Selected items have different text here.");
0239 
0240         if      (qobject_cast<AltLangStrEdit*>(widget))
0241         {
0242             titleEdit->setPlaceholderText(msg);
0243         }
0244         else if (qobject_cast<CaptionEdit*>(widget))
0245         {
0246             captionsEdit->setPlaceholderText(msg);
0247         }
0248     }
0249     else
0250     {
0251         widget->setPalette(QPalette());
0252 
0253         if      (qobject_cast<AltLangStrEdit*>(widget))
0254         {
0255             q->resetTitleEditPlaceholderText();
0256         }
0257         else if (qobject_cast<CaptionEdit*>(widget))
0258         {
0259             q->resetCaptionEditPlaceholderText();
0260         }
0261     }
0262 }
0263 
0264 void ItemDescEditTab::Private::metadataChange(qlonglong imageId)
0265 {
0266     if (ignoreItemAttributesWatch || modified)
0267     {
0268         // Don't lose modifications
0269 
0270         return;
0271     }
0272 
0273     metadataChangeIds << imageId;
0274     metadataChangeTimer->start();
0275 }
0276 
0277 void ItemDescEditTab::Private::initProgressIndicator()
0278 {
0279     if (!ProgressManager::instance()->findItembyId(QLatin1String("ItemDescEditTabProgress")))
0280     {
0281         FileActionProgress* const item = new FileActionProgress(QLatin1String("ItemDescEditTabProgress"));
0282 
0283         QObject::connect(q, SIGNAL(signalProgressMessageChanged(QString)),
0284                          item, SLOT(slotProgressStatus(QString)));
0285 
0286         QObject::connect(q, SIGNAL(signalProgressValueChanged(float)),
0287                          item, SLOT(slotProgressValue(float)));
0288 
0289         QObject::connect(q, SIGNAL(signalProgressFinished()),
0290                          item, SLOT(slotCompleted()));
0291     }
0292 }
0293 
0294 } // namespace Digikam