Git commit d780d15ea9d78ea9ed3914382b844cf796af2f70 by Montel Laurent. Committed on 17/03/2015 at 07:47. Pushed by mlaurent into branch 'frameworks'.
Merge remote-tracking branch 'origin/master' into frameworks Conflicts: autotests/mainshelltest.cpp part.cpp part.h shell/shell.cpp R +119 -1 autotests/mainshelltest.cpp M +1 -1 core/fileprinter.h M +10 -0 doc/index.docbook M +6 -20 part.cpp M +3 -2 part.h M +1 -1 shell/main.cpp M +38 -17 shell/shell.cpp M +11 -5 shell/shell.h M +55 -15 ui/pageview.cpp M +2 -0 ui/pageview.h M +9 -0 ui/sidebar.cpp M +2 -0 ui/sidebar.h http://commits.kde.org/okular/d780d15ea9d78ea9ed3914382b844cf796af2f70 diff --cc autotests/mainshelltest.cpp index 475bf23,a044895..f050d39 --- a/autotests/mainshelltest.cpp +++ b/autotests/mainshelltest.cpp @@@ -7,12 -7,11 +7,12 @@@ * (at your option) any later version. * ***************************************************************************/ -#include <qtest_kde.h> +#include <QtTest> + #include <qprintdialog.h> #include <qwidget.h> - #include <kglobal.h> -#include <ktabwidget.h> +#include <qtabwidget.h> + #include <kconfiggroup.h> #include "../shell/okular_main.h" #include "../shell/shell.h" @@@ -469,6 -484,108 +485,108 @@@ void MainShellTest::test2FilesError( QVERIFY(!s); } + void MainShellTest::testSessionRestore_data() + { + QTest::addColumn<QStringList>("paths"); + QTest::addColumn<QString>("options"); + QTest::addColumn<bool>("useTabsOpen"); + QTest::addColumn<bool>("useTabsRestore"); + + QStringList oneDocPaths( KDESRCDIR "data/file1.pdf" ); + QStringList twoDocPaths( oneDocPaths ); + twoDocPaths << KDESRCDIR "data/formSamples.pdf"; + + const QString options = ShellUtils::serializeOptions(false, false, false, false, QString()); + + QTest::newRow("1 doc, 1 window, tabs") << oneDocPaths << options << true << true; + QTest::newRow("2 docs, 1 window, tabs") << twoDocPaths << options << true << true; + QTest::newRow("2 docs, 2 windows, tabs") << twoDocPaths << options << false << true; + QTest::newRow("2 docs, 2 windows, no tabs") << twoDocPaths << options << false << false; + QTest::newRow("2 docs, 1 window, no tabs") << twoDocPaths << options << true << false; + } + + void MainShellTest::testSessionRestore() + { + QFETCH( QStringList, paths ); + QFETCH( QString, options ); + QFETCH( bool, useTabsOpen ); + QFETCH( bool, useTabsRestore ); + + Okular::Settings::self()->setShellOpenFileInTabs( useTabsOpen ); + + Okular::Status status = Okular::main( paths, options ); + QCOMPARE( status, Okular::Success ); + + // Gather some information about the state + // Verify that the correct number of windows/tabs were opened + QList<Shell*> shells = getShells(); + QVERIFY( !shells.isEmpty() ); + int numDocs = 0; + foreach( Shell* shell, shells ) + { + QTest::qWaitForWindowShown( shell ); + numDocs += shell->m_tabs.size(); + } + + QCOMPARE( numDocs, paths.size() ); + QCOMPARE( shells.size(), useTabsOpen ? 1 : paths.size() ); + QTest::qWait( 100 ); + + // Simulate session shutdown. The actual shutdown path comes through + // QSessionManager XSMP handlers, then KApplication::commitData/saveState, + // then KMWSessionManager::commitData/saveState. Without simulating an X + // session manager, the best we can do here is to make a temporary Config + // and call KMainWindows save functions directly. + QTemporaryFile configFile; + QVERIFY( configFile.open() ); + + int numWindows = 0; + { // Scope for config so that we can reconstruct from file + KConfig config( configFile.fileName(), KConfig::SimpleConfig ); + foreach( Shell* shell, shells ) + { + shell->savePropertiesInternal( &config, ++numWindows ); + // Windows aren't necessarily closed on shutdown, but we'll use + // this as a way to trigger the destructor code, which is normally + // connected to the aboutToQuit signal + shell->close(); + } + } + + // Wait for shells to delete themselves. QTest::qWait doesn't do deferred + // deletions so we'll set up a full event loop to do that. + QEventLoop eventLoop; + QTimer::singleShot( 100, &eventLoop, SLOT(quit()) ); - eventLoop.exec( QEventLoop::AllEvents | QEventLoop::DeferredDeletion ); ++ eventLoop.exec( QEventLoop::AllEvents ); + shells = getShells(); + QVERIFY( shells.isEmpty() ); + + Okular::Settings::self()->setShellOpenFileInTabs( useTabsRestore ); + + // Simulate session restore. We can't call KMainWindow::restore() directly + // because it asks for info from the session manager, which doesn't know + // about our temporary config. But the logic here mostly mirrors restore(). + KConfig config( configFile.fileName(), KConfig::SimpleConfig ); + for( int i = 1; i <= numWindows; ++i ) + { + Shell* shell = new Shell; + shell->readPropertiesInternal( &config, i ); + shell->show(); + } + + // Verify that the restore state is reasonable + shells = getShells(); + QVERIFY( !shells.isEmpty() ); + numDocs = 0; + foreach( Shell* shell, shells ) + { + QTest::qWaitForWindowShown( shell ); + numDocs += shell->m_tabs.size(); + } + + QCOMPARE( numDocs, paths.size() ); + QCOMPARE( shells.size(), useTabsRestore ? numWindows : paths.size() ); + } -QTEST_KDEMAIN( MainShellTest, GUI ) +QTEST_MAIN( MainShellTest ) #include "mainshelltest.moc" diff --cc part.h index 3abdbb5,9eebdb2..11642db --- a/part.h +++ b/part.h @@@ -157,8 -157,9 +157,9 @@@ class OKULARPART_EXPORT Part : public K void openSourceReference(const QString& absFileName, int line, int column); void viewerMenuStateChange(bool enabled); void enableCloseAction(bool enable); - void mimeTypeChanged(KMimeType::Ptr mimeType); - void urlsDropped( const KUrl::List& urls ); + void mimeTypeChanged(QMimeType mimeType); + void urlsDropped( const QList<QUrl>& urls ); + void fitWindowToPage( const QSize& pageViewPortSize, const QSize& pageSize ); protected: // reimplemented from KParts::ReadWritePart @@@ -233,8 -232,10 +232,10 @@@ void warningMessage( const QString &message, int duration = -1 ); void noticeMessage( const QString &message, int duration = -1 ); + void moveSplitter( const int sideWidgetSize ); + private: - Document::OpenResult doOpenFile(const KMimeType::Ptr &mime, const QString &fileNameToOpen, bool *isCompressedFile); + Document::OpenResult doOpenFile(const QMimeType &mime, const QString &fileNameToOpen, bool *isCompressedFile); void setupViewerActions(); void setViewerShortcuts(); diff --cc shell/shell.cpp index 7c8c164,7355968..6bb89c5 --- a/shell/shell.cpp +++ b/shell/shell.cpp @@@ -328,11 -338,19 +337,19 @@@ void Shell::saveProperties(KConfigGrou void Shell::readProperties(const KConfigGroup &group) { - // the 'config' object points to the session managed - // config file. this function is automatically called whenever - // the app is being restored. read in here whatever you wrote - // in 'saveProperties' - emit restoreDocument(group); + // Reopen documents based on saved settings + QStringList urls = group.readPathEntry( SESSION_URL_KEY, QStringList() ); + + while( !urls.isEmpty() ) + { - openUrl( urls.takeFirst() ); ++ openUrl( QUrl(urls.takeFirst()) ); + } + + int desiredTab = group.readEntry<int>( SESSION_TAB_KEY, 0 ); + if( desiredTab < m_tabs.size() ) + { + setActiveTab( desiredTab ); + } } QStringList Shell::fileFormats() const @@@ -553,12 -565,12 +565,12 @@@ void Shell::applyOptionsToPart( QObject void Shell::connectPart( QObject* part ) { - connect( this, SIGNAL(restoreDocument(KConfigGroup)), part, SLOT(restoreDocument(KConfigGroup))); - connect( this, SIGNAL(saveDocumentRestoreInfo(KConfigGroup&)), part, SLOT(saveDocumentRestoreInfo(KConfigGroup&))); + connect( this, SIGNAL(moveSplitter(int)), part, SLOT(moveSplitter(int)) ); connect( part, SIGNAL(enablePrintAction(bool)), this, SLOT(setPrintEnabled(bool))); connect( part, SIGNAL(enableCloseAction(bool)), this, SLOT(setCloseEnabled(bool))); - connect( part, SIGNAL(mimeTypeChanged(KMimeType::Ptr)), this, SLOT(setTabIcon(KMimeType::Ptr))); - connect( part, SIGNAL(urlsDropped(KUrl::List)), this, SLOT(handleDroppedUrls(KUrl::List)) ); + connect( part, SIGNAL(mimeTypeChanged(QMimeType)), this, SLOT(setTabIcon(QMimeType))); + connect( part, SIGNAL(urlsDropped(QList<QUrl>)), this, SLOT(handleDroppedUrls(QList<QUrl>)) ); + connect( part, SIGNAL(fitWindowToPage(QSize,QSize)), this, SLOT(slotFitWindowToPage(QSize,QSize)) ); } void Shell::print() diff --cc shell/shell.h index bc1a35d,fea80ac..f345cf3 --- a/shell/shell.h +++ b/shell/shell.h @@@ -70,10 -67,8 +70,8 @@@ public bool isValid() const; public slots: - void slotQuit(); - Q_SCRIPTABLE Q_NOREPLY void tryRaise(); - Q_SCRIPTABLE bool openDocument( const QString& url, const QString &serializedOptions = QString() ); + Q_SCRIPTABLE bool openDocument(const QUrl &url, const QString &serializedOptions = QString() ); Q_SCRIPTABLE bool canOpenDocs( int numDocs, int desktop ); protected: diff --cc ui/pageview.cpp index 9951dac,49d6f8a..ff221c2 --- a/ui/pageview.cpp +++ b/ui/pageview.cpp @@@ -218,12 -209,13 +218,13 @@@ public KActionMenu * aViewMode; KToggleAction * aViewContinuous; QAction * aPrevAction; - KAction * aToggleForms; - KAction * aSpeakDoc; - KAction * aSpeakPage; - KAction * aSpeakStop; + QAction * aToggleForms; + QAction * aSpeakDoc; + QAction * aSpeakPage; + QAction * aSpeakStop; KActionCollection * actionCollection; QActionGroup * mouseModeActionGroup; - KAction * aFitWindowToPage; ++ QAction * aFitWindowToPage; int setting_viewCols; @@@ -507,8 -492,14 +508,14 @@@ void PageView::setupViewerActions( KAct ac->addAction("view_auto_fit", d->aZoomAutoFit ); connect( d->aZoomAutoFit, SIGNAL(toggled(bool)), SLOT(slotAutoFitToggled(bool)) ); - d->aFitWindowToPage = new KAction(KIcon( "zoom-fit-width" ), i18n("Fit Wi&ndow to Page"), this); ++ d->aFitWindowToPage = new QAction(QIcon::fromTheme( "zoom-fit-width" ), i18n("Fit Wi&ndow to Page"), this); + d->aFitWindowToPage->setEnabled( Okular::Settings::viewMode() == (int)Okular::Settings::EnumViewMode::Single ); + d->aFitWindowToPage->setShortcut( QKeySequence(Qt::CTRL + Qt::Key_J) ); + ac->addAction( "fit_window_to_page", d->aFitWindowToPage ); + connect( d->aFitWindowToPage, SIGNAL(triggered()), this, SLOT(slotFitWindowToPage()) ); + // View-Layout actions - d->aViewMode = new KActionMenu( KIcon( "view-split-left-right" ), i18n( "&View Mode" ), this ); + d->aViewMode = new KActionMenu( QIcon::fromTheme( "view-split-left-right" ), i18n( "&View Mode" ), this ); d->aViewMode->setDelayed( false ); #define ADD_VIEWMODE_ACTION( text, name, id ) \ do { \ @@@ -1100,9 -1082,10 +1107,11 @@@ void PageView::updateActionState( bool d->aSpeakDoc->setEnabled( enablettsactions ); d->aSpeakPage->setEnabled( enablettsactions ); } +#endif if (d->aMouseMagnifier) d->aMouseMagnifier->setEnabled(d->document->supportsTiles()); + if ( d->aFitWindowToPage ) + d->aFitWindowToPage->setEnabled( haspages && !Okular::Settings::viewContinuous() ); } bool PageView::areSourceLocationsShownGraphically() const @@@ -5095,8 -5081,28 +5115,28 @@@ void PageView::slotToggleChangeColors( viewport()->update(); } + void PageView::slotFitWindowToPage() + { + PageViewItem currentPageItem = NULL; + QSize viewportSize = viewport()->size(); + foreach ( const PageViewItem * pageItem, d->items ) + { + if ( pageItem->isVisible() ) + { + currentPageItem = *pageItem; + break; + } + } + const QSize pageSize = QSize( currentPageItem.uncroppedWidth() + kcolWidthMargin, currentPageItem.uncroppedHeight() + krowHeightMargin ); + if ( verticalScrollBar()->isVisible() ) + viewportSize.setWidth( viewportSize.width() + verticalScrollBar()->width() ); + if ( horizontalScrollBar()->isVisible() ) + viewportSize.setHeight( viewportSize.height() + horizontalScrollBar()->height() ); + emit fitWindowToPage( viewportSize, pageSize ); + } + //END private SLOTS -#include "pageview.moc" +#include "moc_pageview.cpp" /* kate: replace-tabs on; indent-width 4; */ diff --cc ui/sidebar.h index 2c4bfbe,2630166..6b38fa3 --- a/ui/sidebar.h +++ b/ui/sidebar.h @@@ -41,8 -42,10 +41,10 @@@ class Sidebar : public QWidge void setCollapsed( bool collapsed ); bool isCollapsed() const; + void moveSplitter( int sideWidgetSize ); + signals: - void urlsDropped( const KUrl::List& urls ); + void urlsDropped( const QList<QUrl>& urls ); protected: void dragEnterEvent( QDragEnterEvent* event );