File indexing completed on 2025-01-05 04:00:10

0001 /* ============================================================
0002  *
0003  * This file is a part of digiKam project
0004  * https://www.digikam.org
0005  *
0006  * Date        : 2005-02-01
0007  * Description : collections setup tab
0008  *
0009  * SPDX-FileCopyrightText: 2005-2024 by Gilles Caulier <caulier dot gilles at gmail dot com>
0010  *
0011  * SPDX-License-Identifier: GPL-2.0-or-later
0012  *
0013  * ============================================================ */
0014 
0015 #include "setupcollections.h"
0016 
0017 // Qt includes
0018 
0019 #include <QLabel>
0020 #include <QStyle>
0021 #include <QCheckBox>
0022 #include <QLineEdit>
0023 #include <QWhatsThis>
0024 #include <QVBoxLayout>
0025 #include <QApplication>
0026 
0027 // KDE includes
0028 
0029 #include <kconfiggroup.h>
0030 #include <ksharedconfig.h>
0031 #include <klocalizedstring.h>
0032 
0033 // Local includes
0034 
0035 #include "digikam_debug.h"
0036 #include "coredb.h"
0037 #include "coredbaccess.h"
0038 #include "applicationsettings.h"
0039 #include "setupcollectionview.h"
0040 #include "scancontroller.h"
0041 #include "setuputils.h"
0042 
0043 namespace Digikam
0044 {
0045 
0046 class Q_DECL_HIDDEN SetupCollections::Private
0047 {
0048 public:
0049 
0050     explicit Private()
0051       : rootsPathChanged(false),
0052         collectionView  (nullptr),
0053         collectionModel (nullptr),
0054         monitoringBox   (nullptr),
0055         ignoreEdit      (nullptr),
0056         tab             (nullptr),
0057         ignoreLabel     (nullptr)
0058     {
0059     }
0060 
0061     static const QString     configGroupName;
0062     static const QString     configLastAddedCollectionPath;
0063 
0064     bool                     rootsPathChanged;
0065 
0066     SetupCollectionTreeView* collectionView;
0067     SetupCollectionModel*    collectionModel;
0068 
0069     QCheckBox*               monitoringBox;
0070     QLineEdit*               ignoreEdit;
0071     QTabWidget*              tab;
0072     QLabel*                  ignoreLabel;
0073 };
0074 
0075 const QString SetupCollections::Private::configGroupName(QLatin1String("Collection Settings"));
0076 const QString SetupCollections::Private::configLastAddedCollectionPath(QLatin1String("LastAddedCollectionPath"));
0077 
0078 SetupCollections::SetupCollections(QWidget* const parent)
0079     : QScrollArea(parent),
0080       d          (new Private)
0081 {
0082     const int spacing     = qMin(QApplication::style()->pixelMetric(QStyle::PM_LayoutHorizontalSpacing),
0083                              QApplication::style()->pixelMetric(QStyle::PM_LayoutVerticalSpacing));
0084 
0085     d->tab                = new QTabWidget(viewport());
0086     setWidget(d->tab);
0087     setWidgetResizable(true);
0088 
0089     // --------------------------------------------------------
0090 
0091     QWidget* const albumPanel      = new QWidget(d->tab);
0092     QVBoxLayout* const albumLayout = new QVBoxLayout(albumPanel);
0093 
0094 #ifndef Q_OS_WIN
0095 
0096     QLabel* const albumPathLabel   = new QLabel(i18n("<p>Below are the locations of your root albums used to store "
0097                                                      "your images. Write access is necessary to be able to edit "
0098                                                      "images in these albums.</p>"
0099                                                      "<p>Note: Removable media (such as USB drives or DVDs) and "
0100                                                      "remote file systems (such as NFS, or Samba mounted with "
0101                                                      "cifs/smbfs) are supported.</p>"
0102                                                      "<p>Important: You need to mount the share natively on your "
0103                                                      "system before to setup a remote collection.</p>"
0104                                                      "<p></p>"),
0105                                                albumPanel);
0106 
0107 #else
0108 
0109     QLabel* const albumPathLabel   = new QLabel(i18n("<p>Below are the locations of your root albums used to store "
0110                                                      "your images. Write access is necessary to be able "
0111                                                      "to edit images in these albums.</p>"
0112                                                      "<p></p>"),
0113                                                 albumPanel);
0114 
0115 #endif
0116 
0117     albumPathLabel->setWordWrap(true);
0118 
0119     d->collectionView              = new SetupCollectionTreeView(albumPanel);
0120     d->collectionModel             = new SetupCollectionModel(albumPanel);
0121     d->collectionView->setModel(d->collectionModel);
0122 
0123     d->monitoringBox               = new QCheckBox(i18n("Monitor the albums for external "
0124                                                         "changes (requires restart)"), albumPanel);
0125 
0126     QLabel* const monitoringNote   = new QLabel(i18n("<b>Note: Album monitoring consumes system resources and "
0127                                                      "can slow down digiKam. If you are using MacOS and network "
0128                                                      "collections, you should not activate album monitoring.</b>"));
0129     monitoringNote->setWordWrap(true);
0130     monitoringNote->setFrameStyle(QFrame::StyledPanel | QFrame::Raised);
0131 
0132     albumLayout->addWidget(albumPathLabel);
0133     albumLayout->addWidget(d->collectionView);
0134     albumLayout->addWidget(d->monitoringBox);
0135     albumLayout->addWidget(monitoringNote);
0136     albumLayout->setContentsMargins(spacing, spacing, spacing, spacing);
0137     albumLayout->setSpacing(spacing);
0138 
0139     d->tab->insertTab(Collections, albumPanel, i18nc("@title:tab", "Root Album Folders"));
0140 
0141     // --------------------------------------------------------
0142 
0143     QWidget* const ignorePanel      = new QWidget(d->tab);
0144     QGridLayout* const ignoreLayout = new QGridLayout(ignorePanel);
0145 
0146     QLabel* const ignoreInfoLabel   = new QLabel(i18n("<p>Set the names of directories that you want to ignore "
0147                                                       "from your photo collections. The names are case sensitive "
0148                                                       "and should be separated by a semicolon.</p>"
0149                                                       "<p>This is for example useful when you store your photos "
0150                                                       "on a Synology NAS (Network Attached Storage). In every "
0151                                                       "directory the system creates a subdirectory @eaDir to "
0152                                                       "store thumbnails. To avoid digiKam inserting the original "
0153                                                       "photo and its corresponding thumbnail twice, @eaDir is "
0154                                                       "ignored by default.</p>"
0155                                                       "<p>To re-include directories that are ignored by default "
0156                                                       "prefix it with a minus, e.g. -@eaDir.</p>"),
0157                                                  ignorePanel);
0158     ignoreInfoLabel->setWordWrap(true);
0159 
0160     QLabel* const logoLabel1        = new QLabel(ignorePanel);
0161     logoLabel1->setPixmap(QIcon::fromTheme(QLatin1String("folder")).pixmap(48));
0162 
0163     d->ignoreLabel                  = new QLabel(ignorePanel);
0164     d->ignoreLabel->setText(i18n("Additional directories to ignore "
0165                                  "(<a href='image'>Currently ignored directories</a>):"));
0166 
0167     d->ignoreEdit                   = new QLineEdit(ignorePanel);
0168     d->ignoreEdit->setClearButtonEnabled(true);
0169     d->ignoreEdit->setPlaceholderText(i18n("Enter directories that you want to "
0170                                            "ignore from adding to your collections."));
0171     ignoreInfoLabel->setBuddy(d->ignoreEdit);
0172 
0173     ignoreLayout->addWidget(ignoreInfoLabel, 0, 0, 1, 2);
0174     ignoreLayout->addWidget(logoLabel1,      1, 0, 2, 1);
0175     ignoreLayout->addWidget(d->ignoreLabel,  1, 1, 1, 1);
0176     ignoreLayout->addWidget(d->ignoreEdit,   2, 1, 1, 1);
0177     ignoreLayout->setColumnStretch(1, 10);
0178     ignoreLayout->setRowStretch(3, 10);
0179     ignoreLayout->setContentsMargins(spacing, spacing, spacing, spacing);
0180     ignoreLayout->setSpacing(spacing);
0181 
0182     connect(d->ignoreLabel, SIGNAL(linkActivated(QString)),
0183             this, SLOT(slotShowCurrentIgnoredDirectoriesSettings()));
0184 
0185     d->tab->insertTab(IgnoreDirs, ignorePanel, i18nc("@title:tab", "Ignored Directories"));
0186 
0187     // --------------------------------------------------------
0188 
0189     readSettings();
0190     adjustSize();
0191 }
0192 
0193 SetupCollections::~SetupCollections()
0194 {
0195     delete d;
0196 }
0197 
0198 void SetupCollections::setActiveTab(CollectionsTab tab)
0199 {
0200     d->tab->setCurrentIndex(tab);
0201 }
0202 
0203 SetupCollections::CollectionsTab SetupCollections::activeTab() const
0204 {
0205     return (CollectionsTab)d->tab->currentIndex();
0206 }
0207 
0208 void SetupCollections::applySettings()
0209 {
0210     KSharedConfig::Ptr config = KSharedConfig::openConfig();
0211     KConfigGroup group        = config->group(d->configGroupName);
0212 
0213     group.writeEntry(d->configLastAddedCollectionPath,
0214                      d->collectionModel->lastAddedCollectionPath);
0215 
0216     d->collectionModel->apply();
0217 
0218     ApplicationSettings* const settings = ApplicationSettings::instance();
0219     settings->setAlbumMonitoring(d->monitoringBox->isChecked());
0220 
0221     QString ignoreDirectory;
0222     CoreDbAccess().db()->getUserIgnoreDirectoryFilterSettings(&ignoreDirectory);
0223 
0224     if (d->ignoreEdit->text() != ignoreDirectory)
0225     {
0226         CoreDbAccess().db()->setUserIgnoreDirectoryFilterSettings(
0227                     cleanUserFilterString(d->ignoreEdit->text(), true, true));
0228 
0229         ScanController::instance()->completeCollectionScanInBackground(false, false);
0230     }
0231 }
0232 
0233 void SetupCollections::readSettings()
0234 {
0235     KSharedConfig::Ptr config = KSharedConfig::openConfig();
0236     KConfigGroup group        = config->group(d->configGroupName);
0237 
0238     d->collectionModel->lastAddedCollectionPath =
0239         group.readEntry(d->configLastAddedCollectionPath, QString());
0240 
0241     d->collectionModel->loadCollections();
0242 
0243     ApplicationSettings* const settings = ApplicationSettings::instance();
0244     d->monitoringBox->setChecked(settings->getAlbumMonitoring());
0245 
0246     QString ignoreDirectory;
0247     CoreDbAccess().db()->getUserIgnoreDirectoryFilterSettings(&ignoreDirectory);
0248     d->ignoreEdit->setText(ignoreDirectory);
0249 }
0250 
0251 void SetupCollections::slotShowCurrentIgnoredDirectoriesSettings() const
0252 {
0253     QStringList ignoreDirectoryList;
0254     CoreDbAccess().db()->getIgnoreDirectoryFilterSettings(&ignoreDirectoryList);
0255 
0256     QString text = i18n("<p>Directories starting with a dot are ignored by "
0257                         "default.<br/> <code>%1</code></p>",
0258                         ignoreDirectoryList.join(QLatin1Char(';')));
0259 
0260     QWhatsThis::showText(d->ignoreLabel->mapToGlobal(QPoint(0, 0)), text, d->ignoreLabel);
0261 }
0262 
0263 } // namespace Digikam
0264 
0265 #include "moc_setupcollections.cpp"