578 lines
22 KiB
C++
578 lines
22 KiB
C++
|
// vim: set tabstop=4 shiftwidth=4 expandtab:
|
||
|
/*
|
||
|
Gwenview: an image viewer
|
||
|
Copyright 2008 Aurélien Gâteau <agateau@kde.org>
|
||
|
|
||
|
This program is free software; you can redistribute it and/or
|
||
|
modify it under the terms of the GNU General Public License
|
||
|
as published by the Free Software Foundation; either version 2
|
||
|
of the License, or (at your option) any later version.
|
||
|
|
||
|
This program is distributed in the hope that it will be useful,
|
||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
GNU General Public License for more details.
|
||
|
|
||
|
You should have received a copy of the GNU General Public License
|
||
|
along with this program; if not, write to the Free Software
|
||
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Cambridge, MA 02110-1301, USA.
|
||
|
|
||
|
*/
|
||
|
// Self
|
||
|
#include "browsemainpage.h"
|
||
|
|
||
|
// Qt
|
||
|
#include <QActionGroup>
|
||
|
#include <QDropEvent>
|
||
|
#include <QMenu>
|
||
|
#include <QVBoxLayout>
|
||
|
|
||
|
// KF
|
||
|
#include <KActionCategory>
|
||
|
#include <KActionCollection>
|
||
|
#include <KActionMenu>
|
||
|
#include <KDirModel>
|
||
|
#include <KFileItem>
|
||
|
#include <KFilePlacesModel>
|
||
|
#include <KIconLoader>
|
||
|
#include <KLocalizedString>
|
||
|
#include <KUrlMimeData>
|
||
|
#include <KUrlNavigator>
|
||
|
|
||
|
// Local
|
||
|
#include <fileoperations.h>
|
||
|
#include <filtercontroller.h>
|
||
|
#include <gvcore.h>
|
||
|
#include <lib/archiveutils.h>
|
||
|
#include <lib/document/documentfactory.h>
|
||
|
#include <lib/gvdebug.h>
|
||
|
#include <lib/gwenviewconfig.h>
|
||
|
#include <lib/semanticinfo/abstractsemanticinfobackend.h>
|
||
|
#include <lib/semanticinfo/sorteddirmodel.h>
|
||
|
#include <lib/semanticinfo/tagmodel.h>
|
||
|
#include <lib/sorting.h>
|
||
|
#include <lib/thumbnailview/previewitemdelegate.h>
|
||
|
#include <lib/thumbnailview/thumbnailview.h>
|
||
|
#include <mimetypeutils.h>
|
||
|
#include <ui_browsemainpage.h>
|
||
|
#ifndef GWENVIEW_SEMANTICINFO_BACKEND_NONE
|
||
|
#include "lib/semanticinfo/semanticinfodirmodel.h"
|
||
|
#endif
|
||
|
|
||
|
namespace Gwenview
|
||
|
{
|
||
|
inline Sorting::Enum sortingFromSortAction(const QAction *action)
|
||
|
{
|
||
|
Q_ASSERT(action);
|
||
|
return Sorting::Enum(action->data().toInt());
|
||
|
}
|
||
|
|
||
|
struct BrowseMainPagePrivate : public Ui_BrowseMainPage {
|
||
|
BrowseMainPage *q = nullptr;
|
||
|
GvCore *mGvCore = nullptr;
|
||
|
KFilePlacesModel *mFilePlacesModel = nullptr;
|
||
|
KUrlNavigator *mUrlNavigator = nullptr;
|
||
|
SortedDirModel *mDirModel = nullptr;
|
||
|
int mDocumentCountImages;
|
||
|
int mDocumentCountVideos;
|
||
|
KFileItemList *mSelectedMediaItems = nullptr;
|
||
|
KActionCollection *mActionCollection = nullptr;
|
||
|
FilterController *mFilterController = nullptr;
|
||
|
QActionGroup *mSortAction = nullptr;
|
||
|
KToggleAction *mSortDescendingAction = nullptr;
|
||
|
QActionGroup *mThumbnailDetailsActionGroup = nullptr;
|
||
|
PreviewItemDelegate *mDelegate = nullptr;
|
||
|
|
||
|
void setupWidgets()
|
||
|
{
|
||
|
setupUi(q);
|
||
|
q->layout()->setContentsMargins(0, 0, 0, 0);
|
||
|
|
||
|
int margins = q->style()->pixelMetric(QStyle::PM_ToolBarItemMargin) + q->style()->pixelMetric(QStyle::PM_ToolBarFrameWidth);
|
||
|
mStatusBarContainer->layout()->setContentsMargins(margins, margins, margins, margins);
|
||
|
mStatusBarContainer->layout()->setSpacing(q->style()->pixelMetric(QStyle::PM_ToolBarItemSpacing));
|
||
|
|
||
|
// mThumbnailView
|
||
|
mThumbnailView->setModel(mDirModel);
|
||
|
|
||
|
mDelegate = new PreviewItemDelegate(mThumbnailView);
|
||
|
mThumbnailView->setItemDelegate(mDelegate);
|
||
|
mThumbnailView->setSelectionMode(QAbstractItemView::ExtendedSelection);
|
||
|
|
||
|
// mUrlNavigator (use stupid layouting code because KUrlNavigator ctor
|
||
|
// can't be used directly from Designer)
|
||
|
mFilePlacesModel = new KFilePlacesModel(q);
|
||
|
mUrlNavigator = new KUrlNavigator(mFilePlacesModel, QUrl(), mUrlNavigatorContainer);
|
||
|
mUrlNavigatorContainer->setAutoFillBackground(true);
|
||
|
mUrlNavigatorContainer->setBackgroundRole(QPalette::Mid);
|
||
|
auto layout = new QVBoxLayout(mUrlNavigatorContainer);
|
||
|
layout->setContentsMargins(0, 0, 0, 0);
|
||
|
layout->addWidget(mUrlNavigator);
|
||
|
QObject::connect(mUrlNavigator, SIGNAL(urlsDropped(QUrl, QDropEvent *)), q, SLOT(slotUrlsDropped(QUrl, QDropEvent *)));
|
||
|
|
||
|
// FullScreen Toolbar
|
||
|
mFullScreenToolBar->setVisible(false);
|
||
|
mFullScreenToolBar2->setVisible(false);
|
||
|
mFullScreenToolBar->setAutoFillBackground(true);
|
||
|
mFullScreenToolBar2->setAutoFillBackground(true);
|
||
|
mFullScreenToolBar->setBackgroundRole(QPalette::Mid);
|
||
|
mFullScreenToolBar2->setBackgroundRole(QPalette::Mid);
|
||
|
|
||
|
// Thumbnail slider
|
||
|
QObject::connect(mThumbnailSlider, &ZoomSlider::valueChanged, mThumbnailView, &ThumbnailView::setThumbnailWidth);
|
||
|
QObject::connect(mThumbnailView, &ThumbnailView::thumbnailWidthChanged, mThumbnailSlider, &ZoomSlider::setValue);
|
||
|
|
||
|
// Document count label
|
||
|
QMargins labelMargins = mDocumentCountLabel->contentsMargins();
|
||
|
labelMargins.setLeft(15);
|
||
|
labelMargins.setRight(15);
|
||
|
mDocumentCountLabel->setContentsMargins(labelMargins);
|
||
|
}
|
||
|
|
||
|
QAction *thumbnailDetailAction(const QString &text, PreviewItemDelegate::ThumbnailDetail detail)
|
||
|
{
|
||
|
auto action = new QAction(q);
|
||
|
action->setText(text);
|
||
|
action->setCheckable(true);
|
||
|
action->setChecked(GwenviewConfig::thumbnailDetails() & detail);
|
||
|
action->setData(QVariant(detail));
|
||
|
mThumbnailDetailsActionGroup->addAction(action);
|
||
|
QObject::connect(action, SIGNAL(triggered(bool)), q, SLOT(updateThumbnailDetails()));
|
||
|
return action;
|
||
|
}
|
||
|
|
||
|
void setupActions(KActionCollection *actionCollection)
|
||
|
{
|
||
|
auto view = new KActionCategory(i18nc("@title actions category - means actions changing smth in interface", "View"), actionCollection);
|
||
|
QAction *action = view->addAction("edit_location", q, SLOT(editLocation()));
|
||
|
action->setText(i18nc("@action:inmenu Navigation Bar", "Edit Location"));
|
||
|
actionCollection->setDefaultShortcut(action, Qt::Key_F6);
|
||
|
|
||
|
auto sortActionMenu = view->add<KActionMenu>("sort_by");
|
||
|
sortActionMenu->setText(i18nc("@action:inmenu", "Sort By"));
|
||
|
sortActionMenu->setIcon(QIcon::fromTheme(QStringLiteral("view-sort")));
|
||
|
sortActionMenu->setPopupMode(QToolButton::InstantPopup);
|
||
|
|
||
|
mSortAction = new QActionGroup(actionCollection);
|
||
|
action = new QAction(i18nc("@addAction:inmenu", "Name"), mSortAction);
|
||
|
action->setCheckable(true);
|
||
|
action->setData(QVariant(Sorting::Name));
|
||
|
action = new QAction(i18nc("@addAction:inmenu", "Date"), mSortAction);
|
||
|
action->setCheckable(true);
|
||
|
action->setData(QVariant(Sorting::Date));
|
||
|
action = new QAction(i18nc("@addAction:inmenu", "Size"), mSortAction);
|
||
|
action->setCheckable(true);
|
||
|
action->setData(QVariant(Sorting::Size));
|
||
|
#ifndef GWENVIEW_SEMANTICINFO_BACKEND_NONE
|
||
|
action = new QAction(i18nc("@addAction:inmenu", "Rating"), mSortAction);
|
||
|
action->setCheckable(true);
|
||
|
action->setData(QVariant(Sorting::Rating));
|
||
|
#endif
|
||
|
QObject::connect(mSortAction, SIGNAL(triggered(QAction *)), q, SLOT(updateSortOrder()));
|
||
|
|
||
|
mSortDescendingAction = view->add<KToggleAction>(QStringLiteral("sort_desc"));
|
||
|
mSortDescendingAction->setText(i18nc("@action:inmenu Sort", "Descending"));
|
||
|
QObject::connect(mSortDescendingAction, SIGNAL(toggled(bool)), q, SLOT(updateSortOrder()));
|
||
|
|
||
|
for (auto action : mSortAction->actions()) {
|
||
|
sortActionMenu->addAction(action);
|
||
|
}
|
||
|
sortActionMenu->addSeparator();
|
||
|
sortActionMenu->addAction(mSortDescendingAction);
|
||
|
|
||
|
mThumbnailDetailsActionGroup = new QActionGroup(q);
|
||
|
mThumbnailDetailsActionGroup->setExclusive(false);
|
||
|
auto thumbnailDetailsAction = view->add<KActionMenu>(QStringLiteral("thumbnail_details"));
|
||
|
thumbnailDetailsAction->setText(i18nc("@action:inmenu", "Thumbnail Details"));
|
||
|
thumbnailDetailsAction->addAction(thumbnailDetailAction(i18nc("@action:inmenu", "Filename"), PreviewItemDelegate::FileNameDetail));
|
||
|
thumbnailDetailsAction->addAction(thumbnailDetailAction(i18nc("@action:inmenu", "Date"), PreviewItemDelegate::DateDetail));
|
||
|
thumbnailDetailsAction->addAction(thumbnailDetailAction(i18nc("@action:inmenu", "Image Size"), PreviewItemDelegate::ImageSizeDetail));
|
||
|
thumbnailDetailsAction->addAction(thumbnailDetailAction(i18nc("@action:inmenu", "File Size"), PreviewItemDelegate::FileSizeDetail));
|
||
|
#ifndef GWENVIEW_SEMANTICINFO_BACKEND_NONE
|
||
|
thumbnailDetailsAction->addAction(thumbnailDetailAction(i18nc("@action:inmenu", "Rating"), PreviewItemDelegate::RatingDetail));
|
||
|
#endif
|
||
|
|
||
|
auto file = new KActionCategory(i18nc("@title actions category", "File"), actionCollection);
|
||
|
action = file->addAction(QStringLiteral("add_folder_to_places"), q, SLOT(addFolderToPlaces()));
|
||
|
action->setText(i18nc("@action:inmenu", "Add Folder to Places"));
|
||
|
action->setIcon(QIcon::fromTheme(QStringLiteral("bookmark-new")));
|
||
|
}
|
||
|
|
||
|
void setupFilterController()
|
||
|
{
|
||
|
auto menu = new QMenu(mAddFilterButton);
|
||
|
mFilterController = new FilterController(mFilterFrame, mDirModel);
|
||
|
const auto actionList = mFilterController->actionList();
|
||
|
for (QAction *action : actionList) {
|
||
|
menu->addAction(action);
|
||
|
}
|
||
|
mAddFilterButton->setMenu(menu);
|
||
|
}
|
||
|
|
||
|
void setupFullScreenToolBar()
|
||
|
{
|
||
|
mFullScreenToolBar->setIconDimensions(KIconLoader::SizeMedium);
|
||
|
mFullScreenToolBar->setToolButtonStyle(Qt::ToolButtonIconOnly);
|
||
|
mFullScreenToolBar->addAction(mActionCollection->action(QStringLiteral("browse")));
|
||
|
mFullScreenToolBar->addAction(mActionCollection->action(QStringLiteral("view")));
|
||
|
|
||
|
mFullScreenToolBar2->setIconDimensions(KIconLoader::SizeMedium);
|
||
|
mFullScreenToolBar2->setToolButtonStyle(Qt::ToolButtonIconOnly);
|
||
|
mFullScreenToolBar2->addAction(mActionCollection->action(QStringLiteral("leave_fullscreen")));
|
||
|
}
|
||
|
|
||
|
void updateSelectedMediaItems(const QItemSelection &selected, const QItemSelection &deselected)
|
||
|
{
|
||
|
for (auto index : selected.indexes()) {
|
||
|
KFileItem item = mDirModel->itemForIndex(index);
|
||
|
if (!ArchiveUtils::fileItemIsDirOrArchive(item)) {
|
||
|
mSelectedMediaItems->append(item);
|
||
|
}
|
||
|
}
|
||
|
for (auto index : deselected.indexes()) {
|
||
|
KFileItem item = mDirModel->itemForIndex(index);
|
||
|
mSelectedMediaItems->removeOne(item);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void updateDocumentCountLabel()
|
||
|
{
|
||
|
if (mSelectedMediaItems->count() > 1) {
|
||
|
KIO::filesize_t totalSize = 0;
|
||
|
for (const auto &item : *mSelectedMediaItems) {
|
||
|
totalSize += item.size();
|
||
|
}
|
||
|
const QString text = i18nc("@info:status %1 number of selected documents, %2 total number of documents, %3 total filesize of selected documents",
|
||
|
"Selected %1 of %2 (%3)",
|
||
|
mSelectedMediaItems->count(),
|
||
|
mDocumentCountImages + mDocumentCountVideos,
|
||
|
KIO::convertSize(totalSize));
|
||
|
mDocumentCountLabel->setText(text);
|
||
|
} else {
|
||
|
const QString imageText = i18ncp("@info:status Image files", "%1 image", "%1 images", mDocumentCountImages);
|
||
|
const QString videoText = i18ncp("@info:status Video files", "%1 video", "%1 videos", mDocumentCountVideos);
|
||
|
QString labelText;
|
||
|
if (mDocumentCountImages > 0 && mDocumentCountVideos == 0) {
|
||
|
labelText = imageText;
|
||
|
} else if (mDocumentCountImages == 0 && mDocumentCountVideos > 0) {
|
||
|
labelText = videoText;
|
||
|
} else {
|
||
|
labelText = i18nc("@info:status images, videos", "%1, %2", imageText, videoText);
|
||
|
}
|
||
|
mDocumentCountLabel->setText(labelText);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void documentCountsForIndexRange(const QModelIndex &parent, int start, int end, int &imageCountOut, int &videoCountOut)
|
||
|
{
|
||
|
imageCountOut = 0;
|
||
|
videoCountOut = 0;
|
||
|
for (int row = start; row <= end; ++row) {
|
||
|
QModelIndex index = mDirModel->index(row, 0, parent);
|
||
|
KFileItem item = mDirModel->itemForIndex(index);
|
||
|
if (!ArchiveUtils::fileItemIsDirOrArchive(item)) {
|
||
|
MimeTypeUtils::Kind kind = MimeTypeUtils::mimeTypeKind(item.mimetype());
|
||
|
if (kind == MimeTypeUtils::KIND_RASTER_IMAGE || kind == MimeTypeUtils::KIND_SVG_IMAGE) {
|
||
|
imageCountOut++;
|
||
|
} else if (kind == MimeTypeUtils::KIND_VIDEO) {
|
||
|
videoCountOut++;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void updateContextBarActions()
|
||
|
{
|
||
|
PreviewItemDelegate::ContextBarActions actions;
|
||
|
switch (GwenviewConfig::thumbnailActions()) {
|
||
|
case ThumbnailActions::None:
|
||
|
actions = PreviewItemDelegate::NoAction;
|
||
|
break;
|
||
|
case ThumbnailActions::ShowSelectionButtonOnly:
|
||
|
actions = PreviewItemDelegate::SelectionAction;
|
||
|
break;
|
||
|
case ThumbnailActions::AllButtons:
|
||
|
default:
|
||
|
actions = PreviewItemDelegate::SelectionAction | PreviewItemDelegate::RotateAction;
|
||
|
if (!q->window()->isFullScreen()) {
|
||
|
actions |= PreviewItemDelegate::FullScreenAction;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
mDelegate->setContextBarActions(actions);
|
||
|
}
|
||
|
|
||
|
void applyPalette(bool fullScreenmode)
|
||
|
{
|
||
|
q->setPalette(mGvCore->palette(fullScreenmode ? GvCore::FullScreenPalette : GvCore::NormalPalette));
|
||
|
mThumbnailView->setPalette(mGvCore->palette(fullScreenmode ? GvCore::FullScreenViewPalette : GvCore::NormalViewPalette));
|
||
|
}
|
||
|
};
|
||
|
|
||
|
BrowseMainPage::BrowseMainPage(QWidget *parent, KActionCollection *actionCollection, GvCore *gvCore)
|
||
|
: QWidget(parent)
|
||
|
, d(new BrowseMainPagePrivate)
|
||
|
{
|
||
|
d->q = this;
|
||
|
d->mGvCore = gvCore;
|
||
|
d->mDirModel = gvCore->sortedDirModel();
|
||
|
d->mDocumentCountImages = 0;
|
||
|
d->mDocumentCountVideos = 0;
|
||
|
d->mSelectedMediaItems = new KFileItemList;
|
||
|
d->mActionCollection = actionCollection;
|
||
|
d->setupWidgets();
|
||
|
d->setupActions(actionCollection);
|
||
|
d->setupFilterController();
|
||
|
loadConfig();
|
||
|
updateSortOrder();
|
||
|
updateThumbnailDetails();
|
||
|
|
||
|
// Set up connections for document count
|
||
|
connect(d->mDirModel, &SortedDirModel::rowsInserted, this, &BrowseMainPage::slotDirModelRowsInserted);
|
||
|
connect(d->mDirModel, &SortedDirModel::rowsAboutToBeRemoved, this, &BrowseMainPage::slotDirModelRowsAboutToBeRemoved);
|
||
|
connect(d->mDirModel, &SortedDirModel::modelReset, this, &BrowseMainPage::slotDirModelReset);
|
||
|
connect(thumbnailView(), &ThumbnailView::selectionChangedSignal, this, &BrowseMainPage::slotSelectionChanged);
|
||
|
|
||
|
connect(qApp, &QApplication::paletteChanged, this, [this]() {
|
||
|
d->applyPalette(window()->isFullScreen());
|
||
|
});
|
||
|
|
||
|
installEventFilter(this);
|
||
|
}
|
||
|
|
||
|
BrowseMainPage::~BrowseMainPage()
|
||
|
{
|
||
|
d->mSelectedMediaItems->clear();
|
||
|
delete d->mSelectedMediaItems;
|
||
|
delete d;
|
||
|
}
|
||
|
|
||
|
void BrowseMainPage::loadConfig()
|
||
|
{
|
||
|
d->applyPalette(window()->isFullScreen());
|
||
|
d->mUrlNavigator->setUrlEditable(GwenviewConfig::urlNavigatorIsEditable());
|
||
|
d->mUrlNavigator->setShowFullPath(GwenviewConfig::urlNavigatorShowFullPath());
|
||
|
|
||
|
d->mThumbnailSlider->setValue(GwenviewConfig::thumbnailSize());
|
||
|
d->mThumbnailSlider->updateToolTip();
|
||
|
// If GwenviewConfig::thumbnailSize() returns the current value of
|
||
|
// mThumbnailSlider, it won't emit valueChanged() and the thumbnail view
|
||
|
// won't be updated. That's why we do it ourself.
|
||
|
d->mThumbnailView->setThumbnailAspectRatio(GwenviewConfig::thumbnailAspectRatio());
|
||
|
d->mThumbnailView->setThumbnailWidth(GwenviewConfig::thumbnailSize());
|
||
|
|
||
|
const auto actionsList = d->mSortAction->actions();
|
||
|
for (QAction *action : actionsList) {
|
||
|
if (sortingFromSortAction(action) == GwenviewConfig::sorting()) {
|
||
|
action->setChecked(true);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
d->mSortDescendingAction->setChecked(GwenviewConfig::sortDescending());
|
||
|
|
||
|
d->updateContextBarActions();
|
||
|
}
|
||
|
|
||
|
void BrowseMainPage::saveConfig() const
|
||
|
{
|
||
|
GwenviewConfig::setUrlNavigatorIsEditable(d->mUrlNavigator->isUrlEditable());
|
||
|
GwenviewConfig::setUrlNavigatorShowFullPath(d->mUrlNavigator->showFullPath());
|
||
|
GwenviewConfig::setThumbnailSize(d->mThumbnailSlider->value());
|
||
|
GwenviewConfig::setSorting(sortingFromSortAction(d->mSortAction->checkedAction()));
|
||
|
GwenviewConfig::setSortDescending(d->mSortDescendingAction->isChecked());
|
||
|
GwenviewConfig::setThumbnailDetails(d->mDelegate->thumbnailDetails());
|
||
|
}
|
||
|
|
||
|
bool BrowseMainPage::eventFilter(QObject *watched, QEvent *event)
|
||
|
{
|
||
|
// Leave fullscreen when not viewing an image
|
||
|
if (window()->isFullScreen() && event->type() == QEvent::ShortcutOverride) {
|
||
|
const QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
|
||
|
if (keyEvent->key() == Qt::Key_Escape) {
|
||
|
d->mActionCollection->action(QStringLiteral("leave_fullscreen"))->trigger();
|
||
|
event->accept();
|
||
|
}
|
||
|
}
|
||
|
return QWidget::eventFilter(watched, event);
|
||
|
}
|
||
|
|
||
|
void BrowseMainPage::mousePressEvent(QMouseEvent *event)
|
||
|
{
|
||
|
switch (event->button()) {
|
||
|
case Qt::ForwardButton:
|
||
|
case Qt::BackButton:
|
||
|
return;
|
||
|
default:
|
||
|
QWidget::mousePressEvent(event);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ThumbnailView *BrowseMainPage::thumbnailView() const
|
||
|
{
|
||
|
return d->mThumbnailView;
|
||
|
}
|
||
|
|
||
|
KUrlNavigator *BrowseMainPage::urlNavigator() const
|
||
|
{
|
||
|
return d->mUrlNavigator;
|
||
|
}
|
||
|
|
||
|
void BrowseMainPage::reload()
|
||
|
{
|
||
|
const QModelIndexList list = d->mThumbnailView->selectionModel()->selectedIndexes();
|
||
|
for (const QModelIndex &index : list) {
|
||
|
d->mThumbnailView->reloadThumbnail(index);
|
||
|
}
|
||
|
d->mDirModel->reload();
|
||
|
}
|
||
|
|
||
|
void BrowseMainPage::editLocation()
|
||
|
{
|
||
|
d->mUrlNavigator->setUrlEditable(true);
|
||
|
d->mUrlNavigator->setFocus();
|
||
|
}
|
||
|
|
||
|
void BrowseMainPage::addFolderToPlaces()
|
||
|
{
|
||
|
QUrl url = d->mUrlNavigator->locationUrl();
|
||
|
QString text = url.adjusted(QUrl::StripTrailingSlash).fileName();
|
||
|
if (text.isEmpty()) {
|
||
|
text = url.toDisplayString();
|
||
|
}
|
||
|
d->mFilePlacesModel->addPlace(text, url);
|
||
|
}
|
||
|
|
||
|
void BrowseMainPage::slotDirModelRowsInserted(const QModelIndex &parent, int start, int end)
|
||
|
{
|
||
|
int imageCount;
|
||
|
int videoCount;
|
||
|
d->documentCountsForIndexRange(parent, start, end, imageCount, videoCount);
|
||
|
if (imageCount > 0 || videoCount > 0) {
|
||
|
d->mDocumentCountImages += imageCount;
|
||
|
d->mDocumentCountVideos += videoCount;
|
||
|
d->updateDocumentCountLabel();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void BrowseMainPage::slotDirModelRowsAboutToBeRemoved(const QModelIndex &parent, int start, int end)
|
||
|
{
|
||
|
int imageCount;
|
||
|
int videoCount;
|
||
|
d->documentCountsForIndexRange(parent, start, end, imageCount, videoCount);
|
||
|
if (imageCount > 0 || videoCount > 0) {
|
||
|
d->mDocumentCountImages -= imageCount;
|
||
|
d->mDocumentCountVideos -= videoCount;
|
||
|
d->updateDocumentCountLabel();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void BrowseMainPage::slotDirModelReset()
|
||
|
{
|
||
|
d->mDocumentCountImages = 0;
|
||
|
d->mDocumentCountVideos = 0;
|
||
|
d->mSelectedMediaItems->clear();
|
||
|
d->updateDocumentCountLabel();
|
||
|
}
|
||
|
|
||
|
void BrowseMainPage::slotSelectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
|
||
|
{
|
||
|
d->updateSelectedMediaItems(selected, deselected);
|
||
|
d->updateDocumentCountLabel();
|
||
|
}
|
||
|
|
||
|
void BrowseMainPage::updateSortOrder()
|
||
|
{
|
||
|
const QAction *action = d->mSortAction->checkedAction();
|
||
|
GV_RETURN_IF_FAIL(action);
|
||
|
|
||
|
const Qt::SortOrder order = d->mSortDescendingAction->isChecked() ? Qt::DescendingOrder : Qt::AscendingOrder;
|
||
|
KDirModel::ModelColumns column = KDirModel::Name;
|
||
|
int sortRole = Qt::DisplayRole;
|
||
|
|
||
|
// Map Sorting::Enum to model columns and sorting roles
|
||
|
switch (sortingFromSortAction(action)) {
|
||
|
case Sorting::Name:
|
||
|
column = KDirModel::Name;
|
||
|
break;
|
||
|
case Sorting::Size:
|
||
|
column = KDirModel::Size;
|
||
|
break;
|
||
|
case Sorting::Date:
|
||
|
column = KDirModel::ModifiedTime;
|
||
|
break;
|
||
|
#ifndef GWENVIEW_SEMANTICINFO_BACKEND_NONE
|
||
|
case Sorting::Rating:
|
||
|
column = KDirModel::Name;
|
||
|
sortRole = SemanticInfoDirModel::RatingRole;
|
||
|
break;
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
d->mDirModel->setSortRole(sortRole);
|
||
|
d->mDirModel->sort(column, order);
|
||
|
d->mGvCore->setTrackFileManagerSorting(false);
|
||
|
}
|
||
|
|
||
|
void BrowseMainPage::updateThumbnailDetails()
|
||
|
{
|
||
|
PreviewItemDelegate::ThumbnailDetails details = {};
|
||
|
const auto actionList = d->mThumbnailDetailsActionGroup->actions();
|
||
|
for (const QAction *action : actionList) {
|
||
|
if (action->isChecked()) {
|
||
|
details |= PreviewItemDelegate::ThumbnailDetail(action->data().toInt());
|
||
|
}
|
||
|
}
|
||
|
d->mDelegate->setThumbnailDetails(details);
|
||
|
}
|
||
|
|
||
|
void BrowseMainPage::setFullScreenMode(bool fullScreen)
|
||
|
{
|
||
|
d->applyPalette(fullScreen);
|
||
|
d->mUrlNavigatorContainer->setContentsMargins(fullScreen ? 6 : 0, 0, 0, 0);
|
||
|
d->updateContextBarActions();
|
||
|
|
||
|
d->mFullScreenToolBar->setVisible(fullScreen);
|
||
|
d->mFullScreenToolBar2->setVisible(fullScreen);
|
||
|
if (fullScreen && d->mFullScreenToolBar->actions().isEmpty()) {
|
||
|
d->setupFullScreenToolBar();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void BrowseMainPage::setStatusBarVisible(bool visible)
|
||
|
{
|
||
|
d->mStatusBarContainer->setVisible(visible);
|
||
|
}
|
||
|
|
||
|
void BrowseMainPage::slotUrlsDropped(const QUrl &destUrl, QDropEvent *event)
|
||
|
{
|
||
|
const QList<QUrl> urlList = KUrlMimeData::urlsFromMimeData(event->mimeData());
|
||
|
if (urlList.isEmpty()) {
|
||
|
return;
|
||
|
}
|
||
|
event->acceptProposedAction();
|
||
|
|
||
|
// We can't call FileOperations::showMenuForDroppedUrls() directly because
|
||
|
// we need the slot to return so that the drop event is accepted. Otherwise
|
||
|
// the drop cursor is still visible when the menu is shown.
|
||
|
QMetaObject::invokeMethod(
|
||
|
this,
|
||
|
[this, urlList, destUrl]() {
|
||
|
showMenuForDroppedUrls(urlList, destUrl);
|
||
|
},
|
||
|
Qt::QueuedConnection);
|
||
|
}
|
||
|
|
||
|
void BrowseMainPage::showMenuForDroppedUrls(const QList<QUrl> &urlList, const QUrl &destUrl)
|
||
|
{
|
||
|
FileOperations::showMenuForDroppedUrls(d->mUrlNavigator, urlList, destUrl);
|
||
|
}
|
||
|
|
||
|
QToolButton *BrowseMainPage::toggleSideBarButton() const
|
||
|
{
|
||
|
return d->mToggleSideBarButton;
|
||
|
}
|
||
|
|
||
|
} // namespace
|
||
|
|
||
|
#include "moc_browsemainpage.cpp"
|