247 lines
7.8 KiB
C++
247 lines
7.8 KiB
C++
/*
|
|
SPDX-FileCopyrightText: 2007 Aaron Seigo <aseigo@kde.org>
|
|
SPDX-FileCopyrightText: 2008 Ménard Alexis <darktears31@gmail.com>
|
|
SPDX-FileCopyrightText: 2009 Chani Armitage <chani@kde.org>
|
|
SPDX-FileCopyrightText: 2012 Marco Martin <notmart@kde.org>
|
|
|
|
SPDX-License-Identifier: LGPL-2.0-or-later
|
|
*/
|
|
|
|
#include "private/containment_p.h"
|
|
|
|
#include <KLocalizedString>
|
|
#include <KWindowSystem>
|
|
#include <QDebug>
|
|
|
|
#include "config-plasma.h"
|
|
|
|
#include "pluginloader.h"
|
|
|
|
#include "debug_p.h"
|
|
#include "private/applet_p.h"
|
|
#include "timetracker.h"
|
|
|
|
namespace Plasma
|
|
{
|
|
const char ContainmentPrivate::defaultWallpaper[] = "org.kde.image";
|
|
|
|
ContainmentPrivate::ContainmentPrivate(Containment *c)
|
|
: q(c)
|
|
, formFactor(Types::Planar)
|
|
, location(Types::Floating)
|
|
, lastScreen(-1)
|
|
, type(Plasma::Types::NoContainmentType) // never had a screen
|
|
, uiReady(false)
|
|
, appletsUiReady(false)
|
|
{
|
|
// if the parent is an applet (i.e we are the systray)
|
|
// we want to follow screen changed signals from the parent's containment
|
|
auto appletParent = qobject_cast<Plasma::Applet *>(c->parent());
|
|
if (appletParent) {
|
|
QObject::connect(appletParent->containment(), &Containment::screenChanged, c, &Containment::screenChanged);
|
|
}
|
|
}
|
|
|
|
Plasma::ContainmentPrivate::~ContainmentPrivate()
|
|
{
|
|
applets.clear();
|
|
}
|
|
|
|
void ContainmentPrivate::addDefaultActions(KActionCollection *actions, Containment *c)
|
|
{
|
|
actions->setConfigGroup(QStringLiteral("Shortcuts-Containment"));
|
|
|
|
// adjust applet actions
|
|
QAction *appAction = qobject_cast<QAction *>(actions->action(QStringLiteral("remove")));
|
|
appAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_D, Qt::ALT + Qt::Key_R));
|
|
if (c && c->d->isPanelContainment()) {
|
|
appAction->setText(i18n("Remove this Panel"));
|
|
} else {
|
|
appAction->setText(i18n("Remove this Activity"));
|
|
}
|
|
|
|
appAction = qobject_cast<QAction *>(actions->action(QStringLiteral("configure")));
|
|
if (appAction) {
|
|
appAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_D, Qt::ALT + Qt::Key_S));
|
|
appAction->setText(i18n("Activity Settings"));
|
|
}
|
|
|
|
// add our own actions
|
|
QAction *appletBrowserAction = actions->add<QAction>(QStringLiteral("add widgets"));
|
|
appletBrowserAction->setAutoRepeat(false);
|
|
appletBrowserAction->setText(i18n("Add Widgets..."));
|
|
appletBrowserAction->setIcon(QIcon::fromTheme(QStringLiteral("list-add")));
|
|
appletBrowserAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_D, Qt::Key_A));
|
|
appletBrowserAction->setData(Plasma::Types::AddAction);
|
|
}
|
|
|
|
KConfigGroup ContainmentPrivate::containmentActionsConfig() const
|
|
{
|
|
KConfigGroup cfg = KConfigGroup(q->corona()->config(), "ActionPlugins");
|
|
return KConfigGroup(&cfg, QString::number(type));
|
|
}
|
|
|
|
void ContainmentPrivate::configChanged()
|
|
{
|
|
KConfigGroup group = q->config();
|
|
q->setWallpaper(group.readEntry("wallpaperplugin", defaultWallpaper));
|
|
}
|
|
|
|
void ContainmentPrivate::checkStatus(Plasma::Types::ItemStatus appletStatus)
|
|
{
|
|
// qCDebug(LOG_PLASMA) << "================== "<< appletStatus << q->status();
|
|
if (appletStatus == q->status()) {
|
|
return;
|
|
}
|
|
|
|
if (appletStatus < q->status() || appletStatus == Plasma::Types::HiddenStatus) {
|
|
// check to see if any other applet has a higher status, and stick with that if we do
|
|
// we'll treat HiddenStatus as lowest as we cannot change the enum value which is highest anymore
|
|
for (Applet *applet : qAsConst(applets)) {
|
|
if (applet->status() > appletStatus && applet->status() != Plasma::Types::HiddenStatus) {
|
|
appletStatus = applet->status();
|
|
}
|
|
}
|
|
}
|
|
|
|
if (appletStatus != Plasma::Types::HiddenStatus) {
|
|
q->setStatus(appletStatus);
|
|
}
|
|
}
|
|
|
|
void ContainmentPrivate::triggerShowAddWidgets()
|
|
{
|
|
Q_EMIT q->showAddWidgetsInterface(QPointF());
|
|
}
|
|
|
|
void ContainmentPrivate::containmentConstraintsEvent(Plasma::Types::Constraints constraints)
|
|
{
|
|
if (!q->isContainment()) {
|
|
return;
|
|
}
|
|
|
|
// qCDebug(LOG_PLASMA) << "got containmentConstraintsEvent" << constraints;
|
|
if (constraints & Plasma::Types::ImmutableConstraint) {
|
|
// update actions
|
|
const bool unlocked = q->immutability() == Types::Mutable;
|
|
|
|
QAction *action = q->actions()->action(QStringLiteral("remove"));
|
|
if (action) {
|
|
action->setEnabled(unlocked);
|
|
action->setVisible(unlocked);
|
|
}
|
|
|
|
action = q->actions()->action(QStringLiteral("add widgets"));
|
|
if (action) {
|
|
action->setEnabled(unlocked);
|
|
action->setVisible(unlocked);
|
|
}
|
|
|
|
// tell the applets too
|
|
for (Applet *a : qAsConst(applets)) {
|
|
/*Why qMin?
|
|
* the applets immutability() is the maximum between internal applet immutability
|
|
* and the immutability of its containment.
|
|
* so not set higher immutability in the internal member of Applet
|
|
* or the applet will not be able to be unlocked properly
|
|
*/
|
|
a->setImmutability(qMin(q->immutability(), a->d->immutability));
|
|
a->updateConstraints(Types::ImmutableConstraint);
|
|
}
|
|
}
|
|
|
|
// pass on the constraints that are relevant here
|
|
Types::Constraints appletConstraints = Types::NoConstraint;
|
|
if (constraints & Types::FormFactorConstraint) {
|
|
appletConstraints |= Types::FormFactorConstraint;
|
|
}
|
|
|
|
if (constraints & Types::ScreenConstraint) {
|
|
appletConstraints |= Types::ScreenConstraint;
|
|
}
|
|
|
|
if (appletConstraints != Types::NoConstraint) {
|
|
for (Applet *applet : qAsConst(applets)) {
|
|
applet->updateConstraints(appletConstraints);
|
|
}
|
|
}
|
|
}
|
|
|
|
Applet *ContainmentPrivate::createApplet(const QString &name, const QVariantList &args, uint id)
|
|
{
|
|
if (!q->isContainment()) {
|
|
return nullptr;
|
|
}
|
|
|
|
if (q->immutability() != Types::Mutable && !args.contains(QVariant::fromValue(QStringLiteral("org.kde.plasma:force-create")))) {
|
|
#ifndef NDEBUG
|
|
// qCDebug(LOG_PLASMA) << "addApplet for" << name << "requested, but we're currently immutable!";
|
|
#endif
|
|
return nullptr;
|
|
}
|
|
|
|
Applet *applet = PluginLoader::self()->loadApplet(name, id, args);
|
|
|
|
if (!applet) {
|
|
qCWarning(LOG_PLASMA) << "Applet" << name << "could not be loaded.";
|
|
applet = new Applet(nullptr, QString(), id);
|
|
applet->setLaunchErrorMessage(i18n("Could not find requested component: %1", name));
|
|
}
|
|
|
|
q->addApplet(applet);
|
|
// mirror behavior of resorecontents: if an applet is not valid, set it immediately to uiReady
|
|
if (!applet->pluginMetaData().isValid()) {
|
|
applet->updateConstraints(Plasma::Types::UiReadyConstraint);
|
|
}
|
|
return applet;
|
|
}
|
|
|
|
void ContainmentPrivate::appletDeleted(Plasma::Applet *applet)
|
|
{
|
|
applets.removeAll(applet);
|
|
|
|
Q_EMIT q->appletRemoved(applet);
|
|
Q_EMIT q->configNeedsSaving();
|
|
}
|
|
|
|
bool ContainmentPrivate::isPanelContainment() const
|
|
{
|
|
return type == Plasma::Types::PanelContainment || type == Plasma::Types::CustomPanelContainment;
|
|
}
|
|
|
|
void ContainmentPrivate::setStarted()
|
|
{
|
|
if (!q->Applet::d->started) {
|
|
q->Applet::d->started = true;
|
|
|
|
if (uiReady) {
|
|
Q_EMIT q->uiReadyChanged(true);
|
|
}
|
|
}
|
|
}
|
|
|
|
void ContainmentPrivate::setUiReady()
|
|
{
|
|
// if we are the containment and there is still some incomplete applet, we're still incomplete
|
|
if (!uiReady) {
|
|
uiReady = true;
|
|
if (q->Applet::d->started && (appletsUiReady || applets.isEmpty()) && loadingApplets.isEmpty()) {
|
|
Q_EMIT q->uiReadyChanged(true);
|
|
}
|
|
}
|
|
}
|
|
|
|
void ContainmentPrivate::appletLoaded(Applet *applet)
|
|
{
|
|
loadingApplets.remove(applet);
|
|
|
|
if (loadingApplets.isEmpty() && !appletsUiReady) {
|
|
appletsUiReady = true;
|
|
if (q->Applet::d->started && uiReady) {
|
|
Q_EMIT q->uiReadyChanged(true);
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|