I've been hacking on dropping URLs onto Plasma again, and although I got a bit further, I'm running into problems still. Let me first explain the concept:
- Something is dropped onto Plasma - we don't understand its mimetype since it's remote content - we open a QMenu stating "fetching mimetype" or similar - the dropEvent and the QMenu are stored in a QHash, indexed by a TransferJob that's started to retrieve the mimetype - We catch the signal mimeType(KJob*, QString) - We get the dropEvent associated with this "drop" using dropEvent[job] (We need this for the coordinates to create the applet at) - We get the QMenu associated using dropMenu[job] (We want to recycle this QMenu, clear it and insert our choices so the user can pick an applet to load) - Profit. Wait, no profit yet. :/ While the mechanism works fine for the dropEvent, it looks like the QMenu vanishes somehow, dropMenu[job] returns a null-pointer. I assume the QMenu is taking a break and going on a long vacation there somewhere. I'm a bit puzzled by this, can anyone enlighten me? Dirty, dirty patch attached. Feedback is of course welcome. -- sebas http://www.kde.org | http://vizZzion.org | GPG Key ID: 9119 0EF9
Index: widgets/scrollbar.cpp
===================================================================
--- widgets/scrollbar.cpp (revision 961916)
+++ widgets/scrollbar.cpp (working copy)
@@ -43,6 +43,9 @@
scrollbar->resize(scrollbar->sizeHint());
connect(scrollbar, SIGNAL(valueChanged(int)), this, SIGNAL(valueChanged(int)));
+ setFlag(QGraphicsItem::ItemClipsChildrenToShape, true);
+ setFlag(QGraphicsItem::ItemClipsToShape, true);
+
}
ScrollBar::~ScrollBar()
Index: widgets/scrollwidget.cpp
===================================================================
--- widgets/scrollwidget.cpp (revision 961916)
+++ widgets/scrollwidget.cpp (working copy)
@@ -41,6 +41,7 @@
ScrollWidgetPrivate(ScrollWidget *parent)
: q(parent),
widget(0),
+ layout(0),
dragging(false)
{
}
@@ -51,6 +52,9 @@
void adjustScrollbars()
{
+ if (!layout) {
+ return;
+ }
verticalScrollBar->nativeWidget()->setMaximum(qMax(0, int((widget->size().height() - scrollingWidget->size().height())/10)));
if (verticalScrollBarPolicy == Qt::ScrollBarAlwaysOff ||
Index: private/containment_p.h
===================================================================
--- private/containment_p.h (revision 961916)
+++ private/containment_p.h (working copy)
@@ -80,6 +80,7 @@
void containmentAppletAnimationComplete(QGraphicsItem *item, Plasma::Animator::Animation anim);
void zoomIn();
void zoomOut();
+ void mimeTypeRetrieved(KIO::Job *job, const QString &mimetype);
void containmentActions(KMenu &desktopMenu);
void appletActions(KMenu &desktopMenu, Applet *applet, bool includeApplet);
bool showContextMenu(const QPointF &point, const QPoint &screenPos, bool includeApplet);
@@ -115,6 +116,17 @@
Containment::Type type;
static bool s_positioning;
bool drawWallpaper;
+ QRectF dropGeometry;
+ QHash<KIO::Job*, QGraphicsSceneDragDropEvent*> dropEvents;
+ QHash<KIO::Job*, QMenu*> dropMenus;
+
+ //public Q_SLOTS:
+ /**
+ * This slot is called when the 'stat' after a job event has finished.
+ */
+ //void mimeTypeRetrieved(KIO::Job *job, const QString &mimetype);
+
+
};
} // Plasma namespace
Index: containment.h
===================================================================
--- containment.h (revision 961916)
+++ containment.h (working copy)
@@ -32,6 +32,11 @@
#include <plasma/applet.h>
#include <plasma/animator.h>
+namespace KIO
+{
+ class Job;
+}
+
namespace Plasma
{
@@ -542,7 +547,7 @@
private:
Q_PRIVATE_SLOT(d, void appletDestroyed(Plasma::Applet*))
- Q_PRIVATE_SLOT(d, void containmentAppletAnimationComplete(QGraphicsItem *item,
+ Q_PRIVATE_SLOT(d, void containmentAppletAnimationComplete(QGraphicsItem *,
Plasma::Animator::Animation anim))
Q_PRIVATE_SLOT(d, void triggerShowAddWidgets())
Q_PRIVATE_SLOT(d, void handleDisappeared(AppletHandle *handle))
@@ -550,6 +555,7 @@
Q_PRIVATE_SLOT(d, void zoomIn())
Q_PRIVATE_SLOT(d, void zoomOut())
Q_PRIVATE_SLOT(d, void requestConfiguration())
+ Q_PRIVATE_SLOT(d, void mimeTypeRetrieved(KIO::Job *, const QString &))
Q_PRIVATE_SLOT(d, void updateToolBoxVisibility())
friend class Applet;
Index: containment.cpp
===================================================================
--- containment.cpp (revision 961916)
+++ containment.cpp (working copy)
@@ -42,6 +42,9 @@
#include <kstandarddirs.h>
#include <ktemporaryfile.h>
#include <kwindowsystem.h>
+#include "kio/jobclasses.h" // for KIO::JobFlags
+#include "kio/job.h"
+#include "kio/scheduler.h"
#include "animator.h"
#include "context.h"
@@ -546,7 +549,7 @@
//if there is only one, don't create a submenu
if(enabled < 2) {
foreach(QAction *action, containmentMenu->actions()) {
- desktopMenu.addAction(action);
+ desktopMenu.addAction(action);
}
} else {
desktopMenu.addMenu(containmentMenu);
@@ -972,13 +975,13 @@
}
QString appletMimetype(corona() ? corona()->appletMimeType() : QString());
+ kDebug() << "Something dropped mimetype, -data: " << appletMimetype << event->mimeData()->text();
if (!appletMimetype.isEmpty() && event->mimeData()->hasFormat(appletMimetype)) {
QString data = event->mimeData()->data(appletMimetype);
QStringList appletNames = data.split('\n', QString::SkipEmptyParts);
-
foreach (const QString &appletName, appletNames) {
- //kDebug() << "doing" << appletName;
+ kDebug() << "doing" << appletName;
QRectF geom(mapFromScene(event->scenePos()), QSize(0, 0));
addApplet(appletName, QVariantList(), geom);
}
@@ -997,22 +1000,29 @@
} else if (KUrl::List::canDecode(event->mimeData())) {
//TODO: collect the mimetypes of available script engines and offer
// to create widgets out of the matching URLs, if any
+ // this is not a TODO anymore?
KUrl::List urls = KUrl::List::fromMimeData(event->mimeData());
foreach (const KUrl &url, urls) {
KMimeType::Ptr mime = KMimeType::findByUrl(url);
QString mimeName = mime->name();
- QRectF geom(event->pos(), QSize());
QVariantList args;
args << url.url();
- // kDebug() << mimeName;
+ kDebug() << "can decode" << mimeName << args;
+ kDebug() << "protocol:" << url.protocol();
KPluginInfo::List appletList = Applet::listAppletInfoForMimetype(mimeName);
- if (!appletList.isEmpty()) {
- //TODO: should we show a dialog here to choose which plasmoid load if
- //!appletList.isEmpty()
+ // FIXME: This is a shortcut until I find a good solution to choose an applet for
+ // akonadi: urls, for now hardcode it to emailmessage
+ if (url.protocol() == "akonadi") {
+ addApplet("emailmessage", args, QRectF(event->pos(), QSize()));
+
+ } else if (!appletList.isEmpty()) {
+ // The mimetype is know, i.e. there are applet that can load this mimetype
+ // Offer the applets in a popupmenu
QMenu choices;
QHash<QAction *, QString> actionsToPlugins;
foreach (const KPluginInfo &info, appletList) {
+ kDebug() << info.name();
QAction *action;
if (!info.icon().isEmpty()) {
action = choices.addAction(KIcon(info.icon()), info.name());
@@ -1021,17 +1031,33 @@
}
actionsToPlugins.insert(action, info.pluginName());
+ kDebug() << info.pluginName();
}
+ actionsToPlugins.insert(choices.addAction(i18n("Icon")), "icon");
- actionsToPlugins.insert(choices.addAction(i18n("Icon")), "icon");
QAction *choice = choices.exec(event->screenPos());
if (choice) {
- addApplet(actionsToPlugins[choice], args, geom);
+ addApplet(actionsToPlugins[choice], args, QRectF(event->pos(), QSize()));
}
- } else if (url.protocol() != "data") {
- // We don't try to do anything with data: URIs
- // no special applet associated with this mimetype, let's
- addApplet("icon", args, geom);
+
+ } else if (url.protocol() != "data") { // Why not data:?
+ kDebug() << "Not handling" << mimeName << url.url();
+ kDebug() << "Let's start a KIO::TransferJob to retrieve the mimetype" << KMimeType::findByUrl(url)->name();
+
+
+ // It may be a directory or a file, let's stat
+ KIO::JobFlags flags = KIO::HideProgressInfo;
+ KIO::TransferJob *job = KIO::get(url, KIO::NoReload, flags);
+
+ d->dropEvents[job] = event;
+ connect(job, SIGNAL(mimetype(KIO::Job *, const QString&)),
+ this, SLOT(mimeTypeRetrieved(KIO::Job *, const QString&)));
+
+ QMenu *choices = new QMenu("Content dropped");
+ choices->addAction(KIcon("process-working"), i18n("Fetching file type..."));
+ QAction *choice = choices->exec(event->screenPos());
+ kDebug() << "Inserting our menu ...";
+ d->dropMenus[job] = choices;
}
}
event->acceptProposedAction();
@@ -1052,13 +1078,14 @@
pluginFormats.insert(plugin.pluginName(), format);
}
}
+ kDebug() << "Mimetype ..." << formats << seenPlugins.keys() << pluginFormats.values();
QString selectedPlugin;
if (seenPlugins.isEmpty()) {
// do nothing, we have no matches =/
}
-
+ kDebug() << "else" << seenPlugins.keys() << pluginFormats.keys();
if (seenPlugins.count() == 1) {
selectedPlugin = seenPlugins.constBegin().key();
} else {
@@ -1105,6 +1132,82 @@
}
}
+void ContainmentPrivate::mimeTypeRetrieved(KIO::Job * job, const QString &mimetype)
+{
+ if (job->error()) {
+ kDebug() << "ERROR" << job->error() << ' ' << job->errorString();
+ } else {
+ KIO::TransferJob* tjob = dynamic_cast<KIO::TransferJob*>(job);
+ if (!tjob) {
+ kDebug() << "job should be a TransferJob, but isn't";
+ return;
+ }
+ if (!dropEvents.keys().contains(tjob)) {
+ kDebug() << "------> Cannot find associated dropEvent";
+ kDebug() << dropEvents.keys() << tjob;
+ return;
+ } else {
+ kDebug() << "------> Got a suitable dropEvent";
+ kDebug() << dropEvents.keys() << tjob;
+ }
+ QMenu *choices = dropMenus[tjob];
+ if (choices) {
+ kDebug() << "Found the QMenu ...";
+ kDebug() << dropMenus.keys() << tjob;
+ } else {
+ kDebug() << "Apparently no QMenu, looks like it has been deleted ...";
+ kDebug() << dropMenus.keys() << tjob;
+ return;
+ }
+
+ QGraphicsSceneDragDropEvent* dropEvent = dropEvents[tjob];
+ kDebug() << "Screenpos:" << dropEvent->screenPos();
+ kDebug() << "scenePos:" << dropEvent->scenePos();
+ kDebug() << "pos:" << dropEvent->pos();
+
+ // Put the job on hold so it can be reused to fetch the actual content,
+ // which is to be expected when something's dropped onto the desktop.
+ tjob->putOnHold();
+ KIO::Scheduler::publishSlaveOnHold();
+
+ QVariantList args;
+ args << tjob->url().url();
+
+ kDebug() << tjob->url() << " has ====> MimeType:" << mimetype << QRectF(dropEvent->pos(), QSize()) << dropEvent->screenPos() << args;
+ KPluginInfo::List appletList = Applet::listAppletInfoForMimetype(mimetype);
+ if (!appletList.isEmpty()) {
+ choices->clear();
+ QHash<QAction *, QString> actionsToPlugins;
+ foreach (const KPluginInfo &info, appletList) {
+ kDebug() << info.name();
+ QAction *action;
+ if (!info.icon().isEmpty()) {
+ action = choices->addAction(KIcon(info.icon()), info.name());
+ } else {
+ action = choices->addAction(info.name());
+ }
+
+ actionsToPlugins.insert(action, info.pluginName());
+ kDebug() << info.pluginName();
+ }
+ actionsToPlugins.insert(choices->addAction(i18n("Icon")), "icon");
+
+ QAction *choice = choices->exec(dropEvent->screenPos());
+ if (choice) {
+ addApplet(actionsToPlugins[choice], args, QRectF(dropEvent->pos(), QSize()));
+ }
+ } else {
+ if (dropEvent) {
+ addApplet("icon", args, QRectF(dropEvent->pos(), QSize()));
+ } else {
+ kDebug() << "============> The Job is not existing, hence no dropEvent!";
+ }
+ }
+
+ // TODO: The file should be saved in a sensible location (Desktop? Documents?)
+ }
+}
+
const QGraphicsItem *Containment::toolBoxItem() const
{
return d->toolBox;
signature.asc
Description: This is a digitally signed message part.
_______________________________________________ Plasma-devel mailing list [email protected] https://mail.kde.org/mailman/listinfo/plasma-devel
