File indexing completed on 2024-05-05 04:19:14

0001 // vim: set tabstop=4 shiftwidth=4 expandtab:
0002 /*
0003 Gwenview: an image viewer
0004 Copyright 2008 Aurélien Gâteau <agateau@kde.org>
0005 
0006 This program is free software; you can redistribute it and/or
0007 modify it under the terms of the GNU General Public License
0008 as published by the Free Software Foundation; either version 2
0009 of the License, or (at your option) any later version.
0010 
0011 This program is distributed in the hope that it will be useful,
0012 but WITHOUT ANY WARRANTY; without even the implied warranty of
0013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0014 GNU General Public License for more details.
0015 
0016 You should have received a copy of the GNU General Public License
0017 along with this program; if not, write to the Free Software
0018 Foundation, Inc., 51 Franklin Street, Fifth Floor, Cambridge, MA 02110-1301, USA.
0019 
0020 */
0021 // Self
0022 #include "browsemainpage.h"
0023 
0024 // Qt
0025 #include <QActionGroup>
0026 #include <QDropEvent>
0027 #include <QMenu>
0028 #include <QVBoxLayout>
0029 
0030 // KF
0031 #include <KActionCategory>
0032 #include <KActionCollection>
0033 #include <KActionMenu>
0034 #include <KDirModel>
0035 #include <KFileItem>
0036 #include <KFilePlacesModel>
0037 #include <KIconLoader>
0038 #include <KLocalizedString>
0039 #include <KUrlMimeData>
0040 #include <KUrlNavigator>
0041 
0042 // Local
0043 #include <fileoperations.h>
0044 #include <filtercontroller.h>
0045 #include <gvcore.h>
0046 #include <lib/archiveutils.h>
0047 #include <lib/document/documentfactory.h>
0048 #include <lib/gvdebug.h>
0049 #include <lib/gwenviewconfig.h>
0050 #include <lib/semanticinfo/abstractsemanticinfobackend.h>
0051 #include <lib/semanticinfo/sorteddirmodel.h>
0052 #include <lib/semanticinfo/tagmodel.h>
0053 #include <lib/sorting.h>
0054 #include <lib/thumbnailview/previewitemdelegate.h>
0055 #include <lib/thumbnailview/thumbnailview.h>
0056 #include <mimetypeutils.h>
0057 #include <ui_browsemainpage.h>
0058 #ifndef GWENVIEW_SEMANTICINFO_BACKEND_NONE
0059 #include "lib/semanticinfo/semanticinfodirmodel.h"
0060 #endif
0061 
0062 namespace Gwenview
0063 {
0064 inline Sorting::Enum sortingFromSortAction(const QAction *action)
0065 {
0066     Q_ASSERT(action);
0067     return Sorting::Enum(action->data().toInt());
0068 }
0069 
0070 struct BrowseMainPagePrivate : public Ui_BrowseMainPage {
0071     BrowseMainPage *q = nullptr;
0072     GvCore *mGvCore = nullptr;
0073     KFilePlacesModel *mFilePlacesModel = nullptr;
0074     KUrlNavigator *mUrlNavigator = nullptr;
0075     SortedDirModel *mDirModel = nullptr;
0076     int mDocumentCountImages;
0077     int mDocumentCountVideos;
0078     KFileItemList *mSelectedMediaItems = nullptr;
0079     KActionCollection *mActionCollection = nullptr;
0080     FilterController *mFilterController = nullptr;
0081     QActionGroup *mSortAction = nullptr;
0082     KToggleAction *mSortDescendingAction = nullptr;
0083     QActionGroup *mThumbnailDetailsActionGroup = nullptr;
0084     PreviewItemDelegate *mDelegate = nullptr;
0085 
0086     void setupWidgets()
0087     {
0088         setupUi(q);
0089         q->layout()->setContentsMargins(0, 0, 0, 0);
0090 
0091         int margins = q->style()->pixelMetric(QStyle::PM_ToolBarItemMargin) + q->style()->pixelMetric(QStyle::PM_ToolBarFrameWidth);
0092         mStatusBarContainer->layout()->setContentsMargins(margins, margins, margins, margins);
0093         mStatusBarContainer->layout()->setSpacing(q->style()->pixelMetric(QStyle::PM_ToolBarItemSpacing));
0094 
0095         // mThumbnailView
0096         mThumbnailView->setModel(mDirModel);
0097 
0098         mDelegate = new PreviewItemDelegate(mThumbnailView);
0099         mThumbnailView->setItemDelegate(mDelegate);
0100         mThumbnailView->setSelectionMode(QAbstractItemView::ExtendedSelection);
0101 
0102         // mUrlNavigator (use stupid layouting code because KUrlNavigator ctor
0103         // can't be used directly from Designer)
0104         mFilePlacesModel = new KFilePlacesModel(q);
0105         mUrlNavigator = new KUrlNavigator(mFilePlacesModel, QUrl(), mUrlNavigatorContainer);
0106         mUrlNavigatorContainer->setAutoFillBackground(true);
0107         mUrlNavigatorContainer->setBackgroundRole(QPalette::Mid);
0108         auto layout = new QVBoxLayout(mUrlNavigatorContainer);
0109         layout->setContentsMargins(0, 0, 0, 0);
0110         layout->addWidget(mUrlNavigator);
0111         QObject::connect(mUrlNavigator, SIGNAL(urlsDropped(QUrl, QDropEvent *)), q, SLOT(slotUrlsDropped(QUrl, QDropEvent *)));
0112 
0113         // FullScreen Toolbar
0114         mFullScreenToolBar->setVisible(false);
0115         mFullScreenToolBar2->setVisible(false);
0116         mFullScreenToolBar->setAutoFillBackground(true);
0117         mFullScreenToolBar2->setAutoFillBackground(true);
0118         mFullScreenToolBar->setBackgroundRole(QPalette::Mid);
0119         mFullScreenToolBar2->setBackgroundRole(QPalette::Mid);
0120 
0121         // Thumbnail slider
0122         QObject::connect(mThumbnailSlider, &ZoomSlider::valueChanged, mThumbnailView, &ThumbnailView::setThumbnailWidth);
0123         QObject::connect(mThumbnailView, &ThumbnailView::thumbnailWidthChanged, mThumbnailSlider, &ZoomSlider::setValue);
0124 
0125         // Document count label
0126         QMargins labelMargins = mDocumentCountLabel->contentsMargins();
0127         labelMargins.setLeft(15);
0128         labelMargins.setRight(15);
0129         mDocumentCountLabel->setContentsMargins(labelMargins);
0130     }
0131 
0132     QAction *thumbnailDetailAction(const QString &text, PreviewItemDelegate::ThumbnailDetail detail)
0133     {
0134         auto action = new QAction(q);
0135         action->setText(text);
0136         action->setCheckable(true);
0137         action->setChecked(GwenviewConfig::thumbnailDetails() & detail);
0138         action->setData(QVariant(detail));
0139         mThumbnailDetailsActionGroup->addAction(action);
0140         QObject::connect(action, SIGNAL(triggered(bool)), q, SLOT(updateThumbnailDetails()));
0141         return action;
0142     }
0143 
0144     void setupActions(KActionCollection *actionCollection)
0145     {
0146         auto view = new KActionCategory(i18nc("@title actions category - means actions changing smth in interface", "View"), actionCollection);
0147         QAction *action = view->addAction("edit_location", q, SLOT(editLocation()));
0148         action->setText(i18nc("@action:inmenu Navigation Bar", "Edit Location"));
0149         actionCollection->setDefaultShortcut(action, Qt::Key_F6);
0150 
0151         auto sortActionMenu = view->add<KActionMenu>("sort_by");
0152         sortActionMenu->setText(i18nc("@action:inmenu", "Sort By"));
0153         sortActionMenu->setIcon(QIcon::fromTheme(QStringLiteral("view-sort")));
0154         sortActionMenu->setPopupMode(QToolButton::InstantPopup);
0155 
0156         mSortAction = new QActionGroup(actionCollection);
0157         action = new QAction(i18nc("@addAction:inmenu", "Name"), mSortAction);
0158         action->setCheckable(true);
0159         action->setData(QVariant(Sorting::Name));
0160         action = new QAction(i18nc("@addAction:inmenu", "Date"), mSortAction);
0161         action->setCheckable(true);
0162         action->setData(QVariant(Sorting::Date));
0163         action = new QAction(i18nc("@addAction:inmenu", "Size"), mSortAction);
0164         action->setCheckable(true);
0165         action->setData(QVariant(Sorting::Size));
0166 #ifndef GWENVIEW_SEMANTICINFO_BACKEND_NONE
0167         action = new QAction(i18nc("@addAction:inmenu", "Rating"), mSortAction);
0168         action->setCheckable(true);
0169         action->setData(QVariant(Sorting::Rating));
0170 #endif
0171         QObject::connect(mSortAction, SIGNAL(triggered(QAction *)), q, SLOT(updateSortOrder()));
0172 
0173         mSortDescendingAction = view->add<KToggleAction>(QStringLiteral("sort_desc"));
0174         mSortDescendingAction->setText(i18nc("@action:inmenu Sort", "Descending"));
0175         QObject::connect(mSortDescendingAction, SIGNAL(toggled(bool)), q, SLOT(updateSortOrder()));
0176 
0177         for (auto action : mSortAction->actions()) {
0178             sortActionMenu->addAction(action);
0179         }
0180         sortActionMenu->addSeparator();
0181         sortActionMenu->addAction(mSortDescendingAction);
0182 
0183         mThumbnailDetailsActionGroup = new QActionGroup(q);
0184         mThumbnailDetailsActionGroup->setExclusive(false);
0185         auto thumbnailDetailsAction = view->add<KActionMenu>(QStringLiteral("thumbnail_details"));
0186         thumbnailDetailsAction->setText(i18nc("@action:inmenu", "Thumbnail Details"));
0187         thumbnailDetailsAction->addAction(thumbnailDetailAction(i18nc("@action:inmenu", "Filename"), PreviewItemDelegate::FileNameDetail));
0188         thumbnailDetailsAction->addAction(thumbnailDetailAction(i18nc("@action:inmenu", "Date"), PreviewItemDelegate::DateDetail));
0189         thumbnailDetailsAction->addAction(thumbnailDetailAction(i18nc("@action:inmenu", "Image Size"), PreviewItemDelegate::ImageSizeDetail));
0190         thumbnailDetailsAction->addAction(thumbnailDetailAction(i18nc("@action:inmenu", "File Size"), PreviewItemDelegate::FileSizeDetail));
0191 #ifndef GWENVIEW_SEMANTICINFO_BACKEND_NONE
0192         thumbnailDetailsAction->addAction(thumbnailDetailAction(i18nc("@action:inmenu", "Rating"), PreviewItemDelegate::RatingDetail));
0193 #endif
0194 
0195         auto file = new KActionCategory(i18nc("@title actions category", "File"), actionCollection);
0196         action = file->addAction(QStringLiteral("add_folder_to_places"), q, SLOT(addFolderToPlaces()));
0197         action->setText(i18nc("@action:inmenu", "Add Folder to Places"));
0198         action->setIcon(QIcon::fromTheme(QStringLiteral("bookmark-new")));
0199     }
0200 
0201     void setupFilterController()
0202     {
0203         auto menu = new QMenu(mAddFilterButton);
0204         mFilterController = new FilterController(mFilterFrame, mDirModel);
0205         const auto actionList = mFilterController->actionList();
0206         for (QAction *action : actionList) {
0207             menu->addAction(action);
0208         }
0209         mAddFilterButton->setMenu(menu);
0210     }
0211 
0212     void setupFullScreenToolBar()
0213     {
0214         mFullScreenToolBar->setIconDimensions(KIconLoader::SizeMedium);
0215         mFullScreenToolBar->setToolButtonStyle(Qt::ToolButtonIconOnly);
0216         mFullScreenToolBar->addAction(mActionCollection->action(QStringLiteral("browse")));
0217         mFullScreenToolBar->addAction(mActionCollection->action(QStringLiteral("view")));
0218 
0219         mFullScreenToolBar2->setIconDimensions(KIconLoader::SizeMedium);
0220         mFullScreenToolBar2->setToolButtonStyle(Qt::ToolButtonIconOnly);
0221         mFullScreenToolBar2->addAction(mActionCollection->action(QStringLiteral("leave_fullscreen")));
0222     }
0223 
0224     void updateSelectedMediaItems(const QItemSelection &selected, const QItemSelection &deselected)
0225     {
0226         for (auto index : selected.indexes()) {
0227             KFileItem item = mDirModel->itemForIndex(index);
0228             if (!ArchiveUtils::fileItemIsDirOrArchive(item)) {
0229                 mSelectedMediaItems->append(item);
0230             }
0231         }
0232         for (auto index : deselected.indexes()) {
0233             KFileItem item = mDirModel->itemForIndex(index);
0234             mSelectedMediaItems->removeOne(item);
0235         }
0236     }
0237 
0238     void updateDocumentCountLabel()
0239     {
0240         if (mSelectedMediaItems->count() > 1) {
0241             KIO::filesize_t totalSize = 0;
0242             for (const auto &item : *mSelectedMediaItems) {
0243                 totalSize += item.size();
0244             }
0245             const QString text = i18nc("@info:status %1 number of selected documents, %2 total number of documents, %3 total filesize of selected documents",
0246                                        "Selected %1 of %2 (%3)",
0247                                        mSelectedMediaItems->count(),
0248                                        mDocumentCountImages + mDocumentCountVideos,
0249                                        KIO::convertSize(totalSize));
0250             mDocumentCountLabel->setText(text);
0251         } else {
0252             const QString imageText = i18ncp("@info:status Image files", "%1 image", "%1 images", mDocumentCountImages);
0253             const QString videoText = i18ncp("@info:status Video files", "%1 video", "%1 videos", mDocumentCountVideos);
0254             QString labelText;
0255             if (mDocumentCountImages > 0 && mDocumentCountVideos == 0) {
0256                 labelText = imageText;
0257             } else if (mDocumentCountImages == 0 && mDocumentCountVideos > 0) {
0258                 labelText = videoText;
0259             } else {
0260                 labelText = i18nc("@info:status images, videos", "%1, %2", imageText, videoText);
0261             }
0262             mDocumentCountLabel->setText(labelText);
0263         }
0264     }
0265 
0266     void documentCountsForIndexRange(const QModelIndex &parent, int start, int end, int &imageCountOut, int &videoCountOut)
0267     {
0268         imageCountOut = 0;
0269         videoCountOut = 0;
0270         for (int row = start; row <= end; ++row) {
0271             QModelIndex index = mDirModel->index(row, 0, parent);
0272             KFileItem item = mDirModel->itemForIndex(index);
0273             if (!ArchiveUtils::fileItemIsDirOrArchive(item)) {
0274                 MimeTypeUtils::Kind kind = MimeTypeUtils::mimeTypeKind(item.mimetype());
0275                 if (kind == MimeTypeUtils::KIND_RASTER_IMAGE || kind == MimeTypeUtils::KIND_SVG_IMAGE) {
0276                     imageCountOut++;
0277                 } else if (kind == MimeTypeUtils::KIND_VIDEO) {
0278                     videoCountOut++;
0279                 }
0280             }
0281         }
0282     }
0283 
0284     void updateContextBarActions()
0285     {
0286         PreviewItemDelegate::ContextBarActions actions;
0287         switch (GwenviewConfig::thumbnailActions()) {
0288         case ThumbnailActions::None:
0289             actions = PreviewItemDelegate::NoAction;
0290             break;
0291         case ThumbnailActions::ShowSelectionButtonOnly:
0292             actions = PreviewItemDelegate::SelectionAction;
0293             break;
0294         case ThumbnailActions::AllButtons:
0295         default:
0296             actions = PreviewItemDelegate::SelectionAction | PreviewItemDelegate::RotateAction;
0297             if (!q->window()->isFullScreen()) {
0298                 actions |= PreviewItemDelegate::FullScreenAction;
0299             }
0300             break;
0301         }
0302         mDelegate->setContextBarActions(actions);
0303     }
0304 
0305     void applyPalette(bool fullScreenmode)
0306     {
0307         q->setPalette(mGvCore->palette(fullScreenmode ? GvCore::FullScreenPalette : GvCore::NormalPalette));
0308         mThumbnailView->setPalette(mGvCore->palette(fullScreenmode ? GvCore::FullScreenViewPalette : GvCore::NormalViewPalette));
0309     }
0310 };
0311 
0312 BrowseMainPage::BrowseMainPage(QWidget *parent, KActionCollection *actionCollection, GvCore *gvCore)
0313     : QWidget(parent)
0314     , d(new BrowseMainPagePrivate)
0315 {
0316     d->q = this;
0317     d->mGvCore = gvCore;
0318     d->mDirModel = gvCore->sortedDirModel();
0319     d->mDocumentCountImages = 0;
0320     d->mDocumentCountVideos = 0;
0321     d->mSelectedMediaItems = new KFileItemList;
0322     d->mActionCollection = actionCollection;
0323     d->setupWidgets();
0324     d->setupActions(actionCollection);
0325     d->setupFilterController();
0326     loadConfig();
0327     updateSortOrder();
0328     updateThumbnailDetails();
0329 
0330     // Set up connections for document count
0331     connect(d->mDirModel, &SortedDirModel::rowsInserted, this, &BrowseMainPage::slotDirModelRowsInserted);
0332     connect(d->mDirModel, &SortedDirModel::rowsAboutToBeRemoved, this, &BrowseMainPage::slotDirModelRowsAboutToBeRemoved);
0333     connect(d->mDirModel, &SortedDirModel::modelReset, this, &BrowseMainPage::slotDirModelReset);
0334     connect(thumbnailView(), &ThumbnailView::selectionChangedSignal, this, &BrowseMainPage::slotSelectionChanged);
0335 
0336     connect(qApp, &QApplication::paletteChanged, this, [this]() {
0337         d->applyPalette(window()->isFullScreen());
0338     });
0339 
0340     installEventFilter(this);
0341 }
0342 
0343 BrowseMainPage::~BrowseMainPage()
0344 {
0345     d->mSelectedMediaItems->clear();
0346     delete d->mSelectedMediaItems;
0347     delete d;
0348 }
0349 
0350 void BrowseMainPage::loadConfig()
0351 {
0352     d->applyPalette(window()->isFullScreen());
0353     d->mUrlNavigator->setUrlEditable(GwenviewConfig::urlNavigatorIsEditable());
0354     d->mUrlNavigator->setShowFullPath(GwenviewConfig::urlNavigatorShowFullPath());
0355 
0356     d->mThumbnailSlider->setValue(GwenviewConfig::thumbnailSize());
0357     d->mThumbnailSlider->updateToolTip();
0358     // If GwenviewConfig::thumbnailSize() returns the current value of
0359     // mThumbnailSlider, it won't emit valueChanged() and the thumbnail view
0360     // won't be updated. That's why we do it ourself.
0361     d->mThumbnailView->setThumbnailAspectRatio(GwenviewConfig::thumbnailAspectRatio());
0362     d->mThumbnailView->setThumbnailWidth(GwenviewConfig::thumbnailSize());
0363 
0364     const auto actionsList = d->mSortAction->actions();
0365     for (QAction *action : actionsList) {
0366         if (sortingFromSortAction(action) == GwenviewConfig::sorting()) {
0367             action->setChecked(true);
0368             break;
0369         }
0370     }
0371     d->mSortDescendingAction->setChecked(GwenviewConfig::sortDescending());
0372 
0373     d->updateContextBarActions();
0374 }
0375 
0376 void BrowseMainPage::saveConfig() const
0377 {
0378     GwenviewConfig::setUrlNavigatorIsEditable(d->mUrlNavigator->isUrlEditable());
0379     GwenviewConfig::setUrlNavigatorShowFullPath(d->mUrlNavigator->showFullPath());
0380     GwenviewConfig::setThumbnailSize(d->mThumbnailSlider->value());
0381     GwenviewConfig::setSorting(sortingFromSortAction(d->mSortAction->checkedAction()));
0382     GwenviewConfig::setSortDescending(d->mSortDescendingAction->isChecked());
0383     GwenviewConfig::setThumbnailDetails(d->mDelegate->thumbnailDetails());
0384 }
0385 
0386 bool BrowseMainPage::eventFilter(QObject *watched, QEvent *event)
0387 {
0388     // Leave fullscreen when not viewing an image
0389     if (window()->isFullScreen() && event->type() == QEvent::ShortcutOverride) {
0390         const QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
0391         if (keyEvent->key() == Qt::Key_Escape) {
0392             d->mActionCollection->action(QStringLiteral("leave_fullscreen"))->trigger();
0393             event->accept();
0394         }
0395     }
0396     return QWidget::eventFilter(watched, event);
0397 }
0398 
0399 void BrowseMainPage::mousePressEvent(QMouseEvent *event)
0400 {
0401     switch (event->button()) {
0402     case Qt::ForwardButton:
0403     case Qt::BackButton:
0404         return;
0405     default:
0406         QWidget::mousePressEvent(event);
0407     }
0408 }
0409 
0410 ThumbnailView *BrowseMainPage::thumbnailView() const
0411 {
0412     return d->mThumbnailView;
0413 }
0414 
0415 KUrlNavigator *BrowseMainPage::urlNavigator() const
0416 {
0417     return d->mUrlNavigator;
0418 }
0419 
0420 void BrowseMainPage::reload()
0421 {
0422     const QModelIndexList list = d->mThumbnailView->selectionModel()->selectedIndexes();
0423     for (const QModelIndex &index : list) {
0424         d->mThumbnailView->reloadThumbnail(index);
0425     }
0426     d->mDirModel->reload();
0427 }
0428 
0429 void BrowseMainPage::editLocation()
0430 {
0431     d->mUrlNavigator->setUrlEditable(true);
0432     d->mUrlNavigator->setFocus();
0433 }
0434 
0435 void BrowseMainPage::addFolderToPlaces()
0436 {
0437     QUrl url = d->mUrlNavigator->locationUrl();
0438     QString text = url.adjusted(QUrl::StripTrailingSlash).fileName();
0439     if (text.isEmpty()) {
0440         text = url.toDisplayString();
0441     }
0442     d->mFilePlacesModel->addPlace(text, url);
0443 }
0444 
0445 void BrowseMainPage::slotDirModelRowsInserted(const QModelIndex &parent, int start, int end)
0446 {
0447     int imageCount;
0448     int videoCount;
0449     d->documentCountsForIndexRange(parent, start, end, imageCount, videoCount);
0450     if (imageCount > 0 || videoCount > 0) {
0451         d->mDocumentCountImages += imageCount;
0452         d->mDocumentCountVideos += videoCount;
0453         d->updateDocumentCountLabel();
0454     }
0455 }
0456 
0457 void BrowseMainPage::slotDirModelRowsAboutToBeRemoved(const QModelIndex &parent, int start, int end)
0458 {
0459     int imageCount;
0460     int videoCount;
0461     d->documentCountsForIndexRange(parent, start, end, imageCount, videoCount);
0462     if (imageCount > 0 || videoCount > 0) {
0463         d->mDocumentCountImages -= imageCount;
0464         d->mDocumentCountVideos -= videoCount;
0465         d->updateDocumentCountLabel();
0466     }
0467 }
0468 
0469 void BrowseMainPage::slotDirModelReset()
0470 {
0471     d->mDocumentCountImages = 0;
0472     d->mDocumentCountVideos = 0;
0473     d->mSelectedMediaItems->clear();
0474     d->updateDocumentCountLabel();
0475 }
0476 
0477 void BrowseMainPage::slotSelectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
0478 {
0479     d->updateSelectedMediaItems(selected, deselected);
0480     d->updateDocumentCountLabel();
0481 }
0482 
0483 void BrowseMainPage::updateSortOrder()
0484 {
0485     const QAction *action = d->mSortAction->checkedAction();
0486     GV_RETURN_IF_FAIL(action);
0487 
0488     const Qt::SortOrder order = d->mSortDescendingAction->isChecked() ? Qt::DescendingOrder : Qt::AscendingOrder;
0489     KDirModel::ModelColumns column = KDirModel::Name;
0490     int sortRole = Qt::DisplayRole;
0491 
0492     // Map Sorting::Enum to model columns and sorting roles
0493     switch (sortingFromSortAction(action)) {
0494     case Sorting::Name:
0495         column = KDirModel::Name;
0496         break;
0497     case Sorting::Size:
0498         column = KDirModel::Size;
0499         break;
0500     case Sorting::Date:
0501         column = KDirModel::ModifiedTime;
0502         break;
0503 #ifndef GWENVIEW_SEMANTICINFO_BACKEND_NONE
0504     case Sorting::Rating:
0505         column = KDirModel::Name;
0506         sortRole = SemanticInfoDirModel::RatingRole;
0507         break;
0508 #endif
0509     }
0510 
0511     d->mDirModel->setSortRole(sortRole);
0512     d->mDirModel->sort(column, order);
0513     d->mGvCore->setTrackFileManagerSorting(false);
0514 }
0515 
0516 void BrowseMainPage::updateThumbnailDetails()
0517 {
0518     PreviewItemDelegate::ThumbnailDetails details = {};
0519     const auto actionList = d->mThumbnailDetailsActionGroup->actions();
0520     for (const QAction *action : actionList) {
0521         if (action->isChecked()) {
0522             details |= PreviewItemDelegate::ThumbnailDetail(action->data().toInt());
0523         }
0524     }
0525     d->mDelegate->setThumbnailDetails(details);
0526 }
0527 
0528 void BrowseMainPage::setFullScreenMode(bool fullScreen)
0529 {
0530     d->applyPalette(fullScreen);
0531     d->mUrlNavigatorContainer->setContentsMargins(fullScreen ? 6 : 0, 0, 0, 0);
0532     d->updateContextBarActions();
0533 
0534     d->mFullScreenToolBar->setVisible(fullScreen);
0535     d->mFullScreenToolBar2->setVisible(fullScreen);
0536     if (fullScreen && d->mFullScreenToolBar->actions().isEmpty()) {
0537         d->setupFullScreenToolBar();
0538     }
0539 }
0540 
0541 void BrowseMainPage::setStatusBarVisible(bool visible)
0542 {
0543     d->mStatusBarContainer->setVisible(visible);
0544 }
0545 
0546 void BrowseMainPage::slotUrlsDropped(const QUrl &destUrl, QDropEvent *event)
0547 {
0548     const QList<QUrl> urlList = KUrlMimeData::urlsFromMimeData(event->mimeData());
0549     if (urlList.isEmpty()) {
0550         return;
0551     }
0552     event->acceptProposedAction();
0553 
0554     // We can't call FileOperations::showMenuForDroppedUrls() directly because
0555     // we need the slot to return so that the drop event is accepted. Otherwise
0556     // the drop cursor is still visible when the menu is shown.
0557     QMetaObject::invokeMethod(
0558         this,
0559         [this, urlList, destUrl]() {
0560             showMenuForDroppedUrls(urlList, destUrl);
0561         },
0562         Qt::QueuedConnection);
0563 }
0564 
0565 void BrowseMainPage::showMenuForDroppedUrls(const QList<QUrl> &urlList, const QUrl &destUrl)
0566 {
0567     FileOperations::showMenuForDroppedUrls(d->mUrlNavigator, urlList, destUrl);
0568 }
0569 
0570 QToolButton *BrowseMainPage::toggleSideBarButton() const
0571 {
0572     return d->mToggleSideBarButton;
0573 }
0574 
0575 } // namespace
0576 
0577 #include "moc_browsemainpage.cpp"