[WIP]: integrate drop menu and filecopy drop menu
Summary: add an optional menu parameter to processMimeData to mnually pass an existing qmenu. folderview can use that to pass its own filecopyjob drop qmenu to be populated with extra entries Test Plan: dropping a file on folderview will show a menu with entries from both. works both with folderview and desktop containments Reviewers: #plasma, hein Reviewed By: #plasma, hein Subscribers: plasma-devel, #frameworks Tags: #plasma, #frameworks Differential Revision: https://phabricator.kde.org/D4576 Change-Id: Iae911d4e692f2e591358959758ca6ddd131379c0
This commit is contained in:
parent
5ea39a32ad
commit
f684e6b2e0
@ -40,6 +40,7 @@
|
||||
#include "kio/jobclasses.h" // for KIO::JobFlags
|
||||
#include "kio/job.h"
|
||||
#include "kio/scheduler.h"
|
||||
#include <KIO/DropJob>
|
||||
#endif
|
||||
|
||||
#include <plasma.h>
|
||||
@ -407,17 +408,17 @@ QPointF ContainmentInterface::adjustToAvailableScreenRegion(int x, int y, int w,
|
||||
return rect.topLeft();
|
||||
}
|
||||
|
||||
void ContainmentInterface::processMimeData(QObject *mimeDataProxy, int x, int y)
|
||||
void ContainmentInterface::processMimeData(QObject *mimeDataProxy, int x, int y, KIO::DropJob *dropJob)
|
||||
{
|
||||
QMimeData* mime = qobject_cast<QMimeData*>(mimeDataProxy);
|
||||
if (mime) {
|
||||
processMimeData(mime, x, y);
|
||||
processMimeData(mime, x, y, dropJob);
|
||||
} else {
|
||||
processMimeData(mimeDataProxy->property("mimeData").value<QMimeData*>(), x, y);
|
||||
processMimeData(mimeDataProxy->property("mimeData").value<QMimeData*>(), x, y, dropJob);
|
||||
}
|
||||
}
|
||||
|
||||
void ContainmentInterface::processMimeData(QMimeData *mimeData, int x, int y)
|
||||
void ContainmentInterface::processMimeData(QMimeData *mimeData, int x, int y, KIO::DropJob *dropJob)
|
||||
{
|
||||
if (!mimeData) {
|
||||
return;
|
||||
@ -458,11 +459,15 @@ void ContainmentInterface::processMimeData(QMimeData *mimeData, int x, int y)
|
||||
QObject::connect(job, SIGNAL(mimetype(KIO::Job*,QString)),
|
||||
this, SLOT(mimeTypeRetrieved(KIO::Job*,QString)));
|
||||
|
||||
QMenu *choices = new QMenu(i18n("Content dropped"));
|
||||
choices->addAction(QIcon::fromTheme(QStringLiteral("process-working")), i18n("Fetching file type..."));
|
||||
choices->popup(window() ? window()->mapToGlobal(QPoint(x, y)) : QPoint(x, y));
|
||||
if (dropJob) {
|
||||
m_dropJobs[job] = dropJob;
|
||||
} else {
|
||||
QMenu *choices = new QMenu(i18n("Content dropped"));
|
||||
choices->addAction(QIcon::fromTheme(QStringLiteral("process-working")), i18n("Fetching file type..."));
|
||||
choices->popup(window() ? window()->mapToGlobal(QPoint(x, y)) : QPoint(x, y));
|
||||
|
||||
m_dropMenus[job] = choices;
|
||||
m_dropMenus[job] = choices;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -489,34 +494,49 @@ void ContainmentInterface::processMimeData(QMimeData *mimeData, int x, int y)
|
||||
|
||||
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 = nullptr;
|
||||
if (!dropJob) {
|
||||
choices = new QMenu();
|
||||
}
|
||||
QList<QAction *> extraActions;
|
||||
QHash<QAction *, QString> actionsToPlugins;
|
||||
foreach (const KPluginInfo &info, seenPlugins) {
|
||||
QAction *action;
|
||||
if (!info.icon().isEmpty()) {
|
||||
action = choices.addAction(QIcon::fromTheme(info.icon()), info.name());
|
||||
action = new QAction(QIcon::fromTheme(info.icon()), info.name());
|
||||
} else {
|
||||
action = choices.addAction(info.name());
|
||||
action = new QAction(info.name());
|
||||
}
|
||||
extraActions << action;
|
||||
if (choices) {
|
||||
choices->addAction(action);
|
||||
}
|
||||
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 the menu was created by ourselves, delete it
|
||||
if (choices) {
|
||||
QAction *choice = choices->exec(window() ? window()->mapToGlobal(QPoint(x, y)) : QPoint(x, y));
|
||||
|
||||
delete choices;
|
||||
} else {
|
||||
Q_ASSERT(dropJob);
|
||||
dropJob->setApplicationActions(extraActions);
|
||||
}
|
||||
}
|
||||
|
||||
if (!selectedPlugin.isEmpty()) {
|
||||
|
||||
Plasma::Applet *applet = createApplet(selectedPlugin, QVariantList(), QRect(x, y, -1, -1));
|
||||
setAppletArgs(applet, pluginFormats[selectedPlugin], mimeData->data(pluginFormats[selectedPlugin]));
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -526,7 +546,7 @@ void ContainmentInterface::clearDataForMimeJob(KIO::Job *job)
|
||||
QObject::disconnect(job, 0, this, 0);
|
||||
m_dropPoints.remove(job);
|
||||
QMenu *choices = m_dropMenus.take(job);
|
||||
delete choices;
|
||||
m_dropJobs.remove(job);
|
||||
job->kill();
|
||||
#endif // PLASMA_NO_KIO
|
||||
}
|
||||
@ -537,9 +557,6 @@ void ContainmentInterface::dropJobResult(KJob *job)
|
||||
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<KIO::Job *>(job), QString());
|
||||
#endif // PLASMA_NO_KIO
|
||||
}
|
||||
|
||||
@ -547,6 +564,7 @@ void ContainmentInterface::mimeTypeRetrieved(KIO::Job *job, const QString &mimet
|
||||
{
|
||||
#ifndef PLASMA_NO_KIO
|
||||
qDebug() << "Mimetype Job returns." << mimetype;
|
||||
|
||||
KIO::TransferJob *tjob = dynamic_cast<KIO::TransferJob *>(job);
|
||||
if (!tjob) {
|
||||
qDebug() << "job should be a TransferJob, but isn't";
|
||||
@ -571,8 +589,11 @@ void ContainmentInterface::mimeTypeRetrieved(KIO::Job *job, const QString &mimet
|
||||
}
|
||||
|
||||
QMenu *choices = m_dropMenus.value(tjob);
|
||||
if (!choices) {
|
||||
qDebug() << "Bailing out. No QMenu found for this job.";
|
||||
QList<QAction *> dropActions;
|
||||
KIO::DropJob *dropJob = m_dropJobs.value(tjob);
|
||||
|
||||
if (!choices && !dropJob) {
|
||||
qDebug() << "Bailing out. No QMenu or drop job found for this job.";
|
||||
clearDataForMimeJob(job);
|
||||
return;
|
||||
}
|
||||
@ -598,71 +619,25 @@ void ContainmentInterface::mimeTypeRetrieved(KIO::Job *job, const QString &mimet
|
||||
if (!appletList.isEmpty() || !wallpaperList.isEmpty() || isPlasmaPackage) {
|
||||
QAction *installPlasmaPackageAction = nullptr;
|
||||
if (isPlasmaPackage) {
|
||||
choices->addSection(i18n("Plasma Package"));
|
||||
installPlasmaPackageAction = choices->addAction(QIcon::fromTheme(QStringLiteral("application-x-plasma")), i18n("Install"));
|
||||
}
|
||||
|
||||
QHash<QAction *, QString> 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());
|
||||
if (choices) {
|
||||
choices->addSection(i18n("Plasma Package"));
|
||||
installPlasmaPackageAction = choices->addAction(QIcon::fromTheme(QStringLiteral("application-x-plasma")), i18n("Install"));
|
||||
} else {
|
||||
action = choices->addAction(info.name());
|
||||
QAction *action = new QAction(i18n("Plasma Package"));
|
||||
action->setSeparator(true);
|
||||
dropActions << action;
|
||||
|
||||
installPlasmaPackageAction = new QAction(QIcon::fromTheme(QStringLiteral("application-x-plasma")), i18n("Install"));
|
||||
Q_ASSERT(dropJob);
|
||||
dropActions << installPlasmaPackageAction;
|
||||
dropJob->setApplicationActions(dropActions);
|
||||
}
|
||||
|
||||
actionsToApplets.insert(action, info.pluginName());
|
||||
qDebug() << info.pluginName();
|
||||
}
|
||||
actionsToApplets.insert(choices->addAction(i18n("Icon")), QStringLiteral("org.kde.plasma.icon"));
|
||||
|
||||
QHash<QAction *, QString> actionsToWallpapers;
|
||||
if (!wallpaperList.isEmpty()) {
|
||||
choices->addSection(i18n("Wallpaper"));
|
||||
|
||||
QMap<QString, KPluginInfo> 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) {
|
||||
const QString &packagePath = tjob->url().toLocalFile();
|
||||
connect(installPlasmaPackageAction, &QAction::triggered, this, [this, tjob, posi, packagePath]() {
|
||||
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) {
|
||||
@ -681,6 +656,7 @@ void ContainmentInterface::mimeTypeRetrieved(KIO::Job *job, const QString &mimet
|
||||
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
|
||||
@ -691,28 +667,128 @@ void ContainmentInterface::mimeTypeRetrieved(KIO::Job *job, const QString &mimet
|
||||
|
||||
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());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (choices) {
|
||||
choices->addSection(i18n("Widgets"));
|
||||
} else {
|
||||
QAction *action = new QAction(i18n("Widgets"));
|
||||
action->setSeparator(true);
|
||||
dropActions << action;
|
||||
}
|
||||
foreach (const KPluginInfo &info, appletList) {
|
||||
qDebug() << info.name();
|
||||
QAction *action;
|
||||
if (!info.icon().isEmpty()) {
|
||||
action = new QAction(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 = new QAction(info.name());
|
||||
}
|
||||
|
||||
clearDataForMimeJob(job);
|
||||
return;
|
||||
if (choices) {
|
||||
choices->addAction(action);
|
||||
}
|
||||
dropActions << action;
|
||||
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 = new QAction(i18n("Icon"));
|
||||
if (choices) {
|
||||
choices->addAction(action);
|
||||
}
|
||||
dropActions << action;
|
||||
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());
|
||||
});
|
||||
}
|
||||
} 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());
|
||||
}
|
||||
}
|
||||
|
||||
clearDataForMimeJob(job);
|
||||
QHash<QAction *, QString> actionsToWallpapers;
|
||||
if (!wallpaperList.isEmpty()) {
|
||||
if (choices) {
|
||||
choices->addSection(i18n("Wallpaper"));
|
||||
} else {
|
||||
QAction *action = new QAction(i18n("Wallpaper"));
|
||||
action->setSeparator(true);
|
||||
dropActions << action;
|
||||
}
|
||||
|
||||
QMap<QString, KPluginInfo> sorted;
|
||||
foreach (const KPluginInfo &info, appletList) {
|
||||
sorted.insert(info.name(), info);
|
||||
}
|
||||
|
||||
foreach (const KPluginInfo &info, wallpaperList) {
|
||||
QAction *action;
|
||||
if (!info.icon().isEmpty()) {
|
||||
action = new QAction(QIcon::fromTheme(info.icon()), info.name());
|
||||
} else {
|
||||
action = new QAction(info.name());
|
||||
}
|
||||
|
||||
if (choices) {
|
||||
choices->addAction(action);
|
||||
}
|
||||
dropActions << action;
|
||||
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 {
|
||||
//case in which we created the menu ourselves, just the "fetching type entry, directly create the icon applet
|
||||
if (choices) {
|
||||
Plasma::Applet *applet = createApplet(QStringLiteral("org.kde.plasma.icon"), QVariantList(), QRect(posi, QSize(-1,-1)));
|
||||
setAppletArgs(applet, mimetype, tjob->url().toString());
|
||||
} else {
|
||||
QAction *action;
|
||||
if (choices) {
|
||||
choices->addSection(i18n("Widgets"));
|
||||
action = choices->addAction(i18n("Icon"));
|
||||
} else {
|
||||
QAction *sep = new QAction(i18n("Widgets"));
|
||||
sep->setSeparator(true);
|
||||
dropActions << sep;
|
||||
// we can at least create an icon as a link to the URL
|
||||
action = new QAction(i18n("Icon"));
|
||||
dropActions << action;
|
||||
}
|
||||
|
||||
const QUrl url = tjob->url();
|
||||
connect(action, &QAction::triggered, this, [this, posi, mimetype, url](){
|
||||
Plasma::Applet *applet = createApplet(QStringLiteral("org.kde.plasma.icon"), QVariantList(), QRect(posi, QSize(-1,-1)));
|
||||
setAppletArgs(applet, mimetype, url.toString());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (choices) {
|
||||
// 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));
|
||||
choices->exec();
|
||||
} else {
|
||||
dropJob->setApplicationActions(dropActions);
|
||||
}
|
||||
|
||||
clearDataForMimeJob(tjob);
|
||||
}
|
||||
#endif // PLASMA_NO_KIO
|
||||
}
|
||||
|
||||
|
@ -32,6 +32,7 @@ class WallpaperInterface;
|
||||
namespace KIO
|
||||
{
|
||||
class Job;
|
||||
class DropJob;
|
||||
}
|
||||
|
||||
namespace KActivities
|
||||
@ -104,12 +105,12 @@ public:
|
||||
/**
|
||||
* 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, KIO::DropJob *dropJob = 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, KIO::DropJob *dropJob = 0);
|
||||
|
||||
/**
|
||||
* Search for a containment at those coordinates.
|
||||
@ -197,6 +198,8 @@ private:
|
||||
QList<QObject *> m_appletInterfaces;
|
||||
QHash<KJob *, QPoint> m_dropPoints;
|
||||
QHash<KJob *, QMenu *> m_dropMenus;
|
||||
QHash<KJob *, QJSValue *> m_dropCallbacks;
|
||||
QHash<KJob *, KIO::DropJob *> m_dropJobs;
|
||||
KActivities::Info *m_activityInfo;
|
||||
QPointer<Plasma::Containment> m_containment;
|
||||
QWeakPointer<QMenu> m_contextMenu;
|
||||
|
Loading…
Reference in New Issue
Block a user