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"