diff --git a/src/scriptengines/qml/plasmoid/containmentinterface.h b/src/scriptengines/qml/plasmoid/containmentinterface.h --- a/src/scriptengines/qml/plasmoid/containmentinterface.h +++ b/src/scriptengines/qml/plasmoid/containmentinterface.h @@ -104,12 +104,12 @@ /** * Process the mime data arrived to a particular coordinate, either with a drag and drop or paste with middle mouse button */ - Q_INVOKABLE void processMimeData(QMimeData *data, int x, int y); + Q_INVOKABLE void processMimeData(QMimeData *data, int x, int y, QMenu *menu = 0); /** * Process the mime data arrived to a particular coordinate, either with a drag and drop or paste with middle mouse button */ - Q_INVOKABLE void processMimeData(QObject *data, int x, int y); + Q_INVOKABLE void processMimeData(QObject *data, int x, int y, QMenu *menu = 0); /** * Search for a containment at those coordinates. @@ -197,6 +197,7 @@ QList m_appletInterfaces; QHash m_dropPoints; QHash m_dropMenus; + QHash m_dropCallbacks; KActivities::Info *m_activityInfo; QPointer m_containment; QWeakPointer m_contextMenu; diff --git a/src/scriptengines/qml/plasmoid/containmentinterface.cpp b/src/scriptengines/qml/plasmoid/containmentinterface.cpp --- a/src/scriptengines/qml/plasmoid/containmentinterface.cpp +++ b/src/scriptengines/qml/plasmoid/containmentinterface.cpp @@ -407,17 +407,17 @@ return rect.topLeft(); } -void ContainmentInterface::processMimeData(QObject *mimeDataProxy, int x, int y) +void ContainmentInterface::processMimeData(QObject *mimeDataProxy, int x, int y, QMenu *menu) { QMimeData* mime = qobject_cast(mimeDataProxy); if (mime) { - processMimeData(mime, x, y); + processMimeData(mime, x, y, menu); } else { - processMimeData(mimeDataProxy->property("mimeData").value(), x, y); + processMimeData(mimeDataProxy->property("mimeData").value(), x, y, menu); } } -void ContainmentInterface::processMimeData(QMimeData *mimeData, int x, int y) +void ContainmentInterface::processMimeData(QMimeData *mimeData, int x, int y, QMenu *menu) { if (!mimeData) { return; @@ -458,7 +458,11 @@ QObject::connect(job, SIGNAL(mimetype(KIO::Job*,QString)), this, SLOT(mimeTypeRetrieved(KIO::Job*,QString))); - QMenu *choices = new QMenu(i18n("Content dropped")); + QMenu *choices = menu ? menu : new QMenu(i18n("Content dropped")); + //if we created the menu ourselves, auto delete on close + if (!menu) { + choices->setAttribute(Qt::WA_DeleteOnClose); + } choices->addAction(QIcon::fromTheme(QStringLiteral("process-working")), i18n("Fetching file type...")); choices->popup(window() ? window()->mapToGlobal(QPoint(x, y)) : QPoint(x, y)); @@ -489,33 +493,37 @@ if (seenPlugins.isEmpty()) { // do nothing + //directly create if only one offer only if the conteinment didn't pass an existing plugin } else if (seenPlugins.count() == 1) { selectedPlugin = seenPlugins.constBegin().key(); + Plasma::Applet *applet = createApplet(selectedPlugin, QVariantList(), QRect(x, y, -1, -1)); + setAppletArgs(applet, pluginFormats[selectedPlugin], mimeData->data(pluginFormats[selectedPlugin])); } else { - QMenu choices; + QMenu *choices = menu ? menu : new QMenu(); QHash actionsToPlugins; foreach (const KPluginInfo &info, seenPlugins) { QAction *action; if (!info.icon().isEmpty()) { - action = choices.addAction(QIcon::fromTheme(info.icon()), info.name()); + action = choices->addAction(QIcon::fromTheme(info.icon()), info.name()); } else { - action = choices.addAction(info.name()); + action = choices->addAction(info.name()); } + action->setData(info.pluginName()); + connect(action, &QAction::triggered, this, [this, x, y, mimeData, action]() { + const QString selectedPlugin = action->data().toString(); + Plasma::Applet *applet = createApplet(selectedPlugin, QVariantList(), QRect(x, y, -1, -1)); + setAppletArgs(applet, selectedPlugin, mimeData->data(selectedPlugin)); + }); actionsToPlugins.insert(action, info.pluginName()); } - QAction *choice = choices.exec(window() ? window()->mapToGlobal(QPoint(x, y)) : QPoint(x, y)); - if (choice) { - selectedPlugin = actionsToPlugins[choice]; - } - } - - if (!selectedPlugin.isEmpty()) { - - Plasma::Applet *applet = createApplet(selectedPlugin, QVariantList(), QRect(x, y, -1, -1)); - setAppletArgs(applet, pluginFormats[selectedPlugin], mimeData->data(pluginFormats[selectedPlugin])); + //if the menu was created by ourselves, delete it + if (!menu) { + QAction *choice = choices->exec(window() ? window()->mapToGlobal(QPoint(x, y)) : QPoint(x, y)); + delete choices; + } } } } @@ -526,7 +534,6 @@ QObject::disconnect(job, 0, this, 0); m_dropPoints.remove(job); QMenu *choices = m_dropMenus.take(job); - delete choices; job->kill(); #endif // PLASMA_NO_KIO } @@ -537,16 +544,14 @@ if (job->error()) { qDebug() << "ERROR" << job->error() << ' ' << job->errorString(); } - // We call mimetypeRetrieved since there might be other mechanisms - // for finding suitable applets. Cleanup happens there as well. - mimeTypeRetrieved(qobject_cast(job), QString()); #endif // PLASMA_NO_KIO } void ContainmentInterface::mimeTypeRetrieved(KIO::Job *job, const QString &mimetype) { #ifndef PLASMA_NO_KIO qDebug() << "Mimetype Job returns." << mimetype; + KIO::TransferJob *tjob = dynamic_cast(job); if (!tjob) { qDebug() << "job should be a TransferJob, but isn't"; @@ -571,6 +576,7 @@ } QMenu *choices = m_dropMenus.value(tjob); + if (!choices) { qDebug() << "Bailing out. No QMenu found for this job."; clearDataForMimeJob(job); @@ -600,63 +606,7 @@ if (isPlasmaPackage) { choices->addSection(i18n("Plasma Package")); installPlasmaPackageAction = choices->addAction(QIcon::fromTheme(QStringLiteral("application-x-plasma")), i18n("Install")); - } - - QHash actionsToApplets; - choices->addSection(i18n("Widgets")); - foreach (const KPluginInfo &info, appletList) { - qDebug() << info.name(); - QAction *action; - if (!info.icon().isEmpty()) { - action = choices->addAction(QIcon::fromTheme(info.icon()), info.name()); - } else { - action = choices->addAction(info.name()); - } - - actionsToApplets.insert(action, info.pluginName()); - qDebug() << info.pluginName(); - } - actionsToApplets.insert(choices->addAction(i18n("Icon")), QStringLiteral("org.kde.plasma.icon")); - - QHash actionsToWallpapers; - if (!wallpaperList.isEmpty()) { - choices->addSection(i18n("Wallpaper")); - - QMap sorted; - foreach (const KPluginInfo &info, appletList) { - sorted.insert(info.name(), info); - } - - foreach (const KPluginInfo &info, wallpaperList) { - QAction *action; - if (!info.icon().isEmpty()) { - action = choices->addAction(QIcon::fromTheme(info.icon()), info.name()); - } else { - action = choices->addAction(info.name()); - } - - actionsToWallpapers.insert(action, info.pluginName()); - } - } - - // HACK If the QMenu becomes empty at any point after the "determining mimetype" - // popup was shown, it self-destructs, does not matter if we call clear() or remove - // the action manually, hence we remove the aforementioned item after we populated the menu - choices->removeAction(choices->actions().at(0)); - - QAction *choice = choices->exec(); - if (choice) { - // Put the job on hold so it can be recycled to fetch the actual content, - // which is to be expected when something's dropped onto the desktop and - // an applet is to be created with this URL - if (!mimetype.isEmpty() && !tjob->error()) { - tjob->putOnHold(); - KIO::Scheduler::publishSlaveOnHold(); - } - - QString plugin = actionsToApplets.value(choice); - - if (choice == installPlasmaPackageAction) { + connect(installPlasmaPackageAction, &QAction::triggered, this, [this, tjob, posi]() { using namespace KPackage; PackageStructure *structure = PackageLoader::self()->loadPackageStructure(QStringLiteral("Plasma/Applet")); Package package(structure); @@ -691,28 +641,89 @@ createApplet(package.metadata().pluginId(), QVariantList(), QRect(posi, QSize(-1,-1))); }); - } else if (plugin.isEmpty()) { - //set wallpapery stuff - plugin = actionsToWallpapers.value(choice); - if (m_wallpaperInterface && tjob->url().isValid()) { - m_wallpaperInterface->setUrl(tjob->url()); - } + }); + } + + choices->addSection(i18n("Widgets")); + foreach (const KPluginInfo &info, appletList) { + qDebug() << info.name(); + QAction *action; + if (!info.icon().isEmpty()) { + action = choices->addAction(QIcon::fromTheme(info.icon()), info.name()); } else { - Plasma::Applet *applet = createApplet(actionsToApplets[choice], QVariantList(), QRect(posi, QSize(-1,-1))); - setAppletArgs(applet, mimetype, tjob->url().toString()); + action = choices->addAction(info.name()); } - clearDataForMimeJob(job); - return; + action->setData(info.pluginName()); + qDebug() << info.pluginName(); + const QUrl url = tjob->url(); + connect(action, &QAction::triggered, this, [this, action, posi, mimetype, url]() { + Plasma::Applet *applet = createApplet(action->data().toString(), QVariantList(), QRect(posi, QSize(-1,-1))); + setAppletArgs(applet, mimetype, url.toString()); + }); + } + { + QAction *action = choices->addAction(i18n("Icon")); + action->setData(QStringLiteral("org.kde.plasma.icon")); + const QUrl url = tjob->url(); + connect(action, &QAction::triggered, this, [this, action, posi, mimetype, url](){ + Plasma::Applet *applet = createApplet(action->data().toString(), QVariantList(), QRect(posi, QSize(-1,-1))); + setAppletArgs(applet, mimetype, url.toString()); + }); } + + QHash actionsToWallpapers; + if (!wallpaperList.isEmpty()) { + choices->addSection(i18n("Wallpaper")); + + QMap sorted; + foreach (const KPluginInfo &info, appletList) { + sorted.insert(info.name(), info); + } + + foreach (const KPluginInfo &info, wallpaperList) { + QAction *action; + if (!info.icon().isEmpty()) { + action = choices->addAction(QIcon::fromTheme(info.icon()), info.name()); + } else { + action = choices->addAction(info.name()); + } + + actionsToWallpapers.insert(action, info.pluginName()); + const QUrl url = tjob->url(); + connect(action, &QAction::triggered, this, [this, action, url]() { + //set wallpapery stuff + if (m_wallpaperInterface && url.isValid()) { + m_wallpaperInterface->setUrl(url); + } + }); + } + } + } else { - // we can at least create an icon as a link to the URL - Plasma::Applet *applet = createApplet(QStringLiteral("org.kde.plasma.icon"), QVariantList(), QRect(posi, QSize(-1,-1))); - setAppletArgs(applet, mimetype, tjob->url().toString()); + //case in which we created the menu ourselves, just the "fetching type entry, directly create the icon applet + if (choices->actions().count() < 2) { + Plasma::Applet *applet = createApplet(QStringLiteral("org.kde.plasma.icon"), QVariantList(), QRect(posi, QSize(-1,-1))); + setAppletArgs(applet, mimetype, tjob->url().toString()); + } else { + choices->addSection(i18n("Widgets")); + // we can at least create an icon as a link to the URL + QAction *action = choices->addAction(i18n("Icon")); + const QUrl url = tjob->url(); + connect(action, &QAction::triggered, this, [this, action, posi, mimetype, url](){ + Plasma::Applet *applet = createApplet(QStringLiteral("org.kde.plasma.icon"), QVariantList(), QRect(posi, QSize(-1,-1))); + setAppletArgs(applet, mimetype, url.toString()); + }); + } } - } - clearDataForMimeJob(job); + // HACK If the QMenu becomes empty at any point after the "determining mimetype" + // popup was shown, it self-destructs, does not matter if we call clear() or remove + // the action manually, hence we remove the aforementioned item after we populated the menu + choices->removeAction(choices->actions().at(0)); + + clearDataForMimeJob(tjob); + } #endif // PLASMA_NO_KIO }