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;

Attachment: signature.asc
Description: This is a digitally signed message part.

_______________________________________________
Plasma-devel mailing list
Plasma-devel@kde.org
https://mail.kde.org/mailman/listinfo/plasma-devel

Reply via email to