[prev in list] [next in list] [prev in thread] [next in thread]
List: kde-panel-devel
Subject: Extender api review.
From: Rob Scheepmaker <r.scheepmaker () student ! utwente ! nl>
Date: 2008-07-23 21:02:32
Message-ID: 200807232302.32323.r.scheepmaker () student ! utwente ! nl
[Download RAW message or body]
Hello all,
As you'll probably know, I've been working on extenders as part of GSoC. They're shaping up quite
nicely, so now is a good time to review the api I've made so far. What I have done is go trough the
headers in my branch and put all functions and apidox that I've added in one file. I've added comments
where I think things should change (a lot of pimpl'ing to be done). I'm very interested in hearing your
opinion about it.
Regards,
Rob Scheepmaker (pinda)
["extenderapi.h" (text/x-chdr)]
class PLASMA_EXPORT Applet : public QGraphicsWidget
{
public:
/**
* FIXME: Hmm, I guess this should be protected...
* This will wrap the qgw in a DetachableWidget, and add it to the applet. \
This is the way
* to add detachables to your applet. This function requires \
setSupportDetachables to be
* true.
* @param widget The widget to be added.
* @param title The title that should appear in the detachables draghandle.
* @param name The name of the widget. You can give unique names to your \
detachables in
* order to be able to find them back with the detachableWidgetForName() \
function.
* FIXME: Maybe I should use a qvariant instead of name? that way, all data \
relevant to the
* detachable can be passed around, which is probably a lot easier to use \
then the current
* approach, where you have a string as name, and can store extra information \
directly in
* the kconfiggroup.
* @param detachableId The id to give this widget. Actually, to only case in \
which this is
* passed manually is in loadDetachables() so maybe just remove the parameter \
here, and set
* it manually through the pointer to the detachable in loadDetachables()?
*/
virtual DetachableWidget *addDetachableWidget(QGraphicsWidget *widget, const \
QString &title = QString(),
const QString &name = \
QString(),
uint detachableId = 0);
/**
* @return whether or not this applet supports detachables
* FIXME: only detachablewidget and applet uses this, maybe I should just use \
this to
* pimpl... detachable is allready friend. Or at least make it protected.
*/
bool supportDetachables() const;
protected:
/**
* factory method. any applet which is able to create detachables that can \
remain between
* sessions, will have to implement this function to create the detachable \
widgets.
*
* Little example:
* An clock applet that shows different timezones using extenders, might \
implement the
* function like this:
*
* QGraphicsWidget *widget = new SuperAwesomeClockWidget(this);
* hostApplet->dataEngine("time")->connectSource(config.readEntry("timezone"), \
widget,
* 1000);
* return widget;
*
* FIXME: As mentioned in the apidox of createCollapsedExtenderWidget: \
consider not returning a qgw
* here but require the developer to call addDetachableWidget in this \
function to allow devs
* to connect dataengines to the detachable widget itself, and register \
qactions in a bit
* clearer way. I think that could lead to a bit cleaner and easier to \
understand code in
* most cases.
*
* FIXME: as mentioned in the apidox of addDetachableWidget: consider passing \
a QVariant
* instead of QString as name. Of course it wouldn't be called name, but data \
or something
* like that in that case. Or maybe pass a name and data. But at least get \
rid of the
* kconfiggroup. I think they're overly complicated for most cases.
*
* @param name The name of the detachable that can be used to quickly \
identify what to do.
* @param hostApplet The applet that will 'host' the applet. Use this to \
access applet
* api like hostApplet->dataEngine(). Avoid using the source applet \
dataEngine function,
* since the source applet might only exist temporary, just to create \
detachables.
* @param config The configuration data associated with the to be \
instantiated widget.
* Through this you can connect the correct dataengines, set properties, or \
even create
* completely different widgets, depending on configuration data.
* @return The instantiated widget, or 0 if the widget shouldn't be \
instantiated
* (because the source has disappeared for example, think of a deleted email \
or
* something like that)
*/
virtual QGraphicsWidget *createDetachableWidget(const QString &name, \
KConfigGroup config, Applet *hostApplet);
/**
* this function is called when detachables are automagically moved to it's \
extender, for
* example, because there are more detachables then fit in a vertically \
constrained space.
* It's default implementation creates a Plasma::Icon with the icon of the \
applet, and maps
* it's clicked signal to toggle the extender's visibility. Implement this \
function if you
* want to display something more advanced when detachables have been moved \
off to an
* extender.
* FIXME: maybe we should make the default implementation a little bit more \
advanced: a lot
* of times, an applet will probably like to show an icons together with a \
little text
* (number of emails, stuff like that), and change the icon depending on the \
applets status
* (there are new emails). Think about a way to simplify these common cases.
* @return The widget that should be displayed when the applet is in a \
collapsed state.
*/
virtual QGraphicsWidget *createCollapsedExtenderWidget();
/**
* this function is called after a detachable is added, thus allowing the \
applet to add it's
* own qactions to the detachables dragger.
* FIXME: I'm thinking that I should maybe remove this
* function, let createCollapsedExtenderWidget() not return a QGW but require \
that function
* to add the QGW using addDetachableWidget() so that function obtains a \
pointer to the
* detachable and can then register qactions using addAction. I think that \
might be a bit
* cleaner, and add's the possibility to hook the action detachableWidget \
(and not only the
* qgw) to a dataengine to for example show progress in the dragger, which \
might be nice for
* the kuiserver applet. Or maybe even for the notify applet to show the \
expiration time.
*/
virtual QList<QAction*> detachableActions(DetachableWidget *detachable);
/**
* @returns a list of detachable widgets where the source applet is this \
applet.
*/
QList<DetachableWidget*> detachableWidgets() const;
/**
* This function can be used for easily determining if a certain item is \
allready displayed
* in a detachable somewhere, so your applet doesn't duplicate this item. Say \
the applet
* displays 'jobs', from an engine which add's a source for every job. In \
sourceAdded you
* could do something like:
* if (!detchableWidgetForName(source)) {
* //add a detachable widget monitoring this source.
* }
* FIXME: see earlier comments on maybe changing name to a qvariant.
*/
DetachableWidget *detachableWidgetForName(const QString &name) const;
/**
* When an applet contains detachable widgets, the applet collapses into an \
icon by default
* when put into a panel. By setting forcePanelCollapse to false, the applet \
only collapses
* into an icon when the sum of the preferred heights of the detachables is \
smaller then the
* available space.
* @param collapse Whether or not an applet always collapses when put in a \
vertically
* constrained space.
* TODO: maybe we'll need a more flexible approach featuring a couple of \
different
* 'collapsing stratagies'?
*/
void setForcePanelCollapse(bool collapse);
/**
* @return whether or not an applet always collapses when put in a vertically \
constrained
* space.
*/
bool forcePanelCollapse() const;
/**
* When supportDetachables is true, a label will automagically be put in the \
layout whenever
* the layout is empty.
* @param noDetachablesLabel The text to be shown whenever the applet's \
layout is empty.
*/
void setNoDetachablesLabel(const QString &noDetachablesLabel);
/**
* @return The text to be shown whenever the applet's layout is empty.
*/
QString noDetachablesLabel() const;
/**
* @param supportDetachables set to true if your applet whishes to use
* detachables/extenders. This will add a layout to your applet, makes \
detachables consider
* this applet a valid drop target, and automagically add/remove a text label \
when this
* layout is empty.
* By default this behavior is disabled, to ensure there's no breakage all \
around plasma. If
* you wish to support detachables, call this function in your applets \
constructor, and not
* in init, since reinstantiating detachables after a plasma restart happens \
before the call
* to init.
* FIXME: since this function does a certain amount of initialization, maybe \
we should call
* it something like initDetachablesSupport(). I mean: it doesn't really make \
sence to
* actually turn this of again right, so the bool is actually quite obsolete.
*/
void setSupportDetachables(bool supportDetachables);
private:
Q_PRIVATE_SLOT(d, void extenderSizeChanged())
Q_PRIVATE_SLOT(d, void hideExtender())
friend class DetachableWidget;
//TODO: with the kuiserver applet, I didn't need it yet, but for for example \
notify applet, we //might want to have protected attachedDetachableEvent() and \
detachedDetachableEvent() //functions. Notify has detachables that 'expire' after a \
certain amount of time, but we don't //want them to expire when detached, since the \
user detached the thingy to keep it around. This //way we can accomplish that. So \
something like:
protected:
virtual void attachedEvent(DetachableWidget *detachable);
virtual void detachedEvent(DetachableWidget *detachable);
//Actually, also kuiserver might benefit from expiring jobs (finished, non \
detached jobs of //course). Maybe even more applets. Maybe add to detachableWidget \
an //setExpirationTimeWhenNotDetached(uint seconds) or something like that?
//TODO: we want to be able to have scrolling extenders. Implementing this won't \
be that //difficult, but what is a sane policy? To have a maximum size of an \
extender and automatically //insert scroll arrows when it is smaller? And in that \
case: what would be a sane size? Or do we //give the applet the option to control \
wherther or not arrows appear? This still needs some //brainstorming.
};
class PLASMA_EXPORT DetachableWidget : public QGraphicsWidget
public:
/**
* Creating DetachableWidgets is something that an applet itself actually \
never has to
* do (it can just use addWidget, which creates a detachable widget)
* Why not pass a pointer to the applet instead of sourceAppletName and \
sourceAppletId?
* Well, maybe we don't have an instance of the source applet (the detachable \
can live
* on independently of the sourceApplet). But sourceApplet is still relevant: \
what if
* the source applet was removed by the user, but later added again? It makes \
sense to
* make this new applet the source applet of the detachable imo, I think \
that's what
* users would expect...
* FIXME: actually, how it works now, there is always a sourceApplet when a \
detachable is
* created, though it might only exist temporarily. So we still have to store \
it's name and
* id, but we could pass a pointer which cuts down the immense amount of \
parameters a bit.
* @param widget The qgw that has to be wrapped in this widget.
* @param sourceAppletName The name of the source applet.
* @param sourceAppletId The id of the source applet.
* @param detachableId the identifier of the widget that is to be created, 0 \
for
* automatically assigning a new, unique id.
* @param name an unique identifier for this detachable so applets can search \
within
* it's detachables.
* FIXME: maybe use a qvariant as explaned in the apidox of \
addDetachableWidget?
* @param parent the 'host applet' for this detachable widget. Actually, this \
should
* always be set if you want to make sane detachables (config functionality \
needs a host
* applet). So maybe I should remove the default =0 value and move this \
parameter a bit to
* the front of the list.
*/
DetachableWidget(QGraphicsWidget *widget, const QString &sourceAppletName,
uint sourceAppletId, uint detachableId = 0, const QString \
&name = QString(), QGraphicsWidget *parent = 0);
~DetachableWidget();
/**
* fetch the configuration of this widget.
* @return the configuration of this widget.
*/
KConfigGroup config();
/**
* @return the detachable's name.
* FIXME: qvariant?
*/
QString name();
/**
* @return a pointer to the source applet. First this function would want to \
check if
* the sourceAppletName with that sourceAppletId still exists, and return a \
pointer to
* it. If there exists one applet with sourceAppletName, but it has a \
different
* sourceAppletId, it makes sence to return a pointer to that applet. (see \
explanation
* of the ctor)
*/
//FIXME: move to pimpl? only applet uses this and applet could be made \
friend. Applet *sourceApplet() const;
//FIXME: are the following two function actually useful and/or used? I guess \
they should //be removed. At least they aren't used anywhere.
//On the other hand, if you wish to have for example one fixed item in the \
layout that is
//consistent in style with normal detachables, this might be usefull. The \
user must be made //aware though, that that item can't be detached.
//yeah, I guess these functions should just go away.
/**
* @param whether or not this widget is actually detachable.
*/
void setDetachable(bool);
/**
* @return whether or not this widget is actually detachable.
*/
bool detachable();
/**
* @param title the title that will be shown in the detachable's dragger.
*/
void setTitle(const QString &title);
/**
* @return the title shown in the detachable's dragger.
*/
QString title() const;
/**
* @param icon the icon to dispay in the detachable widget's drag bar.
*/
void setIcon(const QString &icon);
//TODO: I guess I should also add a getter for icon.
/**
* @return !(sourceApplet == hostApplet)
*/
bool isDetached() const;
/**
* hmm, maybe make a qaction, just like returntosource? That would be a bit \
more consistend.
*/
/**
* @param collapsed whether or not the detachable is collapsed (when \
collapsed the widget
* won't get shown, only the draghandle will
*/
void setCollapsed(bool collapsed);
/*
* @param collapsed whether or not the detachable is collapsed (when \
collapsed the widget
* won't get shown, only the draghandle will
*/
bool collapsed() const;
/**
* Add an qaction to the detachables dragger. These actions will be shown as \
icons.
*/
void addAction(QAction *action);
//hmm, I don't think applets should ever remove actions: they can just hide \
or disable
//existing qactions, which makes more sence imo. Consider removing this \
function. void removeAction(QAction *action);
//TODO: maybe make the action stuff more like in applet: add an \
action(QString) function for //easy lookup of qactions, and add actions with a name.
//
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget \
*widget);
public slots:
/**
* Destroys the detachable. The difference between calling this function and \
calling
* delete, is that this function also cleans up it's configuration data, \
which is
* something we don't want to happen when we quit plasma.
* FIXME: maybe we should use a qaction for this too for further consistency.
*/
void destroy();
//TODO:
//instead of the detached/attached events in applets, we could instead fire \
signals here. //This way the applet could be made aware of this fact, but the qgw in \
the detachable can be //connected too, to for example show more information when \
detached, or do other special //stuff. Consider this...
//
//TODO:
//maybe add a dataUpdated and setValue function to allow the dragger to show \
progress in the //kuiserver applet? I think that would be super neat :p
protected:
virtual void resizeEvent(QGraphicsSceneResizeEvent *event);
virtual void mousePressEvent(QGraphicsSceneMouseEvent *event);
virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
private:
Q_PRIVATE_SLOT(d, void moveBackToSourceApplet())
Q_PRIVATE_SLOT(d, void toggleCollapse())
Q_PRIVATE_SLOT(d, void updateToolBox())
};
class PLASMA_EXPORT Corona : public QGraphicsScene
{
//the following two functions are only used in detachablewidget (well, maybe \
applethandle might //use it too). Let's just move this to pimpl and make \
detachablewidget friend of corona? /**
* @param pos a position in screen coordinates.
* @return a pointer to the containment that is visible under the mouse pointer.
*/
Containment* containmentFromScreenPos(const QPoint &pos);
/**
* @param pos a position in screen coordinates.
* @return a pointer to the applet that is visible under the mouse pointer.
*/
Applet *appletFromScreenPos(const QPoint &pos);
/**
* FIXME: this function is used in applet and containment. Maybe make both \
friends and move to
* pimpl? I don't think this function is usefull for applets.
* returns a pointer to the requested applet.
* @arg appletName the pluginName of the wanted applet.
* @arg appletId the applet id of the wanted applet.
*/
Applet *appletForName(const QString &appletName, uint appletId = 0) const;
/**
* adds an extender to a seperate containment in the topleft quadrant, which is \
guaranteed to
* remain hidden from ordinary views. Only used in applet so maybe move to pimpl?
* OR make a bit more generic so applets can add all kinds of stuff to this \
containment to hide
* them from view. But in that case there should be an easy generic way to also \
obtain a view on
* it. I'm not entirely sure it would be usefull, think about it.
* @arg extender the applet to add.
*/
void addExtender(Applet *extender);
/**
* FIXME: only used in applet and containment. make both friends and move to \
pimpl?
* @return A pointer to the containment that manages all extenders.
*/
Containment *extenderContainment();
};
_______________________________________________
Plasma-devel mailing list
Plasma-devel@kde.org
https://mail.kde.org/mailman/listinfo/plasma-devel
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic