Git commit 62eea3336b3fdf62102b68bc1ea12f9f8fbce390 by Albert Astals Cid. Committed on 29/10/2016 at 09:13. Pushed by aacid into branch 'frameworks'.
Merge remote-tracking branch 'origin/master' into frameworks M +0 -3 Mainpage.dox A +1 -0 autotests/generatorstest.cpp [License: GPL (v2+)] R +13 -0 autotests/parttest.cpp M +1 -0 conf/dlggeneral.cpp M +73 -13 conf/dlggeneralbase.ui M +3 -0 conf/okular.kcfg M +0 -9 core/area.h M +1 -0 core/document.cpp M +20 -2 doc/index.docbook M +1 -0 generators/chm/okularApplication_chm.desktop M +1 -1 generators/comicbook/document.cpp M +1 -0 generators/comicbook/okularApplication_comicbook.desktop M +1 -0 generators/djvu/okularApplication_djvu.desktop M +1 -0 generators/dvi/okularApplication_dvi.desktop M +1 -0 generators/epub/okularApplication_epub.desktop M +1 -0 generators/fax/okularApplication_fax.desktop M +1 -0 generators/fictionbook/okularApplication_fb.desktop M +1 -0 generators/kimgio/okularApplication_kimgio.desktop M +1 -0 generators/mobipocket/okularApplication_mobi.desktop M +1 -0 generators/ooo/okularApplication_ooo.desktop M +1 -0 generators/plucker/okularApplication_plucker.desktop M +1 -0 generators/poppler/okularApplication_pdf.desktop M +1 -0 generators/spectre/okularApplication_ghostview.desktop M +1 -0 generators/tiff/okularApplication_tiff.desktop M +1 -0 generators/txt/okularApplication_txt.desktop M +1 -0 generators/xps/okularApplication_xps.desktop R +1 -0 shell/org.kde.okular.desktop M +71 -12 ui/embeddedfilesdialog.cpp M +11 -1 ui/embeddedfilesdialog.h M +8 -5 ui/guiutils.cpp M +2 -0 ui/guiutils.h M +4 -4 ui/pagepainter.cpp M +25 -6 ui/pageview.cpp M +1 -1 ui/pageviewannotator.cpp M +29 -21 ui/thumbnaillist.cpp M +59 -12 ui/tocmodel.cpp http://commits.kde.org/okular/62eea3336b3fdf62102b68bc1ea12f9f8fbce390 diff --cc autotests/generatorstest.cpp index 9d63c91,0000000..e8e1962 mode 100644,000000..100644 --- a/autotests/generatorstest.cpp +++ b/autotests/generatorstest.cpp @@@ -1,74 -1,0 +1,75 @@@ +/*************************************************************************** + * Copyright (C) 2015 by Alex Richardson <[email protected]> * + * * + * 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. * + ***************************************************************************/ + +#include <QtTest/QTest> +#include <QDirIterator> +#include <QDebug> +#include <QStringList> +#include <KPluginFactory> +#include <KPluginLoader> + +#include "../generator.h" + +class GeneratorsTest : public QObject +{ + Q_OBJECT +private slots: + void testLoadsCorrectly(); +}; + +void GeneratorsTest::testLoadsCorrectly() +{ + QCoreApplication::setLibraryPaths(QStringList()); + QVERIFY2(QDir(QStringLiteral(GENERATORS_BUILD_DIR)).exists(), GENERATORS_BUILD_DIR); + // find all possible generators in $CMAKE_BINARY_DIR/generators + // We can't simply hardcore the list of generators since some might not be built + // depending on which dependencies were found by CMake + QStringList generatorLibs; + QDirIterator it(QStringLiteral(GENERATORS_BUILD_DIR), QDir::Files | QDir::Executable, QDirIterator::Subdirectories); + while (it.hasNext()) { + it.next(); + if (QLibrary::isLibrary(it.fileName())) { + if (it.fileName().startsWith(QLatin1String("kio_"))) { + continue; // don't check kio_msits.so + } + generatorLibs << it.fileInfo().absoluteFilePath(); + } + } + int failures = 0; + int successful = 0; + foreach (const QString& lib, generatorLibs) { + KPluginLoader loader(lib); + QVERIFY2(!loader.fileName().isEmpty(), qPrintable(lib)); ++ qDebug() << loader.fileName(); + auto factory = loader.factory(); + if (!factory) { + qWarning() << "Could not get KPluginFactory for" << lib; + failures++; + continue; + } + Okular::Generator* generator = factory->create<Okular::Generator>(); + if (!generator) { + qWarning() << "Failed to cast" << lib << "to Okular::Generator"; + // without the necessary Q_INTERFACES() qobject_cast fails! + auto obj = factory->create<QObject>(); + qDebug() << "Object is of type " << obj->metaObject()->className(); + qDebug() << "dynamic_cast:" << dynamic_cast<Okular::Generator*>(obj); + qDebug() << "qobject_cast:" << qobject_cast<Okular::Generator*>(obj); + failures++; + continue; + } + successful++; + } + qDebug() << "Successfully loaded" << successful << "generators"; + QCOMPARE(failures, 0); +} + +QTEST_MAIN(GeneratorsTest) + +#include "generatorstest.moc" diff --cc autotests/parttest.cpp index 46d359d,9afa47d..96085d7 --- a/autotests/parttest.cpp +++ b/autotests/parttest.cpp @@@ -117,22 -111,32 +117,35 @@@ void PartTest::testFowardPDF( QFETCH(QString, dir); QVariantList dummyArgs; - Okular::Part part(NULL, NULL, dummyArgs, KGlobal::mainComponent()); + Okular::Part part(NULL, NULL, dummyArgs); - KTempDir tempDir(dir); - QFile f(KDESRCDIR "data/synctextest.tex"); - const QString texDestination = tempDir.name() + "synctextest.tex"; - QVERIFY(f.copy(texDestination)); + // Create temp dir named like this: ${system temp dir}/${random string}/${dir} + const QTemporaryDir tempDir; + const QDir workDir(QDir(tempDir.path()).filePath(dir)); + workDir.mkpath(QStringLiteral(".")); + QFile f(QStringLiteral(KDESRCDIR "data/synctextest.tex")); + const QString texDestination = workDir.path() + QStringLiteral("/synctextest.tex"); + QVERIFY(f.copy(texDestination)); QProcess process; - process.setWorkingDirectory(tempDir.name()); - process.start("pdflatex", QStringList() << "-synctex=1" << "-interaction=nonstopmode" << texDestination); + process.setWorkingDirectory(workDir.path()); + process.start(QStringLiteral("pdflatex"), QStringList() << QStringLiteral("-synctex=1") << QStringLiteral("-interaction=nonstopmode") << texDestination); + bool started = process.waitForStarted(); + if (!started) { + qDebug() << "start error:" << process.error(); + qDebug() << "start stdout:" << process.readAllStandardOutput(); + qDebug() << "start stderr:" << process.readAllStandardError(); + } + QVERIFY(started); + process.waitForFinished(); + if (process.exitStatus() != QProcess::NormalExit || process.exitCode() != 0) { + qDebug() << "exit error:" << process.error() << "status" << process.exitStatus() << "code" << process.exitCode(); + qDebug() << "exit stdout:" << process.readAllStandardOutput(); + qDebug() << "exit stderr:" << process.readAllStandardError(); + } - const QString pdfResult = tempDir.name() + "synctextest.pdf"; + const QString pdfResult = workDir.path() + QStringLiteral("/synctextest.pdf"); QVERIFY(QFile::exists(pdfResult)); diff --cc conf/dlggeneralbase.ui index c180533,6486747..323d74c mode 100644,100755..100644 --- a/conf/dlggeneralbase.ui +++ b/conf/dlggeneralbase.ui diff --cc core/document.cpp index 848aadd,6953b1f..8bc037e --- a/core/document.cpp +++ b/core/document.cpp @@@ -814,21 -815,21 +814,22 @@@ bool DocumentPrivate::openRelativeFile return true; } -Generator * DocumentPrivate::loadGeneratorLibrary( const KService::Ptr &service ) +Generator * DocumentPrivate::loadGeneratorLibrary( const KPluginMetaData &service ) { - KPluginFactory *factory = KPluginLoader( service->library() ).factory(); + KPluginLoader loader( service.fileName() ); ++ qDebug() << service.fileName(); + KPluginFactory *factory = loader.factory(); if ( !factory ) { - kWarning(OkularDebug).nospace() << "Invalid plugin factory for " << service->library() << "!"; + qCWarning(OkularCoreDebug).nospace() << "Invalid plugin factory for " << service.fileName() << ":" << loader.errorString(); return 0; } - Generator * generator = factory->create< Okular::Generator >( service->pluginKeyword(), 0 ); - GeneratorInfo info( factory->componentData() ); - info.generator = generator; - if ( info.data.isValid() && info.data.aboutData() ) - info.catalogName = info.data.aboutData()->catalogName(); - m_loadedGenerators.insert( service->name(), info ); - return generator; + + Generator * plugin = factory->create<Okular::Generator>(); + + GeneratorInfo info( plugin, service ); + m_loadedGenerators.insert( service.pluginId(), info ); + return plugin; } void DocumentPrivate::loadAllGeneratorLibraries() diff --cc generators/comicbook/document.cpp index 54c4c3c,72b2c55..34c4cb5 --- a/generators/comicbook/document.cpp +++ b/generators/comicbook/document.cpp @@@ -78,7 -75,7 +78,7 @@@ bool Document::open( const QString &fil if ( !processArchive() ) { return false; } - } else if ( mime.inherits( QStringLiteral("application/x-cbr") ) || mime.inherits( QStringLiteral("application/x-rar") ) ) { - } else if ( mime->is( "application/x-cbr" ) || mime->name() == "application/x-rar" || mime->name() == "application/vnd.rar" ) { ++ } else if ( mime.inherits( QStringLiteral("application/x-cbr") ) || mime.inherits( QStringLiteral("application/x-rar") ) || mime.inherits( QStringLiteral("application/vnd.rar") ) ) { if ( !Unrar::isAvailable() ) { mLastErrorString = i18n( "Cannot open document, unrar was not found." ); return false; diff --cc ui/embeddedfilesdialog.cpp index 4d17841,ec0d2b1..f3916f6 --- a/ui/embeddedfilesdialog.cpp +++ b/ui/embeddedfilesdialog.cpp @@@ -11,20 -11,19 +11,24 @@@ #include <QAction> #include <QCursor> + #include <QDir> #include <QDateTime> + #include <QFileInfo> #include <QMenu> #include <QTreeWidget> + #include <QTemporaryFile> -#include <kglobal.h> -#include <kicon.h> -#include <klocale.h> -#include <kmimetype.h> +#include <QIcon> +#include <KLocalizedString> +#include <QMimeType> +#include <QMimeDatabase> #include <kstandardguiitem.h> +#include <KFormat> +#include <KConfigGroup> +#include <QDialogButtonBox> +#include <QPushButton> +#include <QVBoxLayout> + #include <krun.h> #include "core/document.h" #include "guiutils.h" @@@ -40,24 -39,18 +44,29 @@@ static QString dateToString( const QDat : i18nc( "Unknown date", "Unknown" ); } -EmbeddedFilesDialog::EmbeddedFilesDialog(QWidget *parent, const Okular::Document *document) : KDialog(parent) +EmbeddedFilesDialog::EmbeddedFilesDialog(QWidget *parent, const Okular::Document *document) : QDialog(parent) { - setCaption(i18nc("@title:window", "Embedded Files")); - setButtons(Close | User1 | User2); - setDefaultButton(Close); - setButtonGuiItem(User1, KStandardGuiItem::save()); - setButtonGuiItem(User2, KGuiItem(i18nc("@action:button", "View"), "document-open")); - enableButton(User1, false); - enableButton(User2, false); + setWindowTitle(i18nc("@title:window", "Embedded Files")); + QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Close); + QVBoxLayout *mainLayout = new QVBoxLayout; + setLayout(mainLayout); + mUser1Button = new QPushButton; + buttonBox->addButton(mUser1Button, QDialogButtonBox::ActionRole); + connect(buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept); + connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject); + buttonBox->button(QDialogButtonBox::Close)->setDefault(true); + KGuiItem::assign(mUser1Button, KStandardGuiItem::save()); + mUser1Button->setEnabled(false); + ++ mUser2Button = new QPushButton; ++ buttonBox->addButton(mUser2Button, QDialogButtonBox::ActionRole); ++ KGuiItem::assign(mUser2Button, KGuiItem(i18nc("@action:button", "View"), "document-open")); ++ mUser1Button->setEnabled(false); + m_tw = new QTreeWidget(this); - setMainWidget(m_tw); + mainLayout->addWidget(m_tw); - mainLayout->addWidget(buttonBox); ++ mainLayout->addWidget(buttonBox); + QStringList header; header.append(i18nc("@title:column", "Name")); header.append(i18nc("@title:column", "Description")); @@@ -73,36 -66,39 +82,39 @@@ { QTreeWidgetItem *twi = new QTreeWidgetItem(); twi->setText(0, ef->name()); - QMimeDatabase db; - QMimeType mime = db.mimeTypeForFile( ef->name(), QMimeDatabase::MatchExtension); - KMimeType::Ptr mime = KMimeType::findByPath( ef->name(), 0, true ); - if (mime) ++ QMimeDatabase db; ++ QMimeType mime = db.mimeTypeForFile( ef->name(), QMimeDatabase::MatchExtension); + if (mime.isValid()) { - twi->setIcon(0, QIcon::fromTheme(mime.iconName())); - twi->setIcon(0, KIcon(mime->iconName())); ++ twi->setIcon(0, QIcon::fromTheme(mime.iconName())); } twi->setText(1, ef->description()); - twi->setText(2, ef->size() <= 0 ? i18nc("Not available size", "N/A") : KGlobal::locale()->formatByteSize(ef->size())); + twi->setText(2, ef->size() <= 0 ? i18nc("Not available size", "N/A") : KFormat().formatByteSize(ef->size())); twi->setText(3, dateToString( ef->creationDate() ) ); twi->setText(4, dateToString( ef->modificationDate() ) ); twi->setData( 0, EmbeddedFileRole, qVariantFromValue( ef ) ); m_tw->addTopLevelItem(twi); } -- // Having filled the columns, it is nice to resize them to be able to read the contents -- for (int lv = 0; lv < m_tw->columnCount(); ++lv) { -- m_tw->resizeColumnToContents(lv); -- } -- // This is a bit dubious, but I'm not seeing a nice way to say "expand to fit contents" -- m_tw->setMinimumWidth(640); -- m_tw->updateGeometry(); - - connect(this, SIGNAL(user1Clicked()), this, SLOT(saveFile())); - connect(this, SIGNAL(user2Clicked()), this, SLOT(viewFile())); - - connect(m_tw, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(attachViewContextMenu(QPoint))); - connect(m_tw, SIGNAL(itemSelectionChanged()), this, SLOT(updateSaveButton())); ++ // Having filled the columns, it is nice to resize them to be able to read the contents ++ for (int lv = 0; lv < m_tw->columnCount(); ++lv) { ++ m_tw->resizeColumnToContents(lv); ++ } ++ // This is a bit dubious, but I'm not seeing a nice way to say "expand to fit contents" ++ m_tw->setMinimumWidth(640); ++ m_tw->updateGeometry(); + + connect(mUser1Button, SIGNAL(clicked()), this, SLOT(saveFile())); ++ connect(mUser2Button, SIGNAL(clicked()), this, SLOT(viewFile())); + connect(m_tw, &QWidget::customContextMenuRequested, this, &EmbeddedFilesDialog::attachViewContextMenu); + connect(m_tw, &QTreeWidget::itemSelectionChanged, this, &EmbeddedFilesDialog::updateSaveButton); + connect(m_tw, SIGNAL(itemDoubleClicked(QTreeWidgetItem*,int)), this, SLOT(viewFileItem(QTreeWidgetItem*,int))); } void EmbeddedFilesDialog::updateSaveButton() { bool enable = (m_tw->selectedItems().count() > 0); - enableButton(User1, enable); - enableButton(User2, enable); + mUser1Button->setEnabled(enable); ++ mUser2Button->setEnabled(enable); } void EmbeddedFilesDialog::saveFile() @@@ -125,7 -137,8 +153,8 @@@ void EmbeddedFilesDialog::attachViewCon return; QMenu menu( this ); - QAction* saveAsAct = menu.addAction( KIcon( "document-save-as" ), i18nc( "@action:inmenu", "&Save As..." ) ); - QAction* viewAct = menu.addAction( KIcon( "document-open" ), i18nc( "@action:inmenu", "&View..." ) ); + QAction* saveAsAct = menu.addAction( QIcon::fromTheme( QStringLiteral("document-save-as") ), i18nc( "@action:inmenu", "&Save As..." ) ); ++ QAction* viewAct = menu.addAction( QIcon::fromTheme( QStringLiteral("document-open" ) ), i18nc( "@action:inmenu", "&View..." ) ); QAction* act = menu.exec( QCursor::pos() ); if ( !act ) diff --cc ui/embeddedfilesdialog.h index 7ec55a8,bb83540..1def992 --- a/ui/embeddedfilesdialog.h +++ b/ui/embeddedfilesdialog.h @@@ -10,10 -10,12 +10,13 @@@ #ifndef _EMBEDDEDFILESDIALOG_H_ #define _EMBEDDEDFILESDIALOG_H_ -#include <kdialog.h> +#include <QDialog> class QTreeWidget; +class QPushButton; + class QTemporaryFile; + class QTreeWidgetItem; + namespace Okular { class Document; class EmbeddedFile; @@@ -32,9 -36,10 +37,14 @@@ Q_OBJEC private: void saveFile( Okular::EmbeddedFile* ); + void viewFile( Okular::EmbeddedFile* ); QTreeWidget *m_tw; - QPushButton *mUser1Button; ++ ++ ++ QPushButton *mUser1Button; ++ QPushButton *mUser2Button; + QList< QSharedPointer<QTemporaryFile> > m_openedFiles; }; #endif diff --cc ui/guiutils.cpp index 14bb85c,b432105..d4c9228 --- a/ui/guiutils.cpp +++ b/ui/guiutils.cpp @@@ -205,18 -202,22 +205,21 @@@ KIconLoader* iconLoader( void saveEmbeddedFile( Okular::EmbeddedFile *ef, QWidget *parent ) { const QString caption = i18n( "Where do you want to save %1?", ef->name() ); - const QString path = KFileDialog::getSaveFileName( ef->name(), QString(), parent, caption, - KFileDialog::ConfirmOverwrite ); + const QString path = QFileDialog::getSaveFileName( parent, caption, ef->name() ); if ( path.isEmpty() ) return; + QFile targetFile( path ); + writeEmbeddedFile( ef, parent, targetFile ); + } - QFile f( path ); - if ( !f.open( QIODevice::WriteOnly ) ) + void writeEmbeddedFile( Okular::EmbeddedFile *ef, QWidget *parent, QFile& target ) { + if ( !target.open( QIODevice::WriteOnly ) ) { - KMessageBox::error( parent, i18n( "Could not open \"%1\" for writing. File was not saved.", path ) ); + KMessageBox::error( parent, i18n( "Could not open \"%1\" for writing. File was not saved.", target.fileName() ) ); return; } - f.write( ef->data() ); - f.close(); + target.write( ef->data() ); + target.close(); } Okular::Movie* renditionMovieFromScreenAnnotation( const Okular::ScreenAnnotation *annotation ) diff --cc ui/pageview.cpp index 339ba69,bb540cb..3e8d650 --- a/ui/pageview.cpp +++ b/ui/pageview.cpp @@@ -223,16 -214,16 +223,16 @@@ 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; - + bool rtl_Mode; // Keep track of whether tablet pen is currently pressed down bool penDown; }; diff --cc ui/tocmodel.cpp index ccbaa4c,fcc7658..0a4608c --- a/ui/tocmodel.cpp +++ b/ui/tocmodel.cpp @@@ -12,8 -12,9 +12,9 @@@ #include <qapplication.h> #include <qdom.h> #include <qlist.h> + #include <qtreeview.h> -#include <kicon.h> +#include <QIcon> #include "pageitemdelegate.h" #include "core/document.h" @@@ -198,7 -217,31 +226,31 @@@ QVariant TOCModel::data( const QModelIn break; case Qt::DecorationRole: if ( item->highlight ) - return QIcon::fromTheme( QApplication::layoutDirection() == Qt::RightToLeft ? QStringLiteral("arrow-left") : QStringLiteral("arrow-right") ); + { - const QVariant icon = KIcon( QApplication::layoutDirection() == Qt::RightToLeft ? "arrow-left" : "arrow-right" ); ++ const QVariant icon = QIcon::fromTheme( QApplication::layoutDirection() == Qt::RightToLeft ? QStringLiteral("arrow-left") : QStringLiteral("arrow-right") ); + TOCItem *lastHighlighted = d->currentPage.last(); + + // in the mobile version our parent is not a QTreeView; add icon to the last highlighted item + // TODO misusing parent() here, fix + QTreeView *view = dynamic_cast< QTreeView* > ( QObject::parent() ); + if ( !view ) + { + if ( item == lastHighlighted ) + return icon; + return QVariant(); + } + + if ( view->isExpanded( index ) ) + { + // if this is the last highlighted node, its child is on a page below, thus it needs icon + if ( item == lastHighlighted ) + return icon; + } + else + { + return icon; + } + } break; case PageItemDelegate::PageRole: if ( item->viewport.isValid() )
