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>
|
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>
|
|
|
|
#include <QGraphicsSceneContextMenuEvent>
|
|
|
|
#include <QGraphicsView>
|
|
|
|
#include <QMimeData>
|
|
|
|
#include <QPainter>
|
|
|
|
#include <QStyleOptionGraphicsItem>
|
|
|
|
#include <QGraphicsLayout>
|
|
|
|
#include <QGraphicsLinearLayout>
|
|
|
|
|
2008-11-04 03:04:34 +01:00
|
|
|
#include <kaction.h>
|
|
|
|
#include <kauthorized.h>
|
|
|
|
#include <kicon.h>
|
|
|
|
#include <kmenu.h>
|
|
|
|
#include <kmessagebox.h>
|
|
|
|
#include <kmimetype.h>
|
|
|
|
#include <kservicetypetrader.h>
|
|
|
|
#include <kstandarddirs.h>
|
|
|
|
#include <ktemporaryfile.h>
|
|
|
|
#include <kwindowsystem.h>
|
2010-10-14 14:27:15 +02:00
|
|
|
|
|
|
|
#ifndef 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
|
|
|
|
2010-07-31 15:02:07 +02:00
|
|
|
#include "abstracttoolbox.h"
|
2008-11-04 00:08:39 +01:00
|
|
|
#include "animator.h"
|
|
|
|
#include "context.h"
|
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"
|
2010-03-06 02:41:18 +01:00
|
|
|
#include "extender.h"
|
2009-02-09 19:10:45 +01:00
|
|
|
#include "extenderitem.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"
|
2009-02-09 19:10:45 +01:00
|
|
|
#include "private/extenderitemmimedata_p.h"
|
2010-03-06 02:41:18 +01:00
|
|
|
#include "private/extenderapplet_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"
|
|
|
|
#include "animations/animation.h"
|
|
|
|
|
2008-11-04 00:08:39 +01:00
|
|
|
namespace Plasma
|
|
|
|
{
|
|
|
|
|
2010-02-24 15:24:52 +01:00
|
|
|
bool ContainmentPrivate::s_positioningPanels = false;
|
2010-11-11 23:22:39 +01:00
|
|
|
QHash<QString, ContainmentActions*> ContainmentPrivate::globalActionPlugins;
|
2008-11-04 00:08:39 +01:00
|
|
|
static const char defaultWallpaper[] = "image";
|
|
|
|
static const char defaultWallpaperMode[] = "SingleImage";
|
|
|
|
|
|
|
|
Containment::StyleOption::StyleOption()
|
|
|
|
: QStyleOptionGraphicsItem(),
|
|
|
|
view(0)
|
|
|
|
{
|
|
|
|
version = Version;
|
|
|
|
type = Type;
|
|
|
|
}
|
|
|
|
|
|
|
|
Containment::StyleOption::StyleOption(const Containment::StyleOption & other)
|
|
|
|
: QStyleOptionGraphicsItem(other),
|
|
|
|
view(other.view)
|
|
|
|
{
|
|
|
|
version = Version;
|
|
|
|
type = Type;
|
|
|
|
}
|
|
|
|
|
|
|
|
Containment::StyleOption::StyleOption(const QStyleOptionGraphicsItem &other)
|
|
|
|
: QStyleOptionGraphicsItem(other),
|
|
|
|
view(0)
|
|
|
|
{
|
|
|
|
version = Version;
|
|
|
|
type = Type;
|
|
|
|
}
|
|
|
|
|
|
|
|
Containment::Containment(QGraphicsItem *parent,
|
|
|
|
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
|
|
|
|
setPos(0, 0);
|
|
|
|
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
|
|
|
|
setPos(0, 0);
|
|
|
|
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)
|
|
|
|
: Plasma::Applet(packagePath, appletId, 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
|
|
|
|
setPos(0, 0);
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
setCacheMode(NoCache);
|
|
|
|
setFlag(QGraphicsItem::ItemIsMovable, false);
|
2011-12-06 21:11:30 +01:00
|
|
|
setFlag(QGraphicsItem::ItemClipsChildrenToShape, true);
|
2008-11-04 00:08:39 +01:00
|
|
|
setAcceptDrops(true);
|
|
|
|
setAcceptsHoverEvents(true);
|
|
|
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2009-10-14 01:07:35 +02:00
|
|
|
void ContainmentPrivate::addDefaultActions(KActionCollection *actions, Containment *c)
|
2009-05-03 22:22:14 +02:00
|
|
|
{
|
|
|
|
actions->setConfigGroup("Shortcuts-Containment");
|
|
|
|
|
|
|
|
//adjust applet actions
|
|
|
|
KAction *appAction = qobject_cast<KAction*>(actions->action("remove"));
|
|
|
|
appAction->setShortcut(KShortcut("alt+d, alt+r"));
|
2010-04-13 23:10:28 +02:00
|
|
|
if (c && c->d->isPanelContainment()) {
|
2010-05-09 13:03:13 +02:00
|
|
|
appAction->setText(i18n("Remove this Panel"));
|
2009-10-14 01:07:35 +02:00
|
|
|
} else {
|
2010-05-09 13:03:13 +02:00
|
|
|
appAction->setText(i18n("Remove this Activity"));
|
2009-10-14 01:07:35 +02:00
|
|
|
}
|
|
|
|
|
2009-05-03 22:22:14 +02:00
|
|
|
appAction = qobject_cast<KAction*>(actions->action("configure"));
|
|
|
|
if (appAction) {
|
|
|
|
appAction->setShortcut(KShortcut("alt+d, alt+s"));
|
|
|
|
appAction->setText(i18n("Activity Settings"));
|
|
|
|
}
|
|
|
|
|
|
|
|
//add our own actions
|
2009-05-04 00:13:05 +02:00
|
|
|
KAction *appletBrowserAction = actions->addAction("add widgets");
|
2009-06-29 03:22:58 +02:00
|
|
|
appletBrowserAction->setAutoRepeat(false);
|
2009-05-04 00:13:05 +02:00
|
|
|
appletBrowserAction->setText(i18n("Add Widgets..."));
|
2009-05-03 22:22:14 +02:00
|
|
|
appletBrowserAction->setIcon(KIcon("list-add"));
|
|
|
|
appletBrowserAction->setShortcut(KShortcut("alt+d, a"));
|
2010-01-04 07:37:41 +01:00
|
|
|
appletBrowserAction->setData(AbstractToolBox::AddTool);
|
2009-05-03 22:22:14 +02:00
|
|
|
|
2009-05-04 00:13:05 +02:00
|
|
|
KAction *action = actions->addAction("next applet");
|
|
|
|
action->setText(i18n("Next Widget"));
|
2009-05-03 22:22:14 +02:00
|
|
|
//no icon
|
|
|
|
action->setShortcut(KShortcut("alt+d, n"));
|
2010-01-04 07:37:41 +01:00
|
|
|
action->setData(AbstractToolBox::ControlTool);
|
2009-05-03 22:22:14 +02:00
|
|
|
|
2009-05-04 00:13:05 +02:00
|
|
|
action = actions->addAction("previous applet");
|
|
|
|
action->setText(i18n("Previous Widget"));
|
2009-05-03 22:22:14 +02:00
|
|
|
//no icon
|
|
|
|
action->setShortcut(KShortcut("alt+d, p"));
|
2010-01-04 07:37:41 +01:00
|
|
|
action->setData(AbstractToolBox::ControlTool);
|
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)
|
|
|
|
{
|
2009-01-23 08:32:11 +01:00
|
|
|
/*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);
|
|
|
|
kDebug() << " screen:" << group.readEntry("screen", d->screen);*/
|
|
|
|
if (!isContainment()) {
|
|
|
|
Applet::restore(group);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
QRectF geo = group.readEntry("geometry", geometry());
|
|
|
|
//override max/min
|
|
|
|
//this ensures panels are set to their saved size even when they have max & min set to prevent
|
|
|
|
//resizing
|
|
|
|
if (geo.size() != geo.size().boundedTo(maximumSize())) {
|
|
|
|
setMaximumSize(maximumSize().expandedTo(geo.size()));
|
|
|
|
}
|
2010-04-23 20:23:53 +02:00
|
|
|
|
2008-11-04 00:08:39 +01:00
|
|
|
if (geo.size() != geo.size().expandedTo(minimumSize())) {
|
|
|
|
setMinimumSize(minimumSize().boundedTo(geo.size()));
|
|
|
|
}
|
2009-04-08 22:37:45 +02:00
|
|
|
|
2009-05-20 22:27:01 +02:00
|
|
|
|
2010-04-23 20:23:53 +02:00
|
|
|
resize(geo.size());
|
2009-04-08 22:37:45 +02:00
|
|
|
//are we an offscreen containment?
|
|
|
|
if (containmentType() != PanelContainment && containmentType() != CustomPanelContainment && geo.right() < 0) {
|
|
|
|
corona()->addOffscreenWidget(this);
|
|
|
|
}
|
2008-11-04 00:08:39 +01:00
|
|
|
|
|
|
|
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);
|
2010-05-10 03:43:06 +02:00
|
|
|
QString activityId = group.readEntry("activityId", QString());
|
2010-05-11 09:14:54 +02:00
|
|
|
if (!activityId.isEmpty()) {
|
2010-05-11 21:02:24 +02:00
|
|
|
d->context()->setCurrentActivityId(activityId);
|
2010-05-10 03:43:06 +02:00
|
|
|
}
|
2008-11-04 00:08:39 +01:00
|
|
|
setActivity(group.readEntry("activity", QString()));
|
|
|
|
|
|
|
|
flushPendingConstraintsEvents();
|
|
|
|
restoreContents(group);
|
|
|
|
setImmutability((ImmutabilityType)group.readEntry("immutability", (int)Mutable));
|
|
|
|
|
|
|
|
setWallpaper(group.readEntry("wallpaperplugin", defaultWallpaper),
|
|
|
|
group.readEntry("wallpaperpluginmode", defaultWallpaperMode));
|
2009-06-15 15:57:46 +02:00
|
|
|
|
2010-07-31 15:02:07 +02:00
|
|
|
QMetaObject::invokeMethod(d->toolBox.data(), "restore", Q_ARG(KConfigGroup, group));
|
|
|
|
|
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 {
|
|
|
|
QString source = group.readEntry("ActionPluginsSource", QString());
|
|
|
|
if (source == "Global") {
|
|
|
|
cfg = KConfigGroup(corona()->config(), "ActionPlugins");
|
|
|
|
d->containmentActionsSource = ContainmentPrivate::Global;
|
|
|
|
} else if (source == "Activity") {
|
|
|
|
cfg = KConfigGroup(corona()->config(), "Activities");
|
|
|
|
cfg = KConfigGroup(&cfg, activityId);
|
|
|
|
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");
|
|
|
|
}
|
|
|
|
}
|
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
|
|
|
/*
|
|
|
|
kDebug() << "Containment" << id() <<
|
|
|
|
"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);
|
|
|
|
group.writeEntry("activity", d->context()->currentActivity());
|
2010-05-13 23:39:45 +02:00
|
|
|
group.writeEntry("activityId", d->context()->currentActivityId());
|
2008-11-04 00:08:39 +01:00
|
|
|
|
2010-07-31 15:02:07 +02:00
|
|
|
|
|
|
|
QMetaObject::invokeMethod(d->toolBox.data(), "save", Q_ARG(KConfigGroup, group));
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-06-04 23:36:28 +02:00
|
|
|
void ContainmentPrivate::initApplets()
|
|
|
|
{
|
|
|
|
foreach (Applet *applet, applets) {
|
|
|
|
applet->restore(*applet->d->mainConfigGroup());
|
|
|
|
applet->init();
|
|
|
|
kDebug() << "!!{} STARTUP TIME" << QTime().msecsTo(QTime::currentTime()) << "Applet" << applet->name();
|
|
|
|
}
|
2010-06-10 19:07:50 +02:00
|
|
|
|
|
|
|
q->flushPendingConstraintsEvents();
|
|
|
|
|
|
|
|
foreach (Applet *applet, applets) {
|
|
|
|
applet->flushPendingConstraintsEvents();
|
|
|
|
}
|
|
|
|
|
|
|
|
kDebug() << "!!{} STARTUP TIME" << QTime().msecsTo(QTime::currentTime()) << "Containment's applets initialized" << q->name();
|
2010-06-04 23:36:28 +02:00
|
|
|
}
|
|
|
|
|
2008-11-04 00:08:39 +01:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2009-11-25 20:46:33 +01:00
|
|
|
delete d->toolBox.data();
|
2008-11-04 00:08:39 +01:00
|
|
|
d->type = type;
|
2010-04-13 20:36:38 +02:00
|
|
|
d->checkContainmentFurniture();
|
|
|
|
}
|
2008-11-04 00:08:39 +01:00
|
|
|
|
2010-04-13 20:36:38 +02:00
|
|
|
void ContainmentPrivate::checkContainmentFurniture()
|
|
|
|
{
|
2010-04-13 23:10:28 +02:00
|
|
|
if (q->isContainment() &&
|
2010-04-13 20:36:38 +02:00
|
|
|
(type == Containment::DesktopContainment || type == Containment::PanelContainment)) {
|
|
|
|
createToolBox();
|
2008-11-04 00:08:39 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Corona *Containment::corona() const
|
|
|
|
{
|
2011-01-28 23:30:54 +01:00
|
|
|
return qobject_cast<Corona*>(scene());
|
2008-11-04 00:08:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void Containment::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
|
|
|
|
{
|
|
|
|
event->ignore();
|
|
|
|
if (d->wallpaper && d->wallpaper->isInitialized()) {
|
|
|
|
QGraphicsItem *item = scene()->itemAt(event->scenePos());
|
|
|
|
if (item == this) {
|
|
|
|
d->wallpaper->mouseMoveEvent(event);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!event->isAccepted()) {
|
|
|
|
event->accept();
|
|
|
|
Applet::mouseMoveEvent(event);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Containment::mousePressEvent(QGraphicsSceneMouseEvent *event)
|
|
|
|
{
|
2012-06-27 12:33:07 +02:00
|
|
|
//close a toolbox if exists, to emulate qmenu behavior
|
|
|
|
if (d->toolBox) {
|
|
|
|
d->toolBox.data()->setShowing(false);
|
|
|
|
}
|
2008-11-04 00:08:39 +01:00
|
|
|
event->ignore();
|
2009-08-30 20:52:05 +02:00
|
|
|
if (d->appletAt(event->scenePos())) {
|
2009-08-18 00:31:18 +02:00
|
|
|
return; //no unexpected click-throughs
|
|
|
|
}
|
2009-08-18 00:30:34 +02:00
|
|
|
|
|
|
|
if (d->wallpaper && d->wallpaper->isInitialized() && !event->isAccepted()) {
|
2009-08-18 00:31:18 +02:00
|
|
|
d->wallpaper->mousePressEvent(event);
|
2008-11-04 00:08:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (event->isAccepted()) {
|
|
|
|
setFocus(Qt::MouseFocusReason);
|
2010-09-08 23:51:22 +02:00
|
|
|
} else if (event->button() == Qt::RightButton && event->modifiers() == Qt::NoModifier) {
|
|
|
|
// we'll catch this in the context menu even
|
|
|
|
Applet::mousePressEvent(event);
|
2008-11-04 00:08:39 +01:00
|
|
|
} else {
|
2009-08-25 18:14:05 +02:00
|
|
|
QString trigger = ContainmentActions::eventToString(event);
|
2010-09-08 23:51:22 +02:00
|
|
|
if (d->prepareContainmentActions(trigger, event->screenPos())) {
|
2010-11-11 23:22:39 +01:00
|
|
|
d->actionPlugins()->value(trigger)->contextEvent(event);
|
2009-08-25 18:14:05 +02:00
|
|
|
}
|
|
|
|
|
2011-01-10 13:37:04 +01:00
|
|
|
if (!event->isAccepted()) {
|
|
|
|
Applet::mousePressEvent(event);
|
|
|
|
}
|
2008-11-04 00:08:39 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Containment::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
|
|
|
|
{
|
|
|
|
event->ignore();
|
2012-06-27 12:33:07 +02:00
|
|
|
|
2009-08-30 20:52:05 +02:00
|
|
|
if (d->appletAt(event->scenePos())) {
|
2009-08-18 00:31:18 +02:00
|
|
|
return; //no unexpected click-throughs
|
|
|
|
}
|
2009-08-18 00:30:34 +02:00
|
|
|
|
2009-08-18 00:31:32 +02:00
|
|
|
QString trigger = ContainmentActions::eventToString(event);
|
2009-08-18 00:30:34 +02:00
|
|
|
|
2008-11-04 00:08:39 +01:00
|
|
|
if (d->wallpaper && d->wallpaper->isInitialized()) {
|
2009-08-18 00:31:18 +02:00
|
|
|
d->wallpaper->mouseReleaseEvent(event);
|
2008-11-04 00:08:39 +01:00
|
|
|
}
|
|
|
|
|
2009-08-25 18:14:05 +02:00
|
|
|
if (!event->isAccepted() && isContainment()) {
|
2010-09-08 23:51:22 +02:00
|
|
|
if (d->prepareContainmentActions(trigger, event->screenPos())) {
|
2010-11-11 23:22:39 +01:00
|
|
|
d->actionPlugins()->value(trigger)->contextEvent(event);
|
2009-08-25 18:14:05 +02:00
|
|
|
}
|
|
|
|
|
2008-11-04 00:08:39 +01:00
|
|
|
event->accept();
|
|
|
|
Applet::mouseReleaseEvent(event);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
2010-09-08 02:00:19 +02:00
|
|
|
QGraphicsSceneContextMenuEvent gvevent;
|
|
|
|
gvevent.setScreenPos(screenPos);
|
|
|
|
gvevent.setScenePos(mapToScene(containmentPos));
|
|
|
|
gvevent.setPos(containmentPos);
|
2010-09-08 23:51:22 +02:00
|
|
|
gvevent.setReason(QGraphicsSceneContextMenuEvent::Mouse);
|
2010-09-08 02:00:19 +02:00
|
|
|
gvevent.setWidget(view());
|
|
|
|
contextMenuEvent(&gvevent);
|
2008-11-04 00:08:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void Containment::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
|
|
|
|
{
|
2010-09-08 23:51:22 +02:00
|
|
|
if (!isContainment() || !KAuthorized::authorizeKAction("plasma/containment_context_menu")) {
|
2008-11-04 00:08:39 +01:00
|
|
|
Applet::contextMenuEvent(event);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-09-08 23:51:22 +02:00
|
|
|
KMenu desktopMenu;
|
2010-09-09 20:37:28 +02:00
|
|
|
Applet *applet = d->appletAt(event->scenePos());
|
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()) {
|
2010-09-08 23:51:22 +02:00
|
|
|
QPoint pos = event->screenPos();
|
|
|
|
if (applet && d->isPanelContainment()) {
|
2010-12-03 18:03:18 +01:00
|
|
|
menu->adjustSize();
|
|
|
|
pos = applet->popupPosition(menu->size());
|
2010-09-08 23:51:22 +02:00
|
|
|
if (event->reason() == QGraphicsSceneContextMenuEvent::Mouse) {
|
|
|
|
// if the menu pops up way away from the mouse press, then move it
|
|
|
|
// to the mouse press
|
|
|
|
if (d->formFactor == Vertical) {
|
2010-12-03 18:03:18 +01:00
|
|
|
if (pos.y() + menu->height() < event->screenPos().y()) {
|
2010-09-08 23:51:22 +02:00
|
|
|
pos.setY(event->screenPos().y());
|
|
|
|
}
|
|
|
|
} else if (d->formFactor == Horizontal) {
|
2010-12-03 18:03:18 +01:00
|
|
|
if (pos.x() + menu->width() < event->screenPos().x()) {
|
2010-09-08 23:51:22 +02:00
|
|
|
pos.setX(event->screenPos().x());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-12-03 18:03:18 +01:00
|
|
|
menu->exec(pos);
|
2008-11-04 00:08:39 +01:00
|
|
|
event->accept();
|
2009-08-30 20:51:32 +02:00
|
|
|
} else {
|
|
|
|
Applet::contextMenuEvent(event);
|
2008-11-04 00:08:39 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-09-09 20:37:28 +02:00
|
|
|
void ContainmentPrivate::addContainmentActions(KMenu &desktopMenu, QEvent *event)
|
2008-11-14 00:08:58 +01:00
|
|
|
{
|
|
|
|
if (static_cast<Corona*>(q->scene())->immutability() != Mutable &&
|
2010-01-06 05:16:28 +01:00
|
|
|
!KAuthorized::authorizeKAction("plasma/containment_actions")) {
|
2008-11-14 00:08:58 +01:00
|
|
|
//kDebug() << "immutability";
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-09-09 20:37:28 +02:00
|
|
|
const QString trigger = ContainmentActions::eventToString(event);
|
|
|
|
prepareContainmentActions(trigger, QPoint(), &desktopMenu);
|
2008-11-14 00:08:58 +01:00
|
|
|
}
|
|
|
|
|
2010-09-09 20:37:28 +02:00
|
|
|
void ContainmentPrivate::addAppletActions(KMenu &desktopMenu, Applet *applet, QEvent *event)
|
2008-11-14 00:08:58 +01:00
|
|
|
{
|
2010-09-08 23:51:22 +02:00
|
|
|
foreach (QAction *action, applet->contextualActions()) {
|
|
|
|
if (action) {
|
|
|
|
desktopMenu.addAction(action);
|
2008-11-14 00:08:58 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-09-22 18:34:59 +02:00
|
|
|
if (!applet->d->failed) {
|
|
|
|
QAction *configureApplet = applet->d->actions->action("configure");
|
|
|
|
if (configureApplet && configureApplet->isEnabled()) {
|
|
|
|
desktopMenu.addAction(configureApplet);
|
|
|
|
}
|
2008-11-14 00:08:58 +01:00
|
|
|
|
2011-09-22 18:34:59 +02:00
|
|
|
QAction *runAssociatedApplication = applet->d->actions->action("run associated application");
|
|
|
|
if (runAssociatedApplication && runAssociatedApplication->isEnabled()) {
|
|
|
|
desktopMenu.addAction(runAssociatedApplication);
|
|
|
|
}
|
2009-09-16 19:08:45 +02:00
|
|
|
}
|
|
|
|
|
2008-11-14 00:08:58 +01:00
|
|
|
KMenu *containmentMenu = new KMenu(i18nc("%1 is the name of the containment", "%1 Options", q->name()), &desktopMenu);
|
2010-09-09 20:37:28 +02:00
|
|
|
addContainmentActions(*containmentMenu, event);
|
2008-11-14 00:08:58 +01:00
|
|
|
if (!containmentMenu->isEmpty()) {
|
2009-01-13 12:03:48 +01:00
|
|
|
int enabled = 0;
|
|
|
|
//count number of real actions
|
2010-09-09 20:37:28 +02:00
|
|
|
QListIterator<QAction *> actionsIt(containmentMenu->actions());
|
|
|
|
while (enabled < 3 && actionsIt.hasNext()) {
|
|
|
|
QAction *action = actionsIt.next();
|
2009-08-18 00:31:32 +02:00
|
|
|
if (action->isVisible() && !action->isSeparator()) {
|
|
|
|
++enabled;
|
2009-01-13 12:03:48 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-08-18 00:31:32 +02:00
|
|
|
if (enabled) {
|
|
|
|
//if there is only one, don't create a submenu
|
|
|
|
if (enabled < 2) {
|
|
|
|
foreach (QAction *action, containmentMenu->actions()) {
|
2010-09-09 20:37:28 +02:00
|
|
|
if (action->isVisible() && !action->isSeparator()) {
|
|
|
|
desktopMenu.addAction(action);
|
|
|
|
}
|
2009-08-18 00:31:32 +02:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
desktopMenu.addMenu(containmentMenu);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-10-01 03:21:52 +02:00
|
|
|
if (q->immutability() == Mutable) {
|
2009-08-18 00:31:32 +02:00
|
|
|
QAction *closeApplet = applet->d->actions->action("remove");
|
2010-12-26 11:44:28 +01:00
|
|
|
//kDebug() << "checking for removal" << closeApplet;
|
2009-08-18 00:31:32 +02:00
|
|
|
if (closeApplet) {
|
2010-09-11 02:48:15 +02:00
|
|
|
if (!desktopMenu.isEmpty()) {
|
|
|
|
desktopMenu.addSeparator();
|
|
|
|
}
|
|
|
|
|
2010-12-26 11:44:28 +01:00
|
|
|
//kDebug() << "adding close action" << closeApplet->isEnabled() << closeApplet->isVisible();
|
2009-08-18 00:31:32 +02:00
|
|
|
desktopMenu.addAction(closeApplet);
|
2009-01-13 12:03:48 +01:00
|
|
|
}
|
2008-11-14 00:08:58 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-08-30 20:52:05 +02:00
|
|
|
Applet* ContainmentPrivate::appletAt(const QPointF &point)
|
2008-11-04 00:08:39 +01:00
|
|
|
{
|
|
|
|
Applet *applet = 0;
|
|
|
|
|
|
|
|
QGraphicsItem *item = q->scene()->itemAt(point);
|
|
|
|
if (item == q) {
|
|
|
|
item = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (item) {
|
2009-08-30 20:51:58 +02:00
|
|
|
if (item->isWidget()) {
|
2009-08-30 20:52:05 +02:00
|
|
|
applet = qobject_cast<Applet*>(static_cast<QGraphicsWidget*>(item));
|
2009-08-30 20:51:58 +02:00
|
|
|
if (applet) {
|
|
|
|
if (applet->isContainment()) {
|
|
|
|
applet = 0;
|
|
|
|
}
|
|
|
|
break;
|
2009-08-30 20:51:51 +02:00
|
|
|
}
|
2009-08-30 20:51:58 +02:00
|
|
|
}
|
2009-08-31 01:41:23 +02:00
|
|
|
AppletHandle *handle = dynamic_cast<AppletHandle*>(item);
|
|
|
|
if (handle) {
|
|
|
|
//pretend it was on the applet
|
|
|
|
applet = handle->applet();
|
|
|
|
break;
|
|
|
|
}
|
2009-08-30 20:52:05 +02:00
|
|
|
item = item->parentItem();
|
2008-11-04 00:08:39 +01:00
|
|
|
}
|
2009-08-30 20:52:05 +02:00
|
|
|
return applet;
|
|
|
|
}
|
|
|
|
|
2008-11-04 00:08:39 +01:00
|
|
|
void Containment::setFormFactor(FormFactor formFactor)
|
|
|
|
{
|
|
|
|
if (d->formFactor == formFactor) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
//kDebug() << "switching FF to " << formFactor;
|
|
|
|
d->formFactor = formFactor;
|
|
|
|
|
|
|
|
if (isContainment() &&
|
2009-02-24 05:54:57 +01:00
|
|
|
(d->type == PanelContainment || d->type == CustomPanelContainment)) {
|
2008-11-04 00:08:39 +01:00
|
|
|
// we are a panel and we have chaged our orientation
|
|
|
|
d->positionPanel(true);
|
|
|
|
}
|
|
|
|
|
2010-07-31 15:02:07 +02:00
|
|
|
QMetaObject::invokeMethod(d->toolBox.data(), "reposition");
|
2009-02-24 05:54:57 +01:00
|
|
|
|
2008-11-04 00:08:39 +01:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (emitGeomChange) {
|
|
|
|
// our geometry on the scene will not actually change,
|
|
|
|
// but for the purposes of views it has
|
|
|
|
emit geometryChanged();
|
|
|
|
}
|
|
|
|
|
|
|
|
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) {
|
|
|
|
kDebug() << "adding null applet!?!";
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (d->applets.contains(applet)) {
|
|
|
|
kDebug() << "already have this applet!";
|
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
applet->setParentItem(this);
|
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 {
|
|
|
|
applet->setParentItem(this);
|
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()));
|
2009-01-28 08:58:17 +01:00
|
|
|
connect(applet, SIGNAL(appletDestroyed(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
|
|
|
|
|
|
|
if (pos != QPointF(-1, -1)) {
|
|
|
|
applet->setPos(pos);
|
|
|
|
}
|
|
|
|
|
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();
|
2010-04-28 19:42:12 +02:00
|
|
|
Plasma::Animation *anim = Plasma::Animator::create(Plasma::Animator::AppearAnimation);
|
|
|
|
if (anim) {
|
|
|
|
connect(anim, SIGNAL(finished()), this, SLOT(appletAppearAnimationComplete()));
|
2010-07-10 12:49:34 +02:00
|
|
|
anim->setTargetWidget(applet);
|
|
|
|
//FIXME: small hack until we have proper js anim support; allows 'zoom' to work in the
|
|
|
|
//'right' direction for appearance
|
|
|
|
anim->setDirection(QAbstractAnimation::Backward);
|
2010-04-28 19:42:12 +02:00
|
|
|
anim->start(QAbstractAnimation::DeleteWhenStopped);
|
|
|
|
} else {
|
|
|
|
d->appletAppeared(applet);
|
|
|
|
}
|
2008-11-04 00:08:39 +01:00
|
|
|
}
|
|
|
|
|
2010-04-30 03:05:52 +02:00
|
|
|
applet->setFlag(QGraphicsItem::ItemIsMovable, true);
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ContainmentPrivate::setScreen(int newScreen, int newDesktop, bool preventInvalidDesktops)
|
2008-11-04 00:08:39 +01:00
|
|
|
{
|
|
|
|
// What we want to do in here is:
|
|
|
|
// * claim the screen as our own
|
|
|
|
// * signal whatever may be watching this containment about the switch
|
|
|
|
// * if we are a full screen containment, then:
|
|
|
|
// * resize to match the screen if we're that kind of containment
|
|
|
|
// * kick other full-screen containments off this screen
|
|
|
|
// * if we had a screen, then give our screen to the containment
|
|
|
|
// we kick out
|
|
|
|
//
|
|
|
|
// a screen of -1 means no associated screen.
|
2010-09-24 21:03:45 +02:00
|
|
|
Corona *corona = q->corona();
|
|
|
|
Q_ASSERT(corona);
|
2010-12-17 19:01:44 +01:00
|
|
|
|
|
|
|
//if it's an offscreen widget, don't allow to claim a screen, after all it's *off*screen
|
|
|
|
if (corona->offscreenWidgets().contains(q)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-09-24 21:03:45 +02:00
|
|
|
int numScreens = corona->numScreens();
|
2009-01-18 20:52:09 +01:00
|
|
|
if (newScreen < -1) {
|
|
|
|
newScreen = -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// -1 == All desktops
|
2010-09-24 21:03:45 +02:00
|
|
|
if (newDesktop < -1 || (preventInvalidDesktops && newDesktop > KWindowSystem::numberOfDesktops() - 1)) {
|
2009-01-18 20:52:09 +01:00
|
|
|
newDesktop = -1;
|
|
|
|
}
|
|
|
|
|
2010-09-24 21:03:45 +02:00
|
|
|
//kDebug() << activity() << "setting screen to " << newScreen << newDesktop << "and type is" << type;
|
2009-01-18 20:52:09 +01:00
|
|
|
|
2008-11-04 00:08:39 +01:00
|
|
|
Containment *swapScreensWith(0);
|
2011-11-20 18:50:41 +01:00
|
|
|
const bool isDesktopContainment = type == Containment::DesktopContainment ||
|
|
|
|
type == Containment::CustomContainment;
|
|
|
|
if (isDesktopContainment) {
|
2008-11-04 00:08:39 +01:00
|
|
|
// we want to listen to changes in work area if our screen changes
|
2010-09-24 21:03:45 +02:00
|
|
|
if (toolBox) {
|
|
|
|
if (screen < 0 && newScreen > -1) {
|
2010-11-19 05:00:09 +01:00
|
|
|
QObject::connect(KWindowSystem::self(), SIGNAL(workAreaChanged()), toolBox.data(), SLOT(reposition()), Qt::UniqueConnection);
|
2010-09-24 21:03:45 +02:00
|
|
|
} else if (newScreen < 0) {
|
2010-11-19 05:00:09 +01:00
|
|
|
QObject::disconnect(KWindowSystem::self(), SIGNAL(workAreaChanged()), toolBox.data(), SLOT(reposition()));
|
2010-09-24 21:03:45 +02:00
|
|
|
}
|
2008-11-04 00:08:39 +01:00
|
|
|
}
|
2008-11-05 23:57:45 +01:00
|
|
|
|
2010-09-24 21:03:45 +02:00
|
|
|
if (newScreen > -1) {
|
2008-11-04 00:08:39 +01:00
|
|
|
// sanity check to make sure someone else doesn't have this screen already!
|
2010-09-24 21:03:45 +02:00
|
|
|
Containment *currently = corona->containmentForScreen(newScreen, newDesktop);
|
|
|
|
if (currently && currently != q) {
|
2008-12-15 19:28:28 +01:00
|
|
|
kDebug() << "currently is on screen" << currently->screen()
|
2009-04-11 18:23:38 +02:00
|
|
|
<< "desktop" << currently->desktop()
|
|
|
|
<< "and is" << currently->activity()
|
2010-09-24 21:03:45 +02:00
|
|
|
<< (QObject*)currently << "i'm" << (QObject*)q;
|
2010-11-23 23:21:24 +01:00
|
|
|
currently->setScreen(-1, currently->desktop());
|
2008-11-04 00:08:39 +01:00
|
|
|
swapScreensWith = currently;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-11-20 18:50:41 +01:00
|
|
|
if (newScreen < numScreens && newScreen > -1 && isDesktopContainment) {
|
2010-09-24 21:03:45 +02:00
|
|
|
q->resize(corona->screenGeometry(newScreen).size());
|
2008-11-04 00:08:39 +01:00
|
|
|
}
|
|
|
|
|
2010-09-24 21:03:45 +02:00
|
|
|
int oldDesktop = desktop;
|
|
|
|
desktop = newDesktop;
|
2008-11-17 05:34:55 +01:00
|
|
|
|
2010-09-24 21:03:45 +02:00
|
|
|
int oldScreen = screen;
|
|
|
|
screen = newScreen;
|
2009-01-18 20:52:09 +01:00
|
|
|
|
2010-09-24 21:03:45 +02:00
|
|
|
q->updateConstraints(Plasma::ScreenConstraint);
|
2009-01-18 20:52:09 +01:00
|
|
|
|
2009-06-01 19:30:52 +02:00
|
|
|
if (oldScreen != newScreen || oldDesktop != newDesktop) {
|
2010-11-23 23:21:24 +01:00
|
|
|
/*
|
|
|
|
kDebug() << "going to signal change for" << q
|
|
|
|
<< ", old screen & desktop:" << oldScreen << oldDesktop
|
|
|
|
<< ", new:" << screen << desktop;
|
|
|
|
*/
|
2010-09-24 21:03:45 +02:00
|
|
|
KConfigGroup c = q->config();
|
|
|
|
c.writeEntry("screen", screen);
|
|
|
|
c.writeEntry("desktop", desktop);
|
2010-05-19 04:43:07 +02:00
|
|
|
if (newScreen != -1) {
|
2010-09-24 21:03:45 +02:00
|
|
|
lastScreen = newScreen;
|
|
|
|
lastDesktop = newDesktop;
|
|
|
|
c.writeEntry("lastScreen", lastScreen);
|
|
|
|
c.writeEntry("lastDesktop", lastDesktop);
|
2010-05-19 04:43:07 +02:00
|
|
|
}
|
2010-09-24 21:03:45 +02:00
|
|
|
emit q->configNeedsSaving();
|
2010-10-29 10:25:57 +02:00
|
|
|
emit q->screenChanged(oldScreen, newScreen, q);
|
2008-11-04 00:08:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (swapScreensWith) {
|
2009-06-01 19:30:52 +02:00
|
|
|
//kDebug() << "setScreen due to swap, part 2";
|
2009-01-18 18:56:06 +01:00
|
|
|
swapScreensWith->setScreen(oldScreen, oldDesktop);
|
2008-11-04 00:08:39 +01:00
|
|
|
}
|
2008-12-01 13:40:08 +01:00
|
|
|
|
2010-09-24 21:03:45 +02:00
|
|
|
checkRemoveAction();
|
2009-06-15 15:58:23 +02:00
|
|
|
|
|
|
|
if (newScreen >= 0) {
|
2010-09-24 21:03:45 +02:00
|
|
|
emit q->activate();
|
2009-06-15 15:58:23 +02:00
|
|
|
}
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
KPluginInfo::List Containment::listContainmentsForMimetype(const QString &mimetype)
|
|
|
|
{
|
2009-07-06 13:49:01 +02:00
|
|
|
const QString constraint = QString("'%1' in [X-Plasma-DropMimeTypes]").arg(mimetype);
|
2008-11-04 00:08:39 +01:00
|
|
|
//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();
|
|
|
|
}
|
|
|
|
|
2008-11-04 00:08:39 +01:00
|
|
|
void Containment::dragEnterEvent(QGraphicsSceneDragDropEvent *event)
|
|
|
|
{
|
|
|
|
//kDebug() << immutability() << Mutable << (immutability() == Mutable);
|
|
|
|
event->setAccepted(immutability() == Mutable &&
|
|
|
|
(event->mimeData()->hasFormat(static_cast<Corona*>(scene())->appletMimeType()) ||
|
2009-02-09 19:10:45 +01:00
|
|
|
KUrl::List::canDecode(event->mimeData()) ||
|
|
|
|
event->mimeData()->hasFormat(ExtenderItemMimeData::mimeType())));
|
2008-11-04 00:08:39 +01:00
|
|
|
|
|
|
|
if (!event->isAccepted()) {
|
|
|
|
// check to see if we have an applet that accepts the format.
|
|
|
|
QStringList formats = event->mimeData()->formats();
|
|
|
|
|
|
|
|
foreach (const QString &format, formats) {
|
|
|
|
KPluginInfo::List appletList = Applet::listAppletInfoForMimetype(format);
|
|
|
|
if (!appletList.isEmpty()) {
|
|
|
|
event->setAccepted(true);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2009-09-03 22:40:22 +02:00
|
|
|
|
|
|
|
if (!event->isAccepted()) {
|
|
|
|
foreach (const QString &format, formats) {
|
|
|
|
KPluginInfo::List wallpaperList = Wallpaper::listWallpaperInfoForMimetype(format);
|
|
|
|
if (!wallpaperList.isEmpty()) {
|
|
|
|
event->setAccepted(true);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2008-11-04 00:08:39 +01:00
|
|
|
}
|
2009-03-11 15:41:37 +01:00
|
|
|
|
2009-10-23 00:14:22 +02:00
|
|
|
if (event->isAccepted()) {
|
2009-11-05 21:27:08 +01:00
|
|
|
if (d->dropZoneStarted) {
|
|
|
|
showDropZone(event->pos().toPoint());
|
|
|
|
} else {
|
|
|
|
if (!d->showDropZoneDelayTimer) {
|
|
|
|
d->showDropZoneDelayTimer = new QTimer(this);
|
|
|
|
d->showDropZoneDelayTimer->setInterval(300);
|
|
|
|
d->showDropZoneDelayTimer->setSingleShot(true);
|
|
|
|
connect(d->showDropZoneDelayTimer, SIGNAL(timeout()), this, SLOT(showDropZoneDelayed()));
|
|
|
|
}
|
2009-10-23 00:14:22 +02:00
|
|
|
|
2009-11-05 21:27:08 +01:00
|
|
|
d->dropPoints.insert(0, event->pos());
|
|
|
|
d->showDropZoneDelayTimer->start();
|
|
|
|
}
|
2009-10-23 00:14:22 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Containment::dragLeaveEvent(QGraphicsSceneDragDropEvent *event)
|
|
|
|
{
|
2009-11-05 21:27:08 +01:00
|
|
|
//kDebug() << event->pos() << size().height() << size().width();
|
2009-10-23 00:14:22 +02:00
|
|
|
if (d->showDropZoneDelayTimer) {
|
|
|
|
d->showDropZoneDelayTimer->stop();
|
2009-03-11 15:41:37 +01:00
|
|
|
}
|
2009-11-05 21:27:08 +01:00
|
|
|
|
|
|
|
if (event->pos().y() < 1 || event->pos().y() > size().height() ||
|
|
|
|
event->pos().x() < 1 || event->pos().x() > size().width()) {
|
|
|
|
showDropZone(QPoint());
|
|
|
|
d->dropZoneStarted = false;
|
|
|
|
}
|
2008-11-04 00:08:39 +01:00
|
|
|
}
|
|
|
|
|
2009-10-23 00:14:22 +02:00
|
|
|
void ContainmentPrivate::showDropZoneDelayed()
|
|
|
|
{
|
2009-11-05 21:27:08 +01:00
|
|
|
dropZoneStarted = true;
|
2009-10-23 00:14:22 +02:00
|
|
|
q->showDropZone(dropPoints.value(0).toPoint());
|
|
|
|
dropPoints.remove(0);
|
|
|
|
}
|
|
|
|
|
2008-11-04 00:08:39 +01:00
|
|
|
void Containment::dragMoveEvent(QGraphicsSceneDragDropEvent *event)
|
|
|
|
{
|
|
|
|
QGraphicsItem *item = scene()->itemAt(event->scenePos());
|
2009-11-25 20:46:33 +01:00
|
|
|
event->setAccepted(item == this || item == d->toolBox.data() || !item);
|
2009-11-05 21:27:08 +01:00
|
|
|
//kDebug() << event->isAccepted() << d->showDropZoneDelayTimer->isActive();
|
2009-10-23 00:14:22 +02:00
|
|
|
if (!event->isAccepted()) {
|
|
|
|
if (d->showDropZoneDelayTimer) {
|
|
|
|
d->showDropZoneDelayTimer->stop();
|
|
|
|
}
|
|
|
|
} else if (!d->showDropZoneDelayTimer->isActive() && immutability() == Plasma::Mutable) {
|
|
|
|
showDropZone(event->pos().toPoint());
|
|
|
|
}
|
2008-11-04 00:08:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void Containment::dropEvent(QGraphicsSceneDragDropEvent *event)
|
|
|
|
{
|
2009-05-05 07:19:35 +02:00
|
|
|
if (isContainment()) {
|
2009-08-18 00:31:03 +02:00
|
|
|
d->dropData(event->scenePos(), event->screenPos(), event);
|
2009-05-05 07:19:35 +02:00
|
|
|
} else {
|
2008-11-04 00:08:39 +01:00
|
|
|
Applet::dropEvent(event);
|
2009-05-05 07:19:35 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-08-18 00:31:03 +02:00
|
|
|
void ContainmentPrivate::dropData(QPointF scenePos, QPoint screenPos, QGraphicsSceneDragDropEvent *dropEvent)
|
2009-05-05 07:19:35 +02:00
|
|
|
{
|
|
|
|
if (q->immutability() != Mutable) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-08-18 00:31:03 +02:00
|
|
|
QPointF pos = q->mapFromScene(scenePos);
|
2009-06-16 19:46:32 +02:00
|
|
|
const QMimeData *mimeData = 0;
|
2009-05-05 07:19:35 +02:00
|
|
|
|
|
|
|
if (dropEvent) {
|
|
|
|
mimeData = dropEvent->mimeData();
|
2009-08-18 00:31:03 +02:00
|
|
|
} else {
|
2009-05-05 07:19:35 +02:00
|
|
|
QClipboard *clipboard = QApplication::clipboard();
|
|
|
|
mimeData = clipboard->mimeData(QClipboard::Selection);
|
|
|
|
//TODO if that's not supported (ie non-linux) should we try clipboard instead of selection?
|
2009-06-16 19:46:32 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!mimeData) {
|
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
|
|
|
//Selection is either empty or not supported on this OS
|
2009-06-16 19:46:32 +02:00
|
|
|
kDebug() << "no mime data";
|
2008-11-04 00:08:39 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-05-05 07:19:35 +02:00
|
|
|
//kDebug() << event->mimeData()->text();
|
|
|
|
|
|
|
|
QString appletMimetype(q->corona() ? q->corona()->appletMimeType() : QString());
|
2008-11-04 00:08:39 +01:00
|
|
|
|
2009-05-05 07:19:35 +02:00
|
|
|
if (!appletMimetype.isEmpty() && mimeData->hasFormat(appletMimetype)) {
|
|
|
|
QString data = mimeData->data(appletMimetype);
|
2009-07-06 13:49:01 +02:00
|
|
|
const QStringList appletNames = data.split('\n', QString::SkipEmptyParts);
|
2008-11-04 00:08:39 +01:00
|
|
|
foreach (const QString &appletName, appletNames) {
|
|
|
|
//kDebug() << "doing" << appletName;
|
2009-08-18 00:31:03 +02:00
|
|
|
QRectF geom(pos, QSize(0, 0));
|
2009-05-05 07:19:35 +02:00
|
|
|
q->addApplet(appletName, QVariantList(), geom);
|
|
|
|
}
|
|
|
|
if (dropEvent) {
|
|
|
|
dropEvent->acceptProposedAction();
|
2008-11-04 00:08:39 +01:00
|
|
|
}
|
2009-05-05 07:19:35 +02:00
|
|
|
} else if (mimeData->hasFormat(ExtenderItemMimeData::mimeType())) {
|
2009-02-09 19:10:45 +01:00
|
|
|
kDebug() << "mimetype plasma/extenderitem is dropped, creating internal:extender";
|
|
|
|
//Handle dropping extenderitems.
|
2009-05-05 07:19:35 +02:00
|
|
|
const ExtenderItemMimeData *extenderData = qobject_cast<const ExtenderItemMimeData*>(mimeData);
|
|
|
|
if (extenderData) {
|
|
|
|
ExtenderItem *item = extenderData->extenderItem();
|
2010-03-06 02:41:18 +01:00
|
|
|
QRectF geometry(pos - extenderData->pointerOffset(), item->size());
|
2009-02-09 19:10:45 +01:00
|
|
|
kDebug() << "desired geometry: " << geometry;
|
2010-03-06 02:41:18 +01:00
|
|
|
Applet *applet = qobject_cast<ExtenderApplet *>(item->extender() ? item->extender()->applet() : 0);
|
|
|
|
if (applet) {
|
|
|
|
qreal left, top, right, bottom;
|
|
|
|
applet->getContentsMargins(&left, &top, &right, &bottom);
|
|
|
|
applet->setPos(geometry.topLeft() - QPointF(int(left), int(top)));
|
|
|
|
applet->show();
|
|
|
|
} else {
|
2010-09-30 14:47:45 +02:00
|
|
|
applet = addApplet("internal:extender", QVariantList(), geometry, 0, true);
|
|
|
|
applet->hide();
|
|
|
|
applet->init();
|
|
|
|
appletAppeared(applet);
|
|
|
|
applet->flushPendingConstraintsEvents();
|
|
|
|
applet->d->scheduleModificationNotification();
|
|
|
|
applet->adjustSize();
|
|
|
|
applet->show();
|
2010-03-06 02:41:18 +01:00
|
|
|
}
|
2009-02-09 19:10:45 +01:00
|
|
|
item->setExtender(applet->extender());
|
|
|
|
}
|
2009-05-05 07:19:35 +02:00
|
|
|
} else if (KUrl::List::canDecode(mimeData)) {
|
2008-11-04 00:08:39 +01:00
|
|
|
//TODO: collect the mimetypes of available script engines and offer
|
|
|
|
// to create widgets out of the matching URLs, if any
|
2009-07-06 13:49:01 +02:00
|
|
|
const KUrl::List urls = KUrl::List::fromMimeData(mimeData);
|
2008-11-04 00:08:39 +01:00
|
|
|
foreach (const KUrl &url, urls) {
|
2009-09-22 17:29:08 +02:00
|
|
|
if (AccessManager::supportedProtocols().contains(url.protocol())) {
|
|
|
|
AccessAppletJob *job = AccessManager::self()->accessRemoteApplet(url);
|
2009-12-23 17:36:16 +01:00
|
|
|
if (dropEvent) {
|
2009-12-10 03:16:49 +01:00
|
|
|
dropPoints[job] = dropEvent->pos();
|
2009-12-23 17:36:16 +01:00
|
|
|
} else {
|
2009-12-10 03:16:49 +01:00
|
|
|
dropPoints[job] = scenePos;
|
2009-12-23 17:36:16 +01:00
|
|
|
}
|
2009-09-22 17:29:08 +02:00
|
|
|
QObject::connect(AccessManager::self(), SIGNAL(finished(Plasma::AccessAppletJob*)),
|
|
|
|
q, SLOT(remoteAppletReady(Plasma::AccessAppletJob*)));
|
2010-10-14 14:27:15 +02:00
|
|
|
}
|
|
|
|
#ifndef PLASMA_NO_KIO
|
|
|
|
else {
|
2009-09-22 17:29:08 +02:00
|
|
|
KMimeType::Ptr mime = KMimeType::findByUrl(url);
|
|
|
|
QString mimeName = mime->name();
|
|
|
|
QRectF geom(pos, QSize());
|
|
|
|
QVariantList args;
|
|
|
|
args << url.url();
|
|
|
|
kDebug() << "can decode" << mimeName << args;
|
2008-11-04 00:08:39 +01:00
|
|
|
|
2009-09-22 17:29:08 +02:00
|
|
|
// It may be a directory or a file, let's stat
|
|
|
|
KIO::JobFlags flags = KIO::HideProgressInfo;
|
2009-12-12 17:07:25 +01:00
|
|
|
KIO::MimetypeJob *job = KIO::mimetype(url, flags);
|
|
|
|
if (dropEvent) {
|
2009-12-10 03:16:49 +01:00
|
|
|
dropPoints[job] = dropEvent->pos();
|
2009-12-12 17:07:25 +01:00
|
|
|
} else {
|
2009-12-10 03:16:49 +01:00
|
|
|
dropPoints[job] = scenePos;
|
2009-12-12 17:07:25 +01:00
|
|
|
}
|
|
|
|
|
2009-09-30 23:42:05 +02:00
|
|
|
QObject::connect(job, SIGNAL(result(KJob*)), q, SLOT(dropJobResult(KJob*)));
|
2012-01-22 03:11:26 +01:00
|
|
|
QObject::connect(job, SIGNAL(mimetype(KIO::Job*,QString)),
|
|
|
|
q, SLOT(mimeTypeRetrieved(KIO::Job*,QString)));
|
2009-09-22 17:29:08 +02:00
|
|
|
|
|
|
|
KMenu *choices = new KMenu("Content dropped");
|
|
|
|
choices->addAction(KIcon("process-working"), i18n("Fetching file type..."));
|
2010-04-30 00:29:07 +02:00
|
|
|
if (dropEvent) {
|
2009-12-10 03:16:49 +01:00
|
|
|
choices->popup(dropEvent->screenPos());
|
2010-04-30 00:29:07 +02:00
|
|
|
} else {
|
2009-12-10 03:16:49 +01:00
|
|
|
choices->popup(screenPos);
|
2010-04-30 00:29:07 +02:00
|
|
|
}
|
|
|
|
|
2009-09-22 17:29:08 +02:00
|
|
|
dropMenus[job] = choices;
|
|
|
|
}
|
2010-10-14 14:27:15 +02:00
|
|
|
#endif
|
2008-11-04 00:08:39 +01:00
|
|
|
}
|
2009-06-16 19:46:32 +02:00
|
|
|
|
2009-05-05 07:19:35 +02:00
|
|
|
if (dropEvent) {
|
|
|
|
dropEvent->acceptProposedAction();
|
|
|
|
}
|
2008-11-04 00:08:39 +01:00
|
|
|
} else {
|
2009-05-05 07:19:35 +02:00
|
|
|
QStringList formats = mimeData->formats();
|
2008-11-04 00:08:39 +01:00
|
|
|
QHash<QString, KPluginInfo> seenPlugins;
|
|
|
|
QHash<QString, QString> pluginFormats;
|
|
|
|
|
|
|
|
foreach (const QString &format, formats) {
|
|
|
|
KPluginInfo::List plugins = Applet::listAppletInfoForMimetype(format);
|
|
|
|
|
|
|
|
foreach (const KPluginInfo &plugin, plugins) {
|
|
|
|
if (seenPlugins.contains(plugin.pluginName())) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
seenPlugins.insert(plugin.pluginName(), plugin);
|
|
|
|
pluginFormats.insert(plugin.pluginName(), format);
|
|
|
|
}
|
|
|
|
}
|
2009-09-04 01:22:48 +02:00
|
|
|
//kDebug() << "Mimetype ..." << formats << seenPlugins.keys() << pluginFormats.values();
|
2008-11-04 00:08:39 +01:00
|
|
|
|
|
|
|
QString selectedPlugin;
|
|
|
|
|
|
|
|
if (seenPlugins.isEmpty()) {
|
2009-06-16 19:46:32 +02:00
|
|
|
// do nothing
|
|
|
|
} else if (seenPlugins.count() == 1) {
|
2008-11-04 00:08:39 +01:00
|
|
|
selectedPlugin = seenPlugins.constBegin().key();
|
|
|
|
} else {
|
2009-09-12 03:44:01 +02:00
|
|
|
KMenu choices;
|
2008-11-04 00:08:39 +01:00
|
|
|
QHash<QAction *, QString> actionsToPlugins;
|
|
|
|
foreach (const KPluginInfo &info, seenPlugins) {
|
|
|
|
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());
|
|
|
|
}
|
|
|
|
|
2009-05-05 07:19:35 +02:00
|
|
|
QAction *choice = choices.exec(screenPos);
|
2008-11-04 00:08:39 +01:00
|
|
|
if (choice) {
|
|
|
|
selectedPlugin = actionsToPlugins[choice];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!selectedPlugin.isEmpty()) {
|
2009-12-02 18:16:18 +01:00
|
|
|
if (!dropEvent) {
|
|
|
|
// since we may have entered an event loop up above with the menu,
|
|
|
|
// the clipboard item may no longer be valid, as QClipboard resets
|
|
|
|
// the object behind the back of the application with a zero timer
|
|
|
|
// so we fetch it again here
|
|
|
|
QClipboard *clipboard = QApplication::clipboard();
|
|
|
|
mimeData = clipboard->mimeData(QClipboard::Selection);
|
|
|
|
}
|
|
|
|
|
2008-11-04 00:08:39 +01:00
|
|
|
KTemporaryFile tempFile;
|
2009-12-02 18:16:18 +01:00
|
|
|
if (mimeData && tempFile.open()) {
|
2008-11-04 00:08:39 +01:00
|
|
|
//TODO: what should we do with files after the applet is done with them??
|
|
|
|
tempFile.setAutoRemove(false);
|
|
|
|
|
|
|
|
{
|
|
|
|
QDataStream stream(&tempFile);
|
2009-05-05 07:19:35 +02:00
|
|
|
QByteArray data = mimeData->data(pluginFormats[selectedPlugin]);
|
2008-11-04 00:08:39 +01:00
|
|
|
stream.writeRawData(data, data.size());
|
|
|
|
}
|
|
|
|
|
2009-05-05 07:19:35 +02:00
|
|
|
QRectF geom(pos, QSize());
|
2008-11-04 00:08:39 +01:00
|
|
|
QVariantList args;
|
|
|
|
args << tempFile.fileName();
|
|
|
|
kDebug() << args;
|
|
|
|
tempFile.close();
|
|
|
|
|
2009-05-05 07:19:35 +02:00
|
|
|
q->addApplet(selectedPlugin, args, geom);
|
2008-11-04 00:08:39 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-09-12 04:38:10 +02:00
|
|
|
void ContainmentPrivate::clearDataForMimeJob(KIO::Job *job)
|
|
|
|
{
|
2010-10-14 14:27:15 +02:00
|
|
|
#ifndef PLASMA_NO_KIO
|
2009-09-30 23:45:19 +02:00
|
|
|
QObject::disconnect(job, 0, q, 0);
|
2009-09-12 04:38:10 +02:00
|
|
|
dropPoints.remove(job);
|
|
|
|
KMenu *choices = dropMenus.take(job);
|
2010-08-25 16:48:41 +02:00
|
|
|
delete choices;
|
2009-09-12 04:38:10 +02:00
|
|
|
job->kill();
|
2010-10-14 14:27:15 +02:00
|
|
|
#endif // PLASMA_NO_KIO
|
2009-09-12 04:38:10 +02:00
|
|
|
}
|
|
|
|
|
2009-09-22 17:29:08 +02:00
|
|
|
void ContainmentPrivate::remoteAppletReady(Plasma::AccessAppletJob *job)
|
|
|
|
{
|
|
|
|
QPointF pos = dropPoints.take(job);
|
|
|
|
if (job->error()) {
|
|
|
|
//TODO: nice user visible error handling (knotification probably?)
|
|
|
|
kDebug() << "remote applet access failed: " << job->errorText();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!job->applet()) {
|
|
|
|
kDebug() << "how did we end up here? if applet is null, the job->error should be nonzero";
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
q->addApplet(job->applet(), pos);
|
|
|
|
}
|
|
|
|
|
2009-09-30 23:42:05 +02:00
|
|
|
void ContainmentPrivate::dropJobResult(KJob *job)
|
|
|
|
{
|
2010-10-14 14:27:15 +02:00
|
|
|
#ifndef PLASMA_NO_KIO
|
2009-10-29 10:09:01 +01:00
|
|
|
KIO::TransferJob* tjob = dynamic_cast<KIO::TransferJob*>(job);
|
|
|
|
if (!tjob) {
|
|
|
|
kDebug() << "job is not a KIO::TransferJob, won't handle the drop...";
|
|
|
|
clearDataForMimeJob(tjob);
|
|
|
|
return;
|
|
|
|
}
|
2009-09-30 23:42:05 +02:00
|
|
|
if (job->error()) {
|
2009-10-29 10:09:01 +01:00
|
|
|
kDebug() << "ERROR" << tjob->error() << ' ' << tjob->errorString();
|
2009-09-30 23:42:05 +02:00
|
|
|
}
|
2009-10-29 10:09:01 +01:00
|
|
|
// 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());
|
2010-10-14 14:27:15 +02:00
|
|
|
#endif // PLASMA_NO_KIO
|
2009-09-30 23:42:05 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void ContainmentPrivate::mimeTypeRetrieved(KIO::Job *job, const QString &mimetype)
|
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
|
|
|
{
|
2010-10-14 14:27:15 +02:00
|
|
|
#ifndef 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
|
|
|
kDebug() << "Mimetype Job returns." << mimetype;
|
2009-10-29 10:09:01 +01:00
|
|
|
KIO::TransferJob* tjob = dynamic_cast<KIO::TransferJob*>(job);
|
|
|
|
if (!tjob) {
|
|
|
|
kDebug() << "job should be a TransferJob, but isn't";
|
|
|
|
clearDataForMimeJob(job);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
KPluginInfo::List appletList = Applet::listAppletInfoForUrl(tjob->url());
|
|
|
|
if (mimetype.isEmpty() && !appletList.count()) {
|
2009-09-12 04:38:10 +02:00
|
|
|
clearDataForMimeJob(job);
|
2009-10-29 10:09:01 +01:00
|
|
|
kDebug() << "No applets found matching the url (" << tjob->url() << ") or the mimetype (" << mimetype << ")";
|
2009-09-12 04:38:10 +02:00
|
|
|
return;
|
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
|
|
|
} else {
|
2009-09-12 04:38:10 +02:00
|
|
|
|
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
|
|
|
QPointF posi; // will be overwritten with the event's position
|
2009-09-12 04:38:10 +02:00
|
|
|
if (dropPoints.keys().contains(tjob)) {
|
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
|
|
|
posi = dropPoints[tjob];
|
|
|
|
kDebug() << "Received a suitable dropEvent at" << posi;
|
2009-09-12 04:38:10 +02:00
|
|
|
} else {
|
|
|
|
kDebug() << "Bailing out. Cannot find associated dropEvent related to the TransferJob";
|
|
|
|
clearDataForMimeJob(job);
|
|
|
|
return;
|
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
|
|
|
}
|
2009-09-12 04:38:10 +02:00
|
|
|
|
|
|
|
KMenu *choices = dropMenus.value(tjob);
|
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
|
|
|
if (!choices) {
|
|
|
|
kDebug() << "Bailing out. No QMenu found for this job.";
|
2009-09-12 04:38:10 +02:00
|
|
|
clearDataForMimeJob(job);
|
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
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
QVariantList args;
|
|
|
|
args << tjob->url().url() << mimetype;
|
|
|
|
|
|
|
|
kDebug() << "Creating menu for:" << mimetype << posi << args;
|
2009-09-12 03:44:01 +02:00
|
|
|
|
2009-10-29 10:09:01 +01:00
|
|
|
appletList << Applet::listAppletInfoForMimetype(mimetype);
|
2009-09-12 03:44:01 +02:00
|
|
|
KPluginInfo::List wallpaperList;
|
2011-01-26 21:10:14 +01:00
|
|
|
if (drawWallpaper) {
|
2011-01-26 21:09:18 +01:00
|
|
|
if (wallpaper && wallpaper->supportsMimetype(mimetype)) {
|
|
|
|
wallpaperList << wallpaper->d->wallpaperDescription;
|
|
|
|
} else {
|
|
|
|
wallpaperList = Wallpaper::listWallpaperInfoForMimetype(mimetype);
|
|
|
|
}
|
2009-09-12 03:44:01 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!appletList.isEmpty() || !wallpaperList.isEmpty()) {
|
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
|
|
|
choices->clear();
|
2009-09-12 03:44:01 +02:00
|
|
|
QHash<QAction *, QString> actionsToApplets;
|
2009-09-12 05:48:56 +02:00
|
|
|
choices->addTitle(i18n("Widgets"));
|
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
|
|
|
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());
|
|
|
|
}
|
|
|
|
|
2009-09-12 03:44:01 +02:00
|
|
|
actionsToApplets.insert(action, info.pluginName());
|
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
|
|
|
kDebug() << info.pluginName();
|
|
|
|
}
|
2009-09-12 03:44:01 +02:00
|
|
|
actionsToApplets.insert(choices->addAction(i18n("Icon")), "icon");
|
|
|
|
|
|
|
|
QHash<QAction *, QString> actionsToWallpapers;
|
|
|
|
if (!wallpaperList.isEmpty()) {
|
|
|
|
choices->addTitle(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(KIcon(info.icon()), info.name());
|
|
|
|
} else {
|
|
|
|
action = choices->addAction(info.name());
|
|
|
|
}
|
|
|
|
|
|
|
|
actionsToWallpapers.insert(action, info.pluginName());
|
|
|
|
}
|
|
|
|
}
|
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
|
|
|
|
|
|
|
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
|
2009-10-29 10:09:01 +01:00
|
|
|
if (!mimetype.isEmpty() && !tjob->error()) {
|
|
|
|
tjob->putOnHold();
|
|
|
|
KIO::Scheduler::publishSlaveOnHold();
|
|
|
|
}
|
2009-09-12 03:44:01 +02:00
|
|
|
QString plugin = actionsToApplets.value(choice);
|
|
|
|
if (plugin.isEmpty()) {
|
|
|
|
//set wallpapery stuff
|
|
|
|
plugin = actionsToWallpapers.value(choice);
|
|
|
|
if (!wallpaper || plugin != wallpaper->pluginName()) {
|
|
|
|
kDebug() << "Wallpaper dropped:" << tjob->url();
|
|
|
|
q->setWallpaper(plugin);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (wallpaper) {
|
|
|
|
kDebug() << "Wallpaper dropped:" << tjob->url();
|
2011-01-25 21:52:33 +01:00
|
|
|
wallpaper->setUrls(KUrl::List() << tjob->url());
|
2009-09-12 03:44:01 +02:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
addApplet(actionsToApplets[choice], args, QRectF(posi, QSize()));
|
|
|
|
}
|
2009-09-12 04:38:10 +02:00
|
|
|
|
|
|
|
clearDataForMimeJob(job);
|
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
|
|
|
return;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// we can at least create an icon as a link to the URL
|
|
|
|
addApplet("icon", args, QRectF(posi, QSize()));
|
|
|
|
}
|
|
|
|
}
|
2009-09-12 04:38:10 +02:00
|
|
|
|
|
|
|
clearDataForMimeJob(job);
|
2010-10-14 14:27:15 +02:00
|
|
|
#endif // 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
|
|
|
}
|
|
|
|
|
2010-11-04 09:06:43 +01:00
|
|
|
#ifndef KDE_NO_DEPRECATED
|
2008-11-18 21:49:42 +01:00
|
|
|
const QGraphicsItem *Containment::toolBoxItem() const
|
|
|
|
{
|
2009-11-25 20:46:33 +01:00
|
|
|
return d->toolBox.data();
|
2008-11-18 21:49:42 +01:00
|
|
|
}
|
2010-11-04 09:06:43 +01:00
|
|
|
#endif
|
2008-11-18 21:49:42 +01:00
|
|
|
|
2009-10-20 16:14:53 +02:00
|
|
|
void Containment::setToolBox(AbstractToolBox *toolBox)
|
|
|
|
{
|
2009-11-25 20:46:33 +01:00
|
|
|
if (d->toolBox.data()) {
|
|
|
|
d->toolBox.data()->deleteLater();
|
2009-10-20 16:14:53 +02:00
|
|
|
}
|
|
|
|
d->toolBox = toolBox;
|
|
|
|
}
|
|
|
|
|
|
|
|
AbstractToolBox *Containment::toolBox() const
|
|
|
|
{
|
2009-11-25 20:46:33 +01:00
|
|
|
return d->toolBox.data();
|
2009-10-20 16:14:53 +02:00
|
|
|
}
|
|
|
|
|
2008-11-04 00:08:39 +01:00
|
|
|
void Containment::resizeEvent(QGraphicsSceneResizeEvent *event)
|
|
|
|
{
|
|
|
|
Applet::resizeEvent(event);
|
2009-02-19 20:50:19 +01:00
|
|
|
|
2010-04-23 21:06:55 +02:00
|
|
|
if (isContainment()) {
|
|
|
|
if (d->isPanelContainment()) {
|
|
|
|
d->positionPanel();
|
|
|
|
} else if (corona()) {
|
|
|
|
QMetaObject::invokeMethod(corona(), "layoutContainments");
|
|
|
|
}
|
2009-02-19 20:50:19 +01:00
|
|
|
|
2010-04-23 21:06:55 +02:00
|
|
|
if (d->wallpaper) {
|
|
|
|
d->wallpaper->setBoundingRect(QRectF(QPointF(0, 0), size()));
|
|
|
|
}
|
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()) {
|
|
|
|
kDebug() << "let's give focus to...." << (QObject*)d->applets.first();
|
|
|
|
d->applets.first()->setFocus(Qt::TabFocusReason);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Containment::wheelEvent(QGraphicsSceneWheelEvent *event)
|
|
|
|
{
|
2009-08-18 00:31:18 +02:00
|
|
|
event->ignore();
|
2009-08-30 20:52:05 +02:00
|
|
|
if (d->appletAt(event->scenePos())) {
|
2009-08-18 00:31:18 +02:00
|
|
|
return; //no unexpected click-throughs
|
|
|
|
}
|
|
|
|
|
2009-08-18 00:30:34 +02:00
|
|
|
if (d->wallpaper && d->wallpaper->isInitialized()) {
|
2008-11-04 00:08:39 +01:00
|
|
|
QGraphicsItem *item = scene()->itemAt(event->scenePos());
|
|
|
|
if (item == this) {
|
2009-08-18 00:30:34 +02:00
|
|
|
event->ignore();
|
|
|
|
d->wallpaper->wheelEvent(event);
|
2008-11-04 00:08:39 +01:00
|
|
|
|
2009-08-18 00:30:34 +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);
|
|
|
|
|
2010-09-08 23:51:22 +02:00
|
|
|
if (d->prepareContainmentActions(trigger, event->screenPos())) {
|
2010-11-11 23:22:39 +01:00
|
|
|
d->actionPlugins()->value(trigger)->contextEvent(event);
|
2009-12-30 00:23:25 +01:00
|
|
|
event->accept();
|
2010-09-08 23:51:22 +02:00
|
|
|
} else {
|
|
|
|
event->ignore();
|
|
|
|
Applet::wheelEvent(event);
|
2009-12-30 00:23:25 +01:00
|
|
|
}
|
2008-11-04 00:08:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
bool Containment::sceneEventFilter(QGraphicsItem *watched, QEvent *event)
|
|
|
|
{
|
2011-07-19 09:37:55 +02:00
|
|
|
return Applet::sceneEventFilter(watched, event);
|
2008-11-04 00:08:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
QVariant Containment::itemChange(GraphicsItemChange change, const QVariant &value)
|
|
|
|
{
|
|
|
|
//FIXME if the applet is moved to another containment we need to unfocus it
|
|
|
|
|
2010-02-24 15:24:52 +01:00
|
|
|
if (isContainment() &&
|
|
|
|
(change == QGraphicsItem::ItemSceneHasChanged ||
|
|
|
|
change == QGraphicsItem::ItemPositionHasChanged)) {
|
2009-02-16 23:11:24 +01:00
|
|
|
switch (d->type) {
|
|
|
|
case PanelContainment:
|
|
|
|
case CustomPanelContainment:
|
|
|
|
d->positionPanel();
|
|
|
|
break;
|
|
|
|
default:
|
2010-02-24 15:24:52 +01:00
|
|
|
if (corona()) {
|
2010-02-24 22:11:02 +01:00
|
|
|
QMetaObject::invokeMethod(corona(), "layoutContainments");
|
2010-02-24 15:24:52 +01:00
|
|
|
}
|
2009-02-16 23:11:24 +01:00
|
|
|
break;
|
2008-11-04 00:08:39 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-02-16 23:11:24 +01:00
|
|
|
return Applet::itemChange(change, value);
|
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)
|
|
|
|
{
|
2010-04-13 20:36:38 +02:00
|
|
|
d->createToolBox();
|
2010-07-31 15:02:07 +02:00
|
|
|
if (d->toolBox) {
|
|
|
|
d->toolBox.data()->addTool(action);
|
|
|
|
}
|
2008-11-04 00:08:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void Containment::removeToolBoxAction(QAction *action)
|
|
|
|
{
|
|
|
|
if (d->toolBox) {
|
2009-11-25 20:46:33 +01:00
|
|
|
d->toolBox.data()->removeTool(action);
|
2008-11-04 00:08:39 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Containment::setToolBoxOpen(bool open)
|
|
|
|
{
|
|
|
|
if (open) {
|
|
|
|
openToolBox();
|
|
|
|
} else {
|
|
|
|
closeToolBox();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-06-09 15:18:04 +02:00
|
|
|
bool Containment::isToolBoxOpen() const
|
|
|
|
{
|
|
|
|
return (d->toolBox && d->toolBox.data()->isShowing());
|
|
|
|
}
|
|
|
|
|
2008-11-04 00:08:39 +01:00
|
|
|
void Containment::openToolBox()
|
|
|
|
{
|
2009-11-25 20:46:33 +01:00
|
|
|
if (d->toolBox && !d->toolBox.data()->isShowing()) {
|
|
|
|
d->toolBox.data()->setShowing(true);
|
2009-04-24 21:27:58 +02:00
|
|
|
emit toolBoxVisibilityChanged(true);
|
2008-11-04 00:08:39 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Containment::closeToolBox()
|
|
|
|
{
|
2009-11-25 20:46:33 +01:00
|
|
|
if (d->toolBox && d->toolBox.data()->isShowing()) {
|
|
|
|
d->toolBox.data()->setShowing(false);
|
2009-04-24 21:27:58 +02:00
|
|
|
emit toolBoxVisibilityChanged(false);
|
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();
|
2009-07-06 13:49:01 +02:00
|
|
|
const QString wallpaper = cfg.readEntry("wallpaperplugin", defaultWallpaper);
|
|
|
|
const QString mode = cfg.readEntry("wallpaperpluginmode", 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);
|
2009-03-26 20:14:58 +01:00
|
|
|
d->wallpaper->setBoundingRect(QRectF(QPointF(0, 0), size()));
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
update();
|
|
|
|
}
|
|
|
|
|
|
|
|
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:
|
|
|
|
plugin = ContainmentActions::load(this, pluginName);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
plugin = ContainmentActions::load(0, pluginName);
|
|
|
|
}
|
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
|
|
|
}
|
|
|
|
|
2008-11-04 00:08:39 +01:00
|
|
|
void Containment::setActivity(const QString &activity)
|
|
|
|
{
|
|
|
|
Context *context = d->context();
|
|
|
|
if (context->currentActivity() != activity) {
|
|
|
|
context->setCurrentActivity(activity);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-05-11 21:02:24 +02:00
|
|
|
void ContainmentPrivate::onContextChanged(Plasma::Context *con)
|
2010-05-10 03:43:06 +02:00
|
|
|
{
|
2010-05-11 21:02:24 +02:00
|
|
|
foreach (Applet *a, applets) {
|
|
|
|
a->updateConstraints(ContextConstraint);
|
|
|
|
}
|
2010-05-10 03:43:06 +02:00
|
|
|
|
2010-05-11 21:02:24 +02:00
|
|
|
KConfigGroup c = q->config();
|
|
|
|
QString act = con->currentActivityId();
|
2010-05-10 03:43:06 +02:00
|
|
|
|
2010-05-11 21:02:24 +02:00
|
|
|
//save anything that's been set (boy I hope this avoids overwriting things)
|
|
|
|
//FIXME of course if the user sets the name to an empty string we have a bug
|
|
|
|
//but once we get context retrieving the name as soon as the id is set, this issue should go away
|
|
|
|
if (!act.isEmpty()) {
|
|
|
|
c.writeEntry("activityId", act);
|
|
|
|
}
|
|
|
|
act = con->currentActivity();
|
|
|
|
if (!act.isEmpty()) {
|
|
|
|
c.writeEntry("activity", act);
|
|
|
|
}
|
2010-05-10 03:43:06 +02:00
|
|
|
|
2010-05-11 21:02:24 +02:00
|
|
|
if (toolBox) {
|
|
|
|
toolBox.data()->update();
|
2010-05-10 03:43:06 +02:00
|
|
|
}
|
2010-05-11 21:02:24 +02:00
|
|
|
emit q->configNeedsSaving();
|
|
|
|
emit q->contextChanged(con);
|
2010-05-10 03:43:06 +02:00
|
|
|
}
|
|
|
|
|
2008-11-04 00:08:39 +01:00
|
|
|
QString Containment::activity() const
|
|
|
|
{
|
|
|
|
return d->context()->currentActivity();
|
|
|
|
}
|
|
|
|
|
2010-05-11 21:02:24 +02:00
|
|
|
Context *Containment::context() const
|
2010-05-10 03:43:06 +02:00
|
|
|
{
|
2010-05-11 21:02:24 +02:00
|
|
|
return d->context();
|
2010-05-10 03:43:06 +02:00
|
|
|
}
|
|
|
|
|
2008-11-04 00:08:39 +01:00
|
|
|
Context *ContainmentPrivate::context()
|
|
|
|
{
|
|
|
|
if (!con) {
|
|
|
|
con = new Context(q);
|
|
|
|
q->connect(con, SIGNAL(changed(Plasma::Context*)),
|
2010-05-11 21:02:24 +02:00
|
|
|
q, SLOT(onContextChanged(Plasma::Context*)));
|
2008-11-04 00:08:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return con;
|
|
|
|
}
|
|
|
|
|
2009-05-03 22:22:14 +02:00
|
|
|
KActionCollection* ContainmentPrivate::actions()
|
2008-11-04 00:08:39 +01:00
|
|
|
{
|
|
|
|
return static_cast<Applet*>(q)->d->actions;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ContainmentPrivate::focusApplet(Plasma::Applet *applet)
|
|
|
|
{
|
|
|
|
if (focusedApplet == applet) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-05-03 22:22:14 +02:00
|
|
|
QList<QWidget *> widgets = actions()->associatedWidgets();
|
2008-11-04 00:08:39 +01:00
|
|
|
if (focusedApplet) {
|
|
|
|
foreach (QWidget *w, widgets) {
|
|
|
|
focusedApplet->removeAssociatedWidget(w);
|
|
|
|
}
|
|
|
|
}
|
2009-01-04 08:59:10 +01:00
|
|
|
|
2008-11-04 00:08:39 +01:00
|
|
|
if (applet && applets.contains(applet)) {
|
|
|
|
//kDebug() << "switching to" << applet->name();
|
|
|
|
focusedApplet = applet;
|
|
|
|
foreach (QWidget *w, widgets) {
|
|
|
|
focusedApplet->addAssociatedWidget(w);
|
|
|
|
}
|
2009-01-04 08:59:10 +01:00
|
|
|
|
|
|
|
if (!focusedApplet->hasFocus()) {
|
|
|
|
focusedApplet->setFocus(Qt::ShortcutFocusReason);
|
|
|
|
}
|
2008-11-04 00:08:39 +01:00
|
|
|
} else {
|
|
|
|
focusedApplet = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
kDebug() << "index" << index;
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
kDebug() << "index" << index;
|
|
|
|
d->focusApplet(d->applets.at(index));
|
|
|
|
}
|
|
|
|
|
|
|
|
void Containment::destroy()
|
|
|
|
{
|
|
|
|
destroy(true);
|
|
|
|
}
|
|
|
|
|
2008-11-10 02:26:27 +01:00
|
|
|
void Containment::showConfigurationInterface()
|
|
|
|
{
|
|
|
|
Applet::showConfigurationInterface();
|
|
|
|
}
|
|
|
|
|
2010-10-14 17:46:05 +02:00
|
|
|
void Containment::configChanged()
|
|
|
|
{
|
2011-04-25 16:43:15 +02:00
|
|
|
}
|
2010-10-14 17:46:05 +02:00
|
|
|
|
2011-04-25 16:43:15 +02:00
|
|
|
void ContainmentPrivate::configChanged()
|
|
|
|
{
|
|
|
|
if (drawWallpaper) {
|
|
|
|
KConfigGroup group = q->config();
|
|
|
|
q->setWallpaper(group.readEntry("wallpaperplugin", defaultWallpaper),
|
|
|
|
group.readEntry("wallpaperpluginmode", defaultWallpaperMode));
|
|
|
|
}
|
2010-10-14 17:46:05 +02:00
|
|
|
}
|
|
|
|
|
2008-11-10 02:26:27 +01:00
|
|
|
void ContainmentPrivate::requestConfiguration()
|
|
|
|
{
|
|
|
|
emit q->configureRequested(q);
|
|
|
|
}
|
|
|
|
|
2010-05-06 00:33:52 +02:00
|
|
|
void ContainmentPrivate::checkStatus(Plasma::ItemStatus appletStatus)
|
|
|
|
{
|
|
|
|
//kDebug() << "================== "<< appletStatus << q->status();
|
|
|
|
if (appletStatus == q->status()) {
|
|
|
|
emit q->newStatus(appletStatus);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (appletStatus < q->status()) {
|
|
|
|
// check to see if any other applet has a higher status, and stick with that
|
|
|
|
// if we do
|
|
|
|
foreach (Applet *applet, applets) {
|
|
|
|
if (applet->status() > appletStatus) {
|
|
|
|
appletStatus = applet->status();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
q->setStatus(appletStatus);
|
|
|
|
}
|
|
|
|
|
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);
|
|
|
|
if (KMessageBox::warningContinueCancel(view(),
|
|
|
|
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-04-13 20:36:38 +02:00
|
|
|
void ContainmentPrivate::createToolBox()
|
2008-11-04 00:08:39 +01:00
|
|
|
{
|
2011-04-11 15:06:27 +02:00
|
|
|
if (!toolBox && KAuthorized::authorizeKAction("plasma/containment_context_menu")) {
|
2010-07-31 15:02:07 +02:00
|
|
|
toolBox = Plasma::AbstractToolBox::load(q->corona()->preferredToolBoxPlugin(type), QVariantList(), q);
|
2008-11-04 00:08:39 +01:00
|
|
|
|
|
|
|
if (toolBox) {
|
2009-11-25 20:46:33 +01:00
|
|
|
QObject::connect(toolBox.data(), SIGNAL(toggled()), q, SIGNAL(toolBoxToggled()));
|
|
|
|
QObject::connect(toolBox.data(), SIGNAL(toggled()), q, SLOT(updateToolBoxVisibility()));
|
2010-07-31 15:02:07 +02:00
|
|
|
|
|
|
|
positionToolBox();
|
2008-11-04 00:08:39 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ContainmentPrivate::positionToolBox()
|
|
|
|
{
|
2010-07-31 15:02:07 +02:00
|
|
|
QMetaObject::invokeMethod(toolBox.data(), "reposition");
|
2008-11-04 00:08:39 +01:00
|
|
|
}
|
|
|
|
|
2009-04-24 21:27:58 +02:00
|
|
|
void ContainmentPrivate::updateToolBoxVisibility()
|
2009-04-13 22:26:17 +02:00
|
|
|
{
|
2009-11-25 20:46:33 +01:00
|
|
|
emit q->toolBoxVisibilityChanged(toolBox.data()->isShowing());
|
2009-04-13 22:26:17 +02:00
|
|
|
}
|
|
|
|
|
2008-11-04 00:08:39 +01:00
|
|
|
void ContainmentPrivate::triggerShowAddWidgets()
|
|
|
|
{
|
|
|
|
emit q->showAddWidgetsInterface(QPointF());
|
|
|
|
}
|
|
|
|
|
|
|
|
void ContainmentPrivate::containmentConstraintsEvent(Plasma::Constraints constraints)
|
|
|
|
{
|
|
|
|
if (!q->isContainment()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2008-12-11 20:53:35 +01:00
|
|
|
//kDebug() << "got containmentConstraintsEvent" << constraints << (QObject*)toolBox;
|
2008-11-04 00:08:39 +01:00
|
|
|
if (constraints & Plasma::ImmutableConstraint) {
|
|
|
|
//update actions
|
2008-12-15 17:54:09 +01:00
|
|
|
checkRemoveAction();
|
2010-07-31 15:02:07 +02:00
|
|
|
const bool unlocked = q->immutability() == Mutable;
|
2008-11-04 00:08:39 +01:00
|
|
|
q->setAcceptDrops(unlocked);
|
2008-12-15 17:54:09 +01:00
|
|
|
q->enableAction("add widgets", unlocked);
|
2009-01-16 01:39:07 +01:00
|
|
|
|
2008-11-04 00:08:39 +01:00
|
|
|
// tell the applets too
|
|
|
|
foreach (Applet *a, applets) {
|
2010-04-04 19:59:12 +02:00
|
|
|
a->setImmutability(q->immutability());
|
2008-11-04 00:08:39 +01:00
|
|
|
a->updateConstraints(ImmutableConstraint);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-06-10 18:30:54 +02:00
|
|
|
// pass on the constraints that are relevant here
|
|
|
|
Constraints appletConstraints = NoConstraint;
|
|
|
|
if (constraints & FormFactorConstraint) {
|
|
|
|
appletConstraints |= FormFactorConstraint;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (constraints & ScreenConstraint) {
|
|
|
|
appletConstraints |= ScreenConstraint;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (appletConstraints != NoConstraint) {
|
2008-11-04 00:08:39 +01:00
|
|
|
foreach (Applet *applet, applets) {
|
2010-06-10 18:30:54 +02:00
|
|
|
applet->updateConstraints(appletConstraints);
|
2008-11-04 00:08:39 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-11-18 01:16:45 +01:00
|
|
|
if (toolBox && (constraints & Plasma::SizeConstraint ||
|
|
|
|
constraints & Plasma::FormFactorConstraint ||
|
|
|
|
constraints & Plasma::ScreenConstraint ||
|
|
|
|
constraints & Plasma::StartupCompletedConstraint)) {
|
2008-12-01 13:40:08 +01:00
|
|
|
//kDebug() << "Positioning toolbox";
|
2008-11-04 00:08:39 +01:00
|
|
|
positionToolBox();
|
|
|
|
}
|
2008-12-01 13:40:08 +01:00
|
|
|
|
2010-07-31 15:02:07 +02:00
|
|
|
if (constraints & Plasma::StartupCompletedConstraint && type < Containment::CustomContainment) {
|
|
|
|
q->addToolBoxAction(q->action("remove"));
|
2008-12-15 17:54:09 +01:00
|
|
|
checkRemoveAction();
|
2008-12-01 13:40:08 +01:00
|
|
|
}
|
2008-11-04 00:08:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
Applet *ContainmentPrivate::addApplet(const QString &name, const QVariantList &args,
|
|
|
|
const QRectF &appletGeometry, uint id, bool delayInit)
|
|
|
|
{
|
|
|
|
if (!q->isContainment()) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!delayInit && q->immutability() != Mutable) {
|
|
|
|
kDebug() << "addApplet for" << name << "requested, but we're currently immutable!";
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
QGraphicsView *v = q->view();
|
|
|
|
if (v) {
|
|
|
|
v->setCursor(Qt::BusyCursor);
|
|
|
|
}
|
|
|
|
|
|
|
|
Applet *applet = Applet::load(name, id, args);
|
|
|
|
if (v) {
|
|
|
|
v->unsetCursor();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!applet) {
|
|
|
|
kDebug() << "Applet" << name << "could not be loaded.";
|
|
|
|
applet = new Applet(0, QString(), id);
|
|
|
|
applet->setFailedToLaunch(true, i18n("Could not find requested component: %1", name));
|
|
|
|
}
|
|
|
|
|
|
|
|
//kDebug() << applet->name() << "sizehint:" << applet->sizeHint() << "geometry:" << applet->geometry();
|
|
|
|
|
|
|
|
q->addApplet(applet, appletGeometry.topLeft(), delayInit);
|
|
|
|
return applet;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ContainmentPrivate::regionIsEmpty(const QRectF ®ion, Applet *ignoredApplet) const
|
|
|
|
{
|
|
|
|
foreach (Applet *applet, applets) {
|
|
|
|
if (applet != ignoredApplet && applet->geometry().intersects(region)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2009-01-28 08:58:17 +01:00
|
|
|
void ContainmentPrivate::appletDestroyed(Plasma::Applet *applet)
|
2008-11-04 00:08:39 +01:00
|
|
|
{
|
|
|
|
applets.removeAll(applet);
|
|
|
|
if (focusedApplet == applet) {
|
|
|
|
focusedApplet = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
emit q->appletRemoved(applet);
|
|
|
|
emit q->configNeedsSaving();
|
|
|
|
}
|
|
|
|
|
2010-01-05 00:45:38 +01:00
|
|
|
void ContainmentPrivate::appletAppearAnimationComplete()
|
2008-11-04 00:08:39 +01:00
|
|
|
{
|
2010-01-05 00:45:38 +01:00
|
|
|
Animation *anim = qobject_cast<Animation *>(q->sender());
|
2010-04-28 19:42:12 +02:00
|
|
|
if (anim) {
|
|
|
|
Applet *applet = qobject_cast<Applet*>(anim->targetWidget());
|
|
|
|
if (applet) {
|
|
|
|
appletAppeared(applet);
|
|
|
|
}
|
2010-01-05 00:45:38 +01:00
|
|
|
}
|
2010-04-28 19:42:12 +02:00
|
|
|
}
|
2010-01-05 00:45:38 +01:00
|
|
|
|
2010-04-28 19:42:12 +02:00
|
|
|
void ContainmentPrivate::appletAppeared(Applet *applet)
|
|
|
|
{
|
2011-05-28 00:22:17 +02:00
|
|
|
//kDebug() << type << Containment::DesktopContainment;
|
2010-04-28 19:42:12 +02:00
|
|
|
KConfigGroup *cg = applet->d->mainConfigGroup();
|
|
|
|
applet->save(*cg);
|
|
|
|
emit q->configNeedsSaving();
|
2008-11-04 00:08:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void ContainmentPrivate::positionPanel(bool force)
|
|
|
|
{
|
|
|
|
if (!q->scene()) {
|
|
|
|
kDebug() << "no scene yet";
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-02-24 15:24:52 +01:00
|
|
|
// already positioning the panel - avoid infinite loops
|
|
|
|
if (ContainmentPrivate::s_positioningPanels) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2008-11-04 00:08:39 +01:00
|
|
|
// we position panels in negative coordinates, and stack all horizontal
|
|
|
|
// and all vertical panels with each other.
|
|
|
|
|
2009-02-19 20:50:19 +01:00
|
|
|
|
2008-11-04 00:08:39 +01:00
|
|
|
const QPointF p = q->pos();
|
|
|
|
|
|
|
|
if (!force &&
|
|
|
|
p.y() + q->size().height() < -INTER_CONTAINMENT_MARGIN &&
|
|
|
|
q->scene()->collidingItems(q).isEmpty()) {
|
|
|
|
// already positioned and not running into any other panels
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-04-13 20:36:38 +02:00
|
|
|
|
|
|
|
QPointF newPos = preferredPanelPos(q->corona());
|
|
|
|
if (p != newPos) {
|
|
|
|
ContainmentPrivate::s_positioningPanels = true;
|
|
|
|
q->setPos(newPos);
|
|
|
|
ContainmentPrivate::s_positioningPanels = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ContainmentPrivate::isPanelContainment() const
|
|
|
|
{
|
|
|
|
return type == Containment::PanelContainment || type == Containment::CustomPanelContainment;
|
|
|
|
}
|
|
|
|
|
|
|
|
QPointF ContainmentPrivate::preferredPos(Corona *corona) const
|
|
|
|
{
|
|
|
|
Q_ASSERT(corona);
|
|
|
|
|
|
|
|
if (isPanelContainment()) {
|
2010-04-23 20:23:53 +02:00
|
|
|
//kDebug() << "is a panel, so put it at" << preferredPanelPos(corona);
|
2010-04-13 20:36:38 +02:00
|
|
|
return preferredPanelPos(corona);
|
|
|
|
}
|
|
|
|
|
2010-04-23 20:23:53 +02:00
|
|
|
QPointF pos(0, 0);
|
|
|
|
QTransform t;
|
2010-04-30 04:10:55 +02:00
|
|
|
while (QGraphicsItem *i = corona->itemAt(pos, t)) {
|
|
|
|
pos.setX(i->scenePos().x() + i->boundingRect().width() + 10);
|
2010-04-23 20:23:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//kDebug() << "not a panel, put it at" << pos;
|
|
|
|
return pos;
|
2010-04-13 20:36:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
QPointF ContainmentPrivate::preferredPanelPos(Corona *corona) const
|
|
|
|
{
|
|
|
|
Q_ASSERT(corona);
|
|
|
|
|
2008-11-04 00:08:39 +01:00
|
|
|
//TODO: research how non-Horizontal, non-Vertical (e.g. Planar) panels behave here
|
2009-02-24 05:54:57 +01:00
|
|
|
bool horiz = formFactor == Plasma::Horizontal;
|
2009-02-19 20:47:24 +01:00
|
|
|
qreal bottom = horiz ? 0 : VERTICAL_STACKING_OFFSET;
|
2008-11-04 00:08:39 +01:00
|
|
|
qreal lastHeight = 0;
|
|
|
|
|
|
|
|
// this should be ok for small numbers of panels, but if we ever end
|
|
|
|
// up managing hundreds of them, this simplistic alogrithm will
|
|
|
|
// likely be too slow.
|
2010-04-13 20:36:38 +02:00
|
|
|
foreach (const Containment *other, corona->containments()) {
|
2008-11-04 00:08:39 +01:00
|
|
|
if (other == q ||
|
2010-04-13 23:10:28 +02:00
|
|
|
!other->d->isPanelContainment() ||
|
2008-11-04 00:08:39 +01:00
|
|
|
horiz != (other->formFactor() == Plasma::Horizontal)) {
|
|
|
|
// only line up with panels of the same orientation
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (horiz) {
|
2009-02-19 20:47:24 +01:00
|
|
|
qreal y = other->pos().y();
|
2008-11-04 00:08:39 +01:00
|
|
|
if (y < bottom) {
|
|
|
|
lastHeight = other->size().height();
|
|
|
|
bottom = y;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
qreal width = other->size().width();
|
|
|
|
qreal x = other->pos().x() + width;
|
|
|
|
if (x > bottom) {
|
|
|
|
lastHeight = width;
|
|
|
|
bottom = x + lastHeight;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// give a space equal to the height again of the last item so there is
|
|
|
|
// room to grow.
|
|
|
|
QPointF newPos;
|
|
|
|
if (horiz) {
|
|
|
|
bottom -= lastHeight + INTER_CONTAINMENT_MARGIN;
|
|
|
|
//TODO: fix x position for non-flush-left panels
|
|
|
|
kDebug() << "moved to" << QPointF(0, bottom - q->size().height());
|
|
|
|
newPos = QPointF(0, bottom - q->size().height());
|
|
|
|
} else {
|
|
|
|
bottom += lastHeight + INTER_CONTAINMENT_MARGIN;
|
|
|
|
//TODO: fix y position for non-flush-top panels
|
|
|
|
kDebug() << "moved to" << QPointF(bottom + q->size().width(), -INTER_CONTAINMENT_MARGIN - q->size().height());
|
|
|
|
newPos = QPointF(bottom + q->size().width(), -INTER_CONTAINMENT_MARGIN - q->size().height());
|
|
|
|
}
|
|
|
|
|
2010-04-13 20:36:38 +02:00
|
|
|
return newPos;
|
2008-11-04 00:08:39 +01:00
|
|
|
}
|
|
|
|
|
2009-08-18 00:30:34 +02:00
|
|
|
|
2010-09-09 20:37:28 +02:00
|
|
|
bool ContainmentPrivate::prepareContainmentActions(const QString &trigger, const QPoint &screenPos, KMenu *menu)
|
2009-08-18 00:30:34 +02:00
|
|
|
{
|
2010-11-11 23:22:39 +01:00
|
|
|
ContainmentActions *plugin = actionPlugins()->value(trigger);
|
2010-09-08 23:51:22 +02:00
|
|
|
if (!plugin) {
|
|
|
|
return false;
|
|
|
|
}
|
2010-11-11 23:22:39 +01:00
|
|
|
plugin->setContainment(q);
|
2009-08-18 00:30:34 +02:00
|
|
|
|
2009-08-18 00:31:32 +02:00
|
|
|
if (!plugin->isInitialized()) {
|
2010-11-11 23:22:39 +01:00
|
|
|
KConfigGroup cfg = q->containmentActionsConfig();
|
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:34 +02:00
|
|
|
}
|
|
|
|
|
2009-08-18 00:31:32 +02:00
|
|
|
if (plugin->configurationRequired()) {
|
2010-09-09 20:37:28 +02:00
|
|
|
KMenu *localMenu = menu ? menu : new KMenu();
|
|
|
|
|
|
|
|
localMenu->addTitle(i18n("This plugin needs to be configured"));
|
|
|
|
localMenu->addAction(q->action("configure"));
|
|
|
|
|
|
|
|
if (!menu) {
|
|
|
|
localMenu->exec(screenPos);
|
|
|
|
delete localMenu;
|
|
|
|
}
|
|
|
|
|
2009-08-18 00:30:34 +02:00
|
|
|
return false;
|
2010-09-09 20:37:28 +02:00
|
|
|
} else if (menu) {
|
|
|
|
QList<QAction*> actions = plugin->contextualActions();
|
|
|
|
if (actions.isEmpty()) {
|
|
|
|
//it probably didn't bother implementing the function. give the user a chance to set
|
|
|
|
//a better plugin. note that if the user sets no-plugin this won't happen...
|
|
|
|
if (!isPanelContainment() && q->action("configure")) {
|
|
|
|
menu->addAction(q->action("configure"));
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
menu->addActions(actions);
|
|
|
|
}
|
2009-08-18 00:30:34 +02:00
|
|
|
}
|
2010-09-08 23:51:22 +02:00
|
|
|
|
2009-08-18 00:30:34 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
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");
|
|
|
|
cfg = KConfigGroup(&cfg, d->context()->currentActivityId());
|
|
|
|
cfg = KConfigGroup(&cfg, "ActionPlugins");
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
cfg = KConfigGroup(corona()->config(), "ActionPlugins");
|
|
|
|
}
|
|
|
|
return cfg;
|
|
|
|
}
|
|
|
|
|
|
|
|
QHash<QString, ContainmentActions*> * ContainmentPrivate::actionPlugins()
|
|
|
|
{
|
|
|
|
switch (containmentActionsSource) {
|
|
|
|
case Activity:
|
|
|
|
//FIXME
|
|
|
|
case Local:
|
|
|
|
return &localActionPlugins;
|
|
|
|
default:
|
|
|
|
return &globalActionPlugins;
|
|
|
|
}
|
|
|
|
}
|
2009-08-18 00:30:34 +02:00
|
|
|
|
2008-11-04 00:08:39 +01:00
|
|
|
} // Plasma namespace
|
|
|
|
|
|
|
|
#include "containment.moc"
|
|
|
|
|