2008-11-04 00:08:39 +01:00
|
|
|
/*
|
|
|
|
* Copyright 2007 by Aaron Seigo <aseigo@kde.org>
|
|
|
|
* Copyright 2008 by Ménard Alexis <darktears31@gmail.com>
|
2009-08-18 00:31:18 +02:00
|
|
|
* Copyright 2009 Chani Armitage <chani@kde.org>
|
2012-07-17 14:21:45 +02:00
|
|
|
* Copyright 2012 Marco Martin <notmart@kde.org>
|
2008-11-04 00:08:39 +01:00
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU Library General Public License as
|
|
|
|
* published by the Free Software Foundation; either version 2, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Library General Public
|
|
|
|
* License along with this program; if not, write to the
|
|
|
|
* Free Software Foundation, Inc.,
|
|
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "containment.h"
|
|
|
|
#include "private/containment_p.h"
|
|
|
|
|
2010-10-14 14:27:15 +02:00
|
|
|
#include "config-plasma.h"
|
|
|
|
|
2009-05-05 20:11:50 +02:00
|
|
|
#include <QApplication>
|
2009-05-05 07:19:35 +02:00
|
|
|
#include <QClipboard>
|
2008-11-04 00:08:39 +01:00
|
|
|
#include <QFile>
|
2012-09-25 21:35:53 +02:00
|
|
|
#include <QContextMenuEvent>
|
2008-11-04 00:08:39 +01:00
|
|
|
#include <QMimeData>
|
|
|
|
#include <QPainter>
|
|
|
|
#include <QStyleOptionGraphicsItem>
|
2011-10-04 16:50:44 +02:00
|
|
|
#include <qtemporaryfile.h>
|
2008-11-04 00:08:39 +01:00
|
|
|
|
2008-11-04 03:04:34 +01:00
|
|
|
#include <kaction.h>
|
2012-06-15 16:05:18 +02:00
|
|
|
#include <kcoreauthorized.h>
|
2008-11-04 03:04:34 +01:00
|
|
|
#include <kmenu.h>
|
|
|
|
#include <kmessagebox.h>
|
2012-06-19 15:12:44 +02:00
|
|
|
#include <qmimedatabase.h>
|
2008-11-04 03:04:34 +01:00
|
|
|
#include <kservicetypetrader.h>
|
2012-06-12 12:59:34 +02:00
|
|
|
|
2008-11-04 03:04:34 +01:00
|
|
|
#include <kwindowsystem.h>
|
2010-10-14 14:27:15 +02:00
|
|
|
|
2012-08-24 03:16:04 +02:00
|
|
|
#if !PLASMA_NO_KIO
|
Make dropping remote content onto Plasma work
The idea is that you drop a file from a webpage, or basically a URL onto Plasma and Plasma creates a suitable applet to display this URL. For example an image frame for picture, or a previewer for pdf files. Downloading the data itself (and possibly saving it) is left to the applets. The mimetype needs to be retrieved as it cannot be determined from the URL.
The code pathes I've changed or added are, roughly:
- "something" is dropped onto Plasma
- if it's a remote URL, we don't know the mimetype of the object behind the URL yet
- a KIO::TransferJob is used to retrieve the mimetype asynchronously, and will call back
- we open a QMenu that says "Fetching file type..."
- If the user closes the menu while the mimetype is being retrieved, we will open a new one
- When the TransferJob calls back, and we have our mimetype, we offer a list of applets suitable for this kind of content
- If the user chooses to create an applet, we put the transfer job on hold to make it available for recycling by the applet
- If the user dismisses the offering, we kill the job
Thanks to marco for reviewing and everybody else for the input :)
Next steps are making some more applets work with this.
CCMAIL:plasma-devel@kde.org
svn path=/trunk/KDE/kdelibs/; revision=1009004
2009-08-09 00:01:16 +02:00
|
|
|
#include "kio/jobclasses.h" // for KIO::JobFlags
|
|
|
|
#include "kio/job.h"
|
|
|
|
#include "kio/scheduler.h"
|
2010-10-14 14:27:15 +02:00
|
|
|
#endif
|
2008-11-04 00:08:39 +01:00
|
|
|
|
2009-08-18 00:31:32 +02:00
|
|
|
#include "containmentactions.h"
|
2009-10-05 22:50:57 +02:00
|
|
|
#include "containmentactionspluginsconfig.h"
|
2008-11-04 00:08:39 +01:00
|
|
|
#include "corona.h"
|
2011-07-19 21:40:57 +02:00
|
|
|
#include "pluginloader.h"
|
2008-11-04 00:08:39 +01:00
|
|
|
#include "svg.h"
|
|
|
|
#include "wallpaper.h"
|
|
|
|
|
2009-09-22 17:29:08 +02:00
|
|
|
#include "remote/accessappletjob.h"
|
|
|
|
#include "remote/accessmanager.h"
|
|
|
|
|
2008-11-04 00:08:39 +01:00
|
|
|
#include "private/applet_p.h"
|
2009-10-05 22:50:57 +02:00
|
|
|
#include "private/containmentactionspluginsconfig_p.h"
|
2011-01-26 21:09:18 +01:00
|
|
|
#include "private/wallpaper_p.h"
|
2008-11-04 00:08:39 +01:00
|
|
|
|
2009-12-16 23:33:30 +01:00
|
|
|
#include "plasma/plasma.h"
|
|
|
|
|
2008-11-04 00:08:39 +01:00
|
|
|
namespace Plasma
|
|
|
|
{
|
|
|
|
|
2012-09-24 17:18:55 +02:00
|
|
|
Containment::Containment(QObject *parent,
|
2008-11-04 00:08:39 +01:00
|
|
|
const QString &serviceId,
|
|
|
|
uint containmentId)
|
|
|
|
: Applet(parent, serviceId, containmentId),
|
|
|
|
d(new ContainmentPrivate(this))
|
|
|
|
{
|
|
|
|
// WARNING: do not access config() OR globalConfig() in this method!
|
|
|
|
// that requires a scene, which is not available at this point
|
|
|
|
setBackgroundHints(NoBackground);
|
|
|
|
setContainmentType(CustomContainment);
|
2009-01-22 01:00:16 +01:00
|
|
|
setHasConfigurationInterface(false);
|
2008-11-04 00:08:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
Containment::Containment(QObject *parent, const QVariantList &args)
|
|
|
|
: Applet(parent, args),
|
|
|
|
d(new ContainmentPrivate(this))
|
|
|
|
{
|
|
|
|
// WARNING: do not access config() OR globalConfig() in this method!
|
|
|
|
// that requires a scene, which is not available at this point
|
|
|
|
setBackgroundHints(NoBackground);
|
2009-01-22 01:00:16 +01:00
|
|
|
setHasConfigurationInterface(false);
|
2008-11-04 00:08:39 +01:00
|
|
|
}
|
|
|
|
|
2009-10-23 15:48:29 +02:00
|
|
|
Containment::Containment(const QString &packagePath, uint appletId, const QVariantList &args)
|
2011-11-17 14:40:53 +01:00
|
|
|
: Applet(packagePath, appletId, args),
|
2009-10-23 15:48:29 +02:00
|
|
|
d(new ContainmentPrivate(this))
|
|
|
|
{
|
|
|
|
// WARNING: do not access config() OR globalConfig() in this method!
|
|
|
|
// that requires a scene, which is not available at this point
|
|
|
|
setBackgroundHints(NoBackground);
|
|
|
|
setHasConfigurationInterface(false);
|
|
|
|
}
|
|
|
|
|
2008-11-04 00:08:39 +01:00
|
|
|
Containment::~Containment()
|
|
|
|
{
|
2009-10-15 22:43:12 +02:00
|
|
|
// Applet touches our dptr if we are a containment and is the superclass (think of dtors)
|
|
|
|
// so we reset this as we exit the building
|
|
|
|
Applet::d->isContainment = false;
|
2012-10-10 19:09:29 +02:00
|
|
|
delete d;
|
2008-11-04 00:08:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void Containment::init()
|
|
|
|
{
|
2010-05-04 05:50:11 +02:00
|
|
|
Applet::init();
|
2008-11-04 00:08:39 +01:00
|
|
|
if (!isContainment()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (d->type == NoContainmentType) {
|
|
|
|
setContainmentType(DesktopContainment);
|
|
|
|
}
|
|
|
|
|
2009-05-03 22:22:14 +02:00
|
|
|
//connect actions
|
2009-10-14 01:07:35 +02:00
|
|
|
ContainmentPrivate::addDefaultActions(d->actions(), this);
|
2008-11-04 00:08:39 +01:00
|
|
|
bool unlocked = immutability() == Mutable;
|
|
|
|
|
2009-05-03 22:22:14 +02:00
|
|
|
//fix the text of the actions that need name()
|
|
|
|
//btw, do we really want to use name() when it's a desktopcontainment?
|
2009-06-10 06:51:24 +02:00
|
|
|
QAction *closeApplet = action("remove");
|
|
|
|
if (closeApplet) {
|
|
|
|
closeApplet->setText(i18nc("%1 is the name of the applet", "Remove this %1", name()));
|
|
|
|
}
|
|
|
|
|
|
|
|
QAction *configAction = action("configure");
|
|
|
|
if (configAction) {
|
|
|
|
configAction->setText(i18nc("%1 is the name of the applet", "%1 Settings", name()));
|
|
|
|
}
|
2009-05-03 22:22:14 +02:00
|
|
|
|
|
|
|
QAction *appletBrowserAction = action("add widgets");
|
2009-06-10 06:51:24 +02:00
|
|
|
if (appletBrowserAction) {
|
|
|
|
appletBrowserAction->setVisible(unlocked);
|
|
|
|
appletBrowserAction->setEnabled(unlocked);
|
|
|
|
connect(appletBrowserAction, SIGNAL(triggered()), this, SLOT(triggerShowAddWidgets()));
|
|
|
|
}
|
2008-11-04 00:08:39 +01:00
|
|
|
|
2009-05-03 22:22:14 +02:00
|
|
|
QAction *act = action("next applet");
|
2009-06-10 06:51:24 +02:00
|
|
|
if (act) {
|
|
|
|
connect(act, SIGNAL(triggered()), this, SLOT(focusNextApplet()));
|
|
|
|
}
|
|
|
|
|
2009-05-03 22:22:14 +02:00
|
|
|
act = action("previous applet");
|
2009-06-10 06:51:24 +02:00
|
|
|
if (act) {
|
|
|
|
connect(act, SIGNAL(triggered()), this, SLOT(focusPreviousApplet()));
|
|
|
|
}
|
2008-11-04 00:08:39 +01:00
|
|
|
|
2009-03-10 20:52:50 +01:00
|
|
|
if (immutability() != SystemImmutable && corona()) {
|
|
|
|
QAction *lockDesktopAction = corona()->action("lock widgets");
|
|
|
|
//keep a pointer so nobody notices it moved to corona
|
|
|
|
if (lockDesktopAction) {
|
2009-05-03 22:22:14 +02:00
|
|
|
d->actions()->addAction("lock widgets", lockDesktopAction);
|
2009-03-10 20:52:50 +01:00
|
|
|
}
|
2008-11-04 00:08:39 +01:00
|
|
|
}
|
2010-01-27 00:35:32 +01:00
|
|
|
if (d->type != PanelContainment && d->type != CustomPanelContainment) {
|
2009-03-11 19:37:12 +01:00
|
|
|
if (corona()) {
|
2010-04-24 22:36:43 +02:00
|
|
|
//FIXME this is just here because of the darn keyboard shortcut :/
|
|
|
|
act = corona()->action("manage activities");
|
2010-01-27 00:35:32 +01:00
|
|
|
if (act) {
|
2010-04-24 22:36:43 +02:00
|
|
|
d->actions()->addAction("manage activities", act);
|
2009-05-03 22:22:14 +02:00
|
|
|
}
|
|
|
|
//a stupid hack to make this one's keyboard shortcut work
|
2010-01-27 00:35:32 +01:00
|
|
|
act = corona()->action("configure shortcuts");
|
|
|
|
if (act) {
|
|
|
|
d->actions()->addAction("configure shortcuts", act);
|
2009-03-11 19:37:12 +01:00
|
|
|
}
|
|
|
|
}
|
2008-11-04 00:08:39 +01:00
|
|
|
|
2010-07-31 15:02:07 +02:00
|
|
|
if (d->type == DesktopContainment) {
|
|
|
|
addToolBoxAction(action("add widgets"));
|
2008-12-01 13:40:08 +01:00
|
|
|
|
2009-01-22 01:00:16 +01:00
|
|
|
//TODO: do we need some way to allow this be overridden?
|
|
|
|
// it's always available because shells rely on this
|
|
|
|
// to offer their own custom configuration as well
|
2010-01-27 00:35:32 +01:00
|
|
|
QAction *configureContainment = action("configure");
|
2009-01-22 01:00:16 +01:00
|
|
|
if (configureContainment) {
|
2010-07-31 15:02:07 +02:00
|
|
|
addToolBoxAction(configureContainment);
|
2008-11-04 00:08:39 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2009-05-03 22:22:14 +02:00
|
|
|
}
|
|
|
|
|
2008-11-04 00:08:39 +01:00
|
|
|
// helper function for sorting the list of applets
|
|
|
|
bool appletConfigLessThan(const KConfigGroup &c1, const KConfigGroup &c2)
|
|
|
|
{
|
|
|
|
QPointF p1 = c1.readEntry("geometry", QRectF()).topLeft();
|
|
|
|
QPointF p2 = c2.readEntry("geometry", QRectF()).topLeft();
|
2008-11-14 05:01:01 +01:00
|
|
|
|
|
|
|
if (!qFuzzyCompare(p1.x(), p2.x())) {
|
2009-07-08 02:37:40 +02:00
|
|
|
if (QApplication::layoutDirection() == Qt::RightToLeft) {
|
|
|
|
return p1.x() > p2.x();
|
|
|
|
}
|
|
|
|
|
2008-11-04 00:08:39 +01:00
|
|
|
return p1.x() < p2.x();
|
|
|
|
}
|
2008-11-14 05:01:01 +01:00
|
|
|
|
|
|
|
return qFuzzyCompare(p1.y(), p2.y()) || p1.y() < p2.y();
|
2008-11-04 00:08:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void Containment::restore(KConfigGroup &group)
|
|
|
|
{
|
2011-07-29 15:46:52 +02:00
|
|
|
/*
|
|
|
|
#ifndef NDEBUG
|
|
|
|
kDebug() << "!!!!!!!!!!!!initConstraints" << group.name() << d->type;
|
2008-11-04 00:08:39 +01:00
|
|
|
kDebug() << " location:" << group.readEntry("location", (int)d->location);
|
|
|
|
kDebug() << " geom:" << group.readEntry("geometry", geometry());
|
|
|
|
kDebug() << " formfactor:" << group.readEntry("formfactor", (int)d->formFactor);
|
2011-07-29 15:46:52 +02:00
|
|
|
kDebug() << " screen:" << group.readEntry("screen", d->screen);
|
|
|
|
#endif
|
|
|
|
*/
|
2008-11-04 00:08:39 +01:00
|
|
|
if (!isContainment()) {
|
|
|
|
Applet::restore(group);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
setLocation((Plasma::Location)group.readEntry("location", (int)d->location));
|
|
|
|
setFormFactor((Plasma::FormFactor)group.readEntry("formfactor", (int)d->formFactor));
|
2009-06-01 19:30:52 +02:00
|
|
|
//kDebug() << "setScreen from restore";
|
2010-05-19 04:43:07 +02:00
|
|
|
d->lastScreen = group.readEntry("lastScreen", d->lastScreen);
|
|
|
|
d->lastDesktop = group.readEntry("lastDesktop", d->lastDesktop);
|
2010-09-24 21:03:45 +02:00
|
|
|
d->setScreen(group.readEntry("screen", d->screen), group.readEntry("desktop", d->desktop), false);
|
2011-05-20 09:41:19 +02:00
|
|
|
d->activityId = group.readEntry("activityId", QString());
|
2008-11-04 00:08:39 +01:00
|
|
|
|
|
|
|
flushPendingConstraintsEvents();
|
|
|
|
restoreContents(group);
|
|
|
|
setImmutability((ImmutabilityType)group.readEntry("immutability", (int)Mutable));
|
|
|
|
|
2012-07-17 14:21:45 +02:00
|
|
|
setWallpaper(group.readEntry("wallpaperplugin", ContainmentPrivate::defaultWallpaper),
|
|
|
|
group.readEntry("wallpaperpluginmode", ContainmentPrivate::defaultWallpaperMode));
|
2009-06-15 15:57:46 +02:00
|
|
|
|
2010-11-11 23:22:39 +01:00
|
|
|
KConfigGroup cfg;
|
|
|
|
if (containmentType() == PanelContainment || containmentType() == CustomPanelContainment) {
|
|
|
|
//don't let global desktop actions conflict with panels
|
|
|
|
//this also prevents panels from sharing config with each other
|
|
|
|
//but the panels aren't configurable anyways, and I doubt that'll change.
|
|
|
|
d->containmentActionsSource = ContainmentPrivate::Local;
|
|
|
|
cfg = KConfigGroup(&group, "ActionPlugins");
|
|
|
|
} else {
|
2011-05-20 09:41:19 +02:00
|
|
|
const QString source = group.readEntry("ActionPluginsSource", QString());
|
2010-11-11 23:22:39 +01:00
|
|
|
if (source == "Global") {
|
|
|
|
cfg = KConfigGroup(corona()->config(), "ActionPlugins");
|
|
|
|
d->containmentActionsSource = ContainmentPrivate::Global;
|
|
|
|
} else if (source == "Activity") {
|
|
|
|
cfg = KConfigGroup(corona()->config(), "Activities");
|
2011-05-20 09:41:19 +02:00
|
|
|
cfg = KConfigGroup(&cfg, d->activityId);
|
2010-11-11 23:22:39 +01:00
|
|
|
cfg = KConfigGroup(&cfg, "ActionPlugins");
|
|
|
|
d->containmentActionsSource = ContainmentPrivate::Activity;
|
|
|
|
} else if (source == "Local") {
|
|
|
|
cfg = group;
|
|
|
|
d->containmentActionsSource = ContainmentPrivate::Local;
|
|
|
|
} else {
|
|
|
|
//default to global
|
|
|
|
//but, if there is no global config, try copying it from local.
|
|
|
|
cfg = KConfigGroup(corona()->config(), "ActionPlugins");
|
|
|
|
if (!cfg.exists()) {
|
|
|
|
cfg = KConfigGroup(&group, "ActionPlugins");
|
|
|
|
}
|
|
|
|
d->containmentActionsSource = ContainmentPrivate::Global;
|
|
|
|
group.writeEntry("ActionPluginsSource", "Global");
|
|
|
|
}
|
|
|
|
}
|
2011-05-20 09:41:19 +02:00
|
|
|
|
2010-09-24 21:03:45 +02:00
|
|
|
//kDebug() << cfg.keyList();
|
2009-08-18 00:30:42 +02:00
|
|
|
if (cfg.exists()) {
|
|
|
|
foreach (const QString &key, cfg.keyList()) {
|
2010-09-24 21:03:45 +02:00
|
|
|
//kDebug() << "loading" << key;
|
2009-08-18 00:31:32 +02:00
|
|
|
setContainmentActions(key, cfg.readEntry(key, QString()));
|
2009-08-18 00:30:42 +02:00
|
|
|
}
|
2010-11-11 23:22:39 +01:00
|
|
|
} else { //shell defaults
|
|
|
|
ContainmentActionsPluginsConfig conf = corona()->containmentActionsDefaults(d->type);
|
|
|
|
//steal the data directly, for efficiency
|
|
|
|
QHash<QString,QString> defaults = conf.d->plugins;
|
|
|
|
for (QHash<QString,QString>::const_iterator it = defaults.constBegin(),
|
|
|
|
end = defaults.constEnd(); it != end; ++it) {
|
|
|
|
setContainmentActions(it.key(), it.value());
|
|
|
|
}
|
2009-08-18 00:30:42 +02:00
|
|
|
}
|
|
|
|
|
2008-11-04 00:08:39 +01:00
|
|
|
/*
|
2011-07-29 15:46:52 +02:00
|
|
|
#ifndef NDEBUG
|
2008-11-04 00:08:39 +01:00
|
|
|
kDebug() << "Containment" << id() <<
|
2011-07-29 15:46:52 +02:00
|
|
|
#endif
|
2008-11-04 00:08:39 +01:00
|
|
|
"screen" << screen() <<
|
|
|
|
"geometry is" << geometry() <<
|
|
|
|
"wallpaper" << ((d->wallpaper) ? d->wallpaper->pluginName() : QString()) <<
|
|
|
|
"wallpaper mode" << wallpaperMode() <<
|
|
|
|
"config entries" << group.entryMap();
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
|
|
|
|
void Containment::save(KConfigGroup &g) const
|
|
|
|
{
|
2009-01-22 01:00:16 +01:00
|
|
|
if (Applet::d->transient) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2008-11-04 00:08:39 +01:00
|
|
|
KConfigGroup group = g;
|
|
|
|
if (!group.isValid()) {
|
|
|
|
group = config();
|
|
|
|
}
|
|
|
|
|
|
|
|
// locking is saved in Applet::save
|
|
|
|
Applet::save(group);
|
2010-05-13 23:40:02 +02:00
|
|
|
|
2010-05-13 23:48:13 +02:00
|
|
|
if (!isContainment()) {
|
2010-05-13 23:40:02 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2008-11-04 00:08:39 +01:00
|
|
|
group.writeEntry("screen", d->screen);
|
2010-05-19 04:43:07 +02:00
|
|
|
group.writeEntry("lastScreen", d->lastScreen);
|
2008-11-17 06:16:33 +01:00
|
|
|
group.writeEntry("desktop", d->desktop);
|
2010-05-19 04:43:07 +02:00
|
|
|
group.writeEntry("lastDesktop", d->lastDesktop);
|
2008-11-04 00:08:39 +01:00
|
|
|
group.writeEntry("formfactor", (int)d->formFactor);
|
|
|
|
group.writeEntry("location", (int)d->location);
|
2011-05-20 09:41:19 +02:00
|
|
|
group.writeEntry("activityId", d->activityId);
|
2010-07-31 15:02:07 +02:00
|
|
|
|
2008-11-14 08:28:02 +01:00
|
|
|
|
2008-11-04 00:08:39 +01:00
|
|
|
if (d->wallpaper) {
|
|
|
|
group.writeEntry("wallpaperplugin", d->wallpaper->pluginName());
|
|
|
|
group.writeEntry("wallpaperpluginmode", d->wallpaper->renderingMode().name());
|
|
|
|
|
|
|
|
if (d->wallpaper->isInitialized()) {
|
|
|
|
KConfigGroup wallpaperConfig(&group, "Wallpaper");
|
|
|
|
wallpaperConfig = KConfigGroup(&wallpaperConfig, d->wallpaper->pluginName());
|
|
|
|
d->wallpaper->save(wallpaperConfig);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
saveContents(group);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Containment::saveContents(KConfigGroup &group) const
|
|
|
|
{
|
|
|
|
KConfigGroup applets(&group, "Applets");
|
|
|
|
foreach (const Applet *applet, d->applets) {
|
|
|
|
KConfigGroup appletConfig(&applets, QString::number(applet->id()));
|
|
|
|
applet->save(appletConfig);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Containment::restoreContents(KConfigGroup &group)
|
|
|
|
{
|
|
|
|
KConfigGroup applets(&group, "Applets");
|
|
|
|
|
|
|
|
// Sort the applet configs in order of geometry to ensure that applets
|
|
|
|
// are added from left to right or top to bottom for a panel containment
|
|
|
|
QList<KConfigGroup> appletConfigs;
|
|
|
|
foreach (const QString &appletGroup, applets.groupList()) {
|
|
|
|
//kDebug() << "reading from applet group" << appletGroup;
|
|
|
|
KConfigGroup appletConfig(&applets, appletGroup);
|
|
|
|
appletConfigs.append(appletConfig);
|
|
|
|
}
|
2008-11-14 05:01:01 +01:00
|
|
|
qStableSort(appletConfigs.begin(), appletConfigs.end(), appletConfigLessThan);
|
2008-11-04 00:08:39 +01:00
|
|
|
|
2008-11-06 00:14:47 +01:00
|
|
|
QMutableListIterator<KConfigGroup> it(appletConfigs);
|
|
|
|
while (it.hasNext()) {
|
|
|
|
KConfigGroup &appletConfig = it.next();
|
2008-11-04 00:08:39 +01:00
|
|
|
int appId = appletConfig.name().toUInt();
|
|
|
|
QString plugin = appletConfig.readEntry("plugin", QString());
|
|
|
|
|
|
|
|
if (plugin.isEmpty()) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2010-06-04 23:36:28 +02:00
|
|
|
d->addApplet(plugin, QVariantList(), appletConfig.readEntry("geometry", QRectF()), appId, true);
|
2008-11-04 00:08:39 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Containment::Type Containment::containmentType() const
|
|
|
|
{
|
|
|
|
return d->type;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Containment::setContainmentType(Containment::Type type)
|
|
|
|
{
|
|
|
|
if (d->type == type) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
d->type = type;
|
2010-04-13 20:36:38 +02:00
|
|
|
d->checkContainmentFurniture();
|
|
|
|
}
|
2008-11-04 00:08:39 +01:00
|
|
|
|
|
|
|
Corona *Containment::corona() const
|
|
|
|
{
|
2012-09-24 17:18:55 +02:00
|
|
|
return qobject_cast<Corona*>(parent());
|
2008-11-04 00:08:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void Containment::showDropZone(const QPoint pos)
|
|
|
|
{
|
2008-11-17 05:34:55 +01:00
|
|
|
Q_UNUSED(pos)
|
2008-11-04 00:08:39 +01:00
|
|
|
//Base implementation does nothing, don't put code here
|
|
|
|
}
|
|
|
|
|
|
|
|
void Containment::showContextMenu(const QPointF &containmentPos, const QPoint &screenPos)
|
|
|
|
{
|
2010-09-08 23:51:22 +02:00
|
|
|
//kDebug() << containmentPos << screenPos;
|
2012-09-25 21:35:53 +02:00
|
|
|
QContextMenuEvent gvevent(QContextMenuEvent::Mouse, screenPos);
|
|
|
|
|
2012-09-24 17:18:55 +02:00
|
|
|
//FIXME: do we need views here?
|
|
|
|
//gvevent.setWidget(view());
|
2010-09-08 02:00:19 +02:00
|
|
|
contextMenuEvent(&gvevent);
|
2008-11-04 00:08:39 +01:00
|
|
|
}
|
|
|
|
|
2012-09-25 21:35:53 +02:00
|
|
|
void Containment::contextMenuEvent(QContextMenuEvent *event)
|
2008-11-04 00:08:39 +01:00
|
|
|
{
|
2010-09-08 23:51:22 +02:00
|
|
|
if (!isContainment() || !KAuthorized::authorizeKAction("plasma/containment_context_menu")) {
|
2008-11-04 00:08:39 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-09-08 23:51:22 +02:00
|
|
|
KMenu desktopMenu;
|
2012-11-09 15:46:12 +01:00
|
|
|
//TODO: port to the new containmentactions architecture
|
|
|
|
Applet *applet = 0;//d->appletAt(event->pos());
|
2010-09-08 23:51:22 +02:00
|
|
|
//kDebug() << "context menu event " << (QObject*)applet;
|
2010-09-09 20:37:28 +02:00
|
|
|
|
2010-09-08 23:51:22 +02:00
|
|
|
if (applet) {
|
2010-09-09 20:37:28 +02:00
|
|
|
d->addAppletActions(desktopMenu, applet, event);
|
2010-09-08 23:51:22 +02:00
|
|
|
} else {
|
2010-09-09 20:37:28 +02:00
|
|
|
d->addContainmentActions(desktopMenu, event);
|
2010-09-08 23:51:22 +02:00
|
|
|
}
|
|
|
|
|
2010-12-03 19:24:00 +01:00
|
|
|
//kDebug() << "executing at" << screenPos;
|
2010-12-03 18:03:18 +01:00
|
|
|
QMenu *menu = &desktopMenu;
|
|
|
|
//kDebug() << "showing menu, actions" << desktopMenu.actions().size() << desktopMenu.actions().first()->menu();
|
|
|
|
if (desktopMenu.actions().size() == 1 && desktopMenu.actions().first()->menu()) {
|
|
|
|
// we have a menu with a single top level menu; just show that top level menu instad.
|
|
|
|
menu = desktopMenu.actions().first()->menu();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!menu->isEmpty()) {
|
2012-09-25 21:35:53 +02:00
|
|
|
QPoint pos = event->globalPos();
|
2010-09-08 23:51:22 +02:00
|
|
|
if (applet && d->isPanelContainment()) {
|
2010-12-03 18:03:18 +01:00
|
|
|
menu->adjustSize();
|
|
|
|
pos = applet->popupPosition(menu->size());
|
2012-09-25 21:35:53 +02:00
|
|
|
if (event->reason() == QContextMenuEvent::Mouse) {
|
2010-09-08 23:51:22 +02:00
|
|
|
// if the menu pops up way away from the mouse press, then move it
|
|
|
|
// to the mouse press
|
|
|
|
if (d->formFactor == Vertical) {
|
2012-09-25 21:35:53 +02:00
|
|
|
if (pos.y() + menu->height() < event->globalPos().y()) {
|
|
|
|
pos.setY(event->globalPos().y());
|
2010-09-08 23:51:22 +02:00
|
|
|
}
|
|
|
|
} else if (d->formFactor == Horizontal) {
|
2012-09-25 21:35:53 +02:00
|
|
|
if (pos.x() + menu->width() < event->globalPos().x()) {
|
|
|
|
pos.setX(event->globalPos().x());
|
2010-09-08 23:51:22 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-12-03 18:03:18 +01:00
|
|
|
menu->exec(pos);
|
2008-11-04 00:08:39 +01:00
|
|
|
event->accept();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Containment::setFormFactor(FormFactor formFactor)
|
|
|
|
{
|
|
|
|
if (d->formFactor == formFactor) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
//kDebug() << "switching FF to " << formFactor;
|
|
|
|
d->formFactor = formFactor;
|
|
|
|
|
|
|
|
updateConstraints(Plasma::FormFactorConstraint);
|
|
|
|
|
|
|
|
KConfigGroup c = config();
|
|
|
|
c.writeEntry("formfactor", (int)formFactor);
|
|
|
|
emit configNeedsSaving();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Containment::setLocation(Location location)
|
|
|
|
{
|
|
|
|
if (d->location == location) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool emitGeomChange = false;
|
|
|
|
|
|
|
|
if ((location == TopEdge || location == BottomEdge) &&
|
|
|
|
(d->location == TopEdge || d->location == BottomEdge)) {
|
|
|
|
emitGeomChange = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((location == RightEdge || location == LeftEdge) &&
|
|
|
|
(d->location == RightEdge || d->location == LeftEdge)) {
|
|
|
|
emitGeomChange = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
d->location = location;
|
|
|
|
|
|
|
|
foreach (Applet *applet, d->applets) {
|
|
|
|
applet->updateConstraints(Plasma::LocationConstraint);
|
|
|
|
}
|
|
|
|
|
|
|
|
updateConstraints(Plasma::LocationConstraint);
|
|
|
|
|
|
|
|
KConfigGroup c = config();
|
|
|
|
c.writeEntry("location", (int)location);
|
|
|
|
emit configNeedsSaving();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Containment::addSiblingContainment()
|
|
|
|
{
|
|
|
|
emit addSiblingContainment(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Containment::clearApplets()
|
|
|
|
{
|
|
|
|
foreach (Applet *applet, d->applets) {
|
|
|
|
applet->d->cleanUpAndDelete();
|
|
|
|
}
|
|
|
|
|
|
|
|
d->applets.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
Applet *Containment::addApplet(const QString &name, const QVariantList &args,
|
|
|
|
const QRectF &appletGeometry)
|
|
|
|
{
|
|
|
|
return d->addApplet(name, args, appletGeometry);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Containment::addApplet(Applet *applet, const QPointF &pos, bool delayInit)
|
|
|
|
{
|
|
|
|
if (!isContainment() || (!delayInit && immutability() != Mutable)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!applet) {
|
2011-07-29 15:46:52 +02:00
|
|
|
#ifndef NDEBUG
|
2008-11-04 00:08:39 +01:00
|
|
|
kDebug() << "adding null applet!?!";
|
2011-07-29 15:46:52 +02:00
|
|
|
#endif
|
2008-11-04 00:08:39 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (d->applets.contains(applet)) {
|
2011-07-29 15:46:52 +02:00
|
|
|
#ifndef NDEBUG
|
2008-11-04 00:08:39 +01:00
|
|
|
kDebug() << "already have this applet!";
|
2011-07-29 15:46:52 +02:00
|
|
|
#endif
|
2008-11-04 00:08:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
Containment *currentContainment = applet->containment();
|
|
|
|
|
2009-01-23 08:32:11 +01:00
|
|
|
if (d->type == PanelContainment) {
|
2008-11-04 00:08:39 +01:00
|
|
|
//panels don't want backgrounds, which is important when setting geometry
|
|
|
|
setBackgroundHints(NoBackground);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (currentContainment && currentContainment != this) {
|
|
|
|
emit currentContainment->appletRemoved(applet);
|
2009-05-13 20:11:08 +02:00
|
|
|
if (currentContainment->d->focusedApplet == applet) {
|
|
|
|
currentContainment->d->focusedApplet = 0;
|
|
|
|
}
|
|
|
|
|
2008-11-25 04:07:18 +01:00
|
|
|
disconnect(applet, 0, currentContainment, 0);
|
2008-11-04 00:08:39 +01:00
|
|
|
KConfigGroup oldConfig = applet->config();
|
|
|
|
currentContainment->d->applets.removeAll(applet);
|
2010-12-16 21:08:16 +01:00
|
|
|
applet->setParent(this);
|
2008-11-04 00:08:39 +01:00
|
|
|
|
|
|
|
// now move the old config to the new location
|
2009-01-23 08:32:11 +01:00
|
|
|
//FIXME: this doesn't seem to get the actual main config group containing plugin=, etc
|
2008-11-04 00:08:39 +01:00
|
|
|
KConfigGroup c = config().group("Applets").group(QString::number(applet->id()));
|
|
|
|
oldConfig.reparent(&c);
|
|
|
|
applet->d->resetConfigurationObject();
|
2009-01-24 11:47:35 +01:00
|
|
|
|
|
|
|
disconnect(applet, SIGNAL(activate()), currentContainment, SIGNAL(activate()));
|
2008-11-04 00:08:39 +01:00
|
|
|
} else {
|
2010-12-16 21:08:16 +01:00
|
|
|
applet->setParent(this);
|
2008-11-04 00:08:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
d->applets << applet;
|
|
|
|
|
|
|
|
connect(applet, SIGNAL(configNeedsSaving()), this, SIGNAL(configNeedsSaving()));
|
|
|
|
connect(applet, SIGNAL(releaseVisualFocus()), this, SIGNAL(releaseVisualFocus()));
|
2012-09-24 13:58:54 +02:00
|
|
|
connect(applet, SIGNAL(appletDeleted(Plasma::Applet*)), this, SLOT(appletDestroyed(Plasma::Applet*)));
|
2010-05-06 00:33:52 +02:00
|
|
|
connect(applet, SIGNAL(newStatus(Plasma::ItemStatus)), this, SLOT(checkStatus(Plasma::ItemStatus)));
|
2009-01-24 11:47:35 +01:00
|
|
|
connect(applet, SIGNAL(activate()), this, SIGNAL(activate()));
|
2008-11-04 00:08:39 +01:00
|
|
|
|
2011-05-28 00:22:17 +02:00
|
|
|
if (!delayInit && !currentContainment) {
|
2010-06-23 19:50:16 +02:00
|
|
|
applet->restore(*applet->d->mainConfigGroup());
|
2008-11-04 00:08:39 +01:00
|
|
|
applet->init();
|
2011-11-17 14:40:53 +01:00
|
|
|
//FIXME: an on-appear animation would be nice to have again
|
|
|
|
d->appletAppeared(applet);
|
2008-11-04 00:08:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
applet->updateConstraints(Plasma::AllConstraints);
|
|
|
|
if (!delayInit) {
|
|
|
|
applet->flushPendingConstraintsEvents();
|
|
|
|
}
|
|
|
|
emit appletAdded(applet, pos);
|
2008-12-12 02:05:00 +01:00
|
|
|
|
|
|
|
if (!currentContainment) {
|
|
|
|
applet->updateConstraints(Plasma::StartupCompletedConstraint);
|
|
|
|
if (!delayInit) {
|
|
|
|
applet->flushPendingConstraintsEvents();
|
|
|
|
}
|
|
|
|
}
|
2010-03-06 02:41:18 +01:00
|
|
|
|
2008-12-15 18:48:28 +01:00
|
|
|
if (!delayInit) {
|
|
|
|
applet->d->scheduleModificationNotification();
|
|
|
|
}
|
2008-11-04 00:08:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
Applet::List Containment::applets() const
|
|
|
|
{
|
|
|
|
return d->applets;
|
|
|
|
}
|
|
|
|
|
2009-01-18 20:52:09 +01:00
|
|
|
void Containment::setScreen(int newScreen, int newDesktop)
|
2010-09-24 21:03:45 +02:00
|
|
|
{
|
|
|
|
d->setScreen(newScreen, newDesktop);
|
|
|
|
}
|
|
|
|
|
2008-11-04 00:08:39 +01:00
|
|
|
int Containment::screen() const
|
|
|
|
{
|
|
|
|
return d->screen;
|
|
|
|
}
|
|
|
|
|
2010-05-19 04:43:07 +02:00
|
|
|
int Containment::lastScreen() const
|
|
|
|
{
|
|
|
|
return d->lastScreen;
|
|
|
|
}
|
|
|
|
|
2008-11-17 05:34:55 +01:00
|
|
|
int Containment::desktop() const
|
|
|
|
{
|
|
|
|
return d->desktop;
|
|
|
|
}
|
|
|
|
|
2010-05-19 04:43:07 +02:00
|
|
|
int Containment::lastDesktop() const
|
|
|
|
{
|
|
|
|
return d->lastDesktop;
|
|
|
|
}
|
|
|
|
|
2008-11-04 00:08:39 +01:00
|
|
|
KPluginInfo::List Containment::listContainments(const QString &category,
|
|
|
|
const QString &parentApp)
|
2009-04-03 02:29:54 +02:00
|
|
|
{
|
|
|
|
return listContainmentsOfType(QString(), category, parentApp);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
KPluginInfo::List Containment::listContainmentsOfType(const QString &type,
|
|
|
|
const QString &category,
|
|
|
|
const QString &parentApp)
|
2008-11-04 00:08:39 +01:00
|
|
|
{
|
|
|
|
QString constraint;
|
|
|
|
|
|
|
|
if (parentApp.isEmpty()) {
|
2010-02-22 17:32:05 +01:00
|
|
|
constraint.append("(not exist [X-KDE-ParentApp] or [X-KDE-ParentApp] == '')");
|
2008-11-04 00:08:39 +01:00
|
|
|
} else {
|
|
|
|
constraint.append("[X-KDE-ParentApp] == '").append(parentApp).append("'");
|
|
|
|
}
|
|
|
|
|
2009-04-03 02:29:54 +02:00
|
|
|
if (!type.isEmpty()) {
|
|
|
|
if (!constraint.isEmpty()) {
|
|
|
|
constraint.append(" and ");
|
|
|
|
}
|
|
|
|
|
2009-04-03 02:34:53 +02:00
|
|
|
constraint.append("'").append(type).append("' ~in [X-Plasma-ContainmentCategories]");
|
2009-04-03 02:29:54 +02:00
|
|
|
}
|
|
|
|
|
2008-11-04 00:08:39 +01:00
|
|
|
if (!category.isEmpty()) {
|
|
|
|
if (!constraint.isEmpty()) {
|
|
|
|
constraint.append(" and ");
|
|
|
|
}
|
|
|
|
|
2009-05-01 20:01:26 +02:00
|
|
|
constraint.append("[X-KDE-PluginInfo-Category] == '").append(category).append("'");
|
2008-11-04 00:08:39 +01:00
|
|
|
if (category == "Miscellaneous") {
|
2009-05-01 20:01:26 +02:00
|
|
|
constraint.append(" or (not exist [X-KDE-PluginInfo-Category] or [X-KDE-PluginInfo-Category] == '')");
|
2008-11-04 00:08:39 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
KService::List offers = KServiceTypeTrader::self()->query("Plasma/Containment", constraint);
|
|
|
|
//kDebug() << "constraint was" << constraint << "which got us" << offers.count() << "matches";
|
|
|
|
return KPluginInfo::fromServices(offers);
|
|
|
|
}
|
|
|
|
|
2011-05-06 12:17:08 +02:00
|
|
|
KPluginInfo::List Containment::listContainmentsForMimeType(const QString &mimeType)
|
2008-11-04 00:08:39 +01:00
|
|
|
{
|
2011-05-06 12:17:08 +02:00
|
|
|
const QString constraint = QString("'%1' in [X-Plasma-DropMimeTypes]").arg(mimeType);
|
|
|
|
//kDebug() << mimeType << constraint;
|
2009-07-06 13:49:01 +02:00
|
|
|
const KService::List offers = KServiceTypeTrader::self()->query("Plasma/Containment", constraint);
|
2008-11-04 00:08:39 +01:00
|
|
|
return KPluginInfo::fromServices(offers);
|
|
|
|
}
|
|
|
|
|
2009-04-03 02:29:54 +02:00
|
|
|
QStringList Containment::listContainmentTypes()
|
|
|
|
{
|
|
|
|
KPluginInfo::List containmentInfos = listContainments();
|
|
|
|
QSet<QString> types;
|
|
|
|
|
|
|
|
foreach (const KPluginInfo &containmentInfo, containmentInfos) {
|
|
|
|
QStringList theseTypes = containmentInfo.service()->property("X-Plasma-ContainmentCategories").toStringList();
|
|
|
|
foreach (const QString &type, theseTypes) {
|
|
|
|
types.insert(type);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return types.toList();
|
|
|
|
}
|
|
|
|
|
2012-09-25 20:35:04 +02:00
|
|
|
void Containment::dropEvent(QDropEvent *event)
|
2008-11-04 00:08:39 +01:00
|
|
|
{
|
2009-05-05 07:19:35 +02:00
|
|
|
if (isContainment()) {
|
2012-09-25 20:35:04 +02:00
|
|
|
d->dropData(event->pos(), event);
|
2009-10-20 16:14:53 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-11-09 16:45:03 +01:00
|
|
|
//TODO: remove and make it GSS
|
2012-09-25 20:46:07 +02:00
|
|
|
void Containment::resizeEvent(QResizeEvent *event)
|
2008-11-04 00:08:39 +01:00
|
|
|
{
|
2010-04-23 21:06:55 +02:00
|
|
|
if (isContainment()) {
|
|
|
|
if (d->wallpaper) {
|
2012-11-09 16:45:03 +01:00
|
|
|
d->wallpaper->setBoundingRect(QRectF(QPointF(0, 0), event->size()));
|
2010-04-23 21:06:55 +02:00
|
|
|
}
|
2008-11-04 00:08:39 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Containment::keyPressEvent(QKeyEvent *event)
|
|
|
|
{
|
|
|
|
//kDebug() << "keyPressEvent with" << event->key()
|
|
|
|
// << "and hoping and wishing for a" << Qt::Key_Tab;
|
|
|
|
if (event->key() == Qt::Key_Tab) { // && event->modifiers() == 0) {
|
|
|
|
if (!d->applets.isEmpty()) {
|
2011-07-29 15:46:52 +02:00
|
|
|
#ifndef NDEBUG
|
2008-11-04 00:08:39 +01:00
|
|
|
kDebug() << "let's give focus to...." << (QObject*)d->applets.first();
|
2011-07-29 15:46:52 +02:00
|
|
|
#endif
|
2008-11-04 00:08:39 +01:00
|
|
|
d->applets.first()->setFocus(Qt::TabFocusReason);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-09-25 21:35:53 +02:00
|
|
|
void Containment::wheelEvent(QWheelEvent *event)
|
2008-11-04 00:08:39 +01:00
|
|
|
{
|
2009-08-18 00:31:18 +02:00
|
|
|
event->ignore();
|
|
|
|
|
2009-08-18 00:30:34 +02:00
|
|
|
if (d->wallpaper && d->wallpaper->isInitialized()) {
|
2012-09-24 17:18:55 +02:00
|
|
|
event->ignore();
|
|
|
|
d->wallpaper->wheelEvent(event);
|
2008-11-04 00:08:39 +01:00
|
|
|
|
2012-09-24 17:18:55 +02:00
|
|
|
if (event->isAccepted()) {
|
|
|
|
return;
|
2008-11-04 00:08:39 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-12-30 00:23:25 +01:00
|
|
|
QString trigger = ContainmentActions::eventToString(event);
|
|
|
|
|
2012-09-25 21:35:53 +02:00
|
|
|
if (d->prepareContainmentActions(trigger, event->globalPos())) {
|
2010-11-11 23:22:39 +01:00
|
|
|
d->actionPlugins()->value(trigger)->contextEvent(event);
|
2009-12-30 00:23:25 +01:00
|
|
|
event->accept();
|
|
|
|
}
|
2008-11-04 00:08:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void Containment::enableAction(const QString &name, bool enable)
|
|
|
|
{
|
|
|
|
QAction *action = this->action(name);
|
|
|
|
if (action) {
|
|
|
|
action->setEnabled(enable);
|
|
|
|
action->setVisible(enable);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Containment::addToolBoxAction(QAction *action)
|
|
|
|
{
|
2012-09-24 17:18:55 +02:00
|
|
|
d->toolBoxActions << action;
|
2008-11-04 00:08:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void Containment::removeToolBoxAction(QAction *action)
|
|
|
|
{
|
2012-09-24 17:18:55 +02:00
|
|
|
d->toolBoxActions.removeAll(action);
|
2008-11-04 00:08:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void Containment::addAssociatedWidget(QWidget *widget)
|
|
|
|
{
|
|
|
|
Applet::addAssociatedWidget(widget);
|
|
|
|
if (d->focusedApplet) {
|
|
|
|
d->focusedApplet->addAssociatedWidget(widget);
|
|
|
|
}
|
|
|
|
|
|
|
|
foreach (const Applet *applet, d->applets) {
|
|
|
|
if (applet->d->activationAction) {
|
|
|
|
widget->addAction(applet->d->activationAction);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Containment::removeAssociatedWidget(QWidget *widget)
|
|
|
|
{
|
|
|
|
Applet::removeAssociatedWidget(widget);
|
|
|
|
if (d->focusedApplet) {
|
|
|
|
d->focusedApplet->removeAssociatedWidget(widget);
|
|
|
|
}
|
|
|
|
|
|
|
|
foreach (const Applet *applet, d->applets) {
|
|
|
|
if (applet->d->activationAction) {
|
|
|
|
widget->removeAction(applet->d->activationAction);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Containment::setDrawWallpaper(bool drawWallpaper)
|
|
|
|
{
|
|
|
|
d->drawWallpaper = drawWallpaper;
|
|
|
|
if (drawWallpaper) {
|
|
|
|
KConfigGroup cfg = config();
|
2012-07-17 14:21:45 +02:00
|
|
|
const QString wallpaper = cfg.readEntry("wallpaperplugin", ContainmentPrivate::defaultWallpaper);
|
|
|
|
const QString mode = cfg.readEntry("wallpaperpluginmode", ContainmentPrivate::defaultWallpaperMode);
|
2008-11-04 00:08:39 +01:00
|
|
|
setWallpaper(wallpaper, mode);
|
|
|
|
} else {
|
|
|
|
delete d->wallpaper;
|
|
|
|
d->wallpaper = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Containment::drawWallpaper()
|
|
|
|
{
|
|
|
|
return d->drawWallpaper;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Containment::setWallpaper(const QString &pluginName, const QString &mode)
|
|
|
|
{
|
|
|
|
KConfigGroup cfg = config();
|
|
|
|
bool newPlugin = true;
|
|
|
|
bool newMode = true;
|
|
|
|
|
|
|
|
if (d->drawWallpaper) {
|
|
|
|
if (d->wallpaper) {
|
|
|
|
// we have a wallpaper, so let's decide whether we need to swap it out
|
|
|
|
if (d->wallpaper->pluginName() != pluginName) {
|
|
|
|
delete d->wallpaper;
|
|
|
|
d->wallpaper = 0;
|
|
|
|
} else {
|
|
|
|
// it's the same plugin, so let's save its state now so when
|
|
|
|
// we call restore later on we're safe
|
|
|
|
newMode = d->wallpaper->renderingMode().name() != mode;
|
|
|
|
newPlugin = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!pluginName.isEmpty() && !d->wallpaper) {
|
|
|
|
d->wallpaper = Plasma::Wallpaper::load(pluginName);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (d->wallpaper) {
|
2009-05-17 20:23:31 +02:00
|
|
|
d->wallpaper->setParent(this);
|
2008-11-04 00:08:39 +01:00
|
|
|
d->wallpaper->setRenderingMode(mode);
|
|
|
|
|
|
|
|
if (newPlugin) {
|
|
|
|
cfg.writeEntry("wallpaperplugin", pluginName);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (d->wallpaper->isInitialized()) {
|
|
|
|
KConfigGroup wallpaperConfig = KConfigGroup(&cfg, "Wallpaper");
|
|
|
|
wallpaperConfig = KConfigGroup(&wallpaperConfig, pluginName);
|
|
|
|
d->wallpaper->restore(wallpaperConfig);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (newMode) {
|
|
|
|
cfg.writeEntry("wallpaperpluginmode", mode);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!d->wallpaper) {
|
|
|
|
cfg.deleteEntry("wallpaperplugin");
|
|
|
|
cfg.deleteEntry("wallpaperpluginmode");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (newPlugin || newMode) {
|
2009-04-02 06:15:50 +02:00
|
|
|
if (newPlugin && d->wallpaper) {
|
2009-04-23 18:38:16 +02:00
|
|
|
connect(d->wallpaper, SIGNAL(configureRequested()), this, SLOT(requestConfiguration()));
|
|
|
|
connect(d->wallpaper, SIGNAL(configNeedsSaving()), this, SIGNAL(configNeedsSaving()));
|
2009-04-02 06:15:50 +02:00
|
|
|
}
|
|
|
|
|
2008-11-04 00:08:39 +01:00
|
|
|
emit configNeedsSaving();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Plasma::Wallpaper *Containment::wallpaper() const
|
|
|
|
{
|
|
|
|
return d->wallpaper;
|
|
|
|
}
|
|
|
|
|
2009-08-18 00:31:32 +02:00
|
|
|
void Containment::setContainmentActions(const QString &trigger, const QString &pluginName)
|
2009-08-18 00:30:34 +02:00
|
|
|
{
|
2010-11-11 23:22:39 +01:00
|
|
|
KConfigGroup cfg = containmentActionsConfig();
|
2009-08-18 00:31:32 +02:00
|
|
|
ContainmentActions *plugin = 0;
|
2009-08-18 00:30:34 +02:00
|
|
|
|
2010-11-11 23:22:39 +01:00
|
|
|
if (d->actionPlugins()->contains(trigger)) {
|
|
|
|
plugin = d->actionPlugins()->value(trigger);
|
2009-08-18 00:31:32 +02:00
|
|
|
if (plugin->pluginName() != pluginName) {
|
2010-11-11 23:22:39 +01:00
|
|
|
d->actionPlugins()->remove(trigger);
|
2009-08-18 00:31:32 +02:00
|
|
|
delete plugin;
|
|
|
|
plugin=0;
|
2009-08-18 00:30:34 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (pluginName.isEmpty()) {
|
|
|
|
cfg.deleteEntry(trigger);
|
2009-08-18 00:31:32 +02:00
|
|
|
} else if (plugin) {
|
2009-08-18 00:31:08 +02:00
|
|
|
//it already existed, just reload config
|
2009-08-18 00:31:32 +02:00
|
|
|
if (plugin->isInitialized()) {
|
2010-11-11 23:22:39 +01:00
|
|
|
plugin->setContainment(this); //to be safe
|
2009-08-18 00:31:08 +02:00
|
|
|
//FIXME make a truly unique config group
|
2009-08-18 00:31:37 +02:00
|
|
|
KConfigGroup pluginConfig = KConfigGroup(&cfg, trigger);
|
2009-08-18 00:31:32 +02:00
|
|
|
plugin->restore(pluginConfig);
|
2009-08-18 00:30:42 +02:00
|
|
|
}
|
2009-08-18 00:31:08 +02:00
|
|
|
} else {
|
2010-11-11 23:22:39 +01:00
|
|
|
switch (d->containmentActionsSource) {
|
|
|
|
case ContainmentPrivate::Activity:
|
|
|
|
//FIXME
|
|
|
|
case ContainmentPrivate::Local:
|
2011-07-19 21:40:57 +02:00
|
|
|
plugin = PluginLoader::self()->loadContainmentActions(this, pluginName);
|
2010-11-11 23:22:39 +01:00
|
|
|
break;
|
|
|
|
default:
|
2011-07-19 21:40:57 +02:00
|
|
|
plugin = PluginLoader::self()->loadContainmentActions(0, pluginName);
|
2010-11-11 23:22:39 +01:00
|
|
|
}
|
2009-08-18 00:31:32 +02:00
|
|
|
if (plugin) {
|
2009-08-18 00:31:08 +02:00
|
|
|
cfg.writeEntry(trigger, pluginName);
|
2010-11-11 23:22:39 +01:00
|
|
|
d->actionPlugins()->insert(trigger, plugin);
|
2009-08-18 00:31:08 +02:00
|
|
|
} else {
|
|
|
|
//bad plugin... gets removed. is this a feature or a bug?
|
|
|
|
cfg.deleteEntry(trigger);
|
2009-08-18 00:30:34 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-08-18 00:30:42 +02:00
|
|
|
emit configNeedsSaving();
|
2009-08-18 00:30:34 +02:00
|
|
|
}
|
|
|
|
|
2009-08-18 00:31:32 +02:00
|
|
|
QStringList Containment::containmentActionsTriggers()
|
2009-08-18 00:30:38 +02:00
|
|
|
{
|
2010-11-11 23:22:39 +01:00
|
|
|
return d->actionPlugins()->keys();
|
2009-08-18 00:30:38 +02:00
|
|
|
}
|
|
|
|
|
2009-08-18 00:31:32 +02:00
|
|
|
QString Containment::containmentActions(const QString &trigger)
|
2009-08-18 00:30:38 +02:00
|
|
|
{
|
2010-11-11 23:22:39 +01:00
|
|
|
ContainmentActions *c = d->actionPlugins()->value(trigger);
|
2009-08-18 00:31:18 +02:00
|
|
|
return c ? c->pluginName() : QString();
|
2009-08-18 00:30:38 +02:00
|
|
|
}
|
|
|
|
|
2011-05-20 09:41:19 +02:00
|
|
|
void Containment::setActivity(const QString &activityId)
|
2008-11-04 00:08:39 +01:00
|
|
|
{
|
2011-05-20 09:41:19 +02:00
|
|
|
if (activityId.isEmpty()) {
|
|
|
|
return;
|
2010-05-11 21:02:24 +02:00
|
|
|
}
|
2010-05-10 03:43:06 +02:00
|
|
|
|
2011-05-20 09:41:19 +02:00
|
|
|
d->activityId = activityId;
|
|
|
|
KConfigGroup c = config();
|
|
|
|
c.writeEntry("activityId", activityId);
|
2010-05-10 03:43:06 +02:00
|
|
|
|
2011-05-20 09:41:19 +02:00
|
|
|
emit configNeedsSaving();
|
2010-05-10 03:43:06 +02:00
|
|
|
}
|
|
|
|
|
2008-11-04 00:08:39 +01:00
|
|
|
QString Containment::activity() const
|
|
|
|
{
|
2011-05-20 09:41:19 +02:00
|
|
|
return d->activityId;
|
2008-11-04 00:08:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void Containment::focusNextApplet()
|
|
|
|
{
|
|
|
|
if (d->applets.isEmpty()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
int index = d->focusedApplet ? d->applets.indexOf(d->focusedApplet) + 1 : 0;
|
|
|
|
if (index >= d->applets.size()) {
|
|
|
|
index = 0;
|
|
|
|
}
|
2011-07-29 15:46:52 +02:00
|
|
|
#ifndef NDEBUG
|
2008-11-04 00:08:39 +01:00
|
|
|
kDebug() << "index" << index;
|
2011-07-29 15:46:52 +02:00
|
|
|
#endif
|
2008-11-04 00:08:39 +01:00
|
|
|
d->focusApplet(d->applets.at(index));
|
|
|
|
}
|
|
|
|
|
|
|
|
void Containment::focusPreviousApplet()
|
|
|
|
{
|
|
|
|
if (d->applets.isEmpty()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
int index = d->focusedApplet ? d->applets.indexOf(d->focusedApplet) - 1 : -1;
|
|
|
|
if (index < 0) {
|
|
|
|
index = d->applets.size() - 1;
|
|
|
|
}
|
2011-07-29 15:46:52 +02:00
|
|
|
#ifndef NDEBUG
|
2008-11-04 00:08:39 +01:00
|
|
|
kDebug() << "index" << index;
|
2011-07-29 15:46:52 +02:00
|
|
|
#endif
|
2008-11-04 00:08:39 +01:00
|
|
|
d->focusApplet(d->applets.at(index));
|
|
|
|
}
|
|
|
|
|
|
|
|
void Containment::destroy()
|
|
|
|
{
|
|
|
|
destroy(true);
|
|
|
|
}
|
|
|
|
|
2008-11-10 02:26:27 +01:00
|
|
|
void Containment::showConfigurationInterface()
|
|
|
|
{
|
|
|
|
Applet::showConfigurationInterface();
|
|
|
|
}
|
|
|
|
|
2008-11-04 00:08:39 +01:00
|
|
|
void Containment::destroy(bool confirm)
|
|
|
|
{
|
2009-05-06 21:08:29 +02:00
|
|
|
if (immutability() != Mutable || Applet::d->transient) {
|
2008-11-04 00:08:39 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2011-04-26 13:04:14 +02:00
|
|
|
if (isContainment() && confirm) {
|
2010-05-08 21:08:00 +02:00
|
|
|
//FIXME: should not be blocking
|
2011-04-26 13:04:14 +02:00
|
|
|
const QString title = i18nc("@title:window %1 is the name of the containment", "Remove %1", name());
|
|
|
|
KGuiItem remove = KStandardGuiItem::remove();
|
|
|
|
remove.setText(title);
|
2012-09-24 17:18:55 +02:00
|
|
|
//FIXME: make the view accessible?
|
|
|
|
if (KMessageBox::warningContinueCancel(0/*view()*/,
|
2011-04-26 13:04:14 +02:00
|
|
|
i18nc("%1 is the name of the containment", "Do you really want to remove this %1?", name()),
|
|
|
|
title, remove) != KMessageBox::Continue) {
|
|
|
|
return;
|
2008-11-04 00:08:39 +01:00
|
|
|
}
|
|
|
|
}
|
2011-04-26 13:04:14 +02:00
|
|
|
|
|
|
|
Applet::destroy();
|
2008-11-04 00:08:39 +01:00
|
|
|
}
|
|
|
|
|
2010-11-11 23:22:39 +01:00
|
|
|
KConfigGroup Containment::containmentActionsConfig()
|
|
|
|
{
|
|
|
|
KConfigGroup cfg;
|
|
|
|
switch (d->containmentActionsSource) {
|
|
|
|
case ContainmentPrivate::Local:
|
2010-11-14 20:10:06 +01:00
|
|
|
cfg = config();
|
|
|
|
cfg = KConfigGroup(&cfg, "ActionPlugins");
|
2010-11-11 23:22:39 +01:00
|
|
|
break;
|
|
|
|
case ContainmentPrivate::Activity:
|
|
|
|
cfg = KConfigGroup(corona()->config(), "Activities");
|
2011-05-20 09:41:19 +02:00
|
|
|
cfg = KConfigGroup(&cfg, d->activityId);
|
2010-11-11 23:22:39 +01:00
|
|
|
cfg = KConfigGroup(&cfg, "ActionPlugins");
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
cfg = KConfigGroup(corona()->config(), "ActionPlugins");
|
|
|
|
}
|
|
|
|
return cfg;
|
|
|
|
}
|
|
|
|
|
2012-09-24 18:10:25 +02:00
|
|
|
|
2008-11-04 00:08:39 +01:00
|
|
|
} // Plasma namespace
|
|
|
|
|
|
|
|
|
2012-02-08 23:33:03 +01:00
|
|
|
|
|
|
|
#include "moc_containment.cpp"
|