You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

304 lines
9.8 KiB

/*
* Copyright 2009 by Chani Armitage <chani@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 "menu.h"
#include <QAction>
#include <QCheckBox>
#include <QVBoxLayout>
#include <QSignalMapper>
#include <KActionCollection>
#include <KAuthorized>
#include <QDebug>
#include <QIcon>
#include <KLocalizedString>
#include <Plasma/Containment>
#include <Plasma/Corona>
#include "kworkspace.h"
#include "krunner_interface.h"
#include "screensaver_interface.h"
#ifdef Q_OS_WIN
#define _WIN32_WINNT 0x0500 // require NT 5.0 (win 2k pro)
#include <windows.h>
#endif // Q_OS_WIN
ContextMenu::ContextMenu(QObject *parent, const QVariantList &args)
: Plasma::ContainmentActions(parent, args),
m_runCommandAction(0),
m_lockScreenAction(0),
m_logoutAction(0),
m_separator1(0),
m_separator2(0),
m_separator3(0),
m_buttons(0)
{
}
ContextMenu::~ContextMenu()
{
}
void ContextMenu::restore(const KConfigGroup &config)
{
Plasma::Containment *c = containment();
Q_ASSERT(c);
m_actions.clear();
m_actionOrder.clear();
QHash<QString, bool> actions;
QSet<QString> disabled;
if (c->containmentType() == Plasma::Types::PanelContainment ||
c->containmentType() == Plasma::Types::CustomPanelContainment) {
m_actionOrder << "add widgets" << "_add panel" << "lock widgets" << "_context" << "configure" << "remove";
} else {
actions.insert("configure shortcuts", false);
m_actionOrder << "_context" << "_run_command" << "add widgets" << "_add panel"
<< "manage activities" << "remove" << "lock widgets" << "_sep1"
<<"_lock_screen" << "_logout" << "_sep2" << "configure"
<< "configure shortcuts" << "_sep3" << "_wallpaper";
disabled.insert("configure shortcuts");
}
foreach (const QString &name, m_actionOrder) {
actions.insert(name, !disabled.contains(name));
}
QHashIterator<QString, bool> it(actions);
while (it.hasNext()) {
it.next();
m_actions.insert(it.key(), config.readEntry(it.key(), it.value()));
}
// everything below should only happen once, so check for it
if (!m_runCommandAction) {
m_runCommandAction = new QAction(i18nc("plasma_containmentactions_contextmenu", "Run Command..."), this);
m_runCommandAction->setIcon(QIcon::fromTheme("system-run"));
connect(m_runCommandAction, SIGNAL(triggered(bool)), this, SLOT(runCommand()));
m_lockScreenAction = new QAction(i18nc("plasma_containmentactions_contextmenu", "Lock Screen"), this);
m_lockScreenAction->setIcon(QIcon::fromTheme("system-lock-screen"));
connect(m_lockScreenAction, SIGNAL(triggered(bool)), this, SLOT(lockScreen()));
m_logoutAction = new QAction(i18nc("plasma_containmentactions_contextmenu", "Leave..."), this);
m_logoutAction->setIcon(QIcon::fromTheme("system-shutdown"));
connect(m_logoutAction, SIGNAL(triggered(bool)), this, SLOT(startLogout()));
m_separator1 = new QAction(this);
m_separator1->setSeparator(true);
m_separator2 = new QAction(this);
m_separator2->setSeparator(true);
m_separator3 = new QAction(this);
m_separator3->setSeparator(true);
}
}
QList<QAction*> ContextMenu::contextualActions()
{
Plasma::Containment *c = containment();
Q_ASSERT(c);
QList<QAction*> actions;
foreach (const QString &name, m_actionOrder) {
if (!m_actions.value(name)) {
continue;
}
if (name == "_context") {
actions << c->contextualActions();
} if (name == "_wallpaper") {
if (!c->wallpaper().isEmpty()) {
QObject *wallpaperGraphicsObject = c->property("wallpaperGraphicsObject").value<QObject *>();
if (wallpaperGraphicsObject) {
actions << wallpaperGraphicsObject->property("contextualActions").value<QList<QAction *> >();
}
}
} else if (QAction *a = action(name)) {
actions << a;
}
}
return actions;
}
QAction *ContextMenu::action(const QString &name)
{
Plasma::Containment *c = containment();
Q_ASSERT(c);
if (name == "_sep1") {
return m_separator1;
} else if (name == "_sep2") {
return m_separator2;
} else if (name == "_sep3") {
return m_separator3;
} else if (name == "_add panel") {
if (c->corona() && c->corona()->immutability() == Plasma::Types::Mutable) {
return c->corona()->actions()->action("add panel");
}
} else if (name == "_run_command") {
if (KAuthorized::authorizeKAction("run_command")) {
return m_runCommandAction;
}
} else if (name == "_lock_screen") {
if (KAuthorized::authorizeKAction("lock_screen")) {
return m_lockScreenAction;
}
} else if (name == "_logout") {
if (KAuthorized::authorizeKAction("logout")) {
return m_logoutAction;
}
} else if (name == "lock widgets") {
if (KAuthorized::authorizeKAction("logout")) {
return c->corona()->actions()->action("lock widgets");
}
} else if (name == "manage activities") {
if (c->corona()) {
return c->corona()->actions()->action("manage activities");
}
} else {
//FIXME: remove action: make removal of current activity possible
return c->actions()->action(name);
}
return 0;
}
void ContextMenu::runCommand()
{
if (!KAuthorized::authorizeKAction("run_command")) {
return;
}
QString interface("org.kde.krunner");
org::kde::krunner::App krunner(interface, "/App", QDBusConnection::sessionBus());
krunner.display();
}
void ContextMenu::lockScreen()
{
if (!KAuthorized::authorizeKAction("lock_screen")) {
return;
}
#ifndef Q_OS_WIN
QString interface("org.freedesktop.ScreenSaver");
org::freedesktop::ScreenSaver screensaver(interface, "/ScreenSaver",
QDBusConnection::sessionBus());
if (screensaver.isValid()) {
screensaver.Lock();
}
#else
LockWorkStation();
#endif // !Q_OS_WIN
}
void ContextMenu::startLogout()
{
// this short delay is due to two issues:
// a) KWorkSpace's DBus alls are all syncronous
// b) the destrution of the menu that this action is in is delayed
//
// (a) leads to the menu hanging out where everyone can see it because
// the even loop doesn't get returned to allowing it to close.
//
// (b) leads to a 0ms timer not working since a 0ms timer just appends to
// the event queue, and then the menu closing event gets appended to that.
//
// ergo a timer with small timeout
QTimer::singleShot(10, this, SLOT(logout()));
}
void ContextMenu::logout()
{
if (!KAuthorized::authorizeKAction("logout")) {
return;
}
KWorkSpace::requestShutDown();
}
QWidget* ContextMenu::createConfigurationInterface(QWidget* parent)
{
QWidget *widget = new QWidget(parent);
QVBoxLayout *lay = new QVBoxLayout();
widget->setLayout(lay);
widget->setWindowTitle(i18nc("plasma_containmentactions_contextmenu", "Configure Contextual Menu Plugin"));
m_buttons = new QButtonGroup(widget);
m_buttons->setExclusive(false);
foreach (const QString &name, m_actionOrder) {
QCheckBox *item = 0;
if (name == "_context") {
item = new QCheckBox(widget);
//FIXME better text
item->setText(i18nc("plasma_containmentactions_contextmenu", "[Other Actions]"));
} else if (name == "_wallpaper") {
item = new QCheckBox(widget);
item->setText(i18nc("plasma_containmentactions_contextmenu", "Wallpaper Actions"));
item->setIcon(QIcon::fromTheme("user-desktop"));
} else if (name == "_sep1" || name =="_sep2" || name == "_sep3") {
item = new QCheckBox(widget);
item->setText(i18nc("plasma_containmentactions_contextmenu", "[Separator]"));
} else {
QAction *a = action(name);
if (a) {
item = new QCheckBox(widget);
item->setText(a->text());
item->setIcon(a->icon());
}
}
if (item) {
item->setChecked(m_actions.value(name));
item->setProperty("actionName", name);
lay->addWidget(item);
m_buttons->addButton(item);
}
}
return widget;
}
void ContextMenu::configurationAccepted()
{
QList<QAbstractButton *> buttons = m_buttons->buttons();
QListIterator<QAbstractButton *> it(buttons);
while (it.hasNext()) {
QAbstractButton *b = it.next();
if (b) {
m_actions.insert(b->property("actionName").toString(), b->isChecked());
}
}
}
void ContextMenu::save(KConfigGroup &config)
{
QHashIterator<QString, bool> it(m_actions);
while (it.hasNext()) {
it.next();
config.writeEntry(it.key(), it.value());
}
}
K_EXPORT_PLASMA_CONTAINMENTACTIONS_WITH_JSON(contextmenu, ContextMenu, "plasma-containmentactions-contextmenu.json")
#include "menu.moc"