Git commit ed3ea7dbbbfb8965d2709193c1d77555fc12fdee by Elvis Angelaccio. Committed on 23/10/2014 at 16:40. Pushed by elvisangelaccio into branch 'KDE/4.14'.
Add the 'open-with' action and show the right-click menu. This patch implements the 'open-with' action, which allows the users to temporarily extract a file and open it with a chosen application. A contextual menu has been implemented as well. This menu is showed when the user right-clicks on an entry in the archive. FEATURE: 179066 FIXED-IN: 4.14.3 REVIEW: 120216 GUI: DIGEST: M +1 -6 app/ark.appdata.xml M +8 -1 part/ark_part.rc M +53 -11 part/part.cpp M +12 -3 part/part.h http://commits.kde.org/ark/ed3ea7dbbbfb8965d2709193c1d77555fc12fdee diff --git a/app/ark.appdata.xml b/app/ark.appdata.xml index 9de3280..e2b3d18 100644 --- a/app/ark.appdata.xml +++ b/app/ark.appdata.xml @@ -66,7 +66,6 @@ <summary xml:lang="sr-ijekavian">?????? ?? ??????????</summary> <summary xml:lang="sr-ijekavianlatin">Alatka za arhiviranje</summary> <summary xml:lang="sv">Arkiveringsverktyg</summary> - <summary xml:lang="tr">Ar?ivleme Arac?</summary> <summary xml:lang="uk">?????????? ?????? ? ????????</summary> <summary xml:lang="x-test">xxArchiving Toolxx</summary> <summary xml:lang="zh-CN">????</summary> @@ -103,7 +102,6 @@ <p xml:lang="sr-ijekavian">??? ?? ???????? ?????? ?? ???????????? ? ?????????????? ???????. ???????? ???? ???????, ???? ???? ?: ???, ????, ????2, ???, ???, ??? ? ?? ??????. ???? ?? ????????? ?? ??????????, ???????????, ???????? ? ?????? ??????.</p> <p xml:lang="sr-ijekavianlatin">Ark je grafi?ka alatka za kompresovanje i dekompresovanje fajlova. Podr?ava vi?e formata, me?u njima i: tar, gzip, bzip2, RAR, ZIP, kao i CD odraze. Mo?e se koristiti za pregledanje, raspakivanje, stvaranje i menjanje arhiva.</p> <p xml:lang="sv">Ark ?r ett grafiskt verktyg f?r komprimering och uppackning av filer med st?d f?r flera format, inklusive tar, gzip, bzip2, rar och zip, samt cd-rom avbilder. Ark kan anv?ndas f?r att bl?ddra i, packa upp, skapa och ?ndra arkiv.</p> - <p xml:lang="tr">Ark; tar, gzip, bzip2, rar ve zip dosyalar?n?n yan?nda CD-ROM kal?plar?n? da destekleyen grafiksel bir dosya s?k??t?rma/a?ma yard?mc?s?d?r. Ark ar?ivlerde gezinmek, ar?iv ay?klamak, olu?turmak ve de?i?tirmek i?in kullan?labilir.</p> <p xml:lang="uk">Ark ? ???????? ? ????????? ???????????, ?????????? ??? ????????? ????? ? ?????? ?? ??????????? ????? ? ???????. ??????????? ????????? ????????? ???????? ???????, ??????? tar, gzip, bzip2, rar ?? zip, ? ????? ??????? ??????. Ark ????? ??????????????? ??? ?????????, ???????????, ????????? ?? ???????? ???? ?? ???????.</p> <p xml:lang="x-test">xxArk is a graphical file compression/decompression utility with support for multiple formats, including tar, gzip, bzip2, rar and zip, as well as CD-ROM images. Ark can be used to browse, extract, create, and modify archives.xx</p> <p xml:lang="zh-CN">Ark ?????????????????????? tar, gzip, bzip2, rar and zip ?? CD-ROM ???Ark ???????????????????</p> @@ -137,11 +135,10 @@ <p xml:lang="sr-ijekavian">??????????:</p> <p xml:lang="sr-ijekavianlatin">Mogu?nosti:</p> <p xml:lang="sv">Funktioner:</p> - <p xml:lang="tr">?zellikler:</p> <p xml:lang="uk">??????????:</p> <p xml:lang="x-test">xxFeatures:xx</p> <p xml:lang="zh-CN">???</p> - <p xml:lang="zh-TW">???</p> + <p xml:lang="zh-TW">???</p> <ul> <li>Several formats supported: gzip, bzip2, zip, rar, 7z and more</li> <li xml:lang="ar">??? ??? ???????: ??? gzip? ? bzip2? ? zip? ? rar? ? 7z ??????</li> @@ -171,7 +168,6 @@ <li xml:lang="sr-ijekavian">???? ????????? ???????: ????, ????2, ???, ???, 7???, ???.</li> <li xml:lang="sr-ijekavianlatin">Vi?e podr?anih formata: gzip, bzip2, ZIP, RAR, 7zip, itd.</li> <li xml:lang="sv">En m?ngd format st?ds: gzip, bzip2, zip, rar, 7z med flera</li> - <li xml:lang="tr">?e?itli bi?imler destekleniyor: gzip, bzip2, zip, rar, 7z ve dahas?</li> <li xml:lang="uk">????????? ????????? ????????: gzip, bzip2, zip, rar, 7z ????</li> <li xml:lang="x-test">xxSeveral formats supported: gzip, bzip2, zip, rar, 7z and morexx</li> <li xml:lang="zh-CN">???????gzip, bzip2, zip, rar, 7z ?</li> @@ -204,7 +200,6 @@ <li xml:lang="sr-ijekavian">??????? ???????? ??????? ??? ???????????.</li> <li xml:lang="sr-ijekavianlatin">Pregled sadr?aja fajlova bez raspakivanja.</li> <li xml:lang="sv">F?rhandsgranska filinneh?ll utan att packa upp filer</li> - <li xml:lang="tr">Dosyalar? ay?klamadan dosya i?eri?i ?nizlemesi</li> <li xml:lang="uk">?????????? ???????? ?????? ?????? ??? ??????????????</li> <li xml:lang="x-test">xxPreview file contents without extracting filesxx</li> <li xml:lang="zh-CN">????????</li> diff --git a/part/ark_part.rc b/part/ark_part.rc index 044c11a..da04d47 100644 --- a/part/ark_part.rc +++ b/part/ark_part.rc @@ -1,5 +1,5 @@ <!DOCTYPE kpartgui> -<kpartgui name="ark_part" version="1"> +<kpartgui name="ark_part" version="2"> <MenuBar> <Menu name="file"> <text>&File</text> @@ -12,6 +12,7 @@ <Action name="delete"/> <Action name="extract"/> <Action name="preview"/> + <Action name="openwith"/> </Menu> <Menu name="settings"> <text>&Settings</text> @@ -25,4 +26,10 @@ <Action name="extract"/> <Action name="preview"/> </ToolBar> +<Menu name="context_menu"> + <Action name="delete"/> + <Action name="extract"/> + <Action name="preview"/> + <Action name="openwith"/> +</Menu> </kpartgui> diff --git a/part/part.cpp b/part/part.cpp index 09fe1cb..4d5b42f 100644 --- a/part/part.cpp +++ b/part/part.cpp @@ -45,6 +45,7 @@ #include <KIO/NetAccess> #include <KIcon> #include <KInputDialog> +#include <KMenu> #include <KMessageBox> #include <KPluginFactory> #include <KRun> @@ -53,6 +54,7 @@ #include <KStandardGuiItem> #include <KTempDir> #include <KToggleAction> +#include <KXMLGUIFactory> #include <QAction> #include <QCursor> @@ -137,6 +139,8 @@ Part::Part(QWidget *parentWidget, QObject *parent, const QVariantList& args) Part::~Part() { + qDeleteAll(m_previewDirList); + saveSplitterSizes(); m_extractFilesAction->menu()->deleteLater(); @@ -210,6 +214,8 @@ void Part::extractSelectedFilesTo(const QString& localPath) void Part::setupView() { + m_view->setContextMenuPolicy(Qt::CustomContextMenu); + m_view->setModel(m_model); m_view->setSortingEnabled(true); @@ -220,8 +226,10 @@ void Part::setupView() this, SLOT(selectionChanged())); //TODO: fix an actual eventhandler - connect(m_view, SIGNAL(itemTriggered(QModelIndex)), - this, SLOT(slotPreview(QModelIndex))); + connect(m_view, SIGNAL(activated(const QModelIndex &)), + this, SLOT(slotPreviewWithInternalViewer())); + + connect(m_view, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(slotShowContextMenu())); connect(m_model, SIGNAL(columnsInserted(QModelIndex,int,int)), this, SLOT(adjustColumns())); @@ -237,13 +245,19 @@ void Part::setupActions() m_saveAsAction = KStandardAction::saveAs(this, SLOT(slotSaveAs()), actionCollection()); + m_previewChooseAppAction = actionCollection()->addAction(QLatin1String("openwith")); + m_previewChooseAppAction->setText(i18nc("open a file with external program", "Open &With...")); + m_previewChooseAppAction->setIcon(KIcon(QLatin1String("document-open"))); + m_previewChooseAppAction->setStatusTip(i18n("Click to open the selected file with an external program")); + connect(m_previewChooseAppAction, SIGNAL(triggered(bool)), this, SLOT(slotPreviewWithExternalProgram())); + m_previewAction = actionCollection()->addAction(QLatin1String( "preview" )); m_previewAction->setText(i18nc("to preview a file inside an archive", "Pre&view")); m_previewAction->setIcon(KIcon( QLatin1String( "document-preview-archive" ))); m_previewAction->setStatusTip(i18n("Click to preview the selected file")); m_previewAction->setShortcuts(QList<QKeySequence>() << Qt::Key_Return << Qt::Key_Space); connect(m_previewAction, SIGNAL(triggered(bool)), - this, SLOT(slotPreview())); + this, SLOT(slotPreviewWithInternalViewer())); m_extractFilesAction = actionCollection()->addAction(QLatin1String( "extract" )); m_extractFilesAction->setText(i18n("E&xtract")); @@ -289,6 +303,8 @@ void Part::updateActions() m_addDirAction->setEnabled(!isBusy() && isWritable); m_deleteFilesAction->setEnabled(!isBusy() && (m_view->selectionModel()->selectedRows().count() > 0) && isWritable); + m_previewChooseAppAction->setEnabled(!isBusy() && (m_view->selectionModel()->selectedRows().count() > 0) + && isWritable); QMenu *menu = m_extractFilesAction->menu(); if (!menu) { @@ -534,12 +550,17 @@ void Part::setFileNameFromArchive() emit setWindowCaption(prettyName); } -void Part::slotPreview() +void Part::slotPreviewWithInternalViewer() +{ + preview(m_view->selectionModel()->currentIndex(), InternalViewer); +} + +void Part::slotPreviewWithExternalProgram() { - slotPreview(m_view->selectionModel()->currentIndex()); + preview(m_view->selectionModel()->currentIndex(), ExternalProgram); } -void Part::slotPreview(const QModelIndex & index) +void Part::preview(const QModelIndex &index, PreviewMode mode) { if (!isPreviewable(index)) { return; @@ -551,7 +572,10 @@ void Part::slotPreview(const QModelIndex & index) Kerfuffle::ExtractionOptions options; options[QLatin1String( "PreservePaths" )] = true; - ExtractJob *job = m_model->extractFile(entry[ InternalID ], m_previewDir.name(), options); + m_previewDirList.append(new KTempDir); + m_previewMode = mode; + ExtractJob *job = m_model->extractFile(entry[InternalID], m_previewDirList.last()->name(), options); + registerJob(job); connect(job, SIGNAL(result(KJob*)), this, SLOT(slotPreviewExtracted(KJob*))); @@ -568,15 +592,28 @@ void Part::slotPreviewExtracted(KJob *job) const ArchiveEntry& entry = m_model->entryForIndex(m_view->selectionModel()->currentIndex()); - QString fullName = - m_previewDir.name() + QLatin1Char('/') + entry[FileName].toString(); + ExtractJob *extractJob = qobject_cast<ExtractJob*>(job); + Q_ASSERT(extractJob); + QString fullName = extractJob->destinationDirectory() + entry[FileName].toString(); // Make sure a maliciously crafted archive with parent folders named ".." do // not cause the previewed file path to be located outside the temporary // directory, resulting in a directory traversal issue. fullName.remove(QLatin1String("../")); - ArkViewer::view(fullName, widget()); + // TODO: get rid of m_previewMode by extending ExtractJob with a PreviewJob. + // This would prevent race conditions if we ever stop disabling + // the whole UI while extracting a file to preview it. + switch (m_previewMode) { + case InternalViewer: + ArkViewer::view(fullName, widget()); + break; + case ExternalProgram: + KUrl::List list; + list.append(KUrl(fullName)); + KRun::displayOpenWithDialog(list, widget(), true); + break; + } } else { KMessageBox::error(widget(), job->errorString()); } @@ -718,7 +755,6 @@ void Part::slotExtractionDone(KJob* job) } if (ArkSettings::openDestinationFolderAfterExtraction()) { - KUrl destinationDirectory(extractJob->destinationDirectory()); destinationDirectory.cleanPath(); @@ -910,4 +946,10 @@ void Part::slotSaveAs() } } +void Part::slotShowContextMenu() +{ + KMenu *popup = static_cast<KMenu *>(factory()->container(QLatin1String("context_menu"), this)); + popup->popup(QCursor::pos()); +} + } // namespace Ark diff --git a/part/part.h b/part/part.h index 5379b9f..93ed963 100644 --- a/part/part.h +++ b/part/part.h @@ -51,6 +51,11 @@ class Part: public KParts::ReadWritePart, public Interface Q_OBJECT Q_INTERFACES(Interface) public: + enum PreviewMode { + InternalViewer, + ExternalProgram + }; + Part(QWidget *parentWidget, QObject *parent, const QVariantList &); ~Part(); static KAboutData* createAboutData(); @@ -66,8 +71,8 @@ public slots: private slots: void slotLoadingStarted(); void slotLoadingFinished(KJob *job); - void slotPreview(); - void slotPreview(const QModelIndex & index); + void slotPreviewWithInternalViewer(); + void slotPreviewWithExternalProgram(); void slotPreviewExtracted(KJob*); void slotError(const QString& errorMessage, const QString& details); void slotExtractFiles(); @@ -79,6 +84,7 @@ private slots: void slotAddFilesDone(KJob*); void slotDeleteFiles(); void slotDeleteFilesDone(KJob*); + void slotShowContextMenu(); void saveSplitterSizes(); void slotToggleInfoPanel(bool); void slotSaveAs(); @@ -103,9 +109,11 @@ private: QList<QVariant> selectedFiles(); QList<QVariant> selectedFilesWithChildren(); void registerJob(KJob *job); + void preview(const QModelIndex &index, PreviewMode mode); ArchiveModel *m_model; QTreeView *m_view; + KAction *m_previewChooseAppAction; KAction *m_previewAction; KAction *m_extractFilesAction; KAction *m_addFilesAction; @@ -114,8 +122,9 @@ private: KAction *m_saveAsAction; InfoPanel *m_infoPanel; QSplitter *m_splitter; - KTempDir m_previewDir; + QList<KTempDir*> m_previewDirList; bool m_busy; + PreviewMode m_previewMode; KAbstractWidgetJobTracker *m_jobTracker; KParts::StatusBarExtension *m_statusBarExtension;
