2012-07-17 14:21:45 +02:00
|
|
|
/*
|
|
|
|
* Copyright 2007 by Aaron Seigo <aseigo@kde.org>
|
|
|
|
* Copyright 2008 by Ménard Alexis <darktears31@gmail.com>
|
|
|
|
* Copyright 2009 Chani Armitage <chani@kde.org>
|
|
|
|
* Copyright 2012 Marco Martin <notmart@kde.org>
|
|
|
|
*
|
|
|
|
* 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 "private/containment_p.h"
|
|
|
|
|
|
|
|
|
|
|
|
#include <kactioncollection.h>
|
2013-07-29 19:05:59 +02:00
|
|
|
#include <QDebug>
|
2012-12-27 11:25:00 +01:00
|
|
|
#include <kiconloader.h>
|
2013-02-11 21:38:18 +01:00
|
|
|
#include <klocalizedstring.h>
|
2012-07-17 14:21:45 +02:00
|
|
|
#include <kwindowsystem.h>
|
|
|
|
|
2012-08-24 03:16:04 +02:00
|
|
|
#include "config-plasma.h"
|
|
|
|
|
2012-07-17 14:21:45 +02:00
|
|
|
#include "containmentactions.h"
|
|
|
|
#include "corona.h"
|
|
|
|
#include "pluginloader.h"
|
|
|
|
|
|
|
|
#include "private/applet_p.h"
|
|
|
|
|
|
|
|
|
|
|
|
namespace Plasma
|
|
|
|
{
|
|
|
|
|
2013-03-01 15:11:08 +01:00
|
|
|
const char ContainmentPrivate::defaultWallpaper[] = "org.kde.image";
|
2012-07-17 14:21:45 +02:00
|
|
|
|
|
|
|
void ContainmentPrivate::addDefaultActions(KActionCollection *actions, Containment *c)
|
|
|
|
{
|
|
|
|
actions->setConfigGroup("Shortcuts-Containment");
|
|
|
|
|
|
|
|
//adjust applet actions
|
2013-07-10 01:59:39 +02:00
|
|
|
QAction *appAction = qobject_cast<QAction*>(actions->action("remove"));
|
|
|
|
appAction->setShortcut(QKeySequence("alt+d, alt+r"));
|
2012-07-17 14:21:45 +02:00
|
|
|
if (c && c->d->isPanelContainment()) {
|
|
|
|
appAction->setText(i18n("Remove this Panel"));
|
|
|
|
} else {
|
|
|
|
appAction->setText(i18n("Remove this Activity"));
|
|
|
|
}
|
|
|
|
|
2013-07-10 01:59:39 +02:00
|
|
|
appAction = qobject_cast<QAction*>(actions->action("configure"));
|
2012-07-17 14:21:45 +02:00
|
|
|
if (appAction) {
|
2013-07-10 01:59:39 +02:00
|
|
|
appAction->setShortcut(QKeySequence("alt+d, alt+s"));
|
2012-07-17 14:21:45 +02:00
|
|
|
appAction->setText(i18n("Activity Settings"));
|
|
|
|
}
|
|
|
|
|
|
|
|
//add our own actions
|
2013-07-10 01:59:39 +02:00
|
|
|
QAction *appletBrowserAction = actions->add<QAction>("add widgets");
|
2012-07-17 14:21:45 +02:00
|
|
|
appletBrowserAction->setAutoRepeat(false);
|
|
|
|
appletBrowserAction->setText(i18n("Add Widgets..."));
|
2013-04-02 12:55:37 +02:00
|
|
|
appletBrowserAction->setIcon(QIcon::fromTheme("list-add"));
|
2013-07-10 01:59:39 +02:00
|
|
|
appletBrowserAction->setShortcut(QKeySequence("alt+d, a"));
|
2013-05-10 19:29:13 +02:00
|
|
|
appletBrowserAction->setData(Plasma::Types::AddAction);
|
2012-07-17 14:21:45 +02:00
|
|
|
}
|
|
|
|
|
2013-02-18 18:05:45 +01:00
|
|
|
void ContainmentPrivate::setScreen(int newScreen)
|
2012-07-17 14:21:45 +02: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.
|
|
|
|
Corona *corona = q->corona();
|
|
|
|
Q_ASSERT(corona);
|
|
|
|
|
|
|
|
//if it's an offscreen widget, don't allow to claim a screen, after all it's *off*screen
|
2012-09-24 14:30:42 +02:00
|
|
|
//TODO: port away qgv
|
|
|
|
/* should decide in a different way if this is a dashboard containment
|
2012-07-17 14:21:45 +02:00
|
|
|
if (corona->offscreenWidgets().contains(q)) {
|
|
|
|
return;
|
2012-09-24 14:30:42 +02:00
|
|
|
}*/
|
2012-07-17 14:21:45 +02:00
|
|
|
|
|
|
|
if (newScreen < -1) {
|
|
|
|
newScreen = -1;
|
|
|
|
}
|
|
|
|
|
2013-07-29 19:05:59 +02:00
|
|
|
//qDebug() << activity() << "setting screen to " << newScreen << "and type is" << type;
|
2012-07-17 14:21:45 +02:00
|
|
|
|
|
|
|
Containment *swapScreensWith(0);
|
2013-05-10 19:29:13 +02:00
|
|
|
const bool isDesktopContainment = type == Plasma::Types::DesktopContainment ||
|
|
|
|
type == Plasma::Types::CustomContainment;
|
2012-07-17 14:21:45 +02:00
|
|
|
if (isDesktopContainment) {
|
|
|
|
if (newScreen > -1) {
|
|
|
|
// sanity check to make sure someone else doesn't have this screen already!
|
2013-02-18 18:05:45 +01:00
|
|
|
Containment *currently = corona->containmentForScreen(newScreen);
|
2012-07-17 14:21:45 +02:00
|
|
|
if (currently && currently != q) {
|
|
|
|
#ifndef NDEBUG
|
2013-07-29 19:05:59 +02:00
|
|
|
// qDebug() << "currently is on screen" << currently->screen()
|
2013-03-16 12:19:54 +01:00
|
|
|
// << "desktop" << currently->desktop()
|
2013-08-01 12:15:38 +02:00
|
|
|
// << "and is" << currently->activity()
|
|
|
|
// << (QObject*)currently << "i'm" << (QObject*)q;
|
2012-07-17 14:21:45 +02:00
|
|
|
#endif
|
2013-02-18 18:05:45 +01:00
|
|
|
currently->setScreen(-1);
|
2012-07-17 14:21:45 +02:00
|
|
|
swapScreensWith = currently;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int oldScreen = screen;
|
|
|
|
screen = newScreen;
|
|
|
|
|
2013-05-10 19:29:13 +02:00
|
|
|
q->updateConstraints(Plasma::Types::ScreenConstraint);
|
2012-07-17 14:21:45 +02:00
|
|
|
|
2013-02-18 18:05:45 +01:00
|
|
|
if (oldScreen != newScreen) {
|
2012-07-17 14:21:45 +02:00
|
|
|
#ifndef NDEBUG
|
2013-07-29 19:05:59 +02:00
|
|
|
// qDebug() << "going to signal change for" << q
|
2013-08-01 12:15:38 +02:00
|
|
|
// << ", old screen & desktop:" << oldScreen
|
|
|
|
// << ", new:" << screen << desktop;
|
2012-07-17 14:21:45 +02:00
|
|
|
#endif
|
|
|
|
KConfigGroup c = q->config();
|
|
|
|
c.writeEntry("screen", screen);
|
|
|
|
emit q->configNeedsSaving();
|
|
|
|
emit q->screenChanged(oldScreen, newScreen, q);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (swapScreensWith) {
|
2013-07-29 19:05:59 +02:00
|
|
|
//qDebug() << "setScreen due to swap, part 2";
|
2013-02-18 18:05:45 +01:00
|
|
|
swapScreensWith->setScreen(oldScreen);
|
2012-07-17 14:21:45 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (newScreen >= 0) {
|
|
|
|
emit q->activate();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-02-19 12:03:53 +01:00
|
|
|
KConfigGroup ContainmentPrivate::containmentActionsConfig() const
|
|
|
|
{
|
2013-02-25 16:53:58 +01:00
|
|
|
KConfigGroup cfg = KConfigGroup(q->corona()->config(), "ActionPlugins");
|
|
|
|
return KConfigGroup(&cfg, QString::number(type));
|
2013-02-19 12:03:53 +01:00
|
|
|
}
|
2012-07-17 14:21:45 +02:00
|
|
|
|
|
|
|
void ContainmentPrivate::configChanged()
|
|
|
|
{
|
2013-02-06 15:23:48 +01:00
|
|
|
KConfigGroup group = q->config();
|
|
|
|
q->setWallpaper(group.readEntry("wallpaperplugin", defaultWallpaper));
|
2012-07-17 14:21:45 +02:00
|
|
|
}
|
|
|
|
|
2013-05-14 20:49:50 +02:00
|
|
|
void ContainmentPrivate::checkStatus(Plasma::Types::ItemStatus appletStatus)
|
2012-07-17 14:21:45 +02:00
|
|
|
{
|
2013-07-29 19:05:59 +02:00
|
|
|
//qDebug() << "================== "<< appletStatus << q->status();
|
2012-07-17 14:21:45 +02:00
|
|
|
if (appletStatus == q->status()) {
|
2013-02-12 20:44:04 +01:00
|
|
|
emit q->statusChanged(appletStatus);
|
2012-07-17 14:21:45 +02:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ContainmentPrivate::triggerShowAddWidgets()
|
|
|
|
{
|
|
|
|
emit q->showAddWidgetsInterface(QPointF());
|
|
|
|
}
|
|
|
|
|
2013-05-14 18:08:58 +02:00
|
|
|
void ContainmentPrivate::containmentConstraintsEvent(Plasma::Types::Constraints constraints)
|
2012-07-17 14:21:45 +02:00
|
|
|
{
|
|
|
|
if (!q->isContainment()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-07-29 19:05:59 +02:00
|
|
|
//qDebug() << "got containmentConstraintsEvent" << constraints;
|
2013-05-10 19:29:13 +02:00
|
|
|
if (constraints & Plasma::Types::ImmutableConstraint) {
|
2012-07-17 14:21:45 +02:00
|
|
|
//update actions
|
2013-05-10 19:29:13 +02:00
|
|
|
const bool unlocked = q->immutability() == Types::Mutable;
|
2013-02-25 16:43:06 +01:00
|
|
|
|
|
|
|
QAction *action = q->actions()->action("remove");
|
|
|
|
if (action) {
|
|
|
|
action->setEnabled(unlocked);
|
|
|
|
action->setVisible(unlocked);
|
|
|
|
}
|
|
|
|
|
|
|
|
action = q->actions()->action("add widgets");
|
|
|
|
if (action) {
|
|
|
|
action->setEnabled(unlocked);
|
|
|
|
action->setVisible(unlocked);
|
|
|
|
}
|
2012-07-17 14:21:45 +02:00
|
|
|
|
|
|
|
// tell the applets too
|
|
|
|
foreach (Applet *a, applets) {
|
|
|
|
a->setImmutability(q->immutability());
|
2013-05-10 19:29:13 +02:00
|
|
|
a->updateConstraints(Types::ImmutableConstraint);
|
2012-07-17 14:21:45 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// pass on the constraints that are relevant here
|
2013-05-14 18:08:58 +02:00
|
|
|
Types::Constraints appletConstraints = Types::NoConstraint;
|
2013-05-10 19:29:13 +02:00
|
|
|
if (constraints & Types::FormFactorConstraint) {
|
|
|
|
appletConstraints |= Types::FormFactorConstraint;
|
2012-07-17 14:21:45 +02:00
|
|
|
}
|
|
|
|
|
2013-05-10 19:29:13 +02:00
|
|
|
if (constraints & Types::ScreenConstraint) {
|
|
|
|
appletConstraints |= Types::ScreenConstraint;
|
2012-07-17 14:21:45 +02:00
|
|
|
}
|
|
|
|
|
2013-05-10 19:29:13 +02:00
|
|
|
if (appletConstraints != Types::NoConstraint) {
|
2012-07-17 14:21:45 +02:00
|
|
|
foreach (Applet *applet, applets) {
|
|
|
|
applet->updateConstraints(appletConstraints);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-02-28 13:32:47 +01:00
|
|
|
Applet *ContainmentPrivate::createApplet(const QString &name, const QVariantList &args, uint id)
|
2012-07-17 14:21:45 +02:00
|
|
|
{
|
|
|
|
if (!q->isContainment()) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-05-10 19:29:13 +02:00
|
|
|
if (q->immutability() != Types::Mutable) {
|
2012-07-17 14:21:45 +02:00
|
|
|
#ifndef NDEBUG
|
2013-07-29 19:05:59 +02:00
|
|
|
// qDebug() << "addApplet for" << name << "requested, but we're currently immutable!";
|
2012-07-17 14:21:45 +02:00
|
|
|
#endif
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
Applet *applet = PluginLoader::self()->loadApplet(name, id, args);
|
|
|
|
|
|
|
|
if (!applet) {
|
|
|
|
#ifndef NDEBUG
|
2013-07-29 19:05:59 +02:00
|
|
|
// qDebug() << "Applet" << name << "could not be loaded.";
|
2012-07-17 14:21:45 +02:00
|
|
|
#endif
|
|
|
|
applet = new Applet(0, QString(), id);
|
2013-02-12 20:07:23 +01:00
|
|
|
applet->setLaunchErrorMessage(i18n("Could not find requested component: %1", name));
|
2012-07-17 14:21:45 +02:00
|
|
|
}
|
|
|
|
|
2013-02-18 17:28:29 +01:00
|
|
|
q->addApplet(applet);
|
2012-07-17 14:21:45 +02:00
|
|
|
return applet;
|
|
|
|
}
|
|
|
|
|
2012-09-24 13:58:54 +02:00
|
|
|
void ContainmentPrivate::appletDeleted(Plasma::Applet *applet)
|
2012-07-17 14:21:45 +02:00
|
|
|
{
|
|
|
|
applets.removeAll(applet);
|
|
|
|
|
|
|
|
emit q->appletRemoved(applet);
|
|
|
|
emit q->configNeedsSaving();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ContainmentPrivate::isPanelContainment() const
|
|
|
|
{
|
2013-05-10 19:29:13 +02:00
|
|
|
return type == Plasma::Types::PanelContainment || type == Plasma::Types::CustomPanelContainment;
|
2012-07-17 14:21:45 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|