[kde-doc-english] [ark/KDE/4.14] /: Add the 'open-with' action and show the right-click menu.

Elvis Angelaccio elvis.angelaccio at kdemail.net
Thu Oct 23 16:48:02 UTC 2014


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;


More information about the kde-doc-english mailing list