File indexing completed on 2024-06-02 04:16:56

0001 /* ============================================================
0002  *
0003  * This file is a part of digiKam project
0004  * https://www.digikam.org
0005  *
0006  * Date        : 2021-08-27
0007  * Description : Side Bar Widget for the Showfoto folder view.
0008  *
0009  * SPDX-FileCopyrightText: 2021-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 "showfotofolderviewsidebar.h"
0016 
0017 // Qt includes
0018 
0019 #include <QApplication>
0020 #include <QStyle>
0021 #include <QIcon>
0022 #include <QUndoStack>
0023 #include <QVBoxLayout>
0024 #include <QFileInfo>
0025 #include <QDir>
0026 #include <QTimer>
0027 #include <QSplitter>
0028 
0029 // KDE includes
0030 
0031 #include <kconfiggroup.h>
0032 #include <klocalizedstring.h>
0033 
0034 // Local includes
0035 
0036 #include "digikam_debug.h"
0037 #include "digikam_globals.h"
0038 #include "showfoto.h"
0039 #include "showfotofolderviewbar.h"
0040 #include "showfotofolderviewundo.h"
0041 #include "showfotofolderviewmodel.h"
0042 #include "showfotofolderviewlist.h"
0043 #include "showfotofolderviewbookmarks.h"
0044 
0045 namespace ShowFoto
0046 {
0047 
0048 class Q_DECL_HIDDEN ShowfotoFolderViewSideBar::Private
0049 {
0050 
0051 public:
0052 
0053     explicit Private()
0054       : fsmodel     (nullptr),
0055         fsview      (nullptr),
0056         fsbar       (nullptr),
0057         fsmarks     (nullptr),
0058         fsstack     (nullptr),
0059         splitter    (nullptr),
0060         parent      (nullptr),
0061         fsSortOrder (Qt::AscendingOrder),
0062         fsRole      (ShowfotoFolderViewList::FileName)
0063     {
0064     }
0065 
0066     static const QString                   configIconSizeEntry;
0067     static const QString                   configLastFolderEntry;
0068     static const QString                   configFolderViewModeEntry;
0069     static const QString                   configFolderViewTypeMimeEntry;
0070     static const QString                   configBookmarksVisibleEntry;
0071     static const QString                   configSplitterStateEntry;
0072 
0073     ShowfotoFolderViewModel*               fsmodel;
0074     ShowfotoFolderViewList*                fsview;
0075     ShowfotoFolderViewBar*                 fsbar;
0076     ShowfotoFolderViewBookmarks*           fsmarks;
0077     QUndoStack*                            fsstack;
0078     QSplitter*                             splitter;
0079     Showfoto*                              parent;
0080     QList<DPluginAction*>                  pluginActions;
0081     Qt::SortOrder                          fsSortOrder;
0082     ShowfotoFolderViewList::FolderViewRole fsRole;
0083 };
0084 
0085 const QString ShowfotoFolderViewSideBar::Private::configIconSizeEntry(QLatin1String("Icon Size"));
0086 const QString ShowfotoFolderViewSideBar::Private::configLastFolderEntry(QLatin1String("Last Folder"));
0087 const QString ShowfotoFolderViewSideBar::Private::configFolderViewModeEntry(QLatin1String("Folder View Mode"));
0088 const QString ShowfotoFolderViewSideBar::Private::configFolderViewTypeMimeEntry(QLatin1String("Folder View Type Mime"));
0089 const QString ShowfotoFolderViewSideBar::Private::configBookmarksVisibleEntry(QLatin1String("Bookmarks Visible"));
0090 const QString ShowfotoFolderViewSideBar::Private::configSplitterStateEntry(QLatin1String("Splitter State"));
0091 
0092 ShowfotoFolderViewSideBar::ShowfotoFolderViewSideBar(Showfoto* const parent)
0093     : QWidget          (parent),
0094       StateSavingObject(this),
0095       d                (new Private)
0096 {
0097     setObjectName(QLatin1String("ShowfotoFolderView Sidebar"));
0098 
0099     d->parent                  = parent;
0100     d->fsstack                 = new QUndoStack(this);
0101 
0102     // --- Populate the view
0103 
0104     d->fsbar                   = new ShowfotoFolderViewBar(this);
0105     d->fsview                  = new ShowfotoFolderViewList(this, d->fsbar);
0106     d->fsmodel                 = new ShowfotoFolderViewModel(d->fsview);
0107     d->fsview->setModel(d->fsmodel);
0108     d->fsview->setRootIndex(d->fsmodel->index(QDir::rootPath()));
0109 
0110     d->fsmarks                 = new ShowfotoFolderViewBookmarks(this);
0111 
0112     d->splitter                = new QSplitter(Qt::Vertical, this);
0113     d->splitter->addWidget(d->fsview);
0114     d->splitter->addWidget(d->fsmarks);
0115     d->splitter->setStretchFactor(0, 10);
0116     d->splitter->setStretchFactor(1, 3);
0117 
0118     QVBoxLayout* const layout  = new QVBoxLayout(this);
0119     layout->addWidget(d->fsbar);
0120     layout->addWidget(d->splitter);
0121     layout->setContentsMargins(QMargins());
0122 
0123     // --- Setup connections
0124 
0125     connect(d->fsbar, SIGNAL(signalSetup()),
0126             this, SIGNAL(signalSetup()));
0127 
0128     connect(d->fsbar, SIGNAL(signalShowBookmarks(bool)),
0129             this, SLOT(slotShowBookmarks(bool)));
0130 
0131     connect(d->fsbar, SIGNAL(signalViewModeChanged(int)),
0132             this, SLOT(slotViewModeChanged(int)));
0133 
0134     connect(d->fsbar, SIGNAL(signalIconSizeChanged(int)),
0135             d->fsview, SLOT(slotIconSizeChanged(int)));
0136 
0137     connect(d->fsbar, SIGNAL(signalGoHome()),
0138             this, SLOT(slotGoHome()));
0139 
0140     connect(d->fsbar, SIGNAL(signalGoUp()),
0141             this, SLOT(slotGoUp()));
0142 
0143     connect(d->fsbar, SIGNAL(signalLoadContents()),
0144             this, SLOT(slotLoadContents()));
0145 
0146     connect(d->fsbar, SIGNAL(signalAppendContents()),
0147             this, SLOT(slotAppendContents()));
0148 
0149     connect(d->fsmarks, SIGNAL(signalLoadContents()),
0150             this, SLOT(slotLoadContents()));
0151 
0152     connect(d->fsbar, SIGNAL(signalCustomPathChanged(QString)),
0153             this, SLOT(slotCustomPathChanged(QString)));
0154 
0155     connect(d->fsbar, SIGNAL(signalTypeMimesChanged(QString)),
0156             this, SLOT(slotTypeMimesChanged(QString)));
0157 
0158     connect(d->fsbar, SIGNAL(signalGoNext()),
0159             this, SLOT(slotRedo()));
0160 
0161     connect(d->fsbar, SIGNAL(signalGoPrevious()),
0162             this, SLOT(slotUndo()));
0163 
0164     connect(d->fsstack, SIGNAL(canUndoChanged(bool)),
0165             d->fsbar, SLOT(slotPreviousEnabled(bool)));
0166 
0167     connect(d->fsstack, SIGNAL(canRedoChanged(bool)),
0168             d->fsbar, SLOT(slotNextEnabled(bool)));
0169 
0170     connect(d->fsview, SIGNAL(signalAddBookmark()),
0171             this, SIGNAL(signalAddBookmark()));
0172 }
0173 
0174 ShowfotoFolderViewSideBar::~ShowfotoFolderViewSideBar()
0175 {
0176     delete d;
0177 }
0178 
0179 void ShowfotoFolderViewSideBar::slotTypeMimesChanged(const QString& patterns)
0180 {
0181     d->fsmodel->setNameFilters(patterns.split(QLatin1Char(' ')));
0182 }
0183 
0184 void ShowfotoFolderViewSideBar::slotLoadContents()
0185 {
0186     QModelIndex index = d->fsmodel->index(currentPath());
0187     loadContents(index);
0188 }
0189 
0190 void ShowfotoFolderViewSideBar::slotAppendContents()
0191 {
0192     QModelIndex index = d->fsmodel->index(currentPath());
0193     loadContents(index, true);
0194 }
0195 
0196 void ShowfotoFolderViewSideBar::loadContents(const QModelIndex& index, bool append)
0197 {
0198     if (!index.isValid())
0199     {
0200         return;
0201     }
0202 
0203     QStringList lst;
0204     QString currentFile;
0205 
0206     if      (d->fsmodel->isDir(index))
0207     {
0208         setCurrentPath(d->fsmodel->filePath(index));
0209 
0210         lst         = d->fsmodel->currentFilesPath();
0211         currentFile = !lst.isEmpty() ? lst.first() : QString();
0212     }
0213     else if (d->fsmodel->fileInfo(index).isFile())
0214     {
0215         lst         = d->fsmodel->currentFilesPath();
0216         currentFile = d->fsmodel->fileInfo(index).filePath();
0217     }
0218 
0219     qCDebug(DIGIKAM_SHOWFOTO_LOG) << "Load Contents from:" << currentPath() << "Files:" << lst;
0220 
0221     if (!lst.isEmpty())
0222     {
0223         if (!append)
0224         {
0225             Q_EMIT signalLoadContentsFromFiles(lst, currentFile);
0226         }
0227         else
0228         {
0229             Q_EMIT signalAppendContentsFromFiles(lst, currentFile);
0230         }
0231     }
0232 }
0233 
0234 void ShowfotoFolderViewSideBar::slotCustomPathChanged(const QString& path)
0235 {
0236     setCurrentPath(path);
0237 }
0238 
0239 void ShowfotoFolderViewSideBar::slotUndo()
0240 {
0241     d->fsstack->undo();
0242 }
0243 
0244 void ShowfotoFolderViewSideBar::slotRedo()
0245 {
0246     d->fsstack->redo();
0247 }
0248 
0249 void ShowfotoFolderViewSideBar::slotGoHome()
0250 {
0251     setCurrentPath(QDir::homePath());
0252 }
0253 
0254 void ShowfotoFolderViewSideBar::slotGoUp()
0255 {
0256     QDir dir(currentFolder());
0257     dir.cdUp();
0258 
0259     // Is this the same as going back?  If so just go back, so we can keep the view scroll position.
0260 
0261     if (d->fsstack->canUndo())
0262     {
0263         const ShowfotoFolderViewUndo* lastDir = static_cast<const ShowfotoFolderViewUndo*>
0264                                                 (d->fsstack->command(d->fsstack->index() - 1));
0265 
0266         if (lastDir->undoPath() == dir.path())
0267         {
0268             d->fsstack->undo();
0269             return;
0270         }
0271     }
0272 
0273     setCurrentPath(dir.absolutePath());
0274 }
0275 
0276 QString ShowfotoFolderViewSideBar::currentFolder() const
0277 {
0278     QString path = d->fsmodel->rootPath();
0279 
0280     if (!path.endsWith(QDir::separator()))
0281     {
0282         path.append(QDir::separator());
0283     }
0284 
0285     return path;
0286 }
0287 
0288 QString ShowfotoFolderViewSideBar::currentPath() const
0289 {
0290     QModelIndex index = d->fsview->currentIndex();
0291 
0292     if (index.isValid())
0293     {
0294         return (d->fsmodel->filePath(index));
0295     }
0296 
0297     return currentFolder();
0298 }
0299 
0300 void ShowfotoFolderViewSideBar::setCurrentPath(const QString& newPathNative)
0301 {
0302     QFileInfo infoNative(newPathNative);
0303 
0304     if (!infoNative.exists())
0305     {
0306         return;
0307     }
0308 
0309     QString newPath = QDir::fromNativeSeparators(newPathNative);
0310 
0311     if (infoNative.isDir() && !newPath.endsWith(QDir::separator()))
0312     {
0313         newPath.append(QDir::separator());
0314     }
0315 
0316     QString oldDir(d->fsmodel->rootPath());
0317 
0318     if (!oldDir.endsWith(QDir::separator()))
0319     {
0320         oldDir.append(QDir::separator());
0321     }
0322 
0323     if (oldDir == newPath)
0324     {
0325         return;
0326     }
0327 
0328     QFileInfo info(newPath);
0329 
0330     if (info.isDir())
0331     {
0332         QModelIndex index = d->fsmodel->index(newPath);
0333 
0334         if (index.isValid())
0335         {
0336             d->fsstack->push(new ShowfotoFolderViewUndo(this, newPath));
0337             d->fsmodel->setRootPath(newPath);
0338             d->fsview->setRootIndex(index);
0339         }
0340     }
0341     else
0342     {
0343         QModelIndex index = d->fsmodel->index(newPath);
0344 
0345         if (index.isValid())
0346         {
0347             QString newDir = info.absolutePath();
0348 
0349             if (!newDir.endsWith(QDir::separator()))
0350             {
0351                 newDir.append(QDir::separator());
0352             }
0353 
0354             if (newDir != oldDir)
0355             {
0356                 d->fsstack->push(new ShowfotoFolderViewUndo(this, newDir));
0357                 d->fsmodel->setRootPath(newDir);
0358             }
0359 
0360             d->fsview->setCurrentIndex(index);
0361             d->fsview->scrollTo(index);
0362         }
0363     }
0364 }
0365 
0366 void ShowfotoFolderViewSideBar::setCurrentPathWithoutUndo(const QString& newPath)
0367 {
0368     QModelIndex index = d->fsmodel->setRootPath(newPath);
0369 
0370     if (index.isValid())
0371     {
0372         d->fsview->setRootIndex(index);
0373         d->fsbar->setCurrentPath(currentFolder());
0374     }
0375 }
0376 
0377 const QIcon ShowfotoFolderViewSideBar::getIcon()
0378 {
0379     return QIcon::fromTheme(QLatin1String("document-open-folder"));
0380 }
0381 
0382 const QString ShowfotoFolderViewSideBar::getCaption()
0383 {
0384     return i18nc("@title: file system tree", "Folders");
0385 }
0386 
0387 void ShowfotoFolderViewSideBar::doLoadState()
0388 {
0389     KConfigGroup group = getConfigGroup();
0390 
0391     d->fsmarks->readSettings(group);
0392     d->fsbar->setFolderViewMode(group.readEntry(entryName(d->configFolderViewModeEntry),         (int)ShowfotoFolderViewList::ShortView));
0393     d->fsbar->setFolderViewTypeMime(group.readEntry(entryName(d->configFolderViewTypeMimeEntry), (int)ShowfotoFolderViewBar::TYPE_MIME_ALL));
0394     d->fsbar->setBookmarksVisible(group.readEntry(entryName(d->configBookmarksVisibleEntry),     false));
0395     slotViewModeChanged(d->fsbar->folderViewMode());
0396     d->fsbar->setIconSize(group.readEntry(entryName(d->configIconSizeEntry),                     32));
0397 
0398     QByteArray state = group.readEntry(entryName(d->configSplitterStateEntry),                   QByteArray());
0399 
0400     if (!state.isEmpty())
0401     {
0402         d->splitter->restoreState(QByteArray::fromBase64(state));
0403     }
0404 
0405     setCurrentPathWithoutUndo(group.readEntry(entryName(d->configLastFolderEntry),               QDir::rootPath()));
0406     loadContents(d->fsview->currentIndex());
0407 }
0408 
0409 void ShowfotoFolderViewSideBar::doSaveState()
0410 {
0411     KConfigGroup group = getConfigGroup();
0412 
0413     d->fsmarks->saveSettings(group);
0414     group.writeEntry(entryName(d->configFolderViewModeEntry),       d->fsbar->folderViewMode());
0415     group.writeEntry(entryName(d->configFolderViewTypeMimeEntry),   d->fsbar->folderViewTypeMime());
0416     group.writeEntry(entryName(d->configBookmarksVisibleEntry),     d->fsbar->bookmarksVisible());
0417     group.writeEntry(entryName(d->configIconSizeEntry),             d->fsbar->iconSize());
0418     group.writeEntry(entryName(d->configLastFolderEntry),           currentFolder());
0419     group.writeEntry(entryName(d->configSplitterStateEntry),        d->splitter->saveState().toBase64());
0420     group.sync();
0421 }
0422 
0423 void ShowfotoFolderViewSideBar::slotViewModeChanged(int mode)
0424 {
0425     switch (mode)
0426     {
0427         case ShowfotoFolderViewList::ShortView:
0428         {
0429             d->fsview->setColumnHidden(ShowfotoFolderViewList::FileSize, true);
0430             d->fsview->setColumnHidden(ShowfotoFolderViewList::FileType, true);
0431             d->fsview->setColumnHidden(ShowfotoFolderViewList::FileDate, true);
0432             d->fsview->setHeaderHidden(true);
0433             break;
0434         }
0435 
0436         default:    // ShowfotoFolderViewList::DetailledView
0437         {
0438             d->fsview->setColumnHidden(ShowfotoFolderViewList::FileSize, false);
0439             d->fsview->setColumnHidden(ShowfotoFolderViewList::FileType, false);
0440             d->fsview->setColumnHidden(ShowfotoFolderViewList::FileDate, false);
0441             d->fsview->setHeaderHidden(false);
0442             break;
0443         }
0444     }
0445 }
0446 
0447 void ShowfotoFolderViewSideBar::setSortOrder(int order)
0448 {
0449     d->fsSortOrder = (Qt::SortOrder)order;
0450     d->fsmodel->sort(d->fsRole, d->fsSortOrder);
0451 }
0452 
0453 void ShowfotoFolderViewSideBar::setSortRole(int role)
0454 {
0455     d->fsRole = (ShowfotoFolderViewList::FolderViewRole)role;
0456     d->fsmodel->sort(d->fsRole, d->fsSortOrder);
0457 }
0458 
0459 void ShowfotoFolderViewSideBar::slotShowBookmarks(bool visible)
0460 {
0461     d->fsmarks->setVisible(visible);
0462 }
0463 
0464 void ShowfotoFolderViewSideBar::registerPluginActions(const QList<DPluginAction*>& actions)
0465 {
0466     d->pluginActions = actions;
0467 
0468     d->fsbar->registerPluginActions(d->pluginActions);
0469 
0470     connect(d->fsbar, SIGNAL(signalPluginActionTriggered(QAction*)),
0471             this, SLOT(slotPluginActionTriggered(QAction*)));
0472 }
0473 
0474 void ShowfotoFolderViewSideBar::slotPluginActionTriggered(QAction* act)
0475 {
0476     Q_FOREACH (QAction* const dpact, d->pluginActions)
0477     {
0478         if (act->objectName() == dpact->objectName())
0479         {
0480             slotLoadContents();
0481             QTimer::singleShot(1000, dpact, SLOT(trigger()));
0482             return;
0483         }
0484     }
0485 }
0486 
0487 QList<QAction*> ShowfotoFolderViewSideBar::pluginActions() const
0488 {
0489     return d->fsbar->pluginActions();
0490 }
0491 
0492 } // namespace ShowFoto
0493 
0494 #include "moc_showfotofolderviewsidebar.cpp"