-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathqmdilib.dox
373 lines (301 loc) · 14.3 KB
/
qmdilib.dox
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
/**
\mainpage qmdilib
This is a simple MDI library for Qt 4/5. The goal of this project, is to provide an easy way to
modifying menus and toolbars of windows on demand. This can be used to present different menus
and toolbars to widgets inside a QTabWidget, hiding or showing a different set of menus on demand
or even enabling a small plugin system.
The library is fully documented, and contains some demonstrations. It should compile flawlessly
(no warnings) with a single "qmake; make" on the root directory of the project. It is known to work
on Windows and Linux, and there is no reason why it should not work on other platforms supported by Qt4/5.
Currently only gcc/clang are tested, but other compilers should be able to compile this library.
\section getting_started Getting started
Click here to see read the \ref small_tutor .
You can also read some documentation about the demos on this version:
- \ref demo1
- \ref demo2
- \ref demo3
You can see the documentation for the classes of this library:
- qmdiClient
- qmdiServer
- qmdiHost
- qmdiActionGroup
The library can be described using this class diagram:
<img src="../qmdilib_basic_view.png">
\section license License of qmdilib
The license of qmdilib is the LGPL 2.1 or 3, which can be found here
http://www.gnu.org/licenses/lgpl.html
You can see the changelog of this library in the \ref changelog
\page small_tutor Small tutorial and introduction
This library contains 3 main classes:
-# an MDI client, a class which inherits qmdiClient
-# an MDI server, for example qmdiServer
-# an MDI host, a class which inherits qmdiHost
The MDI host is generally the main window.
The MDI server is usually a qmdiTabWidget.
The MDI clients are any widget you define, these are the widgets
inserted into the MDI server.
When a new client is selected on the MDI server (for example a users selects
a new tab), the MDI server (qmdiTabWidget or qmdiWorkspace) will try and merge the menus and
toolbars in the MDI client (the widget inside the tab widget) into the MDI host
(the main window). The MDI server will also un-merge the last MDI client from the
MDI host. It also does a few other things behind the scenes, but you don't have
to worry about it.
There are a few steps you should follow to use the library on your application:
-# Inherit the main window from QMainWindow and qmdiHost.
\code
class myWindow: public QMainWindow, public qmdiHost
{
...
};
\endcode \n
-# Into the main window, insert a qmdiTabWidget (instead of a normal QTabWidget)
\code
myWindow *w = new myWindow;
qmdiTabWidget *tab = new qmdiTabWidget(w);
w->setCentralWidget( tab );
\endcode \n
-# Every widget inserted into the tab widget, must also inherit qmdiClient
\code
class myWidget: public QWidget, public qmdiClient
{
...
};
tab->insert( new myWidget );
\endcode \n
-# Menus and toolbars (on the main window, and on the MDI clients) must be defined
using the qmdiActionGroup widget:
\code
QAction *fileNew = new QAction( this, "New" );
menus["&File"]->addAction( fileNew );
toolbars["File"]->addAction( fileNew );
\endcode \n
-# After the menu and toolbar allocations (usually at the constructor of the main
window), don't forget to call updateGUI:
\code
myWindow::myWindow( QWidget *parent ):QMainWindow(parent)
{
// some initializations
...
// generate some QActions
...
updateGUI( this );
}
\endcode
There are some full examples available, please read the code on these examples to get a
full examples.
Go to the \ref index "Main page"
\page demo1 Demo1 - Advanced menus
This first demo is a basic introduction to the concept of qmdiActionGroup, qmdiActionGroupList and qmdiClient.
Some applications have the concept of advanced menus: by default they only display a limited set of
functionality to the user, and only after he chooses they show the full set of commands. This example shows how you
can modify on the fly another set of commands into your application, and do this in your applications.
To do this using plain Qt classes, the way for you to do this is to disable a lot of commands. The setup is
really hard to implement if you want to switch between several states, and implementing a state machine. With
this library, those things can become trivial.
This application also shows how to build qmdilib as part as your application. All you need to do is add the
following lines to your *.pro file:
\code
#include qmdilib project definition
QMDILIB_SRC_DIR = ../../src/
INCLUDEPATH += $$QMDILIB_SRC_DIR
include ($$QMDILIB_SRC_DIR/qmdilib.pri)
# your code
HEADERS += mainwindow.h
SOURCES += mainwindow.cpp main.cpp
\endcode
<img src="../adv-menus-2.jpg">
We start by defining the default menus used on this application, on a main window which derives QMainWindow \b and qmdiHost .
Note that in this example, empty menus are declared in the beginning of the application, otherwise the new menus
would have been appended to the end of the menu bar. The empty menus will not be displayed on the main window.
\code
class MainWindow: public QMainWindow, public qmdiHost
{
Q_OBJECT
public:
MainWindow( QWidget *owner=NULL );
~MainWindow();
private:
QAction *actionQuit;
QAction *actionShowAll;
QAction *actionFileNew, *actionFileSave, *actionFileSaveAs;
QAction *actionAbout, *actionAboutQt;
QAction *test1, *test2;
qmdiClient *advanced;
};
MainWindow::MainWindow( QWidget *owner )
{
menus["&File"]->addAction( actionFileNew );
menus["&File"]->addAction( actionFileSave );
menus["&File"]->addSeparator();
menus["&File"]->addAction( actionQuit );
menus["&Edit"];
menus["&Test"];
menus["&Settings"]->addAction( actionShowAll );
menus["&Help"]->addAction( actionAbout );
// toolbars
toolbars["Main"]->addAction( actionShowAll );
\endcode
and also the advanced menus:
\code
...
advanced = new qmdiClient;
advanced->menus["&File"]->addAction( actionFileSaveAs );
advanced->menus["&Test"]->addAction( test1 );
advanced->menus["&Test"]->addAction( test2 );
advanced->menus["&Help"]->addAction( actionAboutQt );
// extra toolbars
advanced->toolbars["Main"]->addAction( actionQuit );
advanced->toolbars["File operations"]->addAction( test1 );
advanced->toolbars["File operations"]->addAction( test2 );
updateGUI( this );
}
\endcode
Then, all you need to do is merge or un-merge the new client, to add or remove
menus and toolbars from the GUI:
\code
void MainWindow::showMenus()
{
bool isChecked = actionShowAll->isChecked();
if (isChecked)
mergeClient( advanced );
else
unmergeClient( advanced );
// show the stuff on screen
updateGUI( this );
}
\endcode
\see Next: \ref demo2
\page demo2 Demo2 - Using the new tab widget to display dynamic menus
This second demo is an introduction to the qmdiTabWidget and using it in real life applications, which
load several files of the same type.
The Qt libraries have some basic concept of multi document interface, but it gives you tools for doing this
using top level windows. On modern applications we display the documents in QTabWidget and not top level windows.
In theory, you just need to insert the new QWidgets into a QTabWidget, but then you start getting into problems
when you have to synchronize the "save action" to the document currently displayed on the tab widget. The problems
get bigger and harder when you are trying to insert different widget types into the QTabWidget, and you want each
one to display different menus and toolbars.
Using qmdilib you just need to follow a very minimal step to have very rich and dynamic applications. You just need
to define your own QMainWindow as we did on demo1, and instead of using QTabWidget , you need to use qmdiTabWidget.
The widgets inserted into the tab, need also to inherit qmdiClient.
<img src="../mdi-tab-2.jpg">
This demo contains 3 widget types
- A simple QTextBrowser which will display no additional menus and toolbars.
- A new class which inherits QTextEdit and qmdiClient, which gives you a simple text editor with additional menus and toolbars
- A new class which inherits QTextBrowser and qmdiClient, which gives you a simple help browse with additional menus and toolbars
Please note that when you move from one tab to another, the menus and toolbars will change. Sometimes, even if you move
from an editor to another editor, it will look like the toolbars did not change, but what actually happens, is that the
menus and toolbars are re-created on each move, and the QActions on the toolbars belong to the active widget. This means
that each QWidget inserted into the qmdiTabWidget is responsible for it's own actions.
This demo has also some other compile time options. You can compile the demo to use instead
of one toolbar (the default), different toolbars per mdi client. You can also use qmdiWorkspace
instead of qmdiTabWidget. The definitions are in the header of the main window. Plase feel free
to play with them.
Here are the definitions of the new text editor the help viewer and the main window:
\code
class QexHelpBrowser: public QTextBrowser, public qmdiClient
{
...
}
class QexTextEdit : public QTextEdit, public qmdiClient
{
...
}
class MainWindow2: public QMainWindow, public qmdiHost
{
...
}
void MainWindow2::init_gui()
{
// create own menus
menus["&File"]->addAction( actionFileNew );
menus["&File"]->addSeparator();
menus["&File"]->addAction( actionQuit );
menus["&Edit"];
menus["&Navigation"];
menus["&Search"];
menus["&Configuration"];
menus["&Help"]->addAction( actionQtTopics );
menus["&Help"]->addAction( actionAbout );
// toolbars
toolbars["main"]->addAction( actionFileNew );
toolbars["main"]->addAction( actionQtTopics );
// show the stuff on screen
updateGUI( this );
// make the tab widget
tabWidget = new qmdiTabWidget;
tabNewBtn = new QToolButton(tabWidget);
tabNewBtn->setAutoRaise( true );
connect( tabNewBtn, SIGNAL(clicked()), this, SLOT(fileNew()));
tabNewBtn->setIcon(QIcon(":images/addtab.png"));
tabCloseBtn = new QToolButton(tabWidget);
tabCloseBtn->setAutoRaise( true );
connect( tabCloseBtn, SIGNAL(clicked()), this, SLOT(fileClose()));
tabCloseBtn->setIcon(QIcon(":images/closetab.png"));
tabWidget->setCornerWidget( tabNewBtn, Qt::TopLeftCorner );
tabWidget->setCornerWidget( tabCloseBtn, Qt::TopRightCorner );
setCentralWidget( tabWidget );
}
\endcode
\see \ref demo1
\see \ref small_tutor
\see Next: \ref demo3
\page demo3 Demo3 - Usage of QWorkspace inside qmdiTabWidget
Since Version 0.0.3 you can add into a qmdiTabWidget a normal QWorkspace.
If you add to the workspace any widget which also derives qmdiClient, and then
each time a new window is selected on the workspace, it's menus are merged in
and out from the main window.
<img src="../qworkspace-demo2.jpg">
This feature has been written originally by Nox PasNox ([email protected]).
\page changelog ChangeLog
\section v_0_0_5 0.0.5 - 28 Aug 2018 - Diego Iastrubni <[email protected]>
- code is released now under a dual license: (L)GPL 2 or 3
- code refactoring: qmdiClient::mdiClientFileName() should be used instead of old "filename"
- code refactoring: qmdiClient::name has been renamed to qmdiClient::mdiClientName
- code refactoring: include files for qmdiActionGroup and qmdiActionGroupList changed from
actiongroup.h and actiongrouplist.h into qmdiactiongroup.h and qmdiactiongrouplist.h.
Transitional includes have been added, to be removed next version, please update your code.
- new feature: qmdiClient s are notified of (un)merged from a host
- new feature: qmdiTabWidget will hide the tabbar if the number of tabs is less then 2
- new feature: when qmdiHost adds a qmdiClient if that client is also a widget, add it's menus+toolbars actions to the widget.
- new feature: you can tell qmdiHost not to update it's GUI by changing qmdiHost::updateMenusAndToolBars
- build system: redesign the build system to ease the usage of the library inside your application
- build system: building by default shared and static libraries
\section v_0_0_4 0.0.4 - 29 Jun 2007 - Diego Iastrubni <[email protected]>
- Documentation re-created using doxygen 1.4.7
- code refactoring: qmdiClient - qmdiServer is now a public member
- new feature: qmdiActionGroup - added support for submenus
- new feature: qmdiActionGroup - added support for adding QActionGroup
- new feature: qmdiActionGroup - merge points are computed at run time from list of added groups
- code refactoring: qmdiHost - updateGUI can has been updated, see documentation
- code refactoring: qmdiServer - a lot of functions moved from qmdiTabWidget
- code refactoring: qmdiTabWidget contains less implementation details (see qmdiServer)
- code refactoring: qmdiTabBar has been removed, qmdiTabWidget uses an event filter now
- new demo: plugin demo is working now, soon to be ported to the main library
\section v_0_0_3 0.0.3 - 7 Oct 2006 - Diego Iastrubni <[email protected]>
- new feature: QWorkspace children are also checked for qmdiClient interface,
feature coded by Nox PasNox <[email protected]>
- new feature: merge point for qmdiActionGroup
- new class: qmdiWorkspace, a qmdiServer based on QWorkspace
- core refactoring: qmdiClient does not contain QObject *self any more
- code refactoring: qmdiServer now contains a pointer to the host (was in qmdiTabWidget)
- code refactoring: demos should be easier to read, and hopefully maintain
- removed most internal frames from all widgets in demos, the demos will look nicer
- all the documentation has been spell checked
\section v_0_0_2 0.0.2 - 11 Jul 06 - Diego Iastrubni <[email protected]>
* fixed many flickering issues, now it only flicker when you add QWidgets to qmdiActionGroup
* added demos (4 and 5) which demonstrate how to build the code into dynamic and static libraries.
* Documentation updates.
* Compilation problems on mingw fixed since 0.0.2-pre
\section v_0_0_2-pre 0.0.2-pre - 19 Jul 06 - Diego Iastrubni <[email protected]>
- fixed many flickering issues, now it only flicker when you add QWidgets to qmdiActionGroup
- added demos (4 and 5) which demonstrate how to build the code into dynamic and static libraries
\section v_0_0_1 0.0.1 - 11 Jun 06 - Diego Iastrubni <[email protected]>
- initial release
\defgroup read_only_after_constructor After the constructor this is read only
Please change this value \b only when constructing the class, and not during
it's life time. You may consider this a read only variable outside the
constructor.
\defgroup read_only_property Do not modify this variable
This property is public for read only operations, please do not modify it
yourself as the value is change by qmdilib behind the scenes.
*/