[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-panel-devel
Subject:    Extender api review, round 2
From:       Rob Scheepmaker <r.scheepmaker () student ! utwente ! nl>
Date:       2008-07-29 12:16:35
Message-ID: 200807291416.36177.r.scheepmaker () student ! utwente ! nl
[Download RAW message or body]

Hi all,

I've had a lot of feedback on the extender api, and now I've incorporated a lot of the suggestions into 
a more up to date api. Again, I'm looking forward to getting feedback to fine tune this api all the way.

Oh and another question, does anybody know if there's any way to determine if a top level QWidget is in 
front of another top level QWidget? Because to make drag & drop reliable, there really should be a way 
to determine which plasma view is on top at a specific location. And QApplication::topLevelAt won't do, 
since while dragging, there might be a graphicsView under the mouse cursor when dragging from view to 
view.

Cheers,
Rob Scheepmaker

["extender.h" (text/x-chdr)]

    /**
     * This widget allows using ExtenderItems in you applet. Extender takes care of the presentation
     * of a collection of extenderitems, and keeps track of extenderItems that originated in it.
     * This default extender displays extender items in a vertical layout, and shows spacers in this
     * layout when hovering with an extender item over it, which is probably good for most cases.
     * If you wish to have a different presentation of extender items, you can choose to subclass
     * this class. In this case you'll need to reimplement the extenderItem* events.
     */
    class PLASMA_EXPORT Extender : public QGraphicsWidget
    {
        Q_OBJECT
        Q_PROPERTY(QString emptyExtenderMessage READ emptyExtenderMessage WRITE setEmptyExtenderMessage)
        Q_PROPERTY(bool isPopup READ isPopup WRITE setIsPopup)

    public:
        /**
         * @param applet The applet this extender is part of. Null is not allowed here.
         */
        Extender(Applet *applet);

        ~Extender();

        /**
         * @param popup If false, the applet that is parent to this extender takes care of placing
         * this applet somewhere. If true, the extender takes care of placing itself out of ordinary
         * view, so it can be used with PopupApplet. After calling setIsPopup(false) you'll have to
         * take care to move the extender back to your applet yourself.
         */
        void setIsPopup(bool popup);

        /**
         * @return whether or not this extender is placed outside the ordinary view.
         */
        bool isPopup() const;

        /**
         * @param emptyExtenderMessage The text to be shown whenever the extender is empty.
         */
        void setEmptyExtenderMessage(const QString &message);

        /**
         * @return The text to be shown whenever the extender is empty.
         */
        QString emptyExtenderMessage() const;

        /**
         * @returns a list of all extender items (attached AND detached) where the source applet is
         * this applet.
         */
        QList<ExtenderItem*> extenderItems() const;

        /**
         * @returns a list of all attached extender items.
         */
        QList<ExtenderItem*> attachedExtenderItems() const;

        /**
         * This function can be used for easily determining if a certain item is allready displayed
         * in a extender item 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 (!extender()->extenderItem(source)) {
         *     //add an extender item monitoring this source.
         * }
         */
        ExtenderItem *extenderItem(const QString &name) const;

    protected:
        /**
         * Get's called after an item has been added to this extender. The bookkeeping has allready
         * been done when this function get's called. The only thing left to do is put it somewhere
         * appropriate. The default implementation adds the extenderItem to the appropriate place in
         * a QGraphicsLinearLayout.
         * @param item The item that has just been added.
         * @param pos The location the item has been dropped in local coordinates.
         */
        virtual void extenderItemAddedEvent(ExtenderItem *item, const QPointF &pos);

        /**
         * Get's called after an item has been removed from this extender. All bookkeeping has
         * allready been done when this function get's called.
         * @param item The item that has just been removed.
         */
        virtual void extenderItemRemovedEvent(ExtenderItem *item);

        /**
         * Gets called when an ExtenderItem is hovering over this extender. Implement this function
         * to give some visual feedback about what will happen when the mouse button is released at
         * that position. The default implementation shows a spacer at the appropriate location in
         * the layout.
         * @param item The item that's hovering over this extender. Most usefull for obtaining the
         * size of the spacer.
         * @param pos The location the item is hovering.
         */
        virtual void extenderItemHoverMoveEvent(ExtenderItem *item, const QPointF &pos);

        /**
         * Get's called when an ExtenderItem that was previously hovering over this extender moves
         * away from this extender. The default implementation removes any spacer from the layout.
         */
        virtual void extenderItemHoverLeaveEvent(ExtenderItem *item);

    Q_SIGNALS:
        /**
         * Fires when an extender item is added to this extender.
         */
        void itemAttached(ExtenderItem *);

        /**
         * Fires when an extender item is removed from this extender.
         */
        void itemDetached(ExtenderItem *);

    private:
        ExtenderPrivate* const d;

        friend class ExtenderItem;
    }


    /**
     * This class wraps around a QGraphicsWidget and provides drag&drop handling, a draghandle,
     * title and ability to display qactions as a row of icon, ability to expand, collapse, return
     * to source and tracks configuration associated with this item for you.
     */
    class PLASMA_EXPORT ExtenderItem : public QGraphicsWidget
    {
        Q_OBJECT

        public:
            /**
             * The constructor takes care of adding this item to an extender.
             * @param hostExtender The extender where the extender item belongs to.
             * @param sourceApplet The source applet of the extender item. This should be the applet
             * that created this item, and will be used to create this item again after a plasma
             * restart.
             * @param name A unique name for the extender item, which can be used to obtain it later
             * through Extender::extenderItem(QString).
             * @param widget The qgw that has to be wrapped in this widget.
             * @param extenderItemId the id of the extender item. Use the default 0 to assign a new,
             * unique id to this extender item.
             */
            ExtenderItem(Extender *hostExtender, Applet *sourceApplet,
                         const QString &name = QString(),
                         QGraphicsWidget *widget = 0, uint extenderItemId = 0);

            ~ExtenderItem();

            /**
             * @return A unique identifier for this extender item, used for storing the
             * configuration info.
             */
            uint id();

            /**
             * fetch the configuration of this widget.
             * @return the configuration of this widget.
             */
            KConfigGroup config();

            /**
             * @return the extender item's name.
             */
            QString name();

            /**
             * @param widget The widget that should be wrapped into the extender item.
             */
            void setWidget(QGraphicsWidget *widget);

            /**
             * @return The widget that is wrapped into the extender item.
             */
            QGraphicsWidget *widget() const;

            /**
             * @param title the title that will be shown in the extender item's dragger.
             */
            void setTitle(const QString &title);

            /**
             * @return the title shown in the extender item's dragger.
             */
            QString title() const;

            /**
             * @param icon the icon to display in the extender item's drag handle.
             */
            void setIcon(const QString &icon);

            /**
             * @return the icon being displayed in the extender item's drag handle.
             */
            QIcon icon() const;

            /**
             * @param extender the extender this item belongs to.
             */
            void setExtender(Extender *extender);

            /**
             * @return the extender this items belongs to.
             */
            Extender *extender() const;

            /**
             * @param time (in ms) before this extender item destroys itself unless it is detached,
             * in which case this extender stays around. 0 means forever and is the default.
             * FIXME: I don't like this name.
             */
            void setExpirationTimeWhenAttached(uint time = 0);

            /**
             * @return whether or not this item is detached from it's original source.
             */
            bool isDetached() const;

            /**
             * @return whether or not the extender item  is collapsed.
             */
            bool collapsed() const;

            /**
             * @param name the name to store the action under in our collection.
             * @param action the action to add. Actions will be displayed as an icon in the drag
             * handle.
             */
            void addAction(const QString &name, QAction *action);

            /**
             * @return the QAction with the given name from our collection
             */
            QAction *action(const QString &name) const;

            /**
             * @return the id of the applet this item is contained in.
             */
            uint sourceAppletId() const;

        public Q_SLOTS:
            /**
             * Destroys the extender item.
             */
            void destroy();

            /**
             * Collapse or expand the extender item.
             */
            void setCollapsed(bool collapsed);

            /**
             * Returns the extender item to it's source applet.
             */
            void moveBackToSource();

        protected:
            void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);

            void resizeEvent(QGraphicsSceneResizeEvent *event);

            void mousePressEvent(QGraphicsSceneMouseEvent *event);
            void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
            void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);

            void hoverMoveEvent(QGraphicsSceneHoverEvent *event);
            void hoverLeaveEvent(QGraphicsSceneHoverEvent *event);

        private:
            Q_PRIVATE_SLOT(d, void toggleCollapse())
            Q_PRIVATE_SLOT(d, void updateToolBox())

            ExtenderItemPrivate * const d;

            friend class Extender;
    };

class PLASMA_EXPORT Applet : public QGraphicsWidget
{
    public:
        /**
         * Get's called when and extender item has to be initialized after a plasma restart. If you
         * create ExtenderItems in your applet, you should implement this function to again create
         * the widget that should be shown in this extender item. This function might look something
         * like this:
         *
         * @code
         * SuperCoolWidget *widget = new SuperCoolWidget();
         * dataEngine("engine")->connectSource(item->config("dataSourceName"), widget);
         * item->setWidget(widget);
         * @endcode
         *
         * You can also add one or more custom qactions to this extender item in this function.
         */
        virtual void initExtenderItem(ExtenderItem *item);

        //FIXME: this function might not be entirely necesarry, but it makes the code a lot nicer:
        //Hmm, maybe we should also allow multiple extenders to be part of one applet... I think
        //there can be nice use cases for that.
        /**
         * @return the extender this applet has.
         */
        Extender *extender() const;

        friend class Extender;
        friend class ExtenderItem;
}


_______________________________________________
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