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,9 +606,44 @@ if (isPlasmaPackage) { choices->addSection(i18n("Plasma Package")); installPlasmaPackageAction = choices->addAction(QIcon::fromTheme(QStringLiteral("application-x-plasma")), i18n("Install")); + connect(installPlasmaPackageAction, &QAction::triggered, this, [this, tjob, posi]() { + using namespace KPackage; + PackageStructure *structure = PackageLoader::self()->loadPackageStructure(QStringLiteral("Plasma/Applet")); + Package package(structure); + + const QString &packagePath = tjob->url().toLocalFile(); + + KJob *installJob = package.update(packagePath); + connect(installJob, &KJob::result, this, [this, packagePath, structure, posi](KJob *job) { + auto fail = [job](const QString &text) { + KNotification::event(QStringLiteral("plasmoidInstallationFailed"), i18n("Package Installation Failed"), + text, QStringLiteral("dialog-error"), 0, KNotification::CloseOnTimeout, QStringLiteral("plasma_workspace")); + }; + + // if the applet is already installed, just add it to the containment + if (job->error() != KJob::NoError + && job->error() != Package::PackageAlreadyInstalledError + && job->error() != Package::NewerVersionAlreadyInstalledError) { + fail(job->errorText()); + return; + } + + using namespace KPackage; + Package package(structure); + // TODO how can I get the path of the actual package? + package.setPath(packagePath); + + // TODO how can I get the plugin id? Package::metadata() is deprecated + if (!package.isValid() || !package.metadata().isValid()) { + fail(i18n("The package you just dropped is invalid.")); + return; + } + + createApplet(package.metadata().pluginId(), QVariantList(), QRect(posi, QSize(-1,-1))); + }); + }); } - QHash actionsToApplets; choices->addSection(i18n("Widgets")); foreach (const KPluginInfo &info, appletList) { qDebug() << info.name(); @@ -613,10 +654,23 @@ action = choices->addAction(info.name()); } - actionsToApplets.insert(action, info.pluginName()); + 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()); + }); } - actionsToApplets.insert(choices->addAction(i18n("Icon")), QStringLiteral("org.kde.plasma.icon")); QHash actionsToWallpapers; if (!wallpaperList.isEmpty()) { @@ -636,83 +690,36 @@ } 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); + } + }); } } // 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) { - using namespace KPackage; - PackageStructure *structure = PackageLoader::self()->loadPackageStructure(QStringLiteral("Plasma/Applet")); - Package package(structure); - - const QString &packagePath = tjob->url().toLocalFile(); + // choices->removeAction(choices->actions().at(0)); - KJob *installJob = package.update(packagePath); - connect(installJob, &KJob::result, this, [this, packagePath, structure, posi](KJob *job) { - auto fail = [job](const QString &text) { - KNotification::event(QStringLiteral("plasmoidInstallationFailed"), i18n("Package Installation Failed"), - text, QStringLiteral("dialog-error"), 0, KNotification::CloseOnTimeout, QStringLiteral("plasma_workspace")); - }; - - // if the applet is already installed, just add it to the containment - if (job->error() != KJob::NoError - && job->error() != Package::PackageAlreadyInstalledError - && job->error() != Package::NewerVersionAlreadyInstalledError) { - fail(job->errorText()); - return; - } - - using namespace KPackage; - Package package(structure); - // TODO how can I get the path of the actual package? - package.setPath(packagePath); - - // TODO how can I get the plugin id? Package::metadata() is deprecated - if (!package.isValid() || !package.metadata().isValid()) { - fail(i18n("The package you just dropped is invalid.")); - return; - } - - 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()); - } - } else { - Plasma::Applet *applet = createApplet(actionsToApplets[choice], QVariantList(), QRect(posi, QSize(-1,-1))); - setAppletArgs(applet, mimetype, tjob->url().toString()); - } - - clearDataForMimeJob(job); - return; - } + // QAction *choice = choices->exec(); +qWarning()<<"AAAAAA"<isVisible(); } 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()); + { + 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(tjob); } - - clearDataForMimeJob(job); #endif // PLASMA_NO_KIO }