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>&amp;File</text>
@@ -12,6 +12,7 @@
                <Action name="delete"/>
                <Action name="extract"/>
                <Action name="preview"/>
+               <Action name="openwith"/>
        </Menu>
        <Menu name="settings">
                <text>&amp;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;

Reply via email to