// vim: set tabstop=4 shiftwidth=4 expandtab: /* Gwenview: an image viewer Copyright 2008 Aurélien Gâteau 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 "startmainpage.h" #include // Qt #include #include #ifdef GTK_WORKAROUND_BROKE_IN_KF5_PORT #include #endif #include #include // KF #include #include // Local #include "gwenview_app_debug.h" #include #include #include #include #include #include #include #include #include #include #ifndef GWENVIEW_SEMANTICINFO_BACKEND_NONE #include #endif namespace Gwenview { class HistoryThumbnailViewHelper : public AbstractThumbnailViewHelper { public: HistoryThumbnailViewHelper(QObject *parent) : AbstractThumbnailViewHelper(parent) { } void showContextMenu(QWidget *) override { } void showMenuForUrlDroppedOnViewport(QWidget *, const QList &) override { } void showMenuForUrlDroppedOnDir(QWidget *, const QList &, const QUrl &) override { } }; struct StartMainPagePrivate : public Ui_StartMainPage { StartMainPage *q = nullptr; GvCore *mGvCore = nullptr; KFilePlacesModel *mBookmarksModel = nullptr; ThumbnailProvider *mRecentFilesThumbnailProvider = nullptr; bool mSearchUiInitialized; void setupSearchUi() { #ifdef GWENVIEW_SEMANTICINFO_BACKEND_BALOO mTagView->setModel(TagModel::createAllTagsModel(mTagView, mGvCore->semanticInfoBackEnd())); mTagView->show(); mTagLabel->hide(); #else mTagView->hide(); mTagLabel->hide(); #endif } void updateHistoryTab() { mHistoryWidget->setVisible(GwenviewConfig::historyEnabled()); mHistoryDisabledLabel->setVisible(!GwenviewConfig::historyEnabled()); } void setupHistoryView(ThumbnailView *view) { view->setThumbnailViewHelper(new HistoryThumbnailViewHelper(view)); auto delegate = new PreviewItemDelegate(view); delegate->setContextBarActions(PreviewItemDelegate::NoAction); delegate->setTextElideMode(Qt::ElideLeft); view->setItemDelegate(delegate); view->setThumbnailWidth(128); view->setCreateThumbnailsForRemoteUrls(false); QModelIndex index = view->model()->index(0, 0); if (index.isValid()) { view->setCurrentIndex(index); } } }; static void initViewPalette(QAbstractItemView *view, const QColor &fgColor) { QWidget *viewport = view->viewport(); QPalette palette = viewport->palette(); palette.setColor(viewport->backgroundRole(), Qt::transparent); palette.setColor(QPalette::WindowText, fgColor); palette.setColor(QPalette::Text, fgColor); // QListView uses QStyledItemDelegate, which uses the view palette for // foreground color, while KFilePlacesView uses the viewport palette. viewport->setPalette(palette); view->setPalette(palette); } static bool styleIsGtkBased() { const char *name = QApplication::style()->metaObject()->className(); return qstrcmp(name, "QGtkStyle") == 0; } StartMainPage::StartMainPage(QWidget *parent, GvCore *gvCore) : QFrame(parent) , d(new StartMainPagePrivate) { d->mRecentFilesThumbnailProvider = nullptr; d->q = this; d->mGvCore = gvCore; d->mSearchUiInitialized = false; d->setupUi(this); if (styleIsGtkBased()) { #ifdef GTK_WORKAROUND_BROKE_IN_KF5_PORT // Gtk-based styles do not apply the correct background color on tabs. // As a workaround, use the Plastique style instead. QStyle *fix = new QPlastiqueStyle(); fix->setParent(this); d->mHistoryWidget->tabBar()->setStyle(fix); d->mPlacesTagsWidget->tabBar()->setStyle(fix); #endif } setFrameStyle(QFrame::NoFrame); // Bookmark view d->mBookmarksModel = new KFilePlacesModel(this); d->mBookmarksView->setModel(d->mBookmarksModel); d->mBookmarksView->setAutoResizeItemsEnabled(false); connect(d->mBookmarksView, &KFilePlacesView::urlChanged, this, &StartMainPage::urlSelected); // Tag view connect(d->mTagView, &QListView::clicked, this, &StartMainPage::slotTagViewClicked); // Recent folders view connect(d->mRecentFoldersView, &Gwenview::ThumbnailView::indexActivated, this, &StartMainPage::slotListViewActivated); connect(d->mRecentFoldersView, &Gwenview::ThumbnailView::customContextMenuRequested, this, &StartMainPage::showContextMenu); // Recent files view connect(d->mRecentFilesView, &Gwenview::ThumbnailView::indexActivated, this, &StartMainPage::slotListViewActivated); connect(d->mRecentFilesView, &Gwenview::ThumbnailView::customContextMenuRequested, this, &StartMainPage::showContextMenu); d->updateHistoryTab(); connect(GwenviewConfig::self(), &GwenviewConfig::configChanged, this, &StartMainPage::loadConfig); connect(qApp, &QApplication::paletteChanged, this, [this]() { applyPalette(d->mGvCore->palette(GvCore::NormalViewPalette)); }); d->mRecentFoldersView->setFocus(); ScrollerUtils::setQScroller(d->mBookmarksView->viewport()); d->mBookmarksView->viewport()->installEventFilter(this); } StartMainPage::~StartMainPage() { delete d->mRecentFilesThumbnailProvider; delete d; } bool StartMainPage::eventFilter(QObject *, QEvent *event) { if (event->type() == QEvent::MouseMove) { auto mouseEvent = static_cast(event); if (mouseEvent->source() == Qt::MouseEventSynthesizedByQt) { return true; } } return false; } void StartMainPage::slotTagViewClicked(const QModelIndex &index) { #ifdef GWENVIEW_SEMANTICINFO_BACKEND_BALOO if (!index.isValid()) { return; } // FIXME: Check label encoding const QString tag = index.data().toString(); Q_EMIT urlSelected(QUrl("tags:/" + tag)); #endif } void StartMainPage::applyPalette(const QPalette &newPalette) { QColor fgColor = newPalette.text().color(); QPalette pal = palette(); pal.setBrush(backgroundRole(), newPalette.base()); pal.setBrush(QPalette::Button, newPalette.base()); pal.setBrush(QPalette::WindowText, fgColor); pal.setBrush(QPalette::ButtonText, fgColor); pal.setBrush(QPalette::Text, fgColor); setPalette(pal); initViewPalette(d->mBookmarksView, fgColor); initViewPalette(d->mTagView, fgColor); initViewPalette(d->mRecentFoldersView, fgColor); initViewPalette(d->mRecentFilesView, fgColor); } void StartMainPage::slotListViewActivated(const QModelIndex &index) { if (!index.isValid()) { return; } QVariant data = index.data(KFilePlacesModel::UrlRole); QUrl url = data.toUrl(); // Prevent dir lister error if (!url.isValid()) { qCCritical(GWENVIEW_APP_LOG) << "Tried to open an invalid url"; return; } Q_EMIT urlSelected(url); } void StartMainPage::showEvent(QShowEvent *event) { if (GwenviewConfig::historyEnabled()) { if (!d->mRecentFoldersView->model()) { d->mRecentFoldersView->setModel(d->mGvCore->recentFoldersModel()); d->setupHistoryView(d->mRecentFoldersView); } if (!d->mRecentFilesView->model()) { d->mRecentFilesView->setModel(d->mGvCore->recentFilesModel()); d->mRecentFilesThumbnailProvider = new ThumbnailProvider(); d->mRecentFilesView->setThumbnailProvider(d->mRecentFilesThumbnailProvider); d->setupHistoryView(d->mRecentFilesView); } } if (!d->mSearchUiInitialized) { d->mSearchUiInitialized = true; d->setupSearchUi(); } QFrame::showEvent(event); } void StartMainPage::showContextMenu(const QPoint &pos) { // Create menu DialogGuard menu(this); QAction *addAction = menu->addAction(QIcon::fromTheme(QStringLiteral("bookmark-new")), QString()); QAction *forgetAction = menu->addAction(QIcon::fromTheme(QStringLiteral("edit-delete")), QString()); menu->addSeparator(); QAction *forgetAllAction = menu->addAction(QIcon::fromTheme(QStringLiteral("edit-delete-all")), QString()); if (d->mHistoryWidget->currentWidget() == d->mRecentFoldersTab) { addAction->setText(i18nc("@action Recent Folders view", "Add Folder to Places")); forgetAction->setText(i18nc("@action Recent Folders view", "Forget This Folder")); forgetAllAction->setText(i18nc("@action Recent Folders view", "Forget All Folders")); } else if (d->mHistoryWidget->currentWidget() == d->mRecentFilesTab) { addAction->setText(i18nc("@action Recent Files view", "Add Containing Folder to Places")); forgetAction->setText(i18nc("@action Recent Files view", "Forget This File")); forgetAllAction->setText(i18nc("@action Recent Files view", "Forget All Files")); } else { GV_WARN_AND_RETURN("Context menu not implemented on this tab page"); } const QAbstractItemView *view = qobject_cast(sender()); const QModelIndex index = view->indexAt(pos); addAction->setEnabled(index.isValid()); forgetAction->setEnabled(index.isValid()); // Handle menu const QAction *action = menu->exec(view->mapToGlobal(pos)); if (!action) { return; } const QVariant data = index.data(KFilePlacesModel::UrlRole); QUrl url = data.toUrl(); if (action == addAction) { if (d->mHistoryWidget->currentWidget() == d->mRecentFilesTab) { url = url.adjusted(QUrl::RemoveFilename); } QString text = url.adjusted(QUrl::StripTrailingSlash).fileName(); if (text.isEmpty()) { text = url.toDisplayString(); } d->mBookmarksModel->addPlace(text, url); } else if (action == forgetAction) { view->model()->removeRow(index.row()); if (d->mHistoryWidget->currentWidget() == d->mRecentFilesTab) { Q_EMIT recentFileRemoved(url); } } else if (action == forgetAllAction) { view->model()->removeRows(0, view->model()->rowCount()); if (d->mHistoryWidget->currentWidget() == d->mRecentFilesTab) { Q_EMIT recentFilesCleared(); } } } void StartMainPage::loadConfig() { d->updateHistoryTab(); applyPalette(d->mGvCore->palette(GvCore::NormalViewPalette)); } ThumbnailView *StartMainPage::recentFoldersView() const { return d->mRecentFoldersView; } } // namespace #include "moc_startmainpage.cpp"