kde-extraapps/gwenview/app/mainwindow.cpp
Ivailo Monev 6876731c65 generic: drop Kipi support
Signed-off-by: Ivailo Monev <xakepa10@gmail.com>
2021-08-04 02:10:23 +03:00

1547 lines
52 KiB
C++

/*
Gwenview: an image viewer
Copyright 2007 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, Boston, MA 02110-1301, USA.
*/
#include "moc_mainwindow.cpp"
// Qt
#include <QApplication>
#include <QDateTime>
#include <QDesktopWidget>
#include <QLabel>
#include <QPushButton>
#include <QShortcut>
#include <QSlider>
#include <QSplitter>
#include <QStackedWidget>
#include <QTimer>
#include <QUndoGroup>
#include <QVBoxLayout>
#include <QMenuBar>
// KDE
#include <KIO/NetAccess>
#include <KActionCategory>
#include <KActionCollection>
#include <KAction>
#include <KApplication>
#include <KDirLister>
#include <KEditToolBar>
#include <KFileDialog>
#include <KFileItem>
#include <KLocale>
#include <KMessageBox>
#include <KNotificationRestrictions>
#include <KProtocolManager>
#include <KLinkItemSelectionModel>
#include <KRecentFilesAction>
#include <KStatusBar>
#include <KStandardDirs>
#include <KStandardGuiItem>
#include <KStandardShortcut>
#include <KToggleFullScreenAction>
#include <KToolBar>
#include <KUrl>
#include <KUrlNavigator>
#include <KXMLGUIFactory>
#include <KWindowSystem>
// Local
#include "configdialog.h"
#include "documentinfoprovider.h"
#include "viewmainpage.h"
#include "fileopscontextmanageritem.h"
#include "folderviewcontextmanageritem.h"
#include "fullscreencontent.h"
#include "gvcore.h"
#include "imageopscontextmanageritem.h"
#include "infocontextmanageritem.h"
#include "preloader.h"
#include "savebar.h"
#include "sidebar.h"
#include "splitter.h"
#include "startmainpage.h"
#include "thumbnailviewhelper.h"
#include "browsemainpage.h"
#include <lib/hud/hudbuttonbox.h>
#include <lib/contextmanager.h>
#include <lib/disabledactionshortcutmonitor.h>
#include <lib/document/documentfactory.h>
#include <lib/documentonlyproxymodel.h>
#include <lib/eventwatcher.h>
#include <lib/gvdebug.h>
#include <lib/gwenviewconfig.h>
#include <lib/mimetypeutils.h>
#include <lib/print/printhelper.h>
#include <lib/slideshow.h>
#include <lib/signalblocker.h>
#include <lib/sorteddirmodel.h>
#include <lib/thumbnailview/thumbnailbarview.h>
#include <lib/thumbnailview/thumbnailview.h>
#include <lib/urlutils.h>
namespace Gwenview
{
#undef ENABLE_LOG
#undef LOG
//#define ENABLE_LOG
#ifdef ENABLE_LOG
#define LOG(x) kDebug() << x
#else
#define LOG(x) ;
#endif
static const int BROWSE_PRELOAD_DELAY = 1000;
static const int VIEW_PRELOAD_DELAY = 100;
static const char* BROWSE_MODE_SIDE_BAR_GROUP = "SideBar-BrowseMode";
static const char* VIEW_MODE_SIDE_BAR_GROUP = "SideBar-ViewMode";
static const char* FULLSCREEN_MODE_SIDE_BAR_GROUP = "SideBar-FullScreenMode";
static const char* SIDE_BAR_IS_VISIBLE_KEY = "IsVisible";
static const char* SESSION_CURRENT_PAGE_KEY = "Page";
static const char* SESSION_URL_KEY = "Url";
enum MainPageId {
StartMainPageId,
BrowseMainPageId,
ViewMainPageId
};
struct MainWindowState
{
bool mToolBarVisible;
Qt::WindowStates mWindowState;
};
/*
Layout of the main window looks like this:
.-mCentralSplitter-----------------------------.
|.-mSideBar--. .-mContentWidget---------------.|
|| | |.-mSaveBar-------------------.||
|| | || |||
|| | |'----------------------------'||
|| | |.-mViewStackedWidget---------.||
|| | || |||
|| | || |||
|| | || |||
|| | || |||
|| | |'----------------------------'||
|'-----------' '------------------------------'|
'----------------------------------------------'
*/
struct MainWindow::Private
{
GvCore* mGvCore;
MainWindow* q;
QSplitter* mCentralSplitter;
QWidget* mContentWidget;
ViewMainPage* mViewMainPage;
KUrlNavigator* mUrlNavigator;
ThumbnailView* mThumbnailView;
ThumbnailView* mActiveThumbnailView;
DocumentInfoProvider* mDocumentInfoProvider;
ThumbnailViewHelper* mThumbnailViewHelper;
BrowseMainPage* mBrowseMainPage;
StartMainPage* mStartMainPage;
SideBar* mSideBar;
QStackedWidget* mViewStackedWidget;
FullScreenContent* mFullScreenContent;
SaveBar* mSaveBar;
bool mStartSlideShowWhenDirListerCompleted;
SlideShow* mSlideShow;
Preloader* mPreloader;
bool mPreloadDirectionIsForward;
QActionGroup* mViewModeActionGroup;
KRecentFilesAction* mFileOpenRecentAction;
KAction* mBrowseAction;
KAction* mViewAction;
KAction* mGoUpAction;
KAction* mGoToPreviousAction;
KAction* mGoToNextAction;
KAction* mGoToFirstAction;
KAction* mGoToLastAction;
KToggleAction* mToggleSideBarAction;
KToggleFullScreenAction* mFullScreenAction;
KAction* mToggleSlideShowAction;
KToggleAction* mShowMenuBarAction;
SortedDirModel* mDirModel;
DocumentOnlyProxyModel* mThumbnailBarModel;
KLinkItemSelectionModel* mThumbnailBarSelectionModel;
ContextManager* mContextManager;
MainWindowState mStateBeforeFullScreen;
QString mCaption;
MainPageId mCurrentMainPageId;
QDateTime mFullScreenLeftAt;
KNotificationRestrictions* mNotificationRestrictions;
void setupContextManager()
{
mContextManager = new ContextManager(mDirModel, q);
connect(mContextManager, SIGNAL(selectionChanged()),
q, SLOT(slotSelectionChanged()));
connect(mContextManager, SIGNAL(currentDirUrlChanged(KUrl)),
q, SLOT(slotCurrentDirUrlChanged(KUrl)));
}
void setupWidgets()
{
mFullScreenContent = new FullScreenContent(q);
connect(mContextManager, SIGNAL(currentUrlChanged(KUrl)), mFullScreenContent, SLOT(setCurrentUrl(KUrl)));
mCentralSplitter = new Splitter(Qt::Horizontal, q);
q->setCentralWidget(mCentralSplitter);
// Left side of splitter
mSideBar = new SideBar(mCentralSplitter);
EventWatcher::install(mSideBar, QList<QEvent::Type>() << QEvent::Show << QEvent::Hide,
q, SLOT(updateToggleSideBarAction()));
// Right side of splitter
mContentWidget = new QWidget(mCentralSplitter);
mSaveBar = new SaveBar(mContentWidget, q->actionCollection());
connect(mContextManager, SIGNAL(currentUrlChanged(KUrl)), mSaveBar, SLOT(setCurrentUrl(KUrl)));
mViewStackedWidget = new QStackedWidget(mContentWidget);
QVBoxLayout* layout = new QVBoxLayout(mContentWidget);
layout->addWidget(mSaveBar);
layout->addWidget(mViewStackedWidget);
layout->setMargin(0);
layout->setSpacing(0);
////
mStartSlideShowWhenDirListerCompleted = false;
mSlideShow = new SlideShow(q);
connect(mContextManager, SIGNAL(currentUrlChanged(KUrl)), mSlideShow, SLOT(setCurrentUrl(KUrl)));
setupThumbnailView(mViewStackedWidget);
setupViewMainPage(mViewStackedWidget);
setupStartMainPage(mViewStackedWidget);
mViewStackedWidget->addWidget(mBrowseMainPage);
mViewStackedWidget->addWidget(mViewMainPage);
mViewStackedWidget->addWidget(mStartMainPage);
mViewStackedWidget->setCurrentWidget(mBrowseMainPage);
mCentralSplitter->setStretchFactor(0, 0);
mCentralSplitter->setStretchFactor(1, 1);
connect(mSaveBar, SIGNAL(requestSaveAll()),
mGvCore, SLOT(saveAll()));
connect(mSaveBar, SIGNAL(goToUrl(KUrl)),
q, SLOT(goToUrl(KUrl)));
connect(mSlideShow, SIGNAL(goToUrl(KUrl)),
q, SLOT(goToUrl(KUrl)));
}
void setupThumbnailView(QWidget* parent)
{
Q_ASSERT(mContextManager);
mBrowseMainPage = new BrowseMainPage(parent, q->actionCollection(), mGvCore);
mThumbnailView = mBrowseMainPage->thumbnailView();
mThumbnailView->setSelectionModel(mContextManager->selectionModel());
mUrlNavigator = mBrowseMainPage->urlNavigator();
mDocumentInfoProvider = new DocumentInfoProvider(mDirModel);
mThumbnailView->setDocumentInfoProvider(mDocumentInfoProvider);
mThumbnailViewHelper = new ThumbnailViewHelper(mDirModel, q->actionCollection());
connect(mContextManager, SIGNAL(currentDirUrlChanged(KUrl)),
mThumbnailViewHelper, SLOT(setCurrentDirUrl(KUrl)));
mThumbnailView->setThumbnailViewHelper(mThumbnailViewHelper);
mThumbnailBarSelectionModel = new KLinkItemSelectionModel(mThumbnailBarModel, mContextManager->selectionModel(), q);
// Connect thumbnail view
connect(mThumbnailView, SIGNAL(indexActivated(QModelIndex)),
q, SLOT(slotThumbnailViewIndexActivated(QModelIndex)));
// Connect delegate
QAbstractItemDelegate* delegate = mThumbnailView->itemDelegate();
connect(delegate, SIGNAL(saveDocumentRequested(KUrl)),
mGvCore, SLOT(save(KUrl)));
connect(delegate, SIGNAL(rotateDocumentLeftRequested(KUrl)),
mGvCore, SLOT(rotateLeft(KUrl)));
connect(delegate, SIGNAL(rotateDocumentRightRequested(KUrl)),
mGvCore, SLOT(rotateRight(KUrl)));
connect(delegate, SIGNAL(showDocumentInFullScreenRequested(KUrl)),
q, SLOT(showDocumentInFullScreen(KUrl)));
// Connect url navigator
connect(mUrlNavigator, SIGNAL(urlChanged(KUrl)),
q, SLOT(openDirUrl(KUrl)));
}
void setupViewMainPage(QWidget* parent)
{
mViewMainPage = new ViewMainPage(parent, mSlideShow, q->actionCollection(), mGvCore);
connect(mViewMainPage, SIGNAL(captionUpdateRequested(QString)),
q, SLOT(setCaption(QString)));
connect(mViewMainPage, SIGNAL(completed()),
q, SLOT(slotPartCompleted()));
connect(mViewMainPage, SIGNAL(previousImageRequested()),
q, SLOT(goToPrevious()));
connect(mViewMainPage, SIGNAL(nextImageRequested()),
q, SLOT(goToNext()));
setupThumbnailBar(mViewMainPage->thumbnailBar());
}
void setupThumbnailBar(ThumbnailView* bar)
{
Q_ASSERT(mThumbnailBarModel);
Q_ASSERT(mThumbnailBarSelectionModel);
Q_ASSERT(mDocumentInfoProvider);
Q_ASSERT(mThumbnailViewHelper);
bar->setModel(mThumbnailBarModel);
bar->setSelectionModel(mThumbnailBarSelectionModel);
bar->setDocumentInfoProvider(mDocumentInfoProvider);
bar->setThumbnailViewHelper(mThumbnailViewHelper);
}
void setupStartMainPage(QWidget* parent)
{
mStartMainPage = new StartMainPage(parent, mGvCore);
connect(mStartMainPage, SIGNAL(urlSelected(KUrl)),
q, SLOT(slotStartMainPageUrlSelected(KUrl)));
}
void installDisabledActionShortcutMonitor(QAction* action, const char* slot)
{
DisabledActionShortcutMonitor* monitor = new DisabledActionShortcutMonitor(action, q);
connect(monitor, SIGNAL(activated()), q, slot);
}
void setupActions()
{
KActionCollection* actionCollection = q->actionCollection();
KActionCategory* file = new KActionCategory(i18nc("@title actions category", "File"), actionCollection);
KActionCategory* view = new KActionCategory(i18nc("@title actions category - means actions changing smth in interface", "View"), actionCollection);
file->addAction(KStandardAction::Save, q, SLOT(saveCurrent()));
file->addAction(KStandardAction::SaveAs, q, SLOT(saveCurrentAs()));
file->addAction(KStandardAction::Open, q, SLOT(openFile()));
mFileOpenRecentAction = KStandardAction::openRecent(q, SLOT(openUrl(KUrl)), q);
file->addAction("file_open_recent", mFileOpenRecentAction);
file->addAction(KStandardAction::Print, q, SLOT(print()));
file->addAction(KStandardAction::Quit, KApplication::kApplication(), SLOT(closeAllWindows()));
KAction* action = file->addAction("reload", q, SLOT(reload()));
action->setText(i18nc("@action reload the currently viewed image", "Reload"));
action->setIcon(KIcon("view-refresh"));
action->setShortcut(Qt::Key_F5);
mBrowseAction = view->addAction("browse");
mBrowseAction->setText(i18nc("@action:intoolbar Switch to file list", "Browse"));
mBrowseAction->setToolTip(i18nc("@info:tooltip", "Browse folders for images"));
mBrowseAction->setCheckable(true);
mBrowseAction->setIcon(KIcon("view-list-icons"));
mBrowseAction->setShortcut(Qt::Key_Escape);
connect(mViewMainPage, SIGNAL(goToBrowseModeRequested()),
mBrowseAction, SLOT(trigger()));
mViewAction = view->addAction("view");
mViewAction->setText(i18nc("@action:intoolbar Switch to image view", "View"));
mViewAction->setToolTip(i18nc("@info:tooltip", "View selected images"));
mViewAction->setIcon(KIcon("view-preview"));
mViewAction->setCheckable(true);
mViewModeActionGroup = new QActionGroup(q);
mViewModeActionGroup->addAction(mBrowseAction);
mViewModeActionGroup->addAction(mViewAction);
connect(mViewModeActionGroup, SIGNAL(triggered(QAction*)),
q, SLOT(setActiveViewModeAction(QAction*)));
mFullScreenAction = static_cast<KToggleFullScreenAction*>(view->addAction(KStandardAction::FullScreen, q, SLOT(toggleFullScreen(bool))));
KShortcut shortcut = mFullScreenAction->shortcut();
if (shortcut.alternate().isEmpty()) {
shortcut.setAlternate(Qt::Key_F11);
}
mFullScreenAction->setShortcut(shortcut);
connect(mViewMainPage, SIGNAL(toggleFullScreenRequested()),
mFullScreenAction, SLOT(trigger()));
KAction* leaveFullScreenAction = view->addAction("leave_fullscreen", q, SLOT(leaveFullScreen()));
leaveFullScreenAction->setIcon(KIcon("view-restore"));
leaveFullScreenAction->setPriority(QAction::LowPriority);
leaveFullScreenAction->setText(i18nc("@action", "Leave Fullscreen Mode"));
mGoToPreviousAction = view->addAction("go_previous", q, SLOT(goToPrevious()));
mGoToPreviousAction->setPriority(QAction::LowPriority);
mGoToPreviousAction->setIcon(KIcon("media-skip-backward"));
mGoToPreviousAction->setText(i18nc("@action Go to previous image", "Previous"));
mGoToPreviousAction->setToolTip(i18nc("@info:tooltip", "Go to previous image"));
mGoToPreviousAction->setShortcut(Qt::Key_Backspace);
installDisabledActionShortcutMonitor(mGoToPreviousAction, SLOT(showFirstDocumentReached()));
mGoToNextAction = view->addAction("go_next", q, SLOT(goToNext()));
mGoToNextAction->setPriority(QAction::LowPriority);
mGoToNextAction->setIcon(KIcon("media-skip-forward"));
mGoToNextAction->setText(i18nc("@action Go to next image", "Next"));
mGoToNextAction->setToolTip(i18nc("@info:tooltip", "Go to next image"));
mGoToNextAction->setShortcut(Qt::Key_Space);
installDisabledActionShortcutMonitor(mGoToNextAction, SLOT(showLastDocumentReached()));
mGoToFirstAction = view->addAction("go_first", q, SLOT(goToFirst()));
mGoToFirstAction->setPriority(QAction::LowPriority);
mGoToFirstAction->setText(i18nc("@action Go to first image", "First"));
mGoToFirstAction->setToolTip(i18nc("@info:tooltip", "Go to first image"));
mGoToFirstAction->setShortcut(Qt::Key_Home);
mGoToLastAction = view->addAction("go_last", q, SLOT(goToLast()));
mGoToLastAction->setPriority(QAction::LowPriority);
mGoToLastAction->setText(i18nc("@action Go to last image", "Last"));
mGoToLastAction->setToolTip(i18nc("@info:tooltip", "Go to last image"));
mGoToLastAction->setShortcut(Qt::Key_End);
mPreloadDirectionIsForward = true;
mGoUpAction = view->addAction(KStandardAction::Up, q, SLOT(goUp()));
action = view->addAction("go_start_page", q, SLOT(showStartMainPage()));
action->setPriority(QAction::LowPriority);
action->setIcon(KIcon("go-home"));
action->setText(i18nc("@action", "Start Page"));
action->setToolTip(i18nc("@info:tooltip", "Open the start page"));
mToggleSideBarAction = view->add<KToggleAction>("toggle_sidebar");
connect(mToggleSideBarAction, SIGNAL(toggled(bool)),
q, SLOT(toggleSideBar(bool)));
mToggleSideBarAction->setIcon(KIcon("view-sidetree"));
mToggleSideBarAction->setShortcut(Qt::Key_F4);
mToggleSideBarAction->setText(i18nc("@action", "Sidebar"));
connect(mBrowseMainPage->toggleSideBarButton(), SIGNAL(clicked()),
mToggleSideBarAction, SLOT(trigger()));
connect(mViewMainPage->toggleSideBarButton(), SIGNAL(clicked()),
mToggleSideBarAction, SLOT(trigger()));
mToggleSlideShowAction = view->addAction("toggle_slideshow", q, SLOT(toggleSlideShow()));
q->updateSlideShowAction();
connect(mSlideShow, SIGNAL(stateChanged(bool)),
q, SLOT(updateSlideShowAction()));
mShowMenuBarAction = static_cast<KToggleAction*>(view->addAction(KStandardAction::ShowMenubar, q, SLOT(toggleMenuBar())));
view->addAction(KStandardAction::KeyBindings, q->guiFactory(),
SLOT(configureShortcuts()));
view->addAction(KStandardAction::Preferences, q,
SLOT(showConfigDialog()));
view->addAction(KStandardAction::ConfigureToolbars, q,
SLOT(configureToolbars()));
}
void setupUndoActions()
{
// There is no KUndoGroup similar to KUndoStack. This code basically
// does the same as KUndoStack, but for the KUndoGroup actions.
QUndoGroup* undoGroup = DocumentFactory::instance()->undoGroup();
QAction* action;
KActionCollection* actionCollection = q->actionCollection();
KActionCategory* edit = new KActionCategory(i18nc("@title actions category - means actions changing smth in interface", "Edit"), actionCollection);
action = undoGroup->createRedoAction(actionCollection);
action->setObjectName(KStandardAction::name(KStandardAction::Redo));
action->setIcon(KIcon("edit-redo"));
action->setIconText(i18n("Redo"));
action->setShortcuts(KStandardShortcut::redo());
edit->addAction(action->objectName(), action);
action = undoGroup->createUndoAction(actionCollection);
action->setObjectName(KStandardAction::name(KStandardAction::Undo));
action->setIcon(KIcon("edit-undo"));
action->setIconText(i18n("Undo"));
action->setShortcuts(KStandardShortcut::undo());
edit->addAction(action->objectName(), action);
}
void setupContextManagerItems()
{
Q_ASSERT(mContextManager);
KActionCollection* actionCollection = q->actionCollection();
// Create context manager items
FolderViewContextManagerItem* folderViewItem = new FolderViewContextManagerItem(mContextManager);
connect(folderViewItem, SIGNAL(urlChanged(KUrl)),
q, SLOT(openDirUrl(KUrl)));
InfoContextManagerItem* infoItem = new InfoContextManagerItem(mContextManager);
ImageOpsContextManagerItem* imageOpsItem =
new ImageOpsContextManagerItem(mContextManager, q);
FileOpsContextManagerItem* fileOpsItem = new FileOpsContextManagerItem(mContextManager, mThumbnailView, actionCollection, q);
// Fill sidebar
SideBarPage* page;
page = new SideBarPage(i18n("Folders"));
page->setObjectName(QLatin1String("folders"));
page->addWidget(folderViewItem->widget());
page->layout()->setMargin(0);
mSideBar->addPage(page);
page = new SideBarPage(i18n("Information"));
page->setObjectName(QLatin1String("information"));
page->addWidget(infoItem->widget());
mSideBar->addPage(page);
page = new SideBarPage(i18n("Operations"));
page->setObjectName(QLatin1String("operations"));
page->addWidget(imageOpsItem->widget());
page->addWidget(fileOpsItem->widget());
page->addStretch();
mSideBar->addPage(page);
}
void initDirModel()
{
mDirModel->setKindFilter(
MimeTypeUtils::KIND_DIR
| MimeTypeUtils::KIND_RASTER_IMAGE
| MimeTypeUtils::KIND_SVG_IMAGE);
connect(mDirModel, SIGNAL(rowsInserted(QModelIndex,int,int)),
q, SLOT(slotDirModelNewItems()));
connect(mDirModel, SIGNAL(rowsRemoved(QModelIndex,int,int)),
q, SLOT(updatePreviousNextActions()));
connect(mDirModel, SIGNAL(modelReset()),
q, SLOT(updatePreviousNextActions()));
connect(mDirModel->dirLister(), SIGNAL(completed()),
q, SLOT(slotDirListerCompleted()));
}
void setupThumbnailBarModel()
{
mThumbnailBarModel = new DocumentOnlyProxyModel(q);
mThumbnailBarModel->setSourceModel(mDirModel);
}
bool indexIsDir(const QModelIndex& index) const
{
Q_ASSERT(index.isValid());
KFileItem item = mDirModel->itemForIndex(index);
return item.isDir();
}
void goTo(const QModelIndex& index)
{
if (!index.isValid()) {
return;
}
mThumbnailView->setCurrentIndex(index);
mThumbnailView->scrollTo(index);
}
void goTo(int offset)
{
mPreloadDirectionIsForward = offset > 0;
QModelIndex index = mContextManager->selectionModel()->currentIndex();
index = mDirModel->index(index.row() + offset, 0);
if (index.isValid() && !indexIsDir(index)) {
goTo(index);
}
}
void goToFirstDocument()
{
QModelIndex index;
for (int row = 0;; ++row) {
index = mDirModel->index(row, 0);
if (!index.isValid()) {
return;
}
if (!indexIsDir(index)) {
break;
}
}
goTo(index);
}
void goToLastDocument()
{
QModelIndex index = mDirModel->index(mDirModel->rowCount() - 1, 0);
goTo(index);
}
void setupFullScreenContent()
{
mFullScreenContent->init(q->actionCollection(), mViewMainPage, mSlideShow);
setupThumbnailBar(mFullScreenContent->thumbnailBar());
}
inline void setActionEnabled(const char* name, bool enabled)
{
QAction* action = q->actionCollection()->action(name);
if (action) {
action->setEnabled(enabled);
} else {
kWarning() << "Action" << name << "not found";
}
}
void setActionsDisabledOnStartMainPageEnabled(bool enabled)
{
mBrowseAction->setEnabled(enabled);
mViewAction->setEnabled(enabled);
mToggleSideBarAction->setEnabled(enabled);
mFullScreenAction->setEnabled(enabled);
mToggleSlideShowAction->setEnabled(enabled);
setActionEnabled("reload", enabled);
setActionEnabled("go_start_page", enabled);
setActionEnabled("add_folder_to_places", enabled);
}
void updateActions()
{
bool isRasterImage = false;
bool canSave = false;
bool isModified = false;
const KUrl url = mContextManager->currentUrl();
if (url.isValid()) {
isRasterImage = mContextManager->currentUrlIsRasterImage();
canSave = isRasterImage;
isModified = DocumentFactory::instance()->load(url)->isModified();
if (mCurrentMainPageId != ViewMainPageId) {
// Saving only makes sense if exactly one image is selected
QItemSelection selection = mThumbnailView->selectionModel()->selection();
QModelIndexList indexList = selection.indexes();
if (indexList.count() != 1) {
canSave = false;
}
}
}
KActionCollection* actionCollection = q->actionCollection();
actionCollection->action("file_save")->setEnabled(canSave && isModified);
actionCollection->action("file_save_as")->setEnabled(canSave);
actionCollection->action("file_print")->setEnabled(isRasterImage);
}
const char* sideBarConfigGroupName() const
{
const char* name = 0;
switch (mCurrentMainPageId) {
case StartMainPageId:
GV_WARN_AND_RETURN_VALUE(BROWSE_MODE_SIDE_BAR_GROUP, "mCurrentMainPageId == 'StartMainPageId'");
break;
case BrowseMainPageId:
name = BROWSE_MODE_SIDE_BAR_GROUP;
break;
case ViewMainPageId:
name = mViewMainPage->isFullScreenMode()
? FULLSCREEN_MODE_SIDE_BAR_GROUP
: VIEW_MODE_SIDE_BAR_GROUP;
break;
}
return name;
}
void loadSideBarConfig()
{
static QMap<const char*, bool> defaultVisibility;
if (defaultVisibility.isEmpty()) {
defaultVisibility[BROWSE_MODE_SIDE_BAR_GROUP] = true;
defaultVisibility[VIEW_MODE_SIDE_BAR_GROUP] = true;
defaultVisibility[FULLSCREEN_MODE_SIDE_BAR_GROUP] = false;
}
const char* name = sideBarConfigGroupName();
KConfigGroup group(KGlobal::config(), name);
mSideBar->setVisible(group.readEntry(SIDE_BAR_IS_VISIBLE_KEY, defaultVisibility[name]));
mSideBar->setCurrentPage(GwenviewConfig::sideBarPage());
q->updateToggleSideBarAction();
}
void saveSideBarConfig() const
{
KConfigGroup group(KGlobal::config(), sideBarConfigGroupName());
group.writeEntry(SIDE_BAR_IS_VISIBLE_KEY, mSideBar->isVisible());
GwenviewConfig::setSideBarPage(mSideBar->currentPage());
}
void setScreenSaverEnabled(bool enabled)
{
// Always delete mNotificationRestrictions, it does not hurt
delete mNotificationRestrictions;
if (!enabled) {
mNotificationRestrictions = new KNotificationRestrictions(KNotificationRestrictions::ScreenSaver, q);
} else {
mNotificationRestrictions = 0;
}
}
void assignThumbnailProviderToThumbnailView(ThumbnailView* thumbnailView)
{
GV_RETURN_IF_FAIL(thumbnailView);
mActiveThumbnailView = thumbnailView;
if (mActiveThumbnailView->isVisible()) {
mActiveThumbnailView->generateThumbnailsForItems();
}
}
void autoAssignThumbnailProvider()
{
if (mCurrentMainPageId == ViewMainPageId) {
if (q->windowState() & Qt::WindowFullScreen) {
assignThumbnailProviderToThumbnailView(mFullScreenContent->thumbnailBar());
} else {
assignThumbnailProviderToThumbnailView(mViewMainPage->thumbnailBar());
}
} else if (mCurrentMainPageId == BrowseMainPageId) {
assignThumbnailProviderToThumbnailView(mThumbnailView);
} else if (mCurrentMainPageId == StartMainPageId) {
assignThumbnailProviderToThumbnailView(mStartMainPage->recentFoldersView());
}
}
};
MainWindow::MainWindow()
: KXmlGuiWindow(),
d(new MainWindow::Private)
{
d->q = this;
d->mCurrentMainPageId = StartMainPageId;
d->mDirModel = new SortedDirModel(this);
d->setupContextManager();
d->setupThumbnailBarModel();
d->mGvCore = new GvCore(this, d->mDirModel);
d->mPreloader = new Preloader(this);
d->mNotificationRestrictions = 0;
d->mActiveThumbnailView = 0;
d->initDirModel();
d->setupWidgets();
d->setupActions();
d->setupUndoActions();
d->setupContextManagerItems();
d->setupFullScreenContent();
d->updateActions();
updatePreviousNextActions();
d->mSaveBar->initActionDependentWidgets();
createGUI();
loadConfig();
connect(DocumentFactory::instance(), SIGNAL(modifiedDocumentListChanged()),
SLOT(slotModifiedDocumentListChanged()));
setAutoSaveSettings();
}
MainWindow::~MainWindow()
{
delete d;
}
ContextManager* MainWindow::contextManager() const
{
return d->mContextManager;
}
ViewMainPage* MainWindow::viewMainPage() const
{
return d->mViewMainPage;
}
void MainWindow::setCaption(const QString& caption)
{
// Keep a trace of caption to use it in slotModifiedDocumentListChanged()
d->mCaption = caption;
KXmlGuiWindow::setCaption(caption);
}
void MainWindow::setCaption(const QString& caption, bool modified)
{
d->mCaption = caption;
KXmlGuiWindow::setCaption(caption, modified);
}
void MainWindow::slotModifiedDocumentListChanged()
{
d->updateActions();
// Update caption
QList<KUrl> list = DocumentFactory::instance()->modifiedDocumentList();
bool modified = list.count() > 0;
setCaption(d->mCaption, modified);
}
void MainWindow::setInitialUrl(const KUrl& _url)
{
Q_ASSERT(_url.isValid());
KUrl url = UrlUtils::fixUserEnteredUrl(_url);
if (url.protocol() == "http" || url.protocol() == "https") {
d->mGvCore->addUrlToRecentUrls(url);
}
if (UrlUtils::urlIsDirectory(url)) {
d->mBrowseAction->trigger();
openDirUrl(url);
} else {
d->mViewAction->trigger();
d->mViewMainPage->openUrl(url);
d->mContextManager->setUrlToSelect(url);
}
}
void MainWindow::startSlideShow()
{
d->mViewAction->trigger();
// We need to wait until we have listed all images in the dirlister to
// start the slideshow because the SlideShow objects needs an image list to
// work.
d->mStartSlideShowWhenDirListerCompleted = true;
}
void MainWindow::setActiveViewModeAction(QAction* action)
{
if (d->mCurrentMainPageId != StartMainPageId) {
d->saveSideBarConfig();
}
if (action == d->mViewAction) {
d->mCurrentMainPageId = ViewMainPageId;
// Switching to view mode
d->mViewStackedWidget->setCurrentWidget(d->mViewMainPage);
if (d->mViewMainPage->isEmpty()) {
openSelectedDocuments();
}
d->mPreloadDirectionIsForward = true;
QTimer::singleShot(VIEW_PRELOAD_DELAY, this, SLOT(preloadNextUrl()));
} else {
d->mCurrentMainPageId = BrowseMainPageId;
// Switching to browse mode
d->mViewStackedWidget->setCurrentWidget(d->mBrowseMainPage);
if (!d->mViewMainPage->isEmpty()
&& KProtocolManager::supportsListing(d->mViewMainPage->url())) {
// Reset the view to spare resources, but don't do it if we can't
// browse the url, otherwise if the user starts Gwenview this way:
// gwenview http://example.com/example.png
// and switch to browse mode, switching back to view mode won't bring
// his image back.
d->mViewMainPage->reset();
}
setCaption(QString());
}
d->loadSideBarConfig();
d->autoAssignThumbnailProvider();
emit viewModeChanged();
}
void MainWindow::slotThumbnailViewIndexActivated(const QModelIndex& index)
{
if (!index.isValid()) {
return;
}
KFileItem item = d->mDirModel->itemForIndex(index);
if (item.isDir()) {
// Item is a dir, open it
openDirUrl(item.url());
} else {
// Item is a document, switch to view mode
d->mViewAction->trigger();
}
}
static bool indexRowLessThan(const QModelIndex& i1, const QModelIndex& i2)
{
return i1.row() < i2.row();
}
void MainWindow::openSelectedDocuments()
{
if (d->mCurrentMainPageId != ViewMainPageId) {
return;
}
QModelIndex currentIndex = d->mThumbnailView->currentIndex();
if (!currentIndex.isValid()) {
return;
}
int count = 0;
KUrl::List urls;
KUrl currentUrl;
QModelIndex firstDocumentIndex;
QModelIndexList list = d->mThumbnailView->selectionModel()->selectedIndexes();
// Make 'list' follow the same order as 'mThumbnailView'
qSort(list.begin(), list.end(), indexRowLessThan);
Q_FOREACH(const QModelIndex& index, list) {
KFileItem item = d->mDirModel->itemForIndex(index);
if (!item.isNull() && !item.isDir()) {
KUrl url = item.url();
if (!firstDocumentIndex.isValid()) {
firstDocumentIndex = index;
}
urls << url;
if (index == currentIndex) {
currentUrl = url;
}
++count;
if (count == ViewMainPage::MaxViewCount) {
break;
}
}
}
if (urls.isEmpty()) {
// No image to display
return;
}
if (currentUrl.isEmpty()) {
// Current index is not selected, or it is not a document: set
// firstDocumentIndex as current
GV_RETURN_IF_FAIL(firstDocumentIndex.isValid());
d->mThumbnailView->selectionModel()->setCurrentIndex(firstDocumentIndex, QItemSelectionModel::Current);
currentUrl = urls.first();
}
d->mViewMainPage->openUrls(urls, currentUrl);
}
void MainWindow::goUp()
{
if (d->mCurrentMainPageId == BrowseMainPageId) {
KUrl url = d->mContextManager->currentDirUrl();
url = url.upUrl();
openDirUrl(url);
} else {
d->mBrowseAction->trigger();
}
}
void MainWindow::showStartMainPage()
{
if (d->mCurrentMainPageId != StartMainPageId) {
d->saveSideBarConfig();
d->mCurrentMainPageId = StartMainPageId;
}
d->setActionsDisabledOnStartMainPageEnabled(false);
d->mSideBar->hide();
d->mViewStackedWidget->setCurrentWidget(d->mStartMainPage);
d->updateActions();
updatePreviousNextActions();
d->mContextManager->setCurrentDirUrl(KUrl());
d->mContextManager->setCurrentUrl(KUrl());
d->autoAssignThumbnailProvider();
}
void MainWindow::slotStartMainPageUrlSelected(const KUrl& url)
{
d->setActionsDisabledOnStartMainPageEnabled(true);
if (d->mBrowseAction->isChecked()) {
// Silently uncheck the action so that setInitialUrl() does the right thing
SignalBlocker blocker(d->mBrowseAction);
d->mBrowseAction->setChecked(false);
}
setInitialUrl(url);
}
void MainWindow::openDirUrl(const KUrl& url)
{
const KUrl currentUrl = d->mContextManager->currentDirUrl();
if (url.equals(currentUrl, KUrl::CompareWithoutTrailingSlash)) {
return;
}
if (url.isParentOf(currentUrl)) {
// Keep first child between url and currentUrl selected
// If currentPath is "/home/user/photos/2008/event"
// and wantedPath is "/home/user/photos"
// pathToSelect should be "/home/user/photos/2008"
// To anyone considering using KUrl::toLocalFile() instead of
// KUrl::path() here. Please don't, using KUrl::path() is the right
// thing to do here.
const QString currentPath = QDir::cleanPath(currentUrl.path(KUrl::RemoveTrailingSlash));
const QString wantedPath = QDir::cleanPath(url.path(KUrl::RemoveTrailingSlash));
const QChar separator('/');
const int slashCount = wantedPath.count(separator);
const QString pathToSelect = currentPath.section(separator, 0, slashCount + 1);
KUrl urlToSelect = url;
urlToSelect.setPath(pathToSelect);
d->mContextManager->setUrlToSelect(urlToSelect);
}
d->mContextManager->setCurrentDirUrl(url);
d->mGvCore->addUrlToRecentFolders(url);
d->mViewMainPage->reset();
}
void MainWindow::toggleSideBar(bool on)
{
d->mSideBar->setVisible(on);
}
void MainWindow::updateToggleSideBarAction()
{
SignalBlocker blocker(d->mToggleSideBarAction);
bool visible = d->mSideBar->isVisible();
d->mToggleSideBarAction->setChecked(visible);
QString text;
if (QApplication::isRightToLeft()) {
text = QString::fromUtf8(visible ? "▮→" : "▮←");
} else {
text = QString::fromUtf8(visible ? "▮←" : "▮→");
}
QString toolTip = visible ? i18nc("@info:tooltip", "Hide sidebar") : i18nc("@info:tooltip", "Show sidebar");
QList<QToolButton*> lst;
lst << d->mBrowseMainPage->toggleSideBarButton()
<< d->mViewMainPage->toggleSideBarButton();
Q_FOREACH(QToolButton * button, lst) {
button->setText(text);
button->setToolTip(toolTip);
}
}
void MainWindow::slotPartCompleted()
{
d->updateActions();
KUrl url = d->mViewMainPage->url();
// remember the opened file
if (!url.isEmpty()) {
d->mFileOpenRecentAction->addUrl(url);
}
if (!KProtocolManager::supportsListing(url)) {
return;
}
KUrl dirUrl = url;
dirUrl.setFileName(QString());
if (dirUrl.equals(d->mContextManager->currentDirUrl(), KUrl::CompareWithoutTrailingSlash)) {
QModelIndex index = d->mDirModel->indexForUrl(url);
QItemSelectionModel* selectionModel = d->mThumbnailView->selectionModel();
if (index.isValid() && !selectionModel->isSelected(index)) {
// FIXME: QGV Reactivating this line prevents navigation to prev/next image
//selectionModel->select(index, QItemSelectionModel::SelectCurrent);
}
} else {
d->mContextManager->setCurrentDirUrl(dirUrl);
d->mGvCore->addUrlToRecentFolders(dirUrl);
}
}
void MainWindow::slotSelectionChanged()
{
if (d->mCurrentMainPageId == ViewMainPageId) {
// The user selected a new file in the thumbnail view, since the
// document view is visible, let's show it
openSelectedDocuments();
} else {
// No document view, we need to load the document to set the undo group
// of document factory to the correct QUndoStack
QModelIndex index = d->mThumbnailView->currentIndex();
KFileItem item;
if (index.isValid()) {
item = d->mDirModel->itemForIndex(index);
}
QUndoGroup* undoGroup = DocumentFactory::instance()->undoGroup();
if (!item.isNull() && !item.isDir()) {
KUrl url = item.url();
Document::Ptr doc = DocumentFactory::instance()->load(url);
undoGroup->addStack(doc->undoStack());
undoGroup->setActiveStack(doc->undoStack());
} else {
undoGroup->setActiveStack(0);
}
}
// Update UI
d->updateActions();
updatePreviousNextActions();
// Start preloading
int preloadDelay = d->mCurrentMainPageId == ViewMainPageId ? VIEW_PRELOAD_DELAY : BROWSE_PRELOAD_DELAY;
QTimer::singleShot(preloadDelay, this, SLOT(preloadNextUrl()));
}
void MainWindow::slotCurrentDirUrlChanged(const KUrl& url)
{
if (url.isValid()) {
d->mUrlNavigator->setLocationUrl(url);
d->mGoUpAction->setEnabled(url.path() != "/");
} else {
d->mGoUpAction->setEnabled(false);
}
}
void MainWindow::slotDirModelNewItems()
{
if (d->mThumbnailView->selectionModel()->hasSelection()) {
updatePreviousNextActions();
}
}
void MainWindow::slotDirListerCompleted()
{
if (d->mStartSlideShowWhenDirListerCompleted) {
d->mStartSlideShowWhenDirListerCompleted = false;
QTimer::singleShot(0, d->mToggleSlideShowAction, SLOT(trigger()));
}
if (d->mThumbnailView->selectionModel()->hasSelection()) {
updatePreviousNextActions();
} else if (!d->mContextManager->urlToSelect().isValid()) {
d->goToFirstDocument();
}
d->mThumbnailView->scrollToSelectedIndex();
d->mViewMainPage->thumbnailBar()->scrollToSelectedIndex();
}
void MainWindow::goToPrevious()
{
d->goTo(-1);
}
void MainWindow::goToNext()
{
d->goTo(1);
}
void MainWindow::goToFirst()
{
d->goToFirstDocument();
}
void MainWindow::goToLast()
{
d->goToLastDocument();
}
void MainWindow::goToUrl(const KUrl& url)
{
if (d->mCurrentMainPageId == ViewMainPageId) {
d->mViewMainPage->openUrl(url);
}
KUrl dirUrl = url;
dirUrl.setFileName("");
if (!dirUrl.equals(d->mContextManager->currentDirUrl(), KUrl::CompareWithoutTrailingSlash)) {
d->mContextManager->setCurrentDirUrl(dirUrl);
d->mGvCore->addUrlToRecentFolders(dirUrl);
}
d->mContextManager->setUrlToSelect(url);
}
void MainWindow::updatePreviousNextActions()
{
bool hasPrevious;
bool hasNext;
QModelIndex currentIndex = d->mContextManager->selectionModel()->currentIndex();
if (currentIndex.isValid() && !d->indexIsDir(currentIndex)) {
int row = currentIndex.row();
QModelIndex prevIndex = d->mDirModel->index(row - 1, 0);
QModelIndex nextIndex = d->mDirModel->index(row + 1, 0);
hasPrevious = prevIndex.isValid() && !d->indexIsDir(prevIndex);
hasNext = nextIndex.isValid() && !d->indexIsDir(nextIndex);
} else {
hasPrevious = false;
hasNext = false;
}
d->mGoToPreviousAction->setEnabled(hasPrevious);
d->mGoToNextAction->setEnabled(hasNext);
d->mGoToFirstAction->setEnabled(hasPrevious);
d->mGoToLastAction->setEnabled(hasNext);
}
void MainWindow::leaveFullScreen()
{
if (d->mFullScreenAction->isChecked()) {
d->mFullScreenAction->trigger();
}
}
void MainWindow::toggleFullScreen(bool checked)
{
setUpdatesEnabled(false);
d->saveSideBarConfig();
if (checked) {
// Save MainWindow config now, this way if we quit while in
// fullscreen, we are sure latest MainWindow changes are remembered.
saveMainWindowSettings(autoSaveConfigGroup());
resetAutoSaveSettings();
// Save state
d->mStateBeforeFullScreen.mToolBarVisible = toolBar()->isVisible();
d->mStateBeforeFullScreen.mWindowState = windowState();
// Go full screen
setWindowState(windowState() | Qt::WindowFullScreen);
menuBar()->hide();
toolBar()->hide();
QApplication::setPalette(d->mGvCore->palette(GvCore::FullScreenPalette));
d->mFullScreenContent->setFullScreenMode(true);
d->mBrowseMainPage->setFullScreenMode(true);
d->mViewMainPage->setFullScreenMode(true);
d->mSaveBar->setFullScreenMode(true);
d->setScreenSaverEnabled(false);
// HACK: Only load sidebar config now, because it looks at
// ViewMainPage fullScreenMode property to determine the sidebar
// config group.
d->loadSideBarConfig();
} else {
setAutoSaveSettings();
// Back to normal
QApplication::setPalette(d->mGvCore->palette(GvCore::NormalPalette));
d->mFullScreenContent->setFullScreenMode(false);
d->mBrowseMainPage->setFullScreenMode(false);
d->mViewMainPage->setFullScreenMode(false);
d->mSlideShow->stop();
d->mSaveBar->setFullScreenMode(false);
setWindowState(d->mStateBeforeFullScreen.mWindowState);
menuBar()->setVisible(d->mShowMenuBarAction->isChecked());
toolBar()->setVisible(d->mStateBeforeFullScreen.mToolBarVisible);
d->setScreenSaverEnabled(true);
// Keep this after mViewMainPage->setFullScreenMode(false).
// See call to loadSideBarConfig() above.
d->loadSideBarConfig();
// See resizeEvent
d->mFullScreenLeftAt = QDateTime::currentDateTime();
}
setUpdatesEnabled(true);
d->autoAssignThumbnailProvider();
}
void MainWindow::saveCurrent()
{
d->mGvCore->save(d->mContextManager->currentUrl());
}
void MainWindow::saveCurrentAs()
{
d->mGvCore->saveAs(d->mContextManager->currentUrl());
}
void MainWindow::reload()
{
if (d->mCurrentMainPageId == ViewMainPageId) {
d->mViewMainPage->reload();
} else {
d->mBrowseMainPage->reload();
}
}
void MainWindow::openFile()
{
KUrl dirUrl = d->mContextManager->currentDirUrl();
KFileDialog dialog(dirUrl, QString(), this);
dialog.setCaption(i18nc("@title:window", "Open Image"));
const QStringList mimeFilter = MimeTypeUtils::imageMimeTypes();
dialog.setMimeFilter(mimeFilter);
dialog.setOperationMode(KFileDialog::Opening);
if (!dialog.exec()) {
return;
}
openUrl(dialog.selectedUrl());
}
void MainWindow::openUrl(const KUrl& url)
{
d->setActionsDisabledOnStartMainPageEnabled(true);
d->mViewAction->trigger();
d->mViewMainPage->openUrl(url);
d->mContextManager->setUrlToSelect(url);
}
void MainWindow::showDocumentInFullScreen(const KUrl& url)
{
d->mViewMainPage->openUrl(url);
d->mContextManager->setUrlToSelect(url);
d->mFullScreenAction->trigger();
}
void MainWindow::toggleSlideShow()
{
if (d->mSlideShow->isRunning()) {
d->mSlideShow->stop();
} else {
if (!d->mViewAction->isChecked()) {
d->mViewAction->trigger();
}
if (!d->mFullScreenAction->isChecked()) {
d->mFullScreenAction->trigger();
}
QList<KUrl> list;
for (int pos = 0; pos < d->mDirModel->rowCount(); ++pos) {
QModelIndex index = d->mDirModel->index(pos, 0);
KFileItem item = d->mDirModel->itemForIndex(index);
MimeTypeUtils::Kind kind = MimeTypeUtils::fileItemKind(item);
switch (kind) {
case MimeTypeUtils::KIND_SVG_IMAGE:
case MimeTypeUtils::KIND_RASTER_IMAGE:
list << item.url();
break;
default:
break;
}
}
d->mSlideShow->start(list);
}
updateSlideShowAction();
}
void MainWindow::updateSlideShowAction()
{
if (d->mSlideShow->isRunning()) {
d->mToggleSlideShowAction->setText(i18n("Stop Slideshow"));
d->mToggleSlideShowAction->setIcon(KIcon("media-playback-pause"));
} else {
d->mToggleSlideShowAction->setText(i18n("Start Slideshow"));
d->mToggleSlideShowAction->setIcon(KIcon("media-playback-start"));
}
}
bool MainWindow::queryClose()
{
saveConfig();
d->saveSideBarConfig();
QList<KUrl> list = DocumentFactory::instance()->modifiedDocumentList();
if (list.size() == 0) {
return true;
}
KGuiItem yes(i18n("Save All Changes"), "document-save-all");
KGuiItem no(i18n("Discard Changes"));
QString msg = i18np("One image has been modified.", "%1 images have been modified.", list.size())
+ '\n'
+ i18n("If you quit now, your changes will be lost.");
int answer = KMessageBox::warningYesNoCancel(
this,
msg,
QString() /* caption */,
yes,
no);
switch (answer) {
case KMessageBox::Yes:
d->mGvCore->saveAll();
// We need to wait a bit because the DocumentFactory is notified about
// saved documents through a queued connection.
qApp->processEvents();
return DocumentFactory::instance()->modifiedDocumentList().isEmpty();
case KMessageBox::No:
return true;
default: // cancel
return false;
}
}
void MainWindow::showConfigDialog()
{
ConfigDialog dialog(this);
connect(&dialog, SIGNAL(settingsChanged(QString)), SLOT(loadConfig()));
dialog.exec();
}
void MainWindow::toggleMenuBar()
{
if (!d->mFullScreenAction->isChecked()) {
menuBar()->setVisible(d->mShowMenuBarAction->isChecked());
}
}
void MainWindow::loadConfig()
{
d->mDirModel->setBlackListedExtensions(GwenviewConfig::blackListedExtensions());
d->mFileOpenRecentAction->loadEntries(KConfigGroup(KGlobal::config(), "Recent Files"));
d->mStartMainPage->loadConfig();
d->mViewMainPage->loadConfig();
d->mBrowseMainPage->loadConfig();
}
void MainWindow::saveConfig()
{
d->mFileOpenRecentAction->saveEntries(KConfigGroup(KGlobal::config(), "Recent Files"));
d->mViewMainPage->saveConfig();
d->mBrowseMainPage->saveConfig();
}
void MainWindow::print()
{
if (!d->mContextManager->currentUrlIsRasterImage()) {
return;
}
Document::Ptr doc = DocumentFactory::instance()->load(d->mContextManager->currentUrl());
PrintHelper printHelper(this);
printHelper.print(doc);
}
void MainWindow::preloadNextUrl()
{
static bool disablePreload = qgetenv("GV_MAX_UNREFERENCED_IMAGES") == "0";
if (disablePreload) {
kDebug() << "Preloading disabled";
return;
}
QItemSelection selection = d->mThumbnailView->selectionModel()->selection();
if (selection.size() != 1) {
return;
}
QModelIndexList indexList = selection.indexes();
if (indexList.isEmpty()) {
return;
}
QModelIndex index = indexList.at(0);
if (!index.isValid()) {
return;
}
if (d->mCurrentMainPageId == ViewMainPageId) {
// If we are in view mode, preload the next url, otherwise preload the
// selected one
int offset = d->mPreloadDirectionIsForward ? 1 : -1;
index = d->mDirModel->sibling(index.row() + offset, index.column(), index);
if (!index.isValid()) {
return;
}
}
KFileItem item = d->mDirModel->itemForIndex(index);
if (!item.isDir()) {
KUrl url = item.url();
if (url.isLocalFile()) {
QSize size = d->mViewStackedWidget->size();
d->mPreloader->preload(url, size);
}
}
}
QSize MainWindow::sizeHint() const
{
return KXmlGuiWindow::sizeHint().expandedTo(QSize(750, 500));
}
void MainWindow::showEvent(QShowEvent *event)
{
// We need to delay initializing the action state until the menu bar has
// been initialized, that's why it's done only in the showEvent()
d->mShowMenuBarAction->setChecked(menuBar()->isVisible());
KXmlGuiWindow::showEvent(event);
}
void MainWindow::resizeEvent(QResizeEvent* event)
{
KXmlGuiWindow::resizeEvent(event);
// This is a small hack to execute code after leaving fullscreen, and after
// the window has been resized back to its former size.
if (d->mFullScreenLeftAt.isValid() && d->mFullScreenLeftAt.secsTo(QDateTime::currentDateTime()) < 2) {
if (d->mCurrentMainPageId == BrowseMainPageId) {
d->mThumbnailView->scrollToSelectedIndex();
}
d->mFullScreenLeftAt = QDateTime();
}
}
void MainWindow::setDistractionFreeMode(bool value)
{
d->mFullScreenContent->setDistractionFreeMode(value);
}
void MainWindow::saveProperties(KConfigGroup& group)
{
group.writeEntry(SESSION_CURRENT_PAGE_KEY, int(d->mCurrentMainPageId));
group.writeEntry(SESSION_URL_KEY, d->mContextManager->currentUrl());
}
void MainWindow::readProperties(const KConfigGroup& group)
{
MainPageId pageId = MainPageId(group.readEntry(SESSION_CURRENT_PAGE_KEY, int(StartMainPageId)));
if (pageId == StartMainPageId) {
d->mCurrentMainPageId = StartMainPageId;
showStartMainPage();
} else if (pageId == BrowseMainPageId) {
d->mBrowseAction->trigger();
} else {
d->mViewAction->trigger();
}
KUrl url = group.readEntry(SESSION_URL_KEY, KUrl());
if (!url.isValid()) {
kWarning() << "Invalid url!";
return;
}
goToUrl(url);
}
void MainWindow::showFirstDocumentReached()
{
if (d->mCurrentMainPageId != ViewMainPageId) {
return;
}
HudButtonBox* dlg = new HudButtonBox;
dlg->setText(i18n("You reached the first document, what do you want to do?"));
dlg->addButton(i18n("Stay There"));
dlg->addAction(d->mGoToLastAction, i18n("Go to the Last Document"));
dlg->addAction(d->mBrowseAction, i18n("Go Back to the Document List"));
dlg->addCountDown(15000);
d->mViewMainPage->showMessageWidget(dlg, Qt::AlignCenter);
}
void MainWindow::showLastDocumentReached()
{
if (d->mCurrentMainPageId != ViewMainPageId) {
return;
}
HudButtonBox* dlg = new HudButtonBox;
dlg->setText(i18n("You reached the last document, what do you want to do?"));
dlg->addButton(i18n("Stay There"));
dlg->addAction(d->mGoToFirstAction, i18n("Go to the First Document"));
dlg->addAction(d->mBrowseAction, i18n("Go Back to the Document List"));
dlg->addCountDown(15000);
d->mViewMainPage->showMessageWidget(dlg, Qt::AlignCenter);
}
} // namespace