[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