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