File indexing completed on 2024-09-29 05:04:10

0001 /***************************************************************************
0002  *   Copyright (C) 2003-2005 by David Saxton                               *
0003  *   david@bluehaze.org                                                    *
0004  *                                                                         *
0005  *   This program is free software; you can redistribute it and/or modify  *
0006  *   it under the terms of the GNU General Public License as published by  *
0007  *   the Free Software Foundation; either version 2 of the License, or     *
0008  *   (at your option) any later version.                                   *
0009  ***************************************************************************/
0010 
0011 #ifndef CANVASITEMPARTS_H
0012 #define CANVASITEMPARTS_H
0013 
0014 //#include <canvas.h> // 2018.10.16 - not needed
0015 #include "canvasitems.h"
0016 #include <QIcon>
0017 #include <QPointer>
0018 #include <QSlider>
0019 #include <QToolButton>
0020 
0021 class Cells;
0022 class CIWidgetMgr;
0023 class CNItem;
0024 class SliderWidget;
0025 class ToolButton;
0026 class QString;
0027 
0028 class GuiPart : /* public QObject, */ public KtlQCanvasRectangle
0029 {
0030     Q_OBJECT
0031 public:
0032     /**
0033      * Create a GuiPart. Control the position using setGuiPartSize, instead
0034      * of calling KtlQCanvasRectangle::setSize. This allows GuiPart to know
0035      * when its size has been changed
0036      */
0037     GuiPart(CNItem *parent, const QRect &r, KtlQCanvas *canvas);
0038     ~GuiPart() override;
0039 
0040     virtual QRect recommendedRect() const
0041     {
0042         return m_originalRect;
0043     }
0044     void setOriginalRect(const QRect &r)
0045     {
0046         m_originalRect = r;
0047     }
0048 
0049     virtual void updateConnectorPoints(bool add);
0050 
0051     /**
0052      * Set the angle that the GuiPart draws itself (if the GuiPart chooses
0053      * to use it by calling initPainter and deinitPainter from drawShape).
0054      * Note that this doesn't affect the rectangle position that the
0055      * GuiPart is in. The rotation is taken to be about the center of the
0056      * rectangle.
0057      */
0058     void setAngleDegrees(int angleDegrees);
0059     /**
0060      * Control the size. Call this instead of KtlQCanvasRectangle::setSize. In
0061      * turn, this function will notify subclasses via posChanged();
0062      */
0063     void setGuiPartSize(int width, int height);
0064     /**
0065      * Returns the rectangle to draw in to compensate for rotation of
0066      * the QPainter
0067      */
0068     QRect drawRect();
0069 
0070     int angleDegrees() const
0071     {
0072         return m_angleDegrees;
0073     }
0074     CNItem *parent() const
0075     {
0076         return p_parent;
0077     }
0078 
0079 protected:
0080     /**
0081      * Called when the size or angle changes
0082      */
0083     virtual void posChanged()
0084     {
0085         ;
0086     }
0087     /**
0088      * Rotate / etc the painter. You must call deinitPainter after
0089      * calling this function.
0090      */
0091     void initPainter(QPainter &p);
0092     /**
0093      * Complement function to initPainter - restores painter to normal
0094      * transform
0095      */
0096     void deinitPainter(QPainter &p);
0097     int m_angleDegrees;
0098     CNItem *p_parent;
0099     bool b_pointsAdded;
0100     QRect m_originalRect;
0101 
0102 private slots:
0103     void slotMoveBy(double dx, double dy);
0104 };
0105 
0106 /**
0107 @short Stores internal information about text associated with CNItem
0108 @author David Saxton
0109 */
0110 class Text : public GuiPart
0111 {
0112     Q_OBJECT
0113 public:
0114     Text(const QString &text, CNItem *parent, const QRect &r, KtlQCanvas *canvas, int flags = Qt::AlignHCenter | Qt::AlignVCenter);
0115     ~Text() override;
0116 
0117     /**
0118      * Set the text, returning true if the size of this Text on the canvas
0119      * has changed.
0120      */
0121     bool setText(const QString &text);
0122     QRect recommendedRect() const override;
0123     void drawShape(QPainter &p) override;
0124     /**
0125      * The text flags (see QPainter::drawText) - Qt::AlignmentFlags and
0126      * Qt::TextFlags OR'd together.
0127      */
0128     int flags() const
0129     {
0130         return m_flags;
0131     }
0132     /**
0133      * @see flags
0134      */
0135     void setFlags(int flags);
0136 
0137 protected:
0138     QString m_text;
0139     int m_flags;
0140 };
0141 typedef QMap<QString, QPointer<Text>> TextMap;
0142 
0143 /**
0144 @short Base class for embedding Qt Widgets into the canvas
0145 @author David Saxton
0146 */
0147 class Widget : public GuiPart
0148 {
0149 public:
0150     Widget(const QString &id, CNItem *parent, const QRect &r, KtlQCanvas *canvas);
0151     ~Widget() override;
0152 
0153     virtual QWidget *widget() const = 0;
0154     QString id() const
0155     {
0156         return m_id;
0157     }
0158 
0159     /**
0160      * Set the widget enabled/disabled
0161      */
0162     void setEnabled(bool enabled);
0163 
0164     virtual void enterEvent(QEvent *) {};
0165     virtual void leaveEvent(QEvent *) {};
0166 
0167     /**
0168      * Mouse was pressed. pos is given relative to CNItem position.
0169      */
0170     virtual void mousePressEvent(QMouseEvent *e)
0171     {
0172         Q_UNUSED(e);
0173     }
0174     /**
0175      * Mouse was released. pos is given relative to CNItem position.
0176      */
0177     virtual void mouseReleaseEvent(QMouseEvent *e)
0178     {
0179         Q_UNUSED(e);
0180     }
0181     /**
0182      * Mouse was double clicked. pos is given relative to CNItem position.
0183      */
0184     virtual void mouseDoubleClickEvent(QMouseEvent *e)
0185     {
0186         Q_UNUSED(e);
0187     }
0188     /**
0189      * Mouse was moved. pos is given relative to CNItem position.
0190      */
0191     virtual void mouseMoveEvent(QMouseEvent *e)
0192     {
0193         Q_UNUSED(e);
0194     }
0195     /**
0196      * Mouse was scrolled. pos is given relative to CNItem position.
0197      */
0198     virtual void wheelEvent(QWheelEvent *e)
0199     {
0200         Q_UNUSED(e);
0201     }
0202 
0203     void drawShape(QPainter &p) override;
0204 
0205 protected:
0206     void posChanged() override;
0207     QString m_id;
0208 };
0209 
0210 class ToolButton : public QToolButton
0211 {
0212 public:
0213     ToolButton(QWidget *parent);
0214 
0215     void mousePressEvent(QMouseEvent *e) override
0216     {
0217         QToolButton::mousePressEvent(e);
0218     }
0219     void mouseReleaseEvent(QMouseEvent *e) override
0220     {
0221         QToolButton::mouseReleaseEvent(e);
0222     }
0223     void mouseDoubleClickEvent(QMouseEvent *e) override
0224     {
0225         QToolButton::mouseDoubleClickEvent(e);
0226     }
0227     void mouseMoveEvent(QMouseEvent *e) override
0228     {
0229         QToolButton::mouseMoveEvent(e);
0230     }
0231     void wheelEvent(QWheelEvent *e) override
0232     {
0233         QToolButton::wheelEvent(e);
0234     }
0235     void enterEvent(QEvent *) override
0236     {
0237         QToolButton::enterEvent(nullptr);
0238     }
0239     void leaveEvent(QEvent *) override
0240     {
0241         QToolButton::leaveEvent(nullptr);
0242     }
0243 
0244     // Not overriding because it complains about it being wrong for some
0245     // reason, so just wrap the function.
0246     void initStyleOpt(QStyleOptionToolButton *option) const
0247     {
0248         QToolButton::initStyleOption(option);
0249     }
0250 
0251     void setAngleDegrees(int angleDegrees)
0252     {
0253         m_angleDegrees = angleDegrees;
0254     }
0255 
0256 protected:
0257     virtual void drawButtonLabel(QPainter *p);
0258 
0259     int m_angleDegrees;
0260     QFont m_font;
0261 };
0262 
0263 /**
0264 @short Stores internal information about button associated with CNItem
0265 @author David Saxton
0266 */
0267 class Button : public Widget
0268 {
0269     Q_OBJECT
0270 public:
0271     Button(const QString &id, CNItem *parent, bool isToggle, const QRect &r, KtlQCanvas *canvas);
0272     ~Button() override;
0273 
0274     void mousePressEvent(QMouseEvent *e) override;
0275     void mouseReleaseEvent(QMouseEvent *e) override;
0276     void enterEvent(QEvent *) override;
0277     void leaveEvent(QEvent *) override;
0278 
0279     /**
0280      * Set the text displayed inside the button
0281      */
0282     void setText(const QString &text);
0283     void setToggle(bool toggle);
0284     bool isToggle() const
0285     {
0286         return b_isToggle;
0287     }
0288     QWidget *widget() const override;
0289     bool state() const;
0290     void setIcon(const QIcon &);
0291     void setState(bool state);
0292     QRect recommendedRect() const override;
0293 
0294     void drawShape(QPainter &p) override;
0295 
0296 protected:
0297     void posChanged() override;
0298 
0299 private slots:
0300     void slotStateChanged();
0301 
0302 private:
0303     bool b_isToggle; // i.e. whether it should be depressed when the mouse is released
0304     ToolButton *m_button;
0305 };
0306 
0307 class SliderWidget : public QSlider
0308 {
0309 public:
0310     SliderWidget(QWidget *parent);
0311 
0312     void mousePressEvent(QMouseEvent *e) override
0313     {
0314         QSlider::mousePressEvent(e);
0315     }
0316     void mouseReleaseEvent(QMouseEvent *e) override
0317     {
0318         QSlider::mouseReleaseEvent(e);
0319     }
0320     void mouseDoubleClickEvent(QMouseEvent *e) override
0321     {
0322         QSlider::mouseDoubleClickEvent(e);
0323     }
0324     void mouseMoveEvent(QMouseEvent *e) override
0325     {
0326         QSlider::mouseMoveEvent(e);
0327     }
0328     void wheelEvent(QWheelEvent *e) override
0329     {
0330         QSlider::wheelEvent(e);
0331     }
0332     void enterEvent(QEvent *) override
0333     {
0334         QSlider::enterEvent(nullptr);
0335     }
0336     void leaveEvent(QEvent *) override
0337     {
0338         QSlider::leaveEvent(nullptr);
0339     }
0340 
0341     // Not overriding because it complains about it being wrong for some
0342     // reason, so just wrap the function.
0343     void initStyleOpt(QStyleOptionSlider *option) const
0344     {
0345         QSlider::initStyleOption(option);
0346     }
0347 };
0348 
0349 /**
0350 @short Stores internal information about a QSlider associated with CNItem
0351 @author David Saxton
0352 */
0353 class Slider : public Widget
0354 {
0355     Q_OBJECT
0356 public:
0357     Slider(const QString &id, CNItem *parent, const QRect &r, KtlQCanvas *canvas);
0358     ~Slider() override;
0359 
0360     void mousePressEvent(QMouseEvent *e) override;
0361     void mouseReleaseEvent(QMouseEvent *e) override;
0362     void mouseDoubleClickEvent(QMouseEvent *e) override;
0363     void mouseMoveEvent(QMouseEvent *e) override;
0364     void wheelEvent(QWheelEvent *e) override;
0365     void enterEvent(QEvent *) override;
0366     void leaveEvent(QEvent *) override;
0367 
0368     QWidget *widget() const override;
0369     int value() const;
0370     void setValue(int value);
0371     void setOrientation(Qt::Orientation o);
0372 
0373     void drawShape(QPainter &p) override;
0374 
0375 protected:
0376     void posChanged() override;
0377 
0378 private slots:
0379     void slotValueChanged(int value);
0380 
0381 private:
0382     bool m_bSliderInverted; ///< In some orientations, the slider is reflected
0383     SliderWidget *m_slider;
0384     Qt::Orientation m_orientation;
0385 };
0386 
0387 #endif