├── .gitattributes
├── .gitignore
├── LICENSE
├── README.md
├── Screenshots
├── LibreOffice Writer Properties.png
├── designer_widgetbox.png
├── designer_widgetbox_150x150.png
├── widgetbox_in_qtdesigner.png
├── widgetbox_sample1.png
└── widgetbox_sample2.png
├── Sources
├── CategoryWidgets.cpp
├── CategoryWidgets.h
├── PageEventFilter.cpp
├── PageEventFilter.h
├── WidgetBox.pro
├── collapsed.png
├── expanded.png
├── icons.qrc
├── plugin_export.h
├── widgetbox.cpp
├── widgetbox.h
├── widgetbox.png
├── widgetboxdesignercontainerextension.cpp
├── widgetboxdesignercontainerextension.h
├── widgetboxextensionfactory.cpp
├── widgetboxextensionfactory.h
├── widgetboxplugin.cpp
└── widgetboxplugin.h
└── TODO
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Set the default behavior, in case people don't have core.autocrlf set.
2 | * text=auto
3 |
4 | # Explicitly declare text files you want to always be normalized and converted
5 | # to native line endings on checkout.
6 | *.c text
7 | *.h text
8 |
9 | # Declare files that will always have CRLF line endings on checkout.
10 | *.sln text eol=crlf
11 |
12 | # Denote all files that are truly binary and should not be modified.
13 | *.png binary
14 | *.jpg binary
15 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Qt-es
2 | /.qmake.cache
3 | /.qmake.stash
4 | *.pro.user
5 | *.pro.user.*
6 | *.moc
7 | moc_*.cpp
8 | qrc_*.cpp
9 | ui_*.h
10 | Makefile*
11 | *-build-*
12 |
13 | # QtCreator
14 | *.autosave
15 |
16 | *.user
17 | build-*
18 | release
19 | *.ver
20 | *.o
21 |
22 | # Compiled Object files
23 | *.slo
24 | *.lo
25 | *.o
26 | *.obj
27 |
28 | # Precompiled Headers
29 | *.gch
30 | *.pch
31 |
32 | # Compiled Dynamic libraries
33 | *.so
34 | *.dylib
35 | *.dll
36 |
37 | # Fortran module files
38 | *.mod
39 |
40 | # Compiled Static libraries
41 | *.lai
42 | *.la
43 | *.a
44 | *.lib
45 |
46 | # Executables
47 | *.exe
48 | *.out
49 | *.app
50 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU LESSER GENERAL PUBLIC LICENSE
2 | Version 3, 29 June 2007
3 |
4 | Copyright (C) 2007 Free Software Foundation, Inc.
5 | Everyone is permitted to copy and distribute verbatim copies
6 | of this license document, but changing it is not allowed.
7 |
8 |
9 | This version of the GNU Lesser General Public License incorporates
10 | the terms and conditions of version 3 of the GNU General Public
11 | License, supplemented by the additional permissions listed below.
12 |
13 | 0. Additional Definitions.
14 |
15 | As used herein, "this License" refers to version 3 of the GNU Lesser
16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU
17 | General Public License.
18 |
19 | "The Library" refers to a covered work governed by this License,
20 | other than an Application or a Combined Work as defined below.
21 |
22 | An "Application" is any work that makes use of an interface provided
23 | by the Library, but which is not otherwise based on the Library.
24 | Defining a subclass of a class defined by the Library is deemed a mode
25 | of using an interface provided by the Library.
26 |
27 | A "Combined Work" is a work produced by combining or linking an
28 | Application with the Library. The particular version of the Library
29 | with which the Combined Work was made is also called the "Linked
30 | Version".
31 |
32 | The "Minimal Corresponding Source" for a Combined Work means the
33 | Corresponding Source for the Combined Work, excluding any source code
34 | for portions of the Combined Work that, considered in isolation, are
35 | based on the Application, and not on the Linked Version.
36 |
37 | The "Corresponding Application Code" for a Combined Work means the
38 | object code and/or source code for the Application, including any data
39 | and utility programs needed for reproducing the Combined Work from the
40 | Application, but excluding the System Libraries of the Combined Work.
41 |
42 | 1. Exception to Section 3 of the GNU GPL.
43 |
44 | You may convey a covered work under sections 3 and 4 of this License
45 | without being bound by section 3 of the GNU GPL.
46 |
47 | 2. Conveying Modified Versions.
48 |
49 | If you modify a copy of the Library, and, in your modifications, a
50 | facility refers to a function or data to be supplied by an Application
51 | that uses the facility (other than as an argument passed when the
52 | facility is invoked), then you may convey a copy of the modified
53 | version:
54 |
55 | a) under this License, provided that you make a good faith effort to
56 | ensure that, in the event an Application does not supply the
57 | function or data, the facility still operates, and performs
58 | whatever part of its purpose remains meaningful, or
59 |
60 | b) under the GNU GPL, with none of the additional permissions of
61 | this License applicable to that copy.
62 |
63 | 3. Object Code Incorporating Material from Library Header Files.
64 |
65 | The object code form of an Application may incorporate material from
66 | a header file that is part of the Library. You may convey such object
67 | code under terms of your choice, provided that, if the incorporated
68 | material is not limited to numerical parameters, data structure
69 | layouts and accessors, or small macros, inline functions and templates
70 | (ten or fewer lines in length), you do both of the following:
71 |
72 | a) Give prominent notice with each copy of the object code that the
73 | Library is used in it and that the Library and its use are
74 | covered by this License.
75 |
76 | b) Accompany the object code with a copy of the GNU GPL and this license
77 | document.
78 |
79 | 4. Combined Works.
80 |
81 | You may convey a Combined Work under terms of your choice that,
82 | taken together, effectively do not restrict modification of the
83 | portions of the Library contained in the Combined Work and reverse
84 | engineering for debugging such modifications, if you also do each of
85 | the following:
86 |
87 | a) Give prominent notice with each copy of the Combined Work that
88 | the Library is used in it and that the Library and its use are
89 | covered by this License.
90 |
91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license
92 | document.
93 |
94 | c) For a Combined Work that displays copyright notices during
95 | execution, include the copyright notice for the Library among
96 | these notices, as well as a reference directing the user to the
97 | copies of the GNU GPL and this license document.
98 |
99 | d) Do one of the following:
100 |
101 | 0) Convey the Minimal Corresponding Source under the terms of this
102 | License, and the Corresponding Application Code in a form
103 | suitable for, and under terms that permit, the user to
104 | recombine or relink the Application with a modified version of
105 | the Linked Version to produce a modified Combined Work, in the
106 | manner specified by section 6 of the GNU GPL for conveying
107 | Corresponding Source.
108 |
109 | 1) Use a suitable shared library mechanism for linking with the
110 | Library. A suitable mechanism is one that (a) uses at run time
111 | a copy of the Library already present on the user's computer
112 | system, and (b) will operate properly with a modified version
113 | of the Library that is interface-compatible with the Linked
114 | Version.
115 |
116 | e) Provide Installation Information, but only if you would otherwise
117 | be required to provide such information under section 6 of the
118 | GNU GPL, and only to the extent that such information is
119 | necessary to install and execute a modified version of the
120 | Combined Work produced by recombining or relinking the
121 | Application with a modified version of the Linked Version. (If
122 | you use option 4d0, the Installation Information must accompany
123 | the Minimal Corresponding Source and Corresponding Application
124 | Code. If you use option 4d1, you must provide the Installation
125 | Information in the manner specified by section 6 of the GNU GPL
126 | for conveying Corresponding Source.)
127 |
128 | 5. Combined Libraries.
129 |
130 | You may place library facilities that are a work based on the
131 | Library side by side in a single library together with other library
132 | facilities that are not Applications and are not covered by this
133 | License, and convey such a combined library under terms of your
134 | choice, if you do both of the following:
135 |
136 | a) Accompany the combined library with a copy of the same work based
137 | on the Library, uncombined with any other library facilities,
138 | conveyed under the terms of this License.
139 |
140 | b) Give prominent notice with the combined library that part of it
141 | is a work based on the Library, and explaining where to find the
142 | accompanying uncombined form of the same work.
143 |
144 | 6. Revised Versions of the GNU Lesser General Public License.
145 |
146 | The Free Software Foundation may publish revised and/or new versions
147 | of the GNU Lesser General Public License from time to time. Such new
148 | versions will be similar in spirit to the present version, but may
149 | differ in detail to address new problems or concerns.
150 |
151 | Each version is given a distinguishing version number. If the
152 | Library as you received it specifies that a certain numbered version
153 | of the GNU Lesser General Public License "or any later version"
154 | applies to it, you have the option of following the terms and
155 | conditions either of that published version or of any later version
156 | published by the Free Software Foundation. If the Library as you
157 | received it does not specify a version number of the GNU Lesser
158 | General Public License, you may choose any version of the GNU Lesser
159 | General Public License ever published by the Free Software Foundation.
160 |
161 | If the Library as you received it specifies that a proxy can decide
162 | whether future versions of the GNU Lesser General Public License shall
163 | apply, that proxy's public statement of acceptance of any version is
164 | permanent authorization for you to choose that version for the
165 | Library.
166 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # WidgetBox
2 | Widget Box is a Qt widget which contains a list of widgets (pages) separated by categories
3 |
4 | Widget similar to the Widget Box in the Qt Designer.
5 |
6 | 
7 |
8 | It contains a list of widgets (pages) separated by categories. Each category button can be clicked in order to expand and collapse the list below the button. Sample screenshots on moment of uploading to GitHub:
9 |
10 |  
11 |
--------------------------------------------------------------------------------
/Screenshots/LibreOffice Writer Properties.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akontsevich/WidgetBox/408fcb38270c1696ecbd66ad8a3bb512202f00be/Screenshots/LibreOffice Writer Properties.png
--------------------------------------------------------------------------------
/Screenshots/designer_widgetbox.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akontsevich/WidgetBox/408fcb38270c1696ecbd66ad8a3bb512202f00be/Screenshots/designer_widgetbox.png
--------------------------------------------------------------------------------
/Screenshots/designer_widgetbox_150x150.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akontsevich/WidgetBox/408fcb38270c1696ecbd66ad8a3bb512202f00be/Screenshots/designer_widgetbox_150x150.png
--------------------------------------------------------------------------------
/Screenshots/widgetbox_in_qtdesigner.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akontsevich/WidgetBox/408fcb38270c1696ecbd66ad8a3bb512202f00be/Screenshots/widgetbox_in_qtdesigner.png
--------------------------------------------------------------------------------
/Screenshots/widgetbox_sample1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akontsevich/WidgetBox/408fcb38270c1696ecbd66ad8a3bb512202f00be/Screenshots/widgetbox_sample1.png
--------------------------------------------------------------------------------
/Screenshots/widgetbox_sample2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akontsevich/WidgetBox/408fcb38270c1696ecbd66ad8a3bb512202f00be/Screenshots/widgetbox_sample2.png
--------------------------------------------------------------------------------
/Sources/CategoryWidgets.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | #include "widgetbox.h"
4 | #include "CategoryWidgets.h"
5 | #include "PageEventFilter.h"
6 |
7 | /**
8 | * @class AbstractCategoryButton is abstract ancestor class for all categories
9 | * widgets types
10 | * @brief AbstractCategoryButton::AbstractCategoryButton
11 | */
12 |
13 | AbstractCategory::AbstractCategory(const QString &, QTreeWidget *parent,
14 | QTreeWidgetItem *item)
15 | : QWidget(parent)
16 | , mItem(item)
17 | , mEventFilter(new PageEventFilter(this, item))
18 | {
19 | mItem->setExpanded(true);
20 | connect(mEventFilter, SIGNAL(itemClicked(QTreeWidgetItem*,int)), SLOT(onButtonPress()));
21 | }
22 |
23 | void AbstractCategory::onButtonPress()
24 | {
25 | setExpanded(!mItem->isExpanded());
26 | }
27 |
28 | void AbstractCategory::onPageExpand(bool expanded)
29 | {
30 | mItem->setExpanded(expanded);
31 | int index = mItem->treeWidget()->indexOfTopLevelItem(mItem);
32 | ((WidgetBox *)mItem->treeWidget()->parent())->setCurrentIndex(index);
33 |
34 | emit pageExpanded(isExpanded());
35 | }
36 |
37 | int AbstractCategory::itemIndex() const
38 | {
39 | return mItem->treeWidget()->indexOfTopLevelItem(mItem);
40 | }
41 |
42 | /**
43 | * @class PageButton
44 | * @brief The PageButton class: page (category) button for widget box
45 | */
46 | ButtonCategory::ButtonCategory(const QString &text, QTreeWidget *parent,
47 | QTreeWidgetItem *item)
48 | : AbstractCategory(text, parent, item)
49 |
50 | {
51 | mButton = new QPushButton(text, parent);
52 | mButton->installEventFilter(eventFilter()); // Send mouse events to tree widget
53 | // Prefix __qt__passive_ enables mouse events for widget in Qt Designer
54 | mButton->setObjectName(QString("__qt__passive_ButtonCategory%1").arg(itemIndex()));
55 |
56 | QHBoxLayout *horizontalLayout = new QHBoxLayout(this);
57 | horizontalLayout->setSpacing(0);
58 | horizontalLayout->setContentsMargins(0, 0, 0, 0);
59 | horizontalLayout->addWidget(mButton); // Add button to layout
60 |
61 | mButton->setIcon(QIcon(":/plugins/widgetbox/expanded.png"));
62 | // setFlat(true);
63 |
64 | mButton->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
65 | QFontMetrics fm(font());
66 | mButton->resize(size().width(), fm.height());
67 | }
68 |
69 | void ButtonCategory::setTitle(QString const &title)
70 | {
71 | mButton->setText(title);
72 | }
73 |
74 | void ButtonCategory::onButtonPress()
75 | {
76 | AbstractCategory::onButtonPress();
77 |
78 | if(isExpanded()) {
79 | mButton->setIcon(QIcon(":/plugins/widgetbox/expanded.png"));
80 | } else {
81 | mButton->setIcon(QIcon(":/plugins/widgetbox/collapsed.png"));
82 | }
83 | }
84 |
85 | LineCategory::LineCategory(const QString &text, QTreeWidget *parent, QTreeWidgetItem *item)
86 | : AbstractCategory(text, parent, item)
87 | {
88 | QHBoxLayout *horizontalLayout = new QHBoxLayout(this);
89 | horizontalLayout->setSpacing(4);
90 | horizontalLayout->setContentsMargins(0, 0, 6, 0);
91 |
92 | mCheckBox = new QCheckBox(this);
93 | mCheckBox->setChecked(true);
94 | mCheckBox->installEventFilter(eventFilter()); // Send mouse events to tree widget
95 | horizontalLayout->addWidget(mCheckBox); // Add checkbox to layout
96 | // Prefix __qt__passive_ enables mouse events for widget in Qt Designer
97 | mCheckBox->setObjectName(QString("__qt__passive_CheckBox%1").arg(itemIndex()));
98 |
99 | QFrame *line1 = new QFrame(this);
100 | line1->installEventFilter(eventFilter()); // Send mouse events to tree widget
101 | // Prefix __qt__passive_ enables mouse events for widget in Qt Designer
102 | line1->setObjectName(QString("__qt__passive_line1_%1").arg(itemIndex()));
103 | QSizePolicy sizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
104 | sizePolicy.setHorizontalStretch(0);
105 | sizePolicy.setVerticalStretch(0);
106 | sizePolicy.setHeightForWidth(line1->sizePolicy().hasHeightForWidth());
107 | line1->setSizePolicy(sizePolicy);
108 | line1->setFrameShadow(QFrame::Plain);
109 | line1->setLineWidth(1);
110 | line1->setMidLineWidth(1);
111 | line1->setFrameShape(QFrame::HLine);
112 | horizontalLayout->addWidget(line1); // Add line1 to layout
113 |
114 | mLabel = new QLabel(text, this);
115 | mLabel->installEventFilter(eventFilter()); // Send mouse events to tree widget
116 | // Prefix __qt__passive_ enables mouse events for widget in Qt Designer
117 | mLabel->setObjectName(QString("__qt__passive_Label%1").arg(itemIndex()));
118 | QSizePolicy sizePolicy1(QSizePolicy::Minimum, QSizePolicy::Preferred);
119 | sizePolicy1.setHorizontalStretch(0);
120 | sizePolicy1.setVerticalStretch(0);
121 | sizePolicy1.setHeightForWidth(mLabel->sizePolicy().hasHeightForWidth());
122 | mLabel->setSizePolicy(sizePolicy1);
123 | horizontalLayout->addWidget(mLabel); // Add label to layout
124 |
125 | QFrame *line2 = new QFrame(this);
126 | line2->installEventFilter(eventFilter()); // Send mouse events to tree widget
127 | // Prefix __qt__passive_ enables mouse events for widget in Qt Designer
128 | line2->setObjectName(QString("__qt__passive_line2_%1").arg(itemIndex()));
129 | sizePolicy.setHeightForWidth(line2->sizePolicy().hasHeightForWidth());
130 | line2->setSizePolicy(sizePolicy);
131 | line2->setFrameShadow(QFrame::Plain);
132 | line2->setLineWidth(1);
133 | line2->setMidLineWidth(1);
134 | line2->setFrameShape(QFrame::HLine);
135 | horizontalLayout->addWidget(line2); // Add line2 to layout
136 | }
137 |
138 | void LineCategory::setExpanded(bool expanded)
139 | {
140 | AbstractCategory::setExpanded(expanded);
141 | mCheckBox->setChecked(expanded);
142 | }
143 |
144 | void LineCategory::setTitle(QString const &title)
145 | {
146 | mLabel->setText(title);
147 | }
148 |
--------------------------------------------------------------------------------
/Sources/CategoryWidgets.h:
--------------------------------------------------------------------------------
1 | #ifndef CATEGORYWIDGETS_H
2 | #define CATEGORYWIDGETS_H
3 |
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 |
10 | class PageEventFilter;
11 |
12 | class AbstractCategory : public QWidget
13 | {
14 | Q_OBJECT
15 | public:
16 | AbstractCategory(const QString &text, QTreeWidget *parent, QTreeWidgetItem *item);
17 | bool isExpanded() const { return mItem->isExpanded(); }
18 | virtual QString title() const = 0;
19 |
20 | public slots:
21 | virtual void setTitle(QString const &title) = 0;
22 | virtual void setExpanded(bool expanded) { onPageExpand(expanded); }
23 |
24 | protected:
25 | QTreeWidgetItem *item() const { return mItem; }
26 | PageEventFilter *eventFilter() const { return mEventFilter; }
27 | int itemIndex() const;
28 |
29 | signals:
30 | void pageExpanded(bool expanded);
31 |
32 | protected slots:
33 | virtual void onButtonPress();
34 | void onPageExpand(bool expanded = false);
35 |
36 | private:
37 | QTreeWidgetItem* mItem;
38 | PageEventFilter *mEventFilter;
39 | };
40 |
41 | class ButtonCategory : public AbstractCategory
42 | {
43 | Q_OBJECT
44 | public:
45 | ButtonCategory(const QString &text, QTreeWidget *parent, QTreeWidgetItem *item);
46 | QString title() const override { return mButton->text(); }
47 |
48 | public slots:
49 | void setTitle(QString const &title) override;
50 |
51 | private slots:
52 | void onButtonPress() override;
53 |
54 | private:
55 | QPushButton *mButton;
56 | };
57 |
58 | class LineCategory : public AbstractCategory
59 | {
60 | Q_OBJECT
61 | public:
62 | LineCategory(const QString &text, QTreeWidget *parent, QTreeWidgetItem *item);
63 | QString title() const override { return mLabel->text(); }
64 |
65 | public slots:
66 | void setTitle(QString const &title) override;
67 | void setExpanded(bool expanded) override;
68 |
69 | private:
70 | QLabel *mLabel;
71 | QCheckBox *mCheckBox;
72 | };
73 |
74 | #endif // CATEGORYWIDGETS_H
75 |
--------------------------------------------------------------------------------
/Sources/PageEventFilter.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | #include "PageEventFilter.h"
5 |
6 |
7 | /*!
8 | * \class propagates mouse press event filter to parent QTreeWidget
9 | */
10 |
11 | PageEventFilter::PageEventFilter(QObject *parent, QTreeWidgetItem *item)
12 | : QObject(parent)
13 | , mItem(item)
14 | {
15 | connect(this, SIGNAL(itemClicked(QTreeWidgetItem*,int)),
16 | mItem->treeWidget(), SIGNAL(itemClicked(QTreeWidgetItem*,int)));
17 | }
18 |
19 | bool PageEventFilter::eventFilter(QObject *obj, QEvent *event)
20 | {
21 | if (event->type() == QEvent::MouseButtonPress)
22 | {
23 | // Resend signal to QTreeWidget
24 | emit itemClicked(mItem, 0);
25 | return true; // Filter event to the object
26 | }
27 | else
28 | {
29 | // standard event processing
30 | return QObject::eventFilter(obj, event);
31 | }
32 | }
33 |
34 | /*!
35 | * \class PageResizeFilter provides event filter to change item size hint in
36 | * Qt Designer on page widget resize as seems QTreeWidgetItem knows nothing
37 | * about its widget in design time and does not automatically adjust item
38 | * size like it does in run-time
39 | */
40 |
41 | PageResizeFilter::PageResizeFilter(QObject *parent, QTreeWidgetItem *item)
42 | : QObject(parent)
43 | , mItem(item)
44 | {
45 | }
46 |
47 | /*!
48 | * \brief PageResizeFilter::eventFilter changes item size hint in Qt Designer
49 | * on page widget resize as seems QTreeWidgetItem knows nothing about its
50 | * widget in design time and does not automatically adjust item size
51 | * like it does in run-time
52 | * \param obj page widget to filter QEvent::Resize
53 | * \param event
54 | * \return false to continue event processing by page widget
55 | */
56 | bool PageResizeFilter::eventFilter(QObject *obj, QEvent *event)
57 | {
58 | if (event->type() == QEvent::Resize)
59 | {
60 | QWidget *page = ((QWidget *)obj);
61 | mItem->setSizeHint(0, page->geometry().size());
62 | return false; // Sent event to the object (do not filter it)
63 | }
64 | else
65 | {
66 | // standard event processing
67 | return QObject::eventFilter(obj, event);
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/Sources/PageEventFilter.h:
--------------------------------------------------------------------------------
1 | #ifndef PAGEEVENTFILTER_H
2 | #define PAGEEVENTFILTER_H
3 |
4 | #include
5 |
6 | class QTreeWidgetItem;
7 |
8 | class PageEventFilter : public QObject
9 | {
10 | Q_OBJECT
11 | public:
12 | PageEventFilter(QObject *parent, QTreeWidgetItem *item);
13 |
14 | protected:
15 | bool eventFilter(QObject *obj, QEvent *event);
16 |
17 | signals:
18 | void itemClicked(QTreeWidgetItem *item, int column);
19 |
20 | private:
21 | QTreeWidgetItem *mItem;
22 | };
23 |
24 |
25 | class PageResizeFilter : public QObject
26 | {
27 | Q_OBJECT
28 | public:
29 | PageResizeFilter(QObject *parent, QTreeWidgetItem *item);
30 |
31 | protected:
32 | bool eventFilter(QObject *obj, QEvent *event);
33 |
34 | private:
35 | QTreeWidgetItem *mItem;
36 | };
37 |
38 | #endif // PAGEEVENTFILTER_H
39 |
--------------------------------------------------------------------------------
/Sources/WidgetBox.pro:
--------------------------------------------------------------------------------
1 | CONFIG += plugin debug_and_release
2 | TARGET = $$qtLibraryTarget(WidgetBoxPlugin)
3 | TEMPLATE = lib
4 |
5 | HEADERS = widgetboxplugin.h widgetbox.h \
6 | widgetboxextensionfactory.h \
7 | widgetboxdesignercontainerextension.h \
8 | CategoryWidgets.h \
9 | plugin_export.h \
10 | PageEventFilter.h
11 |
12 | SOURCES = widgetboxplugin.cpp widgetbox.cpp \
13 | widgetboxextensionfactory.cpp \
14 | widgetboxdesignercontainerextension.cpp \
15 | CategoryWidgets.cpp \
16 | PageEventFilter.cpp
17 |
18 | RESOURCES = icons.qrc
19 | LIBS += -L.
20 |
21 | greaterThan(QT_MAJOR_VERSION, 4) {
22 | QT += designer
23 | } else {
24 | CONFIG += designer
25 | }
26 |
27 | target.path = $$[QT_INSTALL_PLUGINS]/designer
28 |
29 | creator_target.name = Copying the target dll to Qt Creator plugins directory as well
30 | creator_target.input = $qtLbraryTarget(WidgetBoxPlugin)
31 | creator_target.path = $$(QTCREATOR_BIN_PATH)/plugins/designer
32 | creator_target.CONFIG += no_check_exist
33 | creator_target.output = WidgetBoxPlugin.dll
34 | win32:creator_target.files = $$OUT_PWD/release/WidgetBoxPlugin.dll
35 | else:unix:creator_target.files = $$OUT_PWD/release/libWidgetBoxPlugin.so
36 | QMAKE_EXTRA_COMPILERS += creator_target
37 |
38 | INSTALLS += target creator_target
39 |
--------------------------------------------------------------------------------
/Sources/collapsed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akontsevich/WidgetBox/408fcb38270c1696ecbd66ad8a3bb512202f00be/Sources/collapsed.png
--------------------------------------------------------------------------------
/Sources/expanded.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akontsevich/WidgetBox/408fcb38270c1696ecbd66ad8a3bb512202f00be/Sources/expanded.png
--------------------------------------------------------------------------------
/Sources/icons.qrc:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | collapsed.png
6 | expanded.png
7 | widgetbox.png
8 |
9 |
10 |
--------------------------------------------------------------------------------
/Sources/plugin_export.h:
--------------------------------------------------------------------------------
1 | #ifndef PLUGIN_EXPORT_H
2 | #define PLUGIN_EXPORT_H
3 |
4 | #include
5 |
6 | #include
7 | #include
8 | #include
9 | #include
10 |
11 | #ifdef QT_PLUGIN
12 | #define PLUGIN_EXPORT QDESIGNER_WIDGET_EXPORT
13 | #else
14 | #define PLUGIN_EXPORT
15 | #endif // QT_PLUGIN
16 |
17 | #endif // PLUGIN_EXPORT_H
18 |
--------------------------------------------------------------------------------
/Sources/widgetbox.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 |
6 | #include "widgetbox.h"
7 | #include "CategoryWidgets.h"
8 | #include "PageEventFilter.h"
9 |
10 | /*!
11 | * \class WidgetBox
12 | * \brief The WidgetBox class: Widget similar to the Widget Box in the Qt Designer.
13 | * It contains a list of widgets (pages) separated by categories. Each category
14 | * can be clicked in order to expand and collapse the list below the category.
15 | *
16 | */
17 |
18 | WidgetBox::WidgetBox(QWidget *parent) : QWidget(parent)
19 | {
20 | // Set default tree widget settings
21 | mTreeWidget = new QTreeWidget(this);
22 | mTreeWidget->setFrameStyle(QFrame::NoFrame);
23 | mTreeWidget->setAnimated(true);
24 | mTreeWidget->setVerticalScrollMode(QTreeWidget::ScrollPerPixel);
25 | mTreeWidget->header()->hide();
26 | mTreeWidget->setRootIsDecorated(false);
27 | mTreeWidget->setIndentation(0);
28 | mTreeWidget->setUniformRowHeights(false);
29 | mTreeWidget->setSelectionMode(QAbstractItemView::NoSelection);
30 | mTreeWidget->setExpandsOnDoubleClick(false);
31 |
32 | // Make tree widget same color as normal widget
33 | QPalette pal = mTreeWidget->palette();
34 | pal.setColor(QPalette::Base, palette().background().color());
35 | mTreeWidget->setPalette(pal);
36 |
37 | // Create WidgetBox layout
38 | QBoxLayout* layout = new QVBoxLayout(this);
39 | layout->setContentsMargins(0, 0, 0, 0);
40 | layout->addWidget(mTreeWidget);
41 |
42 | connect(mTreeWidget, SIGNAL(itemClicked(QTreeWidgetItem*, int)),
43 | SLOT(onItemClicked(QTreeWidgetItem*, int)));
44 | connect(mTreeWidget, SIGNAL(itemActivated(QTreeWidgetItem*, int)),
45 | SLOT(onItemClicked(QTreeWidgetItem*, int)));
46 | }
47 | WidgetBox::~WidgetBox()
48 | {
49 | delete mSheet;
50 | }
51 |
52 |
53 | #if defined(QT_PLUGIN)
54 | QSize WidgetBox::sizeHint() const
55 | {
56 | return QSize(130, 210);
57 | }
58 | #endif
59 |
60 | /*!
61 | * \brief WidgetBox::createCategory create page category widget
62 | * \param page page item
63 | * \param pageName page name to display in category
64 | */
65 | void WidgetBox::createCategory(QTreeWidgetItem* page, QString pageName)
66 | {
67 | AbstractCategory *category;
68 | switch (mCategoryType)
69 | {
70 | case Button:
71 | category = new ButtonCategory(pageName, mTreeWidget, page);
72 | break;
73 | case Line:
74 | category = new LineCategory(pageName, mTreeWidget, page);
75 | break;
76 | default:
77 | category = new ButtonCategory(pageName, mTreeWidget, page);
78 | break;
79 | }
80 | // Set new item widget: Qt removes old widget automatically, no need to delete old one
81 | mTreeWidget->setItemWidget(page, 0, category);
82 | // Change property in Designer on page expand/unexpand
83 | connect(category, SIGNAL(pageExpanded(bool)), SLOT(setPageExpandedProperty()));
84 | }
85 |
86 | /*!
87 | * \brief WidgetBox::recreateCategories recreates categories widgets if
88 | * categoryType was changed
89 | */
90 | void WidgetBox::recreateCategories()
91 | {
92 | for(int i = 0; i < count(); i++)
93 | {
94 | QString pageName = pageTitle(i);
95 | bool expanded = isPageExpanded(i);
96 | // Qt removes old widget automatically, no need to delete old one
97 | createCategory(mTreeWidget->topLevelItem(i), pageName);
98 | category(i)->setExpanded(expanded);
99 | }
100 | }
101 |
102 | void WidgetBox::setCategoryType(const CategoryType type)
103 | {
104 | mCategoryType = type;
105 | recreateCategories();
106 | }
107 |
108 |
109 | QTreeWidgetItem * WidgetBox::addCategory(QString pageName)
110 | {
111 | return insertCategory(count(), pageName);
112 | }
113 |
114 | /**
115 | * @brief WidgetBox::setupWidget set default widget properties
116 | * @param widget
117 | */
118 | void WidgetBox::setupWidget(QWidget *widget)
119 | {
120 | // The given widget's autoFillBackground property must be set to true,
121 | // otherwise the widget's background will be transparent,
122 | // showing both the model data and the tree widget item.
123 | widget->setAutoFillBackground(true);
124 | widget->setPalette(palette());
125 | widget->setBackgroundRole(backgroundRole());
126 | widget->setStyle(style()); // Set parent widget style
127 | }
128 |
129 | void WidgetBox::createContainerWidget(QTreeWidgetItem* page, QWidget *widget)
130 | {
131 | QTreeWidgetItem* container = new QTreeWidgetItem();
132 | container->setDisabled(true);
133 | page->addChild(container);
134 | mTreeWidget->setItemWidget(container, 0, widget);
135 | setupWidget(widget);
136 |
137 | // Send mouse events from page widget to tree widget
138 | PageEventFilter *eventFilter = new PageEventFilter(this, container);
139 | widget->installEventFilter(eventFilter);
140 | widget->setObjectName(QString("__qt__passive_Page%1").arg(count() + 1));
141 |
142 | #if defined(QT_PLUGIN)
143 | QSize size(mTreeWidget->width(), mTreeWidget->width() / 1.618);
144 | container->setSizeHint(0, size);
145 | widget->resize(size);
146 | // Change item size hint in Qt Designer on page widget resize
147 | // as seems QTreeWidgetItem knows nothing about its widget in design time
148 | // and does not automatically adjust item size like it does in run-time
149 | PageResizeFilter *filter = new PageResizeFilter(this, container);
150 | widget->installEventFilter(filter);
151 | #endif
152 | }
153 |
154 | void WidgetBox::addPage(QWidget *widget)
155 | {
156 | insertPage(count(), widget);
157 | }
158 |
159 | QTreeWidgetItem * WidgetBox::insertCategory(int index, QString pageName)
160 | {
161 | QTreeWidgetItem* page = new QTreeWidgetItem();
162 | mTreeWidget->insertTopLevelItem(index, page);
163 | createCategory(page, pageName);
164 |
165 | return page;
166 | }
167 |
168 | void WidgetBox::insertPage(int index, QWidget *widget)
169 | {
170 | if (index < 0 || index > count())
171 | return;
172 |
173 | // Set default page name
174 | QString pageName = widget->windowTitle();
175 | if (pageName.isEmpty())
176 | {
177 | pageName = tr("Page %1").arg(count() + 1);
178 | widget->setWindowTitle(pageName);
179 | }
180 |
181 | QTreeWidgetItem* page = insertCategory(index, pageName);
182 | createContainerWidget(page, widget);
183 |
184 | connect(widget, SIGNAL(windowTitleChanged(QString)),
185 | category(index), SLOT(setTitle(QString)));
186 | }
187 |
188 | void WidgetBox::removePage(int index)
189 | {
190 | QTreeWidgetItem *topLevelItem = mTreeWidget->topLevelItem(index);
191 | if (!topLevelItem)
192 | return;
193 |
194 | if (topLevelItem->childCount() > 0)
195 | mTreeWidget->removeItemWidget(topLevelItem->child(0), 0);
196 | mTreeWidget->removeItemWidget(topLevelItem, 0);
197 |
198 | delete topLevelItem;
199 | }
200 |
201 | int WidgetBox::currentIndex() const
202 | {
203 | if(count() > 0) {
204 | return mTreeWidget->currentIndex().row();
205 | } else {
206 | return -1;
207 | }
208 | }
209 |
210 | void WidgetBox::setCurrentIndex(int index)
211 | {
212 | if (index != currentIndex() && checkIndex(index))
213 | {
214 | mTreeWidget->setCurrentItem(mTreeWidget->topLevelItem(index));
215 | emit currentIndexChanged(index);
216 | }
217 | }
218 |
219 | bool WidgetBox::checkIndex(int index) const
220 | {
221 | return index >= 0 && index < count();
222 | }
223 |
224 | QWidget *WidgetBox::page(int index) const
225 | {
226 | if(checkIndex(index))
227 | {
228 | QTreeWidgetItem* page = mTreeWidget->topLevelItem(index);
229 | return mTreeWidget->itemWidget(page->child(0), 0);
230 | }
231 | else
232 | {
233 | return 0;
234 | }
235 | }
236 |
237 | QWidget* WidgetBox::widget(int index) const
238 | {
239 | return page(index);
240 | }
241 |
242 | void WidgetBox::setPageTitle(QString const &newTitle)
243 | {
244 | if (checkIndex(currentIndex()))
245 | {
246 | category(currentIndex())->setTitle(newTitle);
247 | // Qt doc: use QWidget::windowTitle property to store the page title.
248 | // Note that currently there is no way of adding a custom property
249 | // (e.g., a page title) to the pages without using a predefined property as placeholder.
250 | page(currentIndex())->setWindowTitle(newTitle);
251 | emit pageTitleChanged(newTitle);
252 | }
253 | }
254 |
255 | /*!
256 | * \brief WidgetBox::pageTitle Current page title
257 | * \return
258 | */
259 | QString WidgetBox::pageTitle() const
260 | {
261 | return pageTitle(currentIndex());
262 | }
263 |
264 | /*!
265 | * \brief WidgetBox::pageTitle page title
266 | * \param index page index
267 | * \return
268 | */
269 | QString WidgetBox::pageTitle(int index) const
270 | {
271 | if (checkIndex(index))
272 | {
273 | return category(index)->title();
274 | }
275 | else
276 | {
277 | return QString();
278 | }
279 | }
280 |
281 | AbstractCategory *WidgetBox::category(int index) const
282 | {
283 | return (AbstractCategory *)mTreeWidget->itemWidget(mTreeWidget->topLevelItem(index), 0);
284 | }
285 |
286 |
287 | /*!
288 | * \brief WidgetBox::isPageExpanded Checks current page is expanded
289 | * \return
290 | */
291 | bool WidgetBox::isPageExpanded() const
292 | {
293 | return isPageExpanded(currentIndex());
294 | }
295 |
296 | /*!
297 | * \brief WidgetBox::isPageExpanded Checks page with given index is expanded
298 | * \param index page index
299 | * \return true if specified page expanded
300 | */
301 | bool WidgetBox::isPageExpanded(int index) const
302 | {
303 | if (checkIndex(index))
304 | {
305 | return category(index)->isExpanded();
306 | }
307 | else
308 | {
309 | return false;
310 | }
311 | }
312 |
313 | void WidgetBox::setPageExpandedProperty()
314 | {
315 | changeQtDesignerProperty("isPageExpanded", isPageExpanded(currentIndex()), true);
316 | }
317 |
318 | void WidgetBox::setPageExpanded(bool expanded)
319 | {
320 | if(checkIndex(currentIndex()))
321 | {
322 | setPageExpanded(currentIndex(), expanded);
323 | setPageExpandedProperty();
324 | }
325 | }
326 |
327 | void WidgetBox::setPageExpanded(int index, bool expanded)
328 | {
329 | if(checkIndex(index)) category(index)->setExpanded(expanded);
330 | }
331 |
332 | int WidgetBox::getPageIndex(QTreeWidgetItem *item)
333 | {
334 | if (!item) return -1;
335 |
336 | QTreeWidgetItem *parent = item->parent();
337 | if(parent) // Parent is top level item
338 | {
339 | return mTreeWidget->indexOfTopLevelItem(parent);
340 | }
341 | else // Current item is top level
342 | {
343 | return item->treeWidget()->indexOfTopLevelItem(item);
344 | }
345 | }
346 |
347 | void WidgetBox::onItemClicked(QTreeWidgetItem *item, int )
348 | {
349 | int index = getPageIndex(item);
350 | setCurrentIndex(index);
351 |
352 | changeQtDesignerProperty("currentIndex", index);
353 | }
354 |
355 | void WidgetBox::changeQtDesignerProperty(QString propertyName, QVariant value,
356 | bool markChangedOnly)
357 | {
358 | #if defined(QT_PLUGIN)
359 | QDesignerFormWindowInterface *form =
360 | QDesignerFormWindowInterface::findFormWindow(this);
361 |
362 | if(form)
363 | {
364 | if(!mSheet) // Need to create sheet only once
365 | {
366 | QDesignerFormEditorInterface *editor = form->core();
367 | QExtensionManager *manager = editor->extensionManager();
368 | mSheet = qt_extension(manager, this);
369 | }
370 | // Set property in Qt Designer
371 | int propertyIndex = mSheet->indexOf(propertyName);
372 | if(!markChangedOnly) mSheet->setProperty(propertyIndex, value);
373 | mSheet->setChanged(propertyIndex, true);
374 | }
375 | #else
376 | Q_UNUSED(propertyName);
377 | Q_UNUSED(value);
378 | Q_UNUSED(markChangedOnly);
379 | #endif
380 | }
381 |
--------------------------------------------------------------------------------
/Sources/widgetbox.h:
--------------------------------------------------------------------------------
1 | #ifndef WIDGETBOX_H
2 | #define WIDGETBOX_H
3 |
4 | #include
5 | #include
6 | #include
7 | #include "plugin_export.h"
8 |
9 | class AbstractCategory;
10 |
11 | class PLUGIN_EXPORT WidgetBox : public QWidget
12 | {
13 | Q_OBJECT
14 | Q_PROPERTY(int currentIndex READ currentIndex WRITE setCurrentIndex)
15 | Q_PROPERTY(QString pageTitle READ pageTitle WRITE setPageTitle STORED true)
16 | Q_PROPERTY(bool isPageExpanded READ isPageExpanded WRITE setPageExpanded)
17 | Q_PROPERTY(CategoryType categoryType READ categoryType WRITE setCategoryType)
18 | Q_ENUMS(CategoryType)
19 |
20 | public:
21 | enum CategoryType {
22 | Button,
23 | Line,
24 | Frame // TODO
25 | };
26 |
27 | WidgetBox(QWidget *parent = 0);
28 | ~WidgetBox();
29 |
30 | CategoryType categoryType() const { return mCategoryType; }
31 | void setCategoryType(const CategoryType type);
32 |
33 | #if defined(QT_PLUGIN)
34 | QSize sizeHint() const Q_DECL_OVERRIDE;
35 | #endif
36 |
37 | int count() const { return mTreeWidget->topLevelItemCount(); }
38 | QWidget *page(int index) const;
39 | QWidget *widget(int index) const;
40 | QString pageTitle() const;
41 | QString pageTitle(int index) const;
42 | bool isPageExpanded() const;
43 | bool isPageExpanded(int index) const;
44 | int currentIndex() const;
45 |
46 | public slots:
47 | void setCurrentIndex(int index);
48 |
49 | void addPage(QWidget *widget);
50 | void insertPage(int index, QWidget *widget);
51 | void removePage(int index);
52 |
53 | void setPageTitle(QString const &newTitle);
54 | void setPageExpanded(bool expanded);
55 | void setPageExpanded(int index, bool expanded);
56 |
57 | protected:
58 | QTreeWidgetItem * addCategory(QString pageName);
59 | QTreeWidgetItem * insertCategory(int index, QString pageName);
60 |
61 | AbstractCategory *category(int index) const;
62 |
63 | void createContainerWidget(QTreeWidgetItem* page, QWidget *widget);
64 | void createCategory(QTreeWidgetItem* page, QString pageName);
65 |
66 | void changeQtDesignerProperty(QString propertyName, QVariant value,
67 | bool markChangedOnly = false);
68 |
69 | protected slots:
70 | void onItemClicked(QTreeWidgetItem *item, int);
71 | void setPageExpandedProperty();
72 |
73 | signals:
74 | void currentIndexChanged(int index);
75 | void pageTitleChanged(const QString &title);
76 |
77 | private:
78 | bool checkIndex(int index) const;
79 | void setupWidget(QWidget *widget);
80 | int getPageIndex(QTreeWidgetItem *item);
81 | void recreateCategories();
82 |
83 | QTreeWidget *mTreeWidget;
84 | CategoryType mCategoryType = Button;
85 | // Necessary only in Qt Designer
86 | QDesignerPropertySheetExtension *mSheet = 0;
87 | };
88 |
89 | #endif
90 |
--------------------------------------------------------------------------------
/Sources/widgetbox.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akontsevich/WidgetBox/408fcb38270c1696ecbd66ad8a3bb512202f00be/Sources/widgetbox.png
--------------------------------------------------------------------------------
/Sources/widgetboxdesignercontainerextension.cpp:
--------------------------------------------------------------------------------
1 | #include "widgetbox.h"
2 | #include "widgetboxdesignercontainerextension.h"
3 |
4 |
5 | WidgetBoxDesignerContainerExtension::WidgetBoxDesignerContainerExtension(WidgetBox *widget,
6 | QObject *parent)
7 | : QObject(parent)
8 | , mWidgetBox(widget)
9 | {
10 | }
11 |
12 | void WidgetBoxDesignerContainerExtension::addWidget(QWidget *widget)
13 | {
14 | mWidgetBox->addPage(widget);
15 | }
16 |
17 | int WidgetBoxDesignerContainerExtension::count() const
18 | {
19 | return mWidgetBox->count();
20 | }
21 |
22 | int WidgetBoxDesignerContainerExtension::currentIndex() const
23 | {
24 | return mWidgetBox->currentIndex();
25 | }
26 |
27 | void WidgetBoxDesignerContainerExtension::insertWidget(int index, QWidget *widget)
28 | {
29 | mWidgetBox->insertPage(index, widget);
30 | }
31 |
32 | void WidgetBoxDesignerContainerExtension::remove(int index)
33 | {
34 | mWidgetBox->removePage(index);
35 | }
36 |
37 | void WidgetBoxDesignerContainerExtension::setCurrentIndex(int index)
38 | {
39 | mWidgetBox->setCurrentIndex(index);
40 | }
41 |
42 | QWidget* WidgetBoxDesignerContainerExtension::widget(int index) const
43 | {
44 | return mWidgetBox->widget(index);
45 | }
46 |
--------------------------------------------------------------------------------
/Sources/widgetboxdesignercontainerextension.h:
--------------------------------------------------------------------------------
1 | #ifndef WIDGETBOXDESIGNERCONTAINEREXTENSION_H
2 | #define WIDGETBOXDESIGNERCONTAINEREXTENSION_H
3 |
4 | #include
5 |
6 | QT_BEGIN_NAMESPACE
7 | class QExtensionManager;
8 | QT_END_NAMESPACE
9 | class WidgetBox;
10 |
11 | class WidgetBoxDesignerContainerExtension : public QObject,
12 | public QDesignerContainerExtension
13 | {
14 | Q_OBJECT
15 | Q_INTERFACES(QDesignerContainerExtension)
16 |
17 | public:
18 | explicit WidgetBoxDesignerContainerExtension(WidgetBox *widget, QObject *parent);
19 |
20 | void addWidget(QWidget *widget) Q_DECL_OVERRIDE;
21 | int count() const Q_DECL_OVERRIDE;
22 | int currentIndex() const Q_DECL_OVERRIDE;
23 | void insertWidget(int index, QWidget *widget) Q_DECL_OVERRIDE;
24 | void remove(int index) Q_DECL_OVERRIDE;
25 | void setCurrentIndex(int index) Q_DECL_OVERRIDE;
26 | QWidget *widget(int index) const Q_DECL_OVERRIDE;
27 |
28 | private:
29 | WidgetBox *mWidgetBox;
30 | };
31 |
32 | #endif // WIDGETBOXDESIGNERCONTAINEREXTENSION_H
33 |
--------------------------------------------------------------------------------
/Sources/widgetboxextensionfactory.cpp:
--------------------------------------------------------------------------------
1 | #include "widgetbox.h"
2 | #include "widgetboxextensionfactory.h"
3 | #include "widgetboxdesignercontainerextension.h"
4 |
5 |
6 | WidgetBoxExtensionFactory::WidgetBoxExtensionFactory(QExtensionManager *parent)
7 | : QExtensionFactory(parent)
8 | {
9 |
10 | }
11 |
12 | QObject *WidgetBoxExtensionFactory::createExtension(QObject *object,
13 | const QString &iid,
14 | QObject *parent) const
15 | {
16 | WidgetBox *widget = qobject_cast(object);
17 |
18 | if (widget && (iid == Q_TYPEID(QDesignerContainerExtension)))
19 | {
20 | return new WidgetBoxDesignerContainerExtension(widget, parent);
21 | }
22 | else
23 | {
24 | return 0;
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Sources/widgetboxextensionfactory.h:
--------------------------------------------------------------------------------
1 | #ifndef WIDGETBOXEXTENSIONFACTORY_H
2 | #define WIDGETBOXEXTENSIONFACTORY_H
3 |
4 | #include
5 |
6 | class WidgetBoxExtensionFactory : public QExtensionFactory
7 | {
8 | Q_OBJECT
9 |
10 | public:
11 | WidgetBoxExtensionFactory(QExtensionManager *parent = 0);
12 |
13 | protected:
14 | QObject *createExtension(QObject *object, const QString &iid, QObject *parent) const Q_DECL_OVERRIDE;
15 | };
16 |
17 | #endif // WIDGETBOXEXTENSIONFACTORY_H
18 |
--------------------------------------------------------------------------------
/Sources/widgetboxplugin.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 |
8 | #include
9 |
10 | #include "widgetbox.h"
11 | #include "widgetboxplugin.h"
12 | #include "widgetboxextensionfactory.h"
13 |
14 |
15 | WidgetBoxPlugin::WidgetBoxPlugin(QObject *parent)
16 | : QObject(parent)
17 | {
18 | mInitialized = false;
19 | }
20 |
21 | void WidgetBoxPlugin::initialize(QDesignerFormEditorInterface *formEditor)
22 | {
23 | if (mInitialized)
24 | return;
25 |
26 | // Add extension registrations, etc. here
27 | QExtensionManager *manager = formEditor->extensionManager();
28 | QExtensionFactory *factory = new WidgetBoxExtensionFactory(manager);
29 |
30 | Q_ASSERT(manager != 0);
31 | manager->registerExtensions(factory, Q_TYPEID(QDesignerContainerExtension));
32 |
33 | mInitialized = true;
34 | }
35 |
36 | bool WidgetBoxPlugin::isInitialized() const
37 | {
38 | return mInitialized;
39 | }
40 |
41 | QWidget *WidgetBoxPlugin::createWidget(QWidget *parent)
42 | {
43 | WidgetBox *widget = new WidgetBox(parent);
44 |
45 | connect(widget, &WidgetBox::currentIndexChanged,
46 | this, &WidgetBoxPlugin::currentIndexChanged);
47 | connect(widget, &WidgetBox::pageTitleChanged,
48 | this, &WidgetBoxPlugin::pageTitleChanged);
49 |
50 | return widget;
51 | }
52 |
53 | QString WidgetBoxPlugin::name() const
54 | {
55 | return QLatin1String("WidgetBox");
56 | }
57 |
58 | QString WidgetBoxPlugin::group() const
59 | {
60 | return QLatin1String("Containers");
61 | }
62 |
63 | QIcon WidgetBoxPlugin::icon() const
64 | {
65 | return QIcon(":/plugins/widgetbox/widgetbox.png");
66 | }
67 |
68 | QString WidgetBoxPlugin::toolTip() const
69 | {
70 | return QLatin1String("Widget Box is a Qt widget which contains a list of "
71 | "widgets (pages) separated by categories");
72 | }
73 |
74 | QString WidgetBoxPlugin::whatsThis() const
75 | {
76 | return QLatin1String("Widget similar to the Widget Box in the Qt Designer. "
77 | "It contains a list of widgets (pages) separated by "
78 | "categories. Each category button can be clicked in "
79 | "order to expand and collapse the list below the button.");
80 | }
81 |
82 | bool WidgetBoxPlugin::isContainer() const
83 | {
84 | return true;
85 | }
86 |
87 | QString WidgetBoxPlugin::domXml() const
88 | {
89 | return QLatin1String("\
90 | \
91 | \
92 | \
93 | \
94 | 0\
95 | 0\
96 | 130\
97 | 210\
98 | \
99 | \
100 | \
101 | \
102 | \
103 | WidgetBox\
104 | QWidget\
105 | addPage\
106 | \
107 | \
108 | ");
109 | }
110 |
111 | QString WidgetBoxPlugin::includeFile() const
112 | {
113 | return QLatin1String("widgetbox.h");
114 | }
115 |
116 | void WidgetBoxPlugin::currentIndexChanged(int index)
117 | {
118 | Q_UNUSED(index);
119 | WidgetBox *widget = qobject_cast(sender());
120 |
121 | if(widget)
122 | {
123 | QDesignerFormWindowInterface *form = QDesignerFormWindowInterface::findFormWindow(widget);
124 | if(form)
125 | form->emitSelectionChanged();
126 | }
127 | }
128 |
129 | void WidgetBoxPlugin::pageTitleChanged(const QString &title)
130 | {
131 | Q_UNUSED(title);
132 | WidgetBox *widget = qobject_cast(sender());
133 |
134 | if(widget)
135 | {
136 | QWidget *page = widget->widget(widget->currentIndex());
137 | QDesignerFormWindowInterface *form;
138 | form = QDesignerFormWindowInterface::findFormWindow(widget);
139 |
140 | if(form)
141 | {
142 | QDesignerFormEditorInterface *editor = form->core();
143 | QExtensionManager *manager = editor->extensionManager();
144 |
145 | QDesignerPropertySheetExtension *sheet;
146 | sheet = qt_extension(manager, page);
147 | const int propertyIndex = sheet->indexOf(QLatin1String("windowTitle"));
148 | sheet->setChanged(propertyIndex, true);
149 | }
150 | }
151 | }
152 |
153 | #if QT_VERSION < 0x050000
154 | Q_EXPORT_PLUGIN2(WidgetBoxPlugin, WidgetBoxPlugin)
155 | #endif // QT_VERSION < 0x050000
156 |
--------------------------------------------------------------------------------
/Sources/widgetboxplugin.h:
--------------------------------------------------------------------------------
1 | #ifndef WIDGETBOXPLUGIN_H
2 | #define WIDGETBOXPLUGIN_H
3 |
4 | #include
5 |
6 | class WidgetBoxPlugin : public QObject, public QDesignerCustomWidgetInterface
7 | {
8 | Q_OBJECT
9 | Q_INTERFACES(QDesignerCustomWidgetInterface)
10 | #if QT_VERSION >= 0x050000
11 | Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QDesignerCustomWidgetInterface")
12 | #endif // QT_VERSION >= 0x050000
13 |
14 | public:
15 | WidgetBoxPlugin(QObject *parent = 0);
16 |
17 | bool isContainer() const;
18 | bool isInitialized() const;
19 | QIcon icon() const;
20 | QString domXml() const;
21 | QString group() const;
22 | QString includeFile() const;
23 | QString name() const;
24 | QString toolTip() const;
25 | QString whatsThis() const;
26 | QWidget *createWidget(QWidget *parent);
27 | void initialize(QDesignerFormEditorInterface *formEditor);
28 |
29 | private slots:
30 | void currentIndexChanged(int index);
31 | void pageTitleChanged(const QString &title);
32 |
33 | private:
34 | bool mInitialized;
35 | };
36 |
37 | #endif
38 |
--------------------------------------------------------------------------------
/TODO:
--------------------------------------------------------------------------------
1 | * Fix isPageExpanded propery change in Qt Designer
2 |
3 | * Style category button (or panel) closer to Qt Creator (Designer) look
4 | or like to LibreOffice Writer Properties Tool Box on the right side
5 |
6 | Hope for community participation on these improvements.
7 |
--------------------------------------------------------------------------------