make rightclick plugins possible

this makes rightclicks use the plugin configured for rightclick
and adds a new method to the plugin for when an applet is rightclicked
(we need a list of actions then that we can insert into the menu)
this also adds a signal for immutability and improves handling of
needs-configuring plugins

svn path=/trunk/KDE/kdelibs/; revision=1012639
This commit is contained in:
Chani Armitage 2009-08-17 22:30:46 +00:00
parent a848e4fdcf
commit f0a68d537c
5 changed files with 102 additions and 37 deletions

View File

@ -1101,6 +1101,7 @@ void Applet::flushPendingConstraintsEvents()
action->setVisible(canConfig);
action->setEnabled(canConfig);
}
emit immutabilityChanged(immutability());
}
if (c & Plasma::SizeConstraint) {

View File

@ -698,6 +698,12 @@ class PLASMA_EXPORT Applet : public QGraphicsWidget
*/
void extenderItemRestored(Plasma::ExtenderItem *item);
/**
* Emitted when the immutability changes
* @since 4.4
*/
void immutabilityChanged(const ImmutabilityType immutable);
public Q_SLOTS:
/**
* Sets the immutability type for this applet (not immutable,

View File

@ -234,25 +234,35 @@ void Containment::init()
setContextAction(key, cfg.readEntry(key, QString()));
}
} else {
if (d->type == DesktopContainment) {
//we need to be very careful here to not write anything
//because we have a group, and so the defaults will get merged instead of overwritten
//when copyTo is used (which happens right before restore() is called)
QHash<QString,QString> defaults;
//we need to be very careful here to not write anything
//because we have a group, and so the defaults will get merged instead of overwritten
//when copyTo is used (which happens right before restore() is called)
//FIXME maybe PlasmaApp should handle the defaults?
QHash<QString,QString> defaults;
switch (d->type) {
case DesktopContainment:
defaults.insert("wheel:Vertical;NoModifier", "switchdesktop");
defaults.insert("wheel:Horizontal;ControlModifier", "test");
defaults.insert("LeftButton;NoModifier", "switchdesktop");
defaults.insert("RightButton;NoModifier", "test");
foreach (const QString &trigger, defaults.keys()) {
ContextAction *action = ContextAction::load(defaults.value(trigger));
if (action) {
d->contextActions.insert(trigger, action);
connect(action, SIGNAL(configureRequested()), this, SLOT(requestConfiguration()));
connect(action, SIGNAL(configNeedsSaving()), this, SIGNAL(configNeedsSaving()));
}
defaults.insert("RightButton;NoModifier", "contextmenu");
break;
case PanelContainment:
case CustomPanelContainment:
defaults.insert("RightButton;NoModifier", "contextmenu");
break;
default:
break;
}
foreach (const QString &trigger, defaults.keys()) {
ContextAction *action = ContextAction::load(defaults.value(trigger));
if (action) {
d->contextActions.insert(trigger, action);
connect(action, SIGNAL(configureRequested()), this, SLOT(requestConfiguration()));
connect(action, SIGNAL(configNeedsSaving()), this, SIGNAL(configNeedsSaving()));
action->setParent(this);
}
}
//TODO defaults for panel etc.
}
}
@ -611,28 +621,28 @@ void ContainmentPrivate::containmentActions(KMenu &desktopMenu)
return;
}
QString trigger = "RightButton;NoModifier";
//get base context actions
QList<QAction*> actions = q->contextualActions();
//find the separator to insert the activity settings before it
QAction *separatorAction = 0;
//TODO: should a submenu be created if there are too many containment specific
// actions? see folderview containment
foreach (QAction *action, actions) {
if (action) {
desktopMenu.addAction(action);
if (action->isSeparator()) {
separatorAction = action;
if (ContextAction *cAction = contextActions.value(trigger)) {
if (QAction *a = cAction->configurationAction()) {
//it needs configuring
desktopMenu.addAction(a);
} else {
QList<QAction*> actions = cAction->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...
//FIXME maybe the behaviour could be better
if (type == Containment::DesktopContainment) {
desktopMenu.addAction(q->action("configure"));
}
} else {
//yay!
desktopMenu.addActions(actions);
}
}
}
desktopMenu.addSeparator();
if (type == Containment::DesktopContainment) {
desktopMenu.addAction(q->action("configure"));
}
}
void ContainmentPrivate::appletActions(KMenu &desktopMenu, Applet *applet, bool includeApplet)
@ -717,7 +727,8 @@ bool ContainmentPrivate::showContextMenu(const QPointF &point, const QPoint &scr
if (applet) {
appletActions(desktopMenu, applet, includeApplet);
} else {
containmentActions(desktopMenu);
//containmentActions(desktopMenu);
return false;
}
if (!desktopMenu.isEmpty()) {
@ -2266,11 +2277,9 @@ bool ContainmentPrivate::prepareContextAction(const QString &trigger, const QPoi
action->restore(actionConfig);
}
if (action->configurationRequired()) {
if (QAction *a = action->configurationAction()) {
KMenu menu;
menu.addTitle(i18n("This plugin needs to be configured"));
//TODO show reason
//TODO offer config button
menu.addAction(a);
menu.exec(screenPos);
return false;
}

View File

@ -19,6 +19,9 @@
*/
#include "contextaction.h"
#include "containment.h"
#include <QAction>
#include <kdebug.h>
#include <kglobal.h>
@ -120,6 +123,11 @@ PackageStructure::Ptr ContextAction::packageStructure()
return ContextActionPrivate::s_packageStructure;
}
Containment *ContextAction::containment()
{
return qobject_cast<Plasma::Containment*>(parent());
}
QString ContextAction::name() const
{
if (!d->contextActionDescription.isValid()) {
@ -184,6 +192,12 @@ void ContextAction::wheelEvent(QGraphicsSceneWheelEvent *event)
Q_UNUSED(event)
}
QList<QAction*> ContextAction::contextualActions()
{
//empty list
return QList<QAction*>();
}
DataEngine *ContextAction::dataEngine(const QString &name) const
{
return d->dataEngine(name);
@ -194,6 +208,18 @@ bool ContextAction::configurationRequired() const
return d->needsConfig;
}
QAction *ContextAction::configurationAction()
{
if (d->needsConfig) {
//create the "I need configuring" action
QAction *action = new QAction(i18n("This plugin needs to be configured"), this);
//TODO name/reason?
//TODO connect it to something
return action;
}
return NULL;
}
void ContextAction::setConfigurationRequired(bool needsConfig, const QString &reason)
{
//TODO: implement something for reason. first, we need to decide where/how

View File

@ -21,16 +21,21 @@
#ifndef PLASMA_CONTEXTACTION_H
#define PLASMA_CONTEXTACTION_H
#include <QList>
#include <kplugininfo.h>
#include <plasma/plasma.h>
#include <plasma/packagestructure.h>
#include <plasma/version.h>
class QAction;
namespace Plasma
{
class DataEngine;
class Containment;
class ContextActionPrivate;
/**
@ -164,6 +169,13 @@ class PLASMA_EXPORT ContextAction : public QObject
*/
virtual void wheelEvent(QGraphicsSceneWheelEvent *event);
/**
* Implement this to provide a list of actions that can be added to another menu
* for example, when right-clicking an applet, the "Activity Options" submenu is populated
* with this.
*/
virtual QList<QAction*> contextualActions();
/**
* Loads the given DataEngine
*
@ -190,6 +202,12 @@ class PLASMA_EXPORT ContextAction : public QObject
*/
bool configurationRequired() const;
/**
* @return a config action if the contextaction currently needs to be configured,
* otherwise, null
*/
QAction *configurationAction();
Q_SIGNALS:
/**
* Emitted when the user wants to configure/change the contextaction.
@ -240,6 +258,11 @@ class PLASMA_EXPORT ContextAction : public QObject
*/
void setConfigurationRequired(bool needsConfiguring, const QString &reason = QString());
/**
* return the containment the plugin is associated with, if any.
*/
Containment *containment();
private:
friend class ContextActionPackage;
friend class ContextActionPrivate;