~ubuntu-branches/ubuntu/precise/gwenview/precise-proposed

« back to all changes in this revision

Viewing changes to app/viewmainpage.cpp

  • Committer: Package Import Robot
  • Author(s): Jonathan Riddell
  • Date: 2011-12-15 14:17:54 UTC
  • mto: This revision was merged to the branch mainline in revision 12.
  • Revision ID: package-import@ubuntu.com-20111215141754-z043hyx69dulbggf
Tags: upstream-4.7.90
ImportĀ upstreamĀ versionĀ 4.7.90

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
Gwenview: an image viewer
 
3
Copyright 2007 AurĆ©lien GĆ¢teau <agateau@kde.org>
 
4
 
 
5
This program is free software; you can redistribute it and/or
 
6
modify it under the terms of the GNU General Public License
 
7
as published by the Free Software Foundation; either version 2
 
8
of the License, or (at your option) any later version.
 
9
 
 
10
This program is distributed in the hope that it will be useful,
 
11
but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
GNU General Public License for more details.
 
14
 
 
15
You should have received a copy of the GNU General Public License
 
16
along with this program; if not, write to the Free Software
 
17
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
18
 
 
19
*/
 
20
#include "viewmainpage.moc"
 
21
 
 
22
// Qt
 
23
#include <QCheckBox>
 
24
#include <QItemSelectionModel>
 
25
#include <QLabel>
 
26
#include <QShortcut>
 
27
#include <QToolButton>
 
28
#include <QVBoxLayout>
 
29
 
 
30
// KDE
 
31
#include <kactioncollection.h>
 
32
#include <kactioncategory.h>
 
33
#include <kdebug.h>
 
34
#include <klocale.h>
 
35
#include <kmenu.h>
 
36
#include <kmessagebox.h>
 
37
#include <ktoggleaction.h>
 
38
 
 
39
// Local
 
40
#include "fileoperations.h"
 
41
#include "splitter.h"
 
42
#include <lib/document/document.h>
 
43
#include <lib/documentview/abstractdocumentviewadapter.h>
 
44
#include <lib/documentview/documentview.h>
 
45
#include <lib/documentview/documentviewcontainer.h>
 
46
#include <lib/documentview/documentviewcontroller.h>
 
47
#include <lib/documentview/documentviewsynchronizer.h>
 
48
#include <lib/gwenviewconfig.h>
 
49
#include <lib/paintutils.h>
 
50
#include <lib/semanticinfo/sorteddirmodel.h>
 
51
#include <lib/slidecontainer.h>
 
52
#include <lib/slideshow.h>
 
53
#include <lib/statusbartoolbutton.h>
 
54
#include <lib/thumbnailview/thumbnailbarview.h>
 
55
#include <lib/zoomwidget.h>
 
56
 
 
57
namespace Gwenview
 
