Commit c79d8db2 authored by Raphael Kubo da Costa's avatar Raphael Kubo da Costa
Browse files

Use a different D-Bus object path for each Ark::Part.

So far, all Ark::Part instances used the same D-Bus object path,
"/DndExtract", to receive drag'n'drop notifications.

This does not work correctly ever since we started supporting using Ark as
an embedded KPart (for previewing archived inside Konqueror or Rekonq, for
example). In this case, the object path is added to the embedder (the
`konqueror-5654' service, for example). If one previews multiple archives in
different tabs, multiple calls to QDBusConnection::registerObject() will be
made and only the first one will succeed, since we are always trying to
register the same path.

Fixing this involves touching separate parts of the code:

 o Use a different object path for each KPart instance, just like
   KateDocument or nsplugin do. We do this by keeping a static counter that
   is incremented each time a KPart is created and is part of the path name.

 o Use other, more specific mime types for the data we send when dragging
   out of Ark. So far we used "application/x-kde-dndextract" and passed the
   D-Bus service as its value. We now pass this value in the newly-created
   "application/x-kde-ark-dndextract-service" mime type, and the object
   path, which is now passed to ArchiveModel, in

 o Also use a more specific interface name in the XML file. While here,
   generate the .cpp and .h files with CMake instead of keeping these
   auto-generated files around for no purpose.

 o ArchiveModel::mimeTypes() has been adjusted to indicate the mime types we
   actually use on drag'n'drop. The previous list was mostly bogus, as we
   only use the mime types indicated above.

As it can be seen, applications which support drag'n'drop from Ark also need
to be adjusted to use the new D-Bus interface. Currently, the applications
are Dolphin, the Folderview plasmoid and a Stack Folder plasmoid in
playground. They are all going to be updated accordingly in tandem with this
commit to both KDE/4.9 and master. Users using SVN/git directly might
experience some trouble if they update one part but not the other, but there
is not much we can do in this case.

BUG:		304860
FIXED-IN:	4.9.1
parent fa919438
......@@ -5,9 +5,10 @@ set(arkpart_PART_SRCS
qt4_add_dbus_adaptor(arkpart_PART_SRCS dnddbusinterface.xml part.h Ark::Part)
kde4_add_ui_files(arkpart_PART_SRCS infopanel.ui )
kde4_add_ui_files(arkpart_PART_SRCS jobtracker.ui )
......@@ -3,6 +3,7 @@
* Copyright (C) 2007 Henrique Pinto <>
* Copyright (C) 2008-2009 Harald Hvaal <>
* Copyright (C) 2010-2012 Raphael Kubo da Costa <>
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
......@@ -19,6 +20,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "archivemodel.h"
#include "kerfuffle/archive.h"
#include "kerfuffle/jobs.h"
......@@ -277,9 +279,10 @@ int ArchiveNode::row() const
return 0;
ArchiveModel::ArchiveModel(QObject *parent)
: QAbstractItemModel(parent),
m_rootNode(new ArchiveDirNode(0, ArchiveEntry()))
ArchiveModel::ArchiveModel(const QString &dbusPathName, QObject *parent)
: QAbstractItemModel(parent)
, m_rootNode(new ArchiveDirNode(0, ArchiveEntry()))
, m_dbusPathName(dbusPathName)
......@@ -551,43 +554,23 @@ QStringList ArchiveModel::mimeTypes() const
QStringList types;
types << QLatin1String("text/uri-list")
<< QLatin1String("text/plain")
<< QLatin1String("text/x-moz-url")
<< QLatin1String("application/x-kde-urilist")
<< QLatin1String("application/x-kde-extractdrag");
types << QLatin1String("application/x-kde-ark-dndextract-service")
<< QLatin1String("application/x-kde-ark-dndextract-path");
return types;
QMimeData * ArchiveModel::mimeData(const QModelIndexList & indexes) const
QMimeData *ArchiveModel::mimeData(const QModelIndexList &indexes) const
QStringList files;
QString archiveName = m_archive->fileName();
if (!archiveName.endsWith(QLatin1Char('/'))) {
//Populate the internal list of files
foreach(const QModelIndex &index, indexes) {
//to limit only one index per row
if (index.column() != 0) {
const QString file = archiveName + static_cast<ArchiveNode*>(index.internalPointer())->entry()[ FileName ].toString();
files << file;
//prepare the dbus-based drag/drop mimedata
QMimeData *data = new QMimeData();
QMimeData *mimeData = new QMimeData;
return data;
return mimeData;
bool ArchiveModel::dropMimeData(const QMimeData * data, Qt::DropAction action, int row, int column, const QModelIndex & parent)
......@@ -42,7 +42,7 @@ class ArchiveModel: public QAbstractItemModel
ArchiveModel(QObject *parent = 0);
ArchiveModel(const QString &dbusPathName, QObject *parent = 0);
QVariant data(const QModelIndex &index, int role) const;
......@@ -119,6 +119,8 @@ private:
QList<int> m_showColumns;
QScopedPointer<Kerfuffle::Archive> m_archive;
ArchiveDirNode *m_rootNode;
QString m_dbusPathName;
* This file was generated by dbusxml2cpp version 0.6
* Command line was: dbusxml2cpp -v dnddbusinterface.xml -a dnddbusinterface
* dbusxml2cpp is Copyright (C) 2006 Trolltech ASA. All rights reserved.
* This is an auto-generated file.
* Do not edit! All changes made to it will be lost.
#include "dnddbusinterface.h"
#include <QtCore/QMetaObject>
#include <QtCore/QByteArray>
#include <QtCore/QList>
#include <QtCore/QMap>
#include <QtCore/QString>
#include <QtCore/QStringList>
#include <QtCore/QVariant>
* Implementation of adaptor class DndExtractAdaptor
DndExtractAdaptor::DndExtractAdaptor(QObject *parent)
: QDBusAbstractAdaptor(parent)
// constructor
// destructor
void DndExtractAdaptor::extractSelectedFilesTo(const QString &path)
// handle method call org.kde.DndExtract.extractSelectedFilesTo
QMetaObject::invokeMethod(parent(), "extractSelectedFilesTo", Q_ARG(QString, path));
* This file was generated by dbusxml2cpp version 0.6
* Command line was: dbusxml2cpp -v dnddbusinterface.xml -a dnddbusinterface
* dbusxml2cpp is Copyright (C) 2006 Trolltech ASA. All rights reserved.
* This is an auto-generated file.
* This file may have been hand-edited. Look for HAND-EDIT comments
* before re-generating it.
#ifndef DNDDBUSINTERFACE_H_1217639736
#define DNDDBUSINTERFACE_H_1217639736
#include <QtCore/QObject>
#include <QtDBus/QtDBus>
template<class T> class QList;
template<class Key, class Value> class QMap;
class QString;
* Adaptor class for interface org.kde.DndExtract
class DndExtractAdaptor: public QDBusAbstractAdaptor
Q_CLASSINFO("D-Bus Interface", "org.kde.DndExtract")
Q_CLASSINFO("D-Bus Introspection", ""
" <interface name=\"org.kde.DndExtract\" >\n"
" <method name=\"extractSelectedFilesTo\" >\n"
" <arg direction=\"in\" type=\"s\" name=\"path\" />\n"
" </method>\n"
" </interface>\n"
DndExtractAdaptor(QObject *parent);
virtual ~DndExtractAdaptor();
public: // PROPERTIES
public Q_SLOTS: // METHODS
void extractSelectedFilesTo(const QString &path);
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "">
<node name="/org/kde/dndextract">
<interface name="org.kde.DndExtract">
<interface name="org.kde.ark.DndExtract">
<method name="extractSelectedFilesTo">
<arg direction="in" type="s" name="path" />
......@@ -3,7 +3,7 @@
* Copyright (C) 2007 Henrique Pinto <>
* Copyright (C) 2008-2009 Harald Hvaal <>
* Copyright (C) 2009-2011 Raphael Kubo da Costa <>
* Copyright (C) 2009-2012 Raphael Kubo da Costa <>
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
......@@ -25,7 +25,7 @@
#include "archivemodel.h"
#include "archiveview.h"
#include "arkviewer.h"
#include "dnddbusinterface.h"
#include "dndextractadaptor.h"
#include "infopanel.h"
#include "jobtracker.h"
#include "kerfuffle/archive.h"
......@@ -75,9 +75,10 @@ K_EXPORT_PLUGIN(Factory("ark"))
namespace Ark
static quint32 s_instanceCounter = 1;
Part::Part(QWidget *parentWidget, QObject *parent, const QVariantList& args)
: KParts::ReadWritePart(parent),
m_model(new ArchiveModel(this)),
......@@ -85,6 +86,15 @@ Part::Part(QWidget *parentWidget, QObject *parent, const QVariantList& args)
setComponentData(Factory::componentData(), false);
new DndExtractAdaptor(this);
const QString pathName = QString(QLatin1String("/DndExtract/%1")).arg(s_instanceCounter++);
if (!QDBusConnection::sessionBus().registerObject(pathName, this)) {
kFatal() << "Could not register a D-Bus object for drag'n'drop";
m_model = new ArchiveModel(pathName, this);
m_splitter = new QSplitter(Qt::Horizontal, parentWidget);
......@@ -122,9 +132,6 @@ Part::Part(QWidget *parentWidget, QObject *parent, const QVariantList& args)
m_statusBarExtension = new KParts::StatusBarExtension(this);
new DndExtractAdaptor(this);
QDBusConnection::sessionBus().registerObject(QLatin1String( "/DndExtract" ), this);
setXMLFile(QLatin1String( "ark_part.rc" ));
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment