File indexing completed on 2025-01-19 03:53:23
0001 /* ============================================================ 0002 * 0003 * This file is a part of digiKam project 0004 * https://www.digikam.org 0005 * 0006 * Date : 2010-10-09 0007 * Description : A widget to select Physical or virtual albums with combo-box 0008 * 0009 * SPDX-FileCopyrightText: 2010-2012 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de> 0010 * SPDX-FileCopyrightText: 2012-2024 by Gilles Caulier <caulier dot gilles at gmail dot com> 0011 * 0012 * SPDX-License-Identifier: GPL-2.0-or-later 0013 * 0014 * ============================================================ */ 0015 0016 #include "albumselectors.h" 0017 0018 // Qt includes 0019 0020 #include <QApplication> 0021 #include <QLayout> 0022 #include <QLabel> 0023 #include <QCheckBox> 0024 #include <QRadioButton> 0025 #include <QButtonGroup> 0026 #include <QIcon> 0027 #include <QMessageBox> 0028 0029 // KDE includes 0030 0031 #include <kconfiggroup.h> 0032 #include <ksharedconfig.h> 0033 #include <klocalizedstring.h> 0034 0035 // Local includes 0036 0037 #include "digikam_debug.h" 0038 #include "albummodel.h" 0039 #include "albummanager.h" 0040 #include "albumselectcombobox.h" 0041 #include "albumtreeview.h" 0042 #include "tagtreeview.h" 0043 #include "searchutilities.h" 0044 0045 namespace Digikam 0046 { 0047 0048 class Q_DECL_HIDDEN ModelClearButton : public AnimatedClearButton // clazy:exclude=ctor-missing-parent-argument 0049 { 0050 Q_OBJECT 0051 0052 public: 0053 0054 explicit ModelClearButton(AbstractCheckableAlbumModel* const model) 0055 { 0056 setPixmap(QIcon::fromTheme(qApp->isLeftToRight() ? QLatin1String("edit-clear-locationbar-rtl") 0057 : QLatin1String("edit-clear-locationbar-ltr")).pixmap(style()->pixelMetric(QStyle::PM_SmallIconSize))); 0058 stayVisibleWhenAnimatedOut(true); 0059 0060 connect(this, SIGNAL(clicked()), 0061 model, SLOT(resetAllCheckedAlbums())); 0062 } 0063 }; 0064 0065 // ------------------------------------------------------------------------------------------ 0066 0067 class Q_DECL_HIDDEN AlbumSelectors::Private 0068 { 0069 public: 0070 0071 explicit Private() 0072 : albumSelectCB (nullptr), 0073 tagSelectCB (nullptr), 0074 albumClearButton (nullptr), 0075 tagClearButton (nullptr), 0076 recursiveSelectionAlbum(nullptr), 0077 wholeAlbums (nullptr), 0078 recursiveSelectionTags (nullptr), 0079 wholeTags (nullptr), 0080 tabWidget (nullptr), 0081 albumWidget (nullptr), 0082 tagWidget (nullptr), 0083 selectionMode (All), 0084 allowRecursive (false) 0085 { 0086 } 0087 0088 static const QString configUseWholeAlbumsEntry; 0089 static const QString configUseWholeTagsEntry; 0090 static const QString configAlbumTypeEntry; 0091 0092 QString configName; 0093 0094 AlbumTreeViewSelectComboBox* albumSelectCB; 0095 TagTreeViewSelectComboBox* tagSelectCB; 0096 ModelClearButton* albumClearButton; 0097 ModelClearButton* tagClearButton; 0098 0099 QCheckBox* recursiveSelectionAlbum; 0100 QCheckBox* wholeAlbums; 0101 QCheckBox* recursiveSelectionTags; 0102 QCheckBox* wholeTags; 0103 0104 QTabWidget* tabWidget; 0105 QWidget* albumWidget; 0106 QWidget* tagWidget; 0107 0108 AlbumType selectionMode; 0109 0110 bool allowRecursive; 0111 }; 0112 0113 const QString AlbumSelectors::Private::configUseWholeAlbumsEntry(QLatin1String("UseWholeAlbumsEntry")); 0114 const QString AlbumSelectors::Private::configUseWholeTagsEntry(QLatin1String("UseWholeTagsEntry")); 0115 const QString AlbumSelectors::Private::configAlbumTypeEntry(QLatin1String("AlbumTypeEntry")); 0116 0117 AlbumSelectors::AlbumSelectors(const QString& label, 0118 const QString& configName, 0119 QWidget* const parent, 0120 AlbumType albumType, 0121 bool allowRecursive) 0122 : QWidget(parent), 0123 d (new Private) 0124 { 0125 d->allowRecursive = allowRecursive; 0126 d->configName = configName; 0127 setObjectName(d->configName); 0128 0129 d->selectionMode = albumType; 0130 0131 QVBoxLayout* const mainLayout = new QVBoxLayout(this); 0132 0133 if (!label.isEmpty()) 0134 { 0135 mainLayout->addWidget(new QLabel(label)); 0136 } 0137 0138 switch (d->selectionMode) 0139 { 0140 case All: 0141 { 0142 d->tabWidget = new QTabWidget(this); 0143 0144 initAlbumWidget(); 0145 d->tabWidget->insertTab(PhysAlbum, d->albumWidget, i18nc("@title", "Albums (All)")); 0146 0147 initTagWidget(); 0148 d->tabWidget->insertTab(TagsAlbum, d->tagWidget, i18nc("@title", "Tags (0)")); 0149 0150 mainLayout->addWidget(d->tabWidget); 0151 break; 0152 } 0153 0154 case PhysAlbum: 0155 { 0156 initAlbumWidget(); 0157 mainLayout->addWidget(d->albumWidget); 0158 break; 0159 } 0160 0161 case TagsAlbum: 0162 { 0163 initTagWidget(); 0164 mainLayout->addWidget(d->tagWidget); 0165 break; 0166 } 0167 } 0168 0169 mainLayout->setContentsMargins(QMargins()); 0170 } 0171 0172 AlbumSelectors::~AlbumSelectors() 0173 { 0174 delete d; 0175 } 0176 0177 void AlbumSelectors::initAlbumWidget() 0178 { 0179 d->albumWidget = new QWidget(this); 0180 d->wholeAlbums = new QCheckBox(i18nc("@option", "All albums"), d->albumWidget); 0181 d->recursiveSelectionAlbum = new QCheckBox(i18nc("@option", "Recursive"), d->albumWidget); 0182 d->recursiveSelectionAlbum->setToolTip(i18nc("@info:tooltip", "Recursive selection.")); 0183 d->recursiveSelectionAlbum->setChecked(true); 0184 0185 if (!d->allowRecursive) 0186 { 0187 d->recursiveSelectionAlbum->setVisible(false); 0188 d->recursiveSelectionAlbum->setChecked(false); 0189 } 0190 0191 d->albumSelectCB = new AlbumTreeViewSelectComboBox(d->albumWidget); 0192 d->albumSelectCB->setToolTip(i18nc("@info:tooltip", "Select all albums that should be processed.")); 0193 d->albumSelectCB->setDefaultModel(); 0194 d->albumSelectCB->setRecursive(d->allowRecursive ? d->recursiveSelectionAlbum->isChecked() : false); 0195 d->albumSelectCB->setNoSelectionText(i18nc("@info", "No Album Selected")); 0196 //d->albumSelectCB->setAddExcludeTristate(true); 0197 d->albumSelectCB->addCheckUncheckContextMenuActions(); 0198 0199 d->albumClearButton = new ModelClearButton(d->albumSelectCB->view()->albumModel()); 0200 d->albumClearButton->setToolTip(i18nc("@info:tooltip", "Reset selected albums")); 0201 0202 QHBoxLayout* l = new QHBoxLayout; 0203 l->addWidget(d->wholeAlbums); 0204 l->addWidget(d->recursiveSelectionAlbum); 0205 l->addItem(new QSpacerItem(0, 0, QSizePolicy::Policy::Expanding)); 0206 0207 QGridLayout* const pAlbumsGrid = new QGridLayout(d->albumWidget); 0208 pAlbumsGrid->addLayout(l, 0, 0, 1, 2); 0209 pAlbumsGrid->addWidget(d->albumSelectCB, 1, 0, 1, 1); 0210 pAlbumsGrid->addWidget(d->albumClearButton, 1, 1, 1, 1); 0211 pAlbumsGrid->setSpacing(0); 0212 0213 connect(d->wholeAlbums, SIGNAL(toggled(bool)), 0214 this, SLOT(slotWholeAlbums(bool))); 0215 0216 connect(d->wholeAlbums, SIGNAL(toggled(bool)), 0217 this, SIGNAL(signalSelectionChanged())); 0218 0219 connect(d->recursiveSelectionAlbum, &QCheckBox::clicked, 0220 [this] (bool checked) 0221 { 0222 d->albumSelectCB->setRecursive(checked); 0223 } 0224 ); 0225 0226 connect(d->albumSelectCB->view()->albumModel(), SIGNAL(checkStateChanged(Album*,Qt::CheckState)), 0227 this, SLOT(slotUpdateClearButtons())); 0228 0229 d->albumSelectCB->view()->setObjectName(d->configName); 0230 d->albumSelectCB->view()->setEntryPrefix(QLatin1String("AlbumComboBox-")); 0231 d->albumSelectCB->view()->setRestoreCheckState(true); 0232 } 0233 0234 void AlbumSelectors::initTagWidget() 0235 { 0236 d->tagWidget = new QWidget(this); 0237 d->wholeTags = new QCheckBox(i18nc("@option", "All tags"), d->tagWidget); 0238 d->recursiveSelectionTags = new QCheckBox(i18nc("@option", "Recursive"), d->albumWidget); 0239 d->recursiveSelectionTags->setToolTip(i18nc("@info:tooltip", "Recursive selection.")); 0240 d->recursiveSelectionTags->setChecked(true); 0241 0242 if (!d->allowRecursive) 0243 { 0244 d->recursiveSelectionTags->setVisible(false); 0245 d->recursiveSelectionTags->setChecked(false); 0246 } 0247 0248 d->tagSelectCB = new TagTreeViewSelectComboBox(d->tagWidget); 0249 d->tagSelectCB->setToolTip(i18nc("@info:tooltip", "Select all tags that should be processed.")); 0250 d->tagSelectCB->setDefaultModel(); 0251 d->tagSelectCB->setRecursive(d->allowRecursive ? d->recursiveSelectionTags->isChecked() : false); 0252 d->tagSelectCB->setNoSelectionText(i18nc("@info", "No Tag Selected")); 0253 d->tagSelectCB->addCheckUncheckContextMenuActions(); 0254 0255 d->tagClearButton = new ModelClearButton(d->tagSelectCB->view()->albumModel()); 0256 d->tagClearButton->setToolTip(i18nc("@info:tooltip", "Reset selected tags")); 0257 0258 QHBoxLayout* l = new QHBoxLayout; 0259 l->addWidget(d->wholeTags); 0260 l->addWidget(d->recursiveSelectionTags); 0261 l->addItem(new QSpacerItem(0, 0, QSizePolicy::Policy::Expanding)); 0262 0263 QGridLayout* const tAlbumsGrid = new QGridLayout(d->tagWidget); 0264 tAlbumsGrid->addLayout(l, 0, 0, 1, 2); 0265 tAlbumsGrid->addWidget(d->tagSelectCB, 1, 0, 1, 1); 0266 tAlbumsGrid->addWidget(d->tagClearButton, 1, 1, 1, 1); 0267 tAlbumsGrid->setSpacing(0); 0268 0269 connect(d->wholeTags, SIGNAL(toggled(bool)), 0270 this, SIGNAL(signalSelectionChanged())); 0271 0272 connect(d->wholeTags, SIGNAL(toggled(bool)), 0273 this, SLOT(slotWholeTags(bool))); 0274 0275 connect(d->tagSelectCB->view()->albumModel(), SIGNAL(checkStateChanged(Album*,Qt::CheckState)), 0276 this, SLOT(slotUpdateClearButtons())); 0277 0278 connect(d->recursiveSelectionTags, &QCheckBox::clicked, 0279 [this] (bool checked) 0280 { 0281 d->tagSelectCB->setRecursive(checked); 0282 } 0283 ); 0284 0285 d->tagSelectCB->view()->setObjectName(d->configName); 0286 d->tagSelectCB->view()->setEntryPrefix(QLatin1String("TagComboBox-")); 0287 d->tagSelectCB->view()->setRestoreCheckState(true); 0288 0289 } 0290 0291 void AlbumSelectors::slotWholeAlbums(bool b) 0292 { 0293 if ((d->selectionMode == PhysAlbum) || (d->selectionMode == All)) 0294 { 0295 d->albumSelectCB->setEnabled(!b); 0296 d->albumClearButton->setEnabled(!b); 0297 d->albumSelectCB->setAllSelectedText(b); 0298 } 0299 0300 updateTabText(); 0301 } 0302 0303 void AlbumSelectors::slotWholeTags(bool b) 0304 { 0305 if ((d->selectionMode == TagsAlbum) || (d->selectionMode == All)) 0306 { 0307 d->tagSelectCB->setEnabled(!b); 0308 d->tagClearButton->setEnabled(!b); 0309 d->tagSelectCB->setAllSelectedText(b); 0310 } 0311 0312 updateTabText(); 0313 } 0314 0315 void AlbumSelectors::slotUpdateClearButtons() 0316 { 0317 bool selectionChanged = false; 0318 0319 if ((d->selectionMode == PhysAlbum) || (d->selectionMode == All)) 0320 { 0321 d->albumClearButton->animateVisible(!d->albumSelectCB->model()->checkedAlbums().isEmpty()); 0322 selectionChanged = true; 0323 } 0324 0325 if ((d->selectionMode == TagsAlbum) || (d->selectionMode == All)) 0326 { 0327 d->tagClearButton->animateVisible(!d->tagSelectCB->model()->checkedAlbums().isEmpty()); 0328 selectionChanged = true; 0329 } 0330 0331 if (selectionChanged) 0332 { 0333 Q_EMIT signalSelectionChanged(); 0334 } 0335 0336 updateTabText(); 0337 } 0338 0339 bool AlbumSelectors::wholeAlbumsChecked() const 0340 { 0341 return (d->wholeAlbums && d->wholeAlbums->isChecked()); 0342 } 0343 0344 AlbumList AlbumSelectors::selectedAlbums() const 0345 { 0346 AlbumList albums; 0347 0348 if (wholeAlbumsChecked()) 0349 { 0350 albums << AlbumManager::instance()->allPAlbums(); 0351 } 0352 else if (d->albumSelectCB) 0353 { 0354 albums << d->albumSelectCB->model()->checkedAlbums(); 0355 } 0356 0357 return albums; 0358 } 0359 0360 QList<int> AlbumSelectors::selectedAlbumIds() const 0361 { 0362 QList<int> albumIds; 0363 AlbumList albums = selectedAlbums(); 0364 0365 Q_FOREACH (Album* const album, albums) 0366 { 0367 albumIds << album->id(); 0368 } 0369 0370 return albumIds; 0371 } 0372 0373 bool AlbumSelectors::wholeTagsChecked() const 0374 { 0375 return d->wholeTags && d->wholeTags->isChecked(); 0376 } 0377 0378 AlbumList AlbumSelectors::selectedTags() const 0379 { 0380 AlbumList albums; 0381 0382 if (wholeTagsChecked()) 0383 { 0384 albums << AlbumManager::instance()->allTAlbums(); 0385 } 0386 else if (d->tagSelectCB) 0387 { 0388 albums << d->tagSelectCB->model()->checkedAlbums(); 0389 } 0390 0391 return albums; 0392 } 0393 0394 QList<int> AlbumSelectors::selectedTagIds() const 0395 { 0396 QList<int> tagIds; 0397 AlbumList tags = selectedTags(); 0398 0399 Q_FOREACH (Album* const tag, tags) 0400 { 0401 tagIds << tag->id(); 0402 } 0403 0404 return tagIds; 0405 } 0406 0407 AlbumList AlbumSelectors::selectedAlbumsAndTags() const 0408 { 0409 AlbumList albums; 0410 albums << selectedAlbums(); 0411 albums << selectedTags(); 0412 0413 return albums; 0414 } 0415 0416 void AlbumSelectors::setAlbumSelected(Album* const album, SelectionType type) 0417 { 0418 if (d->albumWidget && album) 0419 { 0420 if (type == SingleSelection) 0421 { 0422 d->albumSelectCB->model()->resetCheckedAlbums(); 0423 } 0424 0425 d->albumSelectCB->model()->setChecked(album, true); 0426 d->wholeAlbums->setChecked(false); 0427 } 0428 } 0429 0430 void AlbumSelectors::setTagSelected(Album* const album, SelectionType type) 0431 { 0432 if (d->tagWidget && album) 0433 { 0434 if (type == SingleSelection) 0435 { 0436 d->tagSelectCB->model()->resetCheckedAlbums(); 0437 } 0438 0439 d->tagSelectCB->model()->setChecked(album, true); 0440 d->wholeTags->setChecked(false); 0441 } 0442 } 0443 0444 void AlbumSelectors::setTypeSelection(int albumType) 0445 { 0446 if (d->selectionMode == All) 0447 { 0448 d->tabWidget->setCurrentIndex(albumType); 0449 } 0450 } 0451 0452 int AlbumSelectors::typeSelection() const 0453 { 0454 if (d->selectionMode == All) 0455 { 0456 return d->tabWidget->currentIndex(); 0457 } 0458 else 0459 { 0460 return d->selectionMode; 0461 } 0462 } 0463 0464 void AlbumSelectors::resetPAlbumSelection() 0465 { 0466 d->albumSelectCB->model()->resetAllCheckedAlbums(); 0467 d->wholeAlbums->setChecked(false); 0468 slotWholeAlbums(wholeAlbumsChecked()); 0469 } 0470 0471 void AlbumSelectors::resetTAlbumSelection() 0472 { 0473 d->tagSelectCB->model()->resetAllCheckedAlbums(); 0474 d->wholeTags->setChecked(false); 0475 slotWholeTags(wholeTagsChecked()); 0476 } 0477 0478 void AlbumSelectors::resetSelection() 0479 { 0480 if (d->albumWidget) 0481 { 0482 resetPAlbumSelection(); 0483 } 0484 0485 if (d->tagWidget) 0486 { 0487 resetTAlbumSelection(); 0488 } 0489 } 0490 0491 void AlbumSelectors::loadState() 0492 { 0493 KSharedConfig::Ptr config = KSharedConfig::openConfig(); 0494 KConfigGroup group = config->group(d->configName); 0495 0496 if (d->albumWidget) 0497 { 0498 d->wholeAlbums->setChecked(group.readEntry(d->configUseWholeAlbumsEntry, true)); 0499 d->albumSelectCB->view()->loadState(); 0500 d->albumClearButton->animateVisible(!d->albumSelectCB->model()->checkedAlbums().isEmpty()); 0501 0502 slotWholeAlbums(wholeAlbumsChecked()); 0503 d->albumSelectCB->updateText(); 0504 } 0505 0506 if (d->tagWidget) 0507 { 0508 d->wholeTags->setChecked(group.readEntry(d->configUseWholeTagsEntry, false)); 0509 d->tagSelectCB->view()->loadState(); 0510 d->tagClearButton->animateVisible(!d->tagSelectCB->model()->checkedAlbums().isEmpty()); 0511 0512 slotWholeTags(wholeTagsChecked()); 0513 d->tagSelectCB->updateText(); 0514 } 0515 0516 if (d->selectionMode == All) 0517 { 0518 d->tabWidget->setCurrentIndex(group.readEntry(d->configAlbumTypeEntry, (int)PhysAlbum)); 0519 } 0520 } 0521 0522 void AlbumSelectors::saveState() 0523 { 0524 KSharedConfig::Ptr config = KSharedConfig::openConfig(); 0525 KConfigGroup group = config->group(d->configName); 0526 0527 if (d->albumWidget) 0528 { 0529 group.writeEntry(d->configUseWholeAlbumsEntry, wholeAlbumsChecked()); 0530 d->albumSelectCB->view()->saveState(); 0531 } 0532 0533 if (d->tagWidget) 0534 { 0535 group.writeEntry(d->configUseWholeTagsEntry, wholeTagsChecked()); 0536 d->tagSelectCB->view()->saveState(); 0537 } 0538 0539 if (d->selectionMode == All) 0540 { 0541 group.writeEntry(d->configAlbumTypeEntry, typeSelection()); 0542 } 0543 } 0544 0545 void AlbumSelectors::updateTabText() 0546 { 0547 if (d->selectionMode == All) 0548 { 0549 d->tabWidget->tabBar()->setTabText(PhysAlbum, 0550 wholeAlbumsChecked() ? i18nc("@title", "Albums (All)") 0551 : i18nc("@title", "Albums (%1)", 0552 selectedAlbums().count())); 0553 d->tabWidget->tabBar()->setTabText(TagsAlbum, 0554 wholeTagsChecked() ? i18nc("@title", "Tags (All)") 0555 : i18nc("@title", "Tags (%1)", 0556 selectedTags().count())); 0557 } 0558 } 0559 0560 } // namespace Digikam 0561 0562 #include "albumselectors.moc" 0563 0564 #include "moc_albumselectors.cpp"