58
{
 
59
 
 
60
#undef ENABLE_LOG
 
61
#undef LOG
 
62
//#define ENABLE_LOG
 
63
#ifdef ENABLE_LOG
 
64
#define LOG(x) kDebug() << x
 
65
#else
 
66
#define LOG(x) ;
 
67
#endif
 
68
 
 
69
const int ViewMainPage::MaxViewCount = 6;
 
70
 
 
71
static QString rgba(const QColor &color)
 
72
{
 
73
    return QString::fromAscii("rgba(%1, %2, %3, %4)")
 
74
           .arg(color.red())
 
75
           .arg(color.green())
 
76
           .arg(color.blue())
 
77
           .arg(color.alpha());
 
78
}
 
79
 
 
80
static QString gradient(Qt::Orientation orientation, const QColor &color, int value)
 
81
{
 
82
    int x2, y2;
 
83
    if (orientation == Qt::Horizontal) {
 
84
        x2 = 0;
 
85
        y2 = 1;
 
86
    } else {
 
87
        x2 = 1;
 
88
        y2 = 0;
 
89
    }
 
90
    QString grad =
 
91
        "qlineargradient(x1:0, y1:0, x2:%1, y2:%2,"
 
92
        "stop:0 %3, stop: 1 %4)";
 
93
    return grad
 
94
           .arg(x2)
 
95
           .arg(y2)
 
96
           .arg(rgba(PaintUtils::adjustedHsv(color, 0, 0, qMin(255 - color.value(), value / 2))))
 
97
           .arg(rgba(PaintUtils::adjustedHsv(color, 0, 0, -qMin(color.value(), value / 2))))
 
98
           ;
 
99
}
 
100
 
 
101
/*
 
102
 * Layout of mThumbnailSplitter is:
 
103
 *
 
104
 * +-mThumbnailSplitter------------------------------------------------+
 
105
 * |+-mAdapterContainer-----------------------------------------------+|
 
106
 * ||+-mDocumentViewContainer----------------------------------------+||
 
107
 * |||+-DocumentView----------------++-DocumentView-----------------+|||
 
108
 * ||||                             ||                              ||||
 
109
 * ||||                             ||                              ||||
 
110
 * ||||                             ||                              ||||
 
111
 * ||||                             ||                              ||||
 
112
 * ||||                             ||                              ||||
 
113
 * ||||                             ||                              ||||
 
114
 * |||+-----------------------------++------------------------------+|||
 
115
 * ||+---------------------------------------------------------------+||
 
116
 * ||+-mToolContainer------------------------------------------------+||
 
117
 * |||                                                               |||
 
118
 * ||+---------------------------------------------------------------+||
 
119
 * ||+-mStatusBarContainer-------------------------------------------+||
 
120
 * |||[mToggleSideBarButton][mToggleThumbnailBarButton] [mZoomWidget]|||
 
121
 * ||+---------------------------------------------------------------+||
 
122
 * |+-----------------------------------------------------------------+|
 
123
 * |===================================================================|
 
124
 * |+-mThumbnailBar---------------------------------------------------+|
 
125
 * ||                                                                 ||
 
126
 * ||                                                                 ||
 
127
 * |+-----------------------------------------------------------------+|
 
128
 * +-------------------------------------------------------------------+
 
129
 */
 
130
struct ViewMainPagePrivate {
 
131
    ViewMainPage* q;
 
132
    SlideShow* mSlideShow;
 
133
    KActionCollection* mActionCollection;
 
134
    QSplitter *mThumbnailSplitter;
 
135
    QWidget* mAdapterContainer;
 
136
    DocumentViewController* mDocumentViewController;
 
137
    QList<DocumentView*> mDocumentViews;
 
138
    DocumentViewSynchronizer* mSynchronizer;
 
139
    QToolButton* mToggleSideBarButton;
 
140
    QToolButton* mToggleThumbnailBarButton;
 
141
    ZoomWidget* mZoomWidget;
 
142
    DocumentViewContainer* mDocumentViewContainer;
 
143
    SlideContainer* mToolContainer;
 
144
    QWidget* mStatusBarContainer;
 
145
    ThumbnailBarView* mThumbnailBar;
 
146
    KToggleAction* mToggleThumbnailBarAction;
 
147
    KToggleAction* mSynchronizeAction;
 
148
    QCheckBox* mSynchronizeCheckBox;
 
149
 
 
150
    bool mFullScreenMode;
 
151
    QPalette mNormalPalette;
 
152
    QPalette mFullScreenPalette;
 
153
    bool mCompareMode;
 
154
    bool mThumbnailBarVisibleBeforeFullScreen;
 
155
 
 
156
    void setupThumbnailBar()
 
157
    {
 
158
        mThumbnailBar = new ThumbnailBarView;
 
159
        ThumbnailBarItemDelegate* delegate = new ThumbnailBarItemDelegate(mThumbnailBar);
 
160
        mThumbnailBar->setItemDelegate(delegate);
 
161
        mThumbnailBar->setVisible(GwenviewConfig::thumbnailBarIsVisible());
 
162
        mThumbnailBar->setSelectionMode(QAbstractItemView::ExtendedSelection);
 
163
    }
 
164
 
 
165
    void setupThumbnailBarStyleSheet()
 
166
    {
 
167
        Qt::Orientation orientation = mThumbnailBar->orientation();
 
168
        QColor bgColor = mNormalPalette.color(QPalette::Normal, QPalette::Window);
 
169
        QColor bgSelColor = mNormalPalette.color(QPalette::Normal, QPalette::Highlight);
 
170
 
 
171
        // Avoid dark and bright colors
 
172
        bgColor.setHsv(bgColor.hue(), bgColor.saturation(), (127 + 3 * bgColor.value()) / 4);
 
173
 
 
174
        QColor leftBorderColor = PaintUtils::adjustedHsv(bgColor, 0, 0, qMin(20, 255 - bgColor.value()));
 
175
        QColor rightBorderColor = PaintUtils::adjustedHsv(bgColor, 0, 0, -qMin(40, bgColor.value()));
 
176
        QColor borderSelColor = PaintUtils::adjustedHsv(bgSelColor, 0, 0, -qMin(60, bgSelColor.value()));
 
177
 
 
178
        QString viewCss =
 
179
            "#thumbnailBarView {"
 
180
            "   background-color: rgba(0, 0, 0, 10%);"
 
181
            "}";
 
182
 
 
183
        QString itemCss =
 
184
            "QListView::item {"
 
185
            "   background-color: %1;"
 
186
            "   border-left: 1px solid %2;"
 
187
            "   border-right: 1px solid %3;"
 
188
            "}";
 
189
        itemCss = itemCss.arg(
 
190
                      gradient(orientation, bgColor, 46),
 
191
                      gradient(orientation, leftBorderColor, 36),
 
192
                      gradient(orientation, rightBorderColor, 26));
 
193
 
 
194
        QString itemSelCss =
 
195
            "QListView::item:selected {"
 
196
            "   background-color: %1;"
 
197
            "   border-left: 1px solid %2;"
 
198
            "   border-right: 1px solid %2;"
 
199
            "}";
 
200
        itemSelCss = itemSelCss.arg(
 
201
                         gradient(orientation, bgSelColor, 56),
 
202
                         rgba(borderSelColor));
 
203
 
 
204
        QString css = viewCss + itemCss + itemSelCss;
 
205
        if (orientation == Qt::Vertical) {
 
206
            css.replace("left", "top").replace("right", "bottom");
 
207
        }
 
208
 
 
209
        mThumbnailBar->setStyleSheet(css);
 
210
    }
 
211
 
 
212
    void setupAdapterContainer()
 
213
    {
 
214
        mAdapterContainer = new QWidget;
 
215
 
 
216
        QVBoxLayout* layout = new QVBoxLayout(mAdapterContainer);
 
217
        layout->setMargin(0);
 
218
        layout->setSpacing(0);
 
219
        mDocumentViewContainer = new DocumentViewContainer;
 
220
        mDocumentViewContainer->setAutoFillBackground(true);
 
221
        mDocumentViewContainer->setBackgroundRole(QPalette::Base);
 
222
        layout->addWidget(mDocumentViewContainer);
 
223
        layout->addWidget(mToolContainer);
 
224
        layout->addWidget(mStatusBarContainer);
 
225
    }
 
226
 
 
227
    void setupDocumentViewController()
 
228
    {
 
229
        mDocumentViewController = new DocumentViewController(mActionCollection, q);
 
230
        mDocumentViewController->setZoomWidget(mZoomWidget);
 
231
        mDocumentViewController->setToolContainer(mToolContainer);
 
232
        mSynchronizer = new DocumentViewSynchronizer(q);
 
233
    }
 
234
 
 
235
    DocumentView* createDocumentView()
 
236
    {
 
237
        DocumentView* view = mDocumentViewContainer->createView();
 
238
 
 
239
        // Connect context menu
 
240
        QObject::connect(view, SIGNAL(contextMenuRequested()),
 
241
                         q, SLOT(showContextMenu()));
 
242
 
 
243
        QObject::connect(view, SIGNAL(completed()),
 
244
                         q, SIGNAL(completed()));
 
245
        QObject::connect(view, SIGNAL(previousImageRequested()),
 
246
                         q, SIGNAL(previousImageRequested()));
 
247
        QObject::connect(view, SIGNAL(nextImageRequested()),
 
248
                         q, SIGNAL(nextImageRequested()));
 
249
        QObject::connect(view, SIGNAL(captionUpdateRequested(QString)),
 
250
                         q, SIGNAL(captionUpdateRequested(QString)));
 
251
        QObject::connect(view, SIGNAL(toggleFullScreenRequested()),
 
252
                         q, SIGNAL(toggleFullScreenRequested()));
 
253
        QObject::connect(view, SIGNAL(focused(DocumentView*)),
 
254
                         q, SLOT(slotViewFocused(DocumentView*)));
 
255
        QObject::connect(view, SIGNAL(hudTrashClicked(DocumentView*)),
 
256
                         q, SLOT(trashView(DocumentView*)));
 
257
        QObject::connect(view, SIGNAL(hudDeselectClicked(DocumentView*)),
 
258
                         q, SLOT(deselectView(DocumentView*)));
 
259
 
 
260
        QObject::connect(view, SIGNAL(videoFinished()),
 
261
                         mSlideShow, SLOT(resumeAndGoToNextUrl()));
 
262
 
 
263
        mDocumentViews << view;
 
264
 
 
265
        return view;
 
266
    }
 
267
 
 
268
    void deleteDocumentView(DocumentView* view)
 
269
    {
 
270
        mDocumentViewContainer->deleteView(view);
 
271
        mDocumentViews.removeOne(view);
 
272
    }
 
273
 
 
274
    void setupToolContainer()
 
275
    {
 
276
        mToolContainer = new SlideContainer;
 
277
    }
 
278
 
 
279
    void setupStatusBar()
 
280
    {
 
281
        mStatusBarContainer = new QWidget;
 
282
        mToggleSideBarButton = new StatusBarToolButton;
 
283
        mToggleThumbnailBarButton = new StatusBarToolButton;
 
284
        mZoomWidget = new ZoomWidget;
 
285
        mSynchronizeCheckBox = new QCheckBox(i18n("Synchronize"));
 
286
        mSynchronizeCheckBox->hide();
 
287
 
 
288
        QHBoxLayout* layout = new QHBoxLayout(mStatusBarContainer);
 
289
        layout->setMargin(0);
 
290
        layout->setSpacing(0);
 
291
        layout->addWidget(mToggleSideBarButton);
 
292
        layout->addWidget(mToggleThumbnailBarButton);
 
293
        layout->addStretch();
 
294
        layout->addWidget(mSynchronizeCheckBox);
 
295
        layout->addStretch();
 
296
        layout->addWidget(mZoomWidget);
 
297
    }
 
298
 
 
299
    void setupSplitter()
 
300
    {
 
301
        Qt::Orientation orientation = GwenviewConfig::thumbnailBarOrientation();
 
302
        mThumbnailSplitter = new Splitter(orientation == Qt::Horizontal ? Qt::Vertical : Qt::Horizontal, q);
 
303
        mThumbnailBar->setOrientation(orientation);
 
304
        mThumbnailBar->setRowCount(GwenviewConfig::thumbnailBarRowCount());
 
305
        mThumbnailSplitter->addWidget(mAdapterContainer);
 
306
        mThumbnailSplitter->addWidget(mThumbnailBar);
 
307
        mThumbnailSplitter->setSizes(GwenviewConfig::thumbnailSplitterSizes());
 
308
 
 
309
        QVBoxLayout* layout = new QVBoxLayout(q);
 
310
        layout->setMargin(0);
 
311
        layout->addWidget(mThumbnailSplitter);
 
312
    }
 
313
 
 
314
    void applyPalette()
 
315
    {
 
316
        QPalette palette = mFullScreenMode ? mFullScreenPalette : mNormalPalette;
 
317
        mDocumentViewContainer->setPalette(palette);
 
318
    }
 
319
 
 
320
    void saveSplitterConfig()
 
321
    {
 
322
        if (mThumbnailBar->isVisible()) {
 
323
            GwenviewConfig::setThumbnailSplitterSizes(mThumbnailSplitter->sizes());
 
324
        }
 
325
    }
 
326
 
 
327
    DocumentView* currentView() const {
 
328
        return mDocumentViewController->view();
 
329
    }
 
330
 
 
331
    void setCurrentView(DocumentView* view)
 
332
    {
 
333
        DocumentView* oldView = currentView();
 
334
        if (view == oldView) {
 
335
            return;
 
336
        }
 
337
        if (oldView) {
 
338
            oldView->setCurrent(false);
 
339
        }
 
340
        view->setCurrent(true);
 
341
        mDocumentViewController->setView(view);
 
342
        mSynchronizer->setCurrentView(view);
 
343
 
 
344
        QModelIndex index = indexForView(view);
 
345
        if (!index.isValid()) {
 
346
            kWarning() << "No index found for current view";
 
347
            return;
 
348
        }
 
349
        mThumbnailBar->selectionModel()->setCurrentIndex(index, QItemSelectionModel::Current);
 
350
    }
 
351
 
 
352
    QModelIndex indexForView(DocumentView* view) const {
 
353
        KUrl url = view->url();
 
354
        if (!url.isValid()) {
 
355
            kWarning() << "View does not display any document!";
 
356
            return QModelIndex();
 
357
        }
 
358
 
 
359
        // FIXME: Ugly coupling!
 
360
        SortedDirModel* model = static_cast<SortedDirModel*>(mThumbnailBar->model());
 
361
        return model->indexForUrl(url);
 
362
    }
 
363
};
 
364
 
 
365
ViewMainPage::ViewMainPage(QWidget* parent, SlideShow* slideShow, KActionCollection* actionCollection)
 
366
: QWidget(parent)
 
367
, d(new ViewMainPagePrivate)
 
368
{
 
369
    d->q = this;
 
370
    d->mSlideShow = slideShow;
 
371
    d->mActionCollection = actionCollection;
 
372
    d->mFullScreenMode = false;
 
373
    d->mCompareMode = false;
 
374
    d->mThumbnailBarVisibleBeforeFullScreen = false;
 
375
    d->mFullScreenPalette = QPalette(palette());
 
376
    d->mFullScreenPalette.setColor(QPalette::Base, Qt::black);
 
377
    d->mFullScreenPalette.setColor(QPalette::Text, Qt::white);
 
378
 
 
379
    QShortcut* toggleFullScreenShortcut = new QShortcut(this);
 
380
    toggleFullScreenShortcut->setKey(Qt::Key_Return);
 
381
    connect(toggleFullScreenShortcut, SIGNAL(activated()), SIGNAL(toggleFullScreenRequested()));
 
382
 
 
383
    d->setupToolContainer();
 
384
    d->setupStatusBar();
 
385
 
 
386
    d->setupAdapterContainer();
 
387
 
 
388
    d->setupThumbnailBar();
 
389
 
 
390
    d->setupSplitter();
 
391
 
 
392
    d->setupDocumentViewController();
 
393
 
 
394
    KActionCategory* view = new KActionCategory(i18nc("@title actions category - means actions changing smth in interface", "View"), actionCollection);
 
395
 
 
396
    d->mToggleThumbnailBarAction = view->add<KToggleAction>(QString("toggle_thumbnailbar"));
 
397
    d->mToggleThumbnailBarAction->setText(i18n("Thumbnail Bar"));
 
398
    d->mToggleThumbnailBarAction->setIcon(KIcon("folder-image"));
 
399
    d->mToggleThumbnailBarAction->setShortcut(Qt::CTRL | Qt::Key_B);
 
400
    d->mToggleThumbnailBarAction->setChecked(GwenviewConfig::thumbnailBarIsVisible());
 
401
    connect(d->mToggleThumbnailBarAction, SIGNAL(triggered(bool)),
 
402
            this, SLOT(setThumbnailBarVisibility(bool)));
 
403
    d->mToggleThumbnailBarButton->setDefaultAction(d->mToggleThumbnailBarAction);
 
404
 
 
405
    d->mSynchronizeAction = view->add<KToggleAction>("synchronize_views");
 
406
    d->mSynchronizeAction->setText(i18n("Synchronize"));
 
407
    d->mSynchronizeAction->setShortcut(Qt::CTRL | Qt::Key_Y);
 
408
    connect(d->mSynchronizeAction, SIGNAL(toggled(bool)),
 
409
            d->mSynchronizer, SLOT(setActive(bool)));
 
410
    // Ensure mSynchronizeAction and mSynchronizeCheckBox are in sync
 
411
    connect(d->mSynchronizeAction, SIGNAL(toggled(bool)),
 
412
            d->mSynchronizeCheckBox, SLOT(setChecked(bool)));
 
413
    connect(d->mSynchronizeCheckBox, SIGNAL(toggled(bool)),
 
414
            d->mSynchronizeAction, SLOT(setChecked(bool)));
 
415
}
 
416
 
 
417
ViewMainPage::~ViewMainPage()
 
418
{
 
419
    delete d;
 
420
}
 
421
 
 
422
void ViewMainPage::loadConfig()
 
423
{
 
424
    // FIXME: Not symetric with saveConfig(). Check if it matters.
 
425
    Q_FOREACH(DocumentView * view, d->mDocumentViews) {
 
426
        view->loadAdapterConfig();
 
427
    }
 
428
 
 
429
    Qt::Orientation orientation = GwenviewConfig::thumbnailBarOrientation();
 
430
    d->mThumbnailSplitter->setOrientation(orientation == Qt::Horizontal ? Qt::Vertical : Qt::Horizontal);
 
431
    d->mThumbnailBar->setOrientation(orientation);
 
432
    d->setupThumbnailBarStyleSheet();
 
433
 
 
434
    int oldRowCount = d->mThumbnailBar->rowCount();
 
435
    int newRowCount = GwenviewConfig::thumbnailBarRowCount();
 
436
    if (oldRowCount != newRowCount) {
 
437
        d->mThumbnailBar->setUpdatesEnabled(false);
 
438
        int gridSize = d->mThumbnailBar->gridSize().width();
 
439
 
 
440
        d->mThumbnailBar->setRowCount(newRowCount);
 
441
 
 
442
        // Adjust splitter to ensure thumbnail size remains the same
 
443
        int delta = (newRowCount - oldRowCount) * gridSize;
 
444
        QList<int> sizes = d->mThumbnailSplitter->sizes();
 
445
        Q_ASSERT(sizes.count() == 2);
 
446
        sizes[0] -= delta;
 
447
        sizes[1] += delta;
 
448
        d->mThumbnailSplitter->setSizes(sizes);
 
449
 
 
450
        d->mThumbnailBar->setUpdatesEnabled(true);
 
451
    }
 
452
}
 
453
 
 
454
void ViewMainPage::saveConfig()
 
455
{
 
456
    d->saveSplitterConfig();
 
457
    GwenviewConfig::setThumbnailBarIsVisible(d->mToggleThumbnailBarAction->isChecked());
 
458
}
 
459
 
 
460
void ViewMainPage::setThumbnailBarVisibility(bool visible)
 
461
{
 
462
    d->saveSplitterConfig();
 
463
    d->mThumbnailBar->setVisible(visible);
 
464
}
 
465
 
 
466
int ViewMainPage::statusBarHeight() const
 
467
{
 
468
    return d->mStatusBarContainer->height();
 
469
}
 
470
 
 
471
void ViewMainPage::setFullScreenMode(bool fullScreenMode)
 
472
{
 
473
    d->mFullScreenMode = fullScreenMode;
 
474
    d->mStatusBarContainer->setVisible(!fullScreenMode);
 
475
    d->applyPalette();
 
476
    if (fullScreenMode) {
 
477
        d->mThumbnailBarVisibleBeforeFullScreen = d->mToggleThumbnailBarAction->isChecked();
 
478
        if (d->mThumbnailBarVisibleBeforeFullScreen) {
 
479
            d->mToggleThumbnailBarAction->trigger();
 
480
        }
 
481
    } else if (d->mThumbnailBarVisibleBeforeFullScreen) {
 
482
        d->mToggleThumbnailBarAction->trigger();
 
483
    }
 
484
    d->mToggleThumbnailBarAction->setEnabled(!fullScreenMode);
 
485
}
 
486
 
 
487
bool ViewMainPage::isFullScreenMode() const
 
488
{
 
489
    return d->mFullScreenMode;
 
490
}
 
491
 
 
492
ThumbnailBarView* ViewMainPage::thumbnailBar() const
 
493
{
 
494
    return d->mThumbnailBar;
 
495
}
 
496
 
 
497
inline void addActionToMenu(KMenu* menu, KActionCollection* actionCollection, const char* name)
 
498
{
 
499
    QAction* action = actionCollection->action(name);
 
500
    if (action) {
 
501
        menu->addAction(action);
 
502
    }
 
503
}
 
504
 
 
505
void ViewMainPage::showContextMenu()
 
506
{
 
507
    KMenu menu(this);
 
508
    addActionToMenu(&menu, d->mActionCollection, "fullscreen");
 
509
    menu.addSeparator();
 
510
    addActionToMenu(&menu, d->mActionCollection, "go_previous");
 
511
    addActionToMenu(&menu, d->mActionCollection, "go_next");
 
512
    if (d->currentView()->canZoom()) {
 
513
        menu.addSeparator();
 
514
        addActionToMenu(&menu, d->mActionCollection, "view_actual_size");
 
515
        addActionToMenu(&menu, d->mActionCollection, "view_zoom_to_fit");
 
516
        addActionToMenu(&menu, d->mActionCollection, "view_zoom_in");
 
517
        addActionToMenu(&menu, d->mActionCollection, "view_zoom_out");
 
518
    }
 
519
    if (d->mCompareMode) {
 
520
        menu.addSeparator();
 
521
        addActionToMenu(&menu, d->mActionCollection, "synchronize_views");
 
522
    }
 
523
 
 
524
    menu.addSeparator();
 
525
    addActionToMenu(&menu, d->mActionCollection, "file_copy_to");
 
526
    addActionToMenu(&menu, d->mActionCollection, "file_move_to");
 
527
    addActionToMenu(&menu, d->mActionCollection, "file_link_to");
 
528
    menu.addSeparator();
 
529
    addActionToMenu(&menu, d->mActionCollection, "file_open_with");
 
530
    menu.exec(QCursor::pos());
 
531
}
 
532
 
 
533
QSize ViewMainPage::sizeHint() const
 
534
{
 
535
    return QSize(400, 300);
 
536
}
 
537
 
 
538
KUrl ViewMainPage::url() const
 
539
{
 
540
    if (!d->currentView()) {
 
541
        LOG("!d->documentView()");
 
542
        return KUrl();
 
543
    }
 
544
 
 
545
    return d->currentView()->url();
 
546
}
 
547
 
 
548
Document::Ptr ViewMainPage::currentDocument() const
 
549
{
 
550
    if (!d->currentView()) {
 
551
        LOG("!d->documentView()");
 
552
        return Document::Ptr();
 
553
    }
 
554
 
 
555
    return d->currentView()->document();
 
556
}
 
557
 
 
558
bool ViewMainPage::isEmpty() const
 
559
{
 
560
    if (!d->currentView()) {
 
561
        return true;
 
562
    }
 
563
    return d->currentView()->isEmpty();
 
564
}
 
565
 
 
566
RasterImageView* ViewMainPage::imageView() const
 
567
{
 
568
    if (!d->currentView()) {
 
569
        return 0;
 
570
    }
 
571
    return d->currentView()->imageView();
 
572
}
 
573
 
 
574
DocumentView* ViewMainPage::documentView() const
 
575
{
 
576
    return d->currentView();
 
577
}
 
578
 
 
579
void ViewMainPage::setNormalPalette(const QPalette& palette)
 
580
{
 
581
    d->mNormalPalette = palette;
 
582
    d->applyPalette();
 
583
    d->setupThumbnailBarStyleSheet();
 
584
}
 
585
 
 
586
void ViewMainPage::openUrl(const KUrl& url)
 
587
{
 
588
    openUrls(KUrl::List() << url, url);
 
589
}
 
590
 
 
591
void ViewMainPage::openUrls(const KUrl::List& _urls, const KUrl& currentUrl)
 
592
{
 
593
    QSet<KUrl> urls = _urls.toSet();
 
594
    d->mCompareMode = urls.count() > 1;
 
595
 
 
596
    // Destroy views which show urls we don't care about, remove from "urls" the
 
597
    // urls which already have a view.
 
598
    Q_FOREACH(DocumentView * view, d->mDocumentViews) {
 
599
        KUrl url = view->url();
 
600
        if (urls.contains(url)) {
 
601
            // view displays an url we must display, keep it
 
602
            urls.remove(url);
 
603
        } else {
 
604
            // view url is not interesting, drop it
 
605
            d->deleteDocumentView(view);
 
606
        }
 
607
    }
 
608
 
 
609
    // Create view for remaining urls
 
610
    typedef QPair<DocumentView*, KUrl> ViewUrlPair;
 
611
    QList<ViewUrlPair> urlForViewList;
 
612
    Q_FOREACH(const KUrl & url, urls) {
 
613
        if (d->mDocumentViews.count() >= MaxViewCount) {
 
614
            kWarning() << "Too many documents to show";
 
615
            break;
 
616
        }
 
617
        DocumentView* view = d->createDocumentView();
 
618
        urlForViewList << qMakePair(view, url);
 
619
    }
 
620
 
 
621
    d->mDocumentViewContainer->updateLayout();
 
622
 
 
623
    // Load urls for new views. Do it only now because the view must have the
 
624
    // correct size before it starts loading its url. Do not do it later because
 
625
    // view->url() needs to be set for the next loop.
 
626
    Q_FOREACH(const ViewUrlPair & pair, urlForViewList) {
 
627
        pair.first->openUrl(pair.second);
 
628
    }
 
629
 
 
630
    // Init views
 
631
    Q_FOREACH(DocumentView * view, d->mDocumentViews) {
 
632
        view->setCompareMode(d->mCompareMode);
 
633
        if (view->url() == currentUrl) {
 
634
            d->setCurrentView(view);
 
635
        } else {
 
636
            view->setCurrent(false);
 
637
        }
 
638
    }
 
639
 
 
640
    d->mSynchronizeCheckBox->setVisible(d->mCompareMode);
 
641
    if (d->mCompareMode) {
 
642
        d->mSynchronizer->setDocumentViews(d->mDocumentViews);
 
643
        d->mSynchronizer->setActive(d->mSynchronizeCheckBox->isChecked());
 
644
    } else {
 
645
        d->mSynchronizer->setDocumentViews(QList<DocumentView*>());
 
646
        d->mSynchronizer->setActive(false);
 
647
    }
 
648
}
 
649
 
 
650
void ViewMainPage::reload()
 
651
{
 
652
    Document::Ptr doc = d->currentView()->document();
 
653
    if (!doc) {
 
654
        kWarning() << "!doc";
 
655
        return;
 
656
    }
 
657
    if (doc->isModified()) {
 
658
        KGuiItem cont = KStandardGuiItem::cont();
 
659
        cont.setText(i18nc("@action:button", "Discard Changes and Reload"));
 
660
        int answer = KMessageBox::warningContinueCancel(this,
 
661
                     i18nc("@info", "This image has been modified. Reloading it will discard all your changes."),
 
662
                     QString() /* caption */,
 
663
                     cont);
 
664
        if (answer != KMessageBox::Continue) {
 
665
            return;
 
666
        }
 
667
    }
 
668
    doc->reload();
 
669
    // Call openUrl again because DocumentView may need to switch to a new
 
670
    // adapter (for example because document was broken and it is not anymore)
 
671
    d->currentView()->openUrl(doc->url());
 
672
}
 
673
 
 
674
void ViewMainPage::reset()
 
675
{
 
676
    d->mDocumentViewController->setView(0);
 
677
    d->mDocumentViewContainer->reset();
 
678
    d->mDocumentViews.clear();
 
679
}
 
680
 
 
681
void ViewMainPage::slotViewFocused(DocumentView* view)
 
682
{
 
683
    d->setCurrentView(view);
 
684
}
 
685
 
 
686
void ViewMainPage::trashView(DocumentView* view)
 
687
{
 
688
    KUrl url = view->url();
 
689
    deselectView(view);
 
690
    FileOperations::trash(KUrl::List() << url, this);
 
691
}
 
692
 
 
693
void ViewMainPage::deselectView(DocumentView* view)
 
694
{
 
695
    DocumentView* newCurrentView = 0;
 
696
    if (view == d->currentView()) {
 
697
        // We need to find a new view to set as current
 
698
        int idx = d->mDocumentViews.indexOf(view);
 
699
        // Look for the next visible view after the current one
 
700
        for (int newIdx = idx + 1; newIdx < d->mDocumentViews.count(); ++newIdx) {
 
701
            newCurrentView = d->mDocumentViews.at(newIdx);
 
702
            break;
 
703
        }
 
704
        if (!newCurrentView) {
 
705
            // No visible view found after the current one, look before
 
706
            for (int newIdx = idx - 1; newIdx >= 0; --newIdx) {
 
707
                newCurrentView = d->mDocumentViews.at(newIdx);
 
708
                break;
 
709
            }
 
710
        }
 
711
        if (!newCurrentView) {
 
712
            kWarning() << "No view found to set as current, this should not happen!";
 
713
        }
 
714
    }
 
715
 
 
716
    QModelIndex index = d->indexForView(view);
 
717
    QItemSelectionModel* selectionModel = d->mThumbnailBar->selectionModel();
 
718
    selectionModel->select(index, QItemSelectionModel::Deselect);
 
719
 
 
720
    if (newCurrentView) {
 
721
        d->setCurrentView(newCurrentView);
 
722
    }
 
723
}
 
724
 
 
725
QToolButton* ViewMainPage::toggleSideBarButton() const
 
726
{
 
727
    return d->mToggleSideBarButton;
 
728
}
 
729
 
 
730
} // namespace