summaryrefslogtreecommitdiffstats
path: root/doc/src/examples/diagramscene.qdoc
blob: 623587b0b1854e3817bd2851ff563821d73d14a4 (plain)
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
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the documentation of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

/*!
    \example graphicsview/diagramscene
    \title Diagram Scene Example
    
    This example shows use of Qt's graphics framework. 

    \image diagramscene.png

    The Diagram Scene example is an application in which you can
    create a flowchart diagram. It is possible to add flowchart shapes
    and text and connect the shapes by arrows as shown in the image
    above.  The shapes, arrows, and text can be given different
    colors, and it is possible to change the font, style, and
    underline of the text.

    The Qt graphics view framework is designed to manage and
    display custom 2D graphics items. The main classes of the
    framework are QGraphicsItem, QGraphicsScene and QGraphicsView. The
    graphics scene manages the items and provides a surface for them.
    QGraphicsView is a widget that is used to render a scene on the
    screen. See the \l{The Graphics View Framework}{overview document}
    for a more detailed description of the framework. 

    In this example we show how to create such custom graphics
    scenes and items by implementing classes that inherit
    QGraphicsScene and QGraphicsItem. 

    In particular we show how to:

    \list
	\o Create custom graphics items.
	\o Handle mouse events and movement of items.
	\o Implement a graphics scene that can manage our custom items.
	\o Custom painting of items.
	\o Create a movable and editable text item.
    \endlist

    The example consists of the following classes:
    \list
	\o \c MainWindow creates the widgets and display
	   them in a QMainWindow. It also manages the interaction 
	   between the widgets and the graphics scene, view and 
	   items.
	\o \c DiagramItem inherits QGraphicsPolygonItem and
	   represents a flowchart shape. 
	\o \c TextDiagramItem inherits QGraphicsTextItem and
	   represents text items in the diagram. The class adds
	   support for moving the item with the mouse, which is not
	   supported by QGraphicsTextItem.
	\o \c Arrow inherits QGraphicsLineItem and is an arrow
	   that connect two DiagramItems. 
	\o \c DiagramScene inherits QGraphicsDiagramScene and
	   provides support for \c DiagramItem, \c Arrow and 
	   \c DiagramTextItem (In addition to the support already
	   handled by QGraphicsScene).
    \endlist

    \section1 MainWindow Class Definition

    \snippet examples/graphicsview/diagramscene/mainwindow.h 0

    The \c MainWindow class creates and lays out the widgets in a
    QMainWindow. The class forwards input from the widgets to the
    DiagramScene. It also updates its widgets when the diagram 
    scene's text item changes, or a diagram item or a diagram text item
    is inserted into the scene.

    The class also deletes items from the scene and handles the
    z-ordering, which decides the order in which items are drawn when
    they overlap each other.

    \section1 MainWindow Class Implementation


    We start with a look at the constructor:

    \snippet examples/graphicsview/diagramscene/mainwindow.cpp 0

    In the constructor we call methods to create the widgets and
    layouts of the example before we create the diagram scene. 
    The toolbars must be created after the scene as they connect 
    to its signals. We then lay the widgets out in the window.

    We connect to the \c itemInserted() and \c textInserted() slots of
    the diagram scenes as we want to uncheck the buttons in the tool
    box when an item is inserted. When an item is selected in
    the scene we receive the \c itemSelected() signal. We use this to
    update the widgets that display font properties if the item
    selected is a \c DiagramTextItem.

    The \c createToolBox() function creates and lays out the widgets 
    of the \c toolBox QToolBox. We will not examine it with a
    high level of detail as it does not deal with graphics framework 
    specific functionality. Here is its implementation:

    \snippet examples/graphicsview/diagramscene/mainwindow.cpp 21
    
    This part of the function sets up the tabbed widget item that
    contains the flowchart shapes. An exclusive QButtonGroup always 
    keeps one button checked; we want the group to allow all buttons
    to be unchecked.
    We still use a button group since we can associate user
    data, which we use to store the diagram type, with each button. 
    The \c createCellWidget() function sets up the buttons in the 
    tabbed widget item and is examined later.

    The buttons of the background tabbed widget item is set up in the
    same way, so we skip to the creation of the tool box:

    \snippet examples/graphicsview/diagramscene/mainwindow.cpp 22

    We set the preferred size of the toolbox as its maximum. This
    way, more space is given to the graphics view. 

    Here is the \c createActions() function:

    \snippet examples/graphicsview/diagramscene/mainwindow.cpp 23

    We show an example of the creation of an action. The
    functionality the actions trigger is discussed in the slots we
    connect the actions to. You can see the \l{Application
    Example}{application example} if you need a high-level
    introduction to actions.

    The is the \c createMenus() function:

    \snippet examples/graphicsview/diagramscene/mainwindow.cpp 24

    We create the three menus' of the example.

    The \c createToolbars() function sets up the examples tool
    bars.  The three \l{QToolButton}s in the \c colorToolBar, the \c
    fontColorToolButton, \c fillColorToolButton, and \c
    lineColorToolButton, are interesting as we create icons for them
    by drawing on a QPixmap with a QPainter. We show how the \c
    fillColorToolButton is created. This button lets the user select a
    color for the diagram items.

    \snippet examples/graphicsview/diagramscene/mainwindow.cpp 25
    \dots
    \snippet examples/graphicsview/diagramscene/mainwindow.cpp 26

    We set the menu of the tool button with
    \l{QToolButton::}{setMenu()}. We need the \c fillAction QAction
    object to always be pointing to the selected action of the menu.
    The menu is created with the \c createColorMenu() function and, as
    we shall see later, contains one menu item for each color that the
    items can have.  When the user presses the button, which trigger
    the \l{QToolButton::}{clicked()} signal, we can set the color of
    the selected item to the color of \c fillAction. It is with \c
    createColorToolButtonIcon() we create the icon for the button.

    \dots
    \snippet examples/graphicsview/diagramscene/mainwindow.cpp 27

    Here is the \c createBackgroundCellWidget() function:

    \snippet examples/graphicsview/diagramscene/mainwindow.cpp 28

    This function creates \l{QWidget}s containing a tool button
    and a label. The widgets created with this function are used for
    the background tabbed widget item in the tool box.

    Here is the \c createCellWidget() function:

    \snippet examples/graphicsview/diagramscene/mainwindow.cpp 29

    This function returns a QWidget containing a QToolButton with
    an image of one of the \c DiagramItems, i.e., flowchart shapes.
    The image is created by the \c DiagramItem through the \c image()
    function.  The QButtonGroup class lets us attach a QVariant with
    each button; we store the diagram's type, i.e., the
    DiagramItem::DiagramType enum. We use the stored diagram type when
    we create new diagram items for the scene.  The widgets created
    with this function is used in the tool box.

    Here is the \c createColorMenu() function:
    
    \snippet examples/graphicsview/diagramscene/mainwindow.cpp 30

    This function creates a color menu that is used as the
    drop-down menu for the tool buttons in the \c colorToolBar. We
    create an action for each color that we add to the menu. We fetch
    the actions data when we set the color of items, lines, and text.

    Here is the \c createColorToolButtonIcon() function:

    \snippet examples/graphicsview/diagramscene/mainwindow.cpp 31

    This function is used to create the QIcon of the \c
    fillColorToolButton, \c fontColorToolButton, and \c
    lineColorToolButton. The \a imageFile string is either the text,
    flood-fill, or line symbol that is used for the buttons. Beneath
    the image we draw a filled rectangle using \a color.

    Here is the \c createColorIcon() function:

    \snippet examples/graphicsview/diagramscene/mainwindow.cpp 32

    This function creates an icon with a filled rectangle in the 
    color of \a color. It is used for creating icons for the color
    menus in the \c fillColorToolButton, \c fontColorToolButton, and
    \c lineColorToolButton.

    Here is the \c backgroundButtonGroupClicked() slot:

    \snippet examples/graphicsview/diagramscene/mainwindow.cpp 1

    In this function we set the QBrush that is used to draw the
    background of the diagramscene. The background can be a grid of
    squares of blue, gray, or white tiles, or no grid at all. We have
    \l{QPixmap}s of the tiles from png files that we create the brush
    with.

    When one of the buttons in the background tabbed widget item is
    clicked we change the brush; we find out which button it is by 
    checking its text. 

    Here is the implementation of \c buttonGroupClicked():

    \snippet examples/graphicsview/diagramscene/mainwindow.cpp 2

    This slot is called when a button in \c buttonGroup is checked.
    When a button is checked the user can click on the graphics view
    and a \c DiagramItem of the selected type will be inserted into
    the \c DiagramScene. We must loop through the buttons in the group
    to uncheck other buttons as only one button is allowed to be
    checked at a time.

    \c QButtonGroup assigns an id to each button. We have set the id
    of each button to the diagram type, as given by DiagramItem::DiagramType 
    that will be inserted into the scene when it is clicked. We can 
    then use the button id when we set the diagram type with 
    \c setItemType(). In the case of text we assigned an id that has a
    value that is not in the DiagramType enum.
    
    Here is the implementation of \c deleteItem():
    
    \snippet examples/graphicsview/diagramscene/mainwindow.cpp 3
    
    This slot deletes the selected item, if any, from the scene. If
    the item to be deleted is a \c DiagramItem, we also need to delete
    arrows connected to it; we don't want arrows in the scene that
    aren't connected to items in both ends.
    
    This is the implementation of pointerGroupClicked():
    
    \snippet examples/graphicsview/diagramscene/mainwindow.cpp 4
    
    The \c pointerTypeGroup decides whether the scene is in ItemMove
    or InsertLine mode. This button group is exclusive, i.e., only 
    one button is checked at any time. As with the \c buttonGroup above
    we have assigned an id to the buttons that matches values of the
    DiagramScene::Mode enum, so that we can use the id to set the
    correct mode.
    
    Here is the \c bringToFront() slot:
    
    \snippet examples/graphicsview/diagramscene/mainwindow.cpp 5
    
    Several items may collide, i.e., overlap, with each other in
    the scene.  This slot is called when the user requests that an
    item should be placed on top of the items it collides with.
    \l{QGraphicsItem}{QGrapicsItems} have a z-value that decides the
    order in which items are stacked in the scene; you can think of it
    as the z-axis in a 3D coordinate system.  When items collide the
    items with higher z-values will be drawn on top of items with
    lower values. When we bring an item to the front we can loop
    through the items it collides with and set a z-value that is
    higher than all of them.
    
    Here is the \c sendToBack() slot:
    
    \snippet examples/graphicsview/diagramscene/mainwindow.cpp 6
    
    This slot works in the same way as \c bringToFront() described
    above, but sets a z-value that is lower than items the item that
    should be send to the back collides with.
    
    This is the implementation of \c itemInserted():
    
    \snippet examples/graphicsview/diagramscene/mainwindow.cpp 7
    
    This slot is called from the \c DiagramScene when an item has been
    added to the scene. We set the mode of the scene back to the mode
    before the item was inserted, which is ItemMove or InsertText
    depending on which button is checked in the \c pointerTypeGroup. 
    We must also uncheck the button in the in the \c buttonGroup.
    
    Here is the implementation of \c textInserted():
    
    \snippet examples/graphicsview/diagramscene/mainwindow.cpp 8
    
    We simply set the mode of the scene back to the mode it had before
    the text was inserted.
    
    Here is the \c currentFontChanged() slot:
    
    \snippet examples/graphicsview/diagramscene/mainwindow.cpp 9
    
    When the user requests a font change, by using one of the
    widgets in the \c fontToolBar, we create a new QFont object and
    set its properties to match the state of the widgets. This is done
    in \c handleFontChange(), so we simply call that slot.
    
    Here is the \c fontSizeChanged() slot:
    
    \snippet examples/graphicsview/diagramscene/mainwindow.cpp 10
    
    When the user requests a font change, by using one of the
    widgets in the \c fontToolBar, we create a new QFont object and
    set its properties to match the state of the widgets. This is done
    in \c handleFontChange(), so we simply call that slot.
    
    Here is the implementation of \c sceneScaleChanged():
    
    \snippet examples/graphicsview/diagramscene/mainwindow.cpp 11
    
    The user can increase or decrease the scale, with the \c
    sceneScaleCombo, the scene is drawn in.
    It is not the scene itself that changes its scale, but only the
    view.  
    
    Here is the \c textColorChanged() slot:
    
    \snippet examples/graphicsview/diagramscene/mainwindow.cpp 12
    
    This slot is called when an item in the drop-down menu of the \c
    fontColorToolButton is pressed. We need to change the icon on 
    the button to the color of the selected QAction. We keep a pointer
    to the selected action in \c textAction. It is in \c
    textButtonTriggered() we change the text color to the color of \c
    textAction, so we call that slot.
    
    Here is the \c itemColorChanged() implementation:
    
    \snippet examples/graphicsview/diagramscene/mainwindow.cpp 13
    
    This slot handles requests for changing the color of \c
    DiagramItems in the same manner as \c textColorChanged() does for
    \c DiagramTextItems.
    
    Here is the implementation of \c lineColorChanged():
    
    \snippet examples/graphicsview/diagramscene/mainwindow.cpp 14
    
    This slot handles requests for changing the color of \c Arrows in
    the same manner that \c textColorChanged() does it for \c
    DiagramTextItems.
    
    Here is the \c textButtonTriggered() slot:
    
    \snippet examples/graphicsview/diagramscene/mainwindow.cpp 15
    
    \c textAction points to the  QAction of the currently selected menu item
    in the \c fontColorToolButton's color drop-down menu. We have set
    the data of the action to the QColor the action represents, so we
    can simply fetch this when we set the color of text with \c
    setTextColor().
    
    Here is the \c fillButtonTriggered() slot:
    
    \snippet examples/graphicsview/diagramscene/mainwindow.cpp 16
    
    \c fillAction points to the selected menu item in the drop-down
    menu of \c fillColorToolButton(). We can therefore use the data of
    this action when we set the item color with \c setItemColor().
    
    Here is the \c lineButtonTriggered() slot:
    
    \snippet examples/graphicsview/diagramscene/mainwindow.cpp 17
    
    \c lineAction point to the selected item in the drop-down menu of
    \c lineColorToolButton. We use its data when we set the arrow 
    color with \c setLineColor().
    
    Here is the \c handleFontChange() function:
    
    \snippet examples/graphicsview/diagramscene/mainwindow.cpp 18
    
    \c handleFontChange() is called when any of the widgets that show
    font properties changes. We create a new QFont object and set its
    properties based on the widgets. We then call the \c setFont()
    function of \c DiagramScene; it is the scene that set the font of
    the \c DiagramTextItems it manages.
    
    Here is the \c itemSelected() slot:
    
    \snippet examples/graphicsview/diagramscene/mainwindow.cpp 19
    
    This slot is called when an item in the \c DiagramScene is
    selected. In the case of this example it is only text items that
    emit signals when they are selected, so we do not need to check
    what kind of graphics \a item is.
    
    We set the state of the widgets to match the properties of the
    font of the selected text item.
    
    This is the \c about() slot:
    
    \snippet examples/graphicsview/diagramscene/mainwindow.cpp 20
    
    This slot displays an about box for the example when the user
    selects the about menu item from the help menu.
    
    \section1 DiagramScene Class Definition
    
    The \c DiagramScene class inherits QGraphicsScene and adds
    functionality to handle \c DiagramItems, \c Arrows, and \c
    DiagramTextItems in addition to the items handled by its super
    class.
    
    
    \snippet examples/graphicsview/diagramscene/diagramscene.h 0
    
    In the \c DiagramScene a mouse click can give three different
    actions: the item under the mouse can be moved, an item may be
    inserted, or an arrow may be connected between to diagram items.
    Which action a mouse click has depends on the mode, given by the
    Mode enum, the scene is in. The mode is set with the \c setMode()
    function.
    
    The scene also sets the color of its items and the font of its
    text items.  The colors and font used by the scene can be set with
    the \c setLineColor(), \c setTextColor(), \c setItemColor() and \c
    setFont() functions. The type of \c DiagramItem, given by the
    DiagramItem::DiagramType function, to be created when an item is
    inserted is set with the \c setItemType() slot.
    
    The \c MainWindow and \c DiagramScene share responsibility for
    the examples functionality. \c MainWindow handles the following
    tasks: the deletion of items, text, and arrows; moving diagram
    items to the back and front; and setting the scale of the scene. 

    \section1 DiagramScene Class Implementation


    We start with the constructor:

    \snippet examples/graphicsview/diagramscene/diagramscene.cpp 0

    The scene uses \c myItemMenu to set the context menu when it
    creates \c DiagramItems. We set the default mode to \c
    DiagramScene::MoveItem as this gives the default behavior of
    QGraphicsScene.

    Here is the \c setLineColor() function:

    \snippet examples/graphicsview/diagramscene/diagramscene.cpp 1

    The \c isItemChange function returns true if an \c Arrow item is
    selected in the scene in which case we want to change its color.
    When the \c DiagramScene creates and adds new arrows to the scene
    it will also use the new \a color.

    Here is the \c setTextColor() function:

    \snippet examples/graphicsview/diagramscene/diagramscene.cpp 2

    This function sets the color of \c DiagramTextItems equal to the
    way \c setLineColor() sets the color of \c Arrows.

    Here is the \c setItemColor() function:

    \snippet examples/graphicsview/diagramscene/diagramscene.cpp 3

    This function sets the color the scene will use when creating 
    \c DiagramItems. It also changes the color of a selected \c
    DiagramItem.

    This is the implementation of \c setFont():
    
    \snippet examples/graphicsview/diagramscene/diagramscene.cpp 4

    Set the font to use for new and selected, if a text item is
    selected, \c DiagramTextItems.

    This is the implementation of \c editorLostFocus() slot:

    \snippet examples/graphicsview/diagramscene/diagramscene.cpp 5

    \c DiagramTextItems emit a signal when they loose focus, which is
    connected to this slot. We remove the item if it has no text.
    If not, we would leak memory and confuse the user as the items
    will be edited when pressed on by the mouse.
    
    The \c mousePressEvent() function handles mouse press event's
    different depending on which mode the \c DiagramScene is in. We
    examine its implementation for each mode:
    
    \snippet examples/graphicsview/diagramscene/diagramscene.cpp 6

    We simply create a new \c DiagramItem and add it to the scene at
    the position the mouse was pressed. Note that the origin of its 
    local coordinate system will be under the mouse pointer position.

    \snippet examples/graphicsview/diagramscene/diagramscene.cpp 7

    The user adds \c Arrows to the scene by stretching a line between
    the items the arrow should connect. The start of the line is fixed
    in the place the user clicked the mouse and the end follows the
    mouse pointer as long as the button is held down. When the user
    releases the mouse button an \c Arrow will be added to the scene
    if there is a \c DiagramItem under the start and end of the line.
    We will see how this is implemented later; here we simply add the
    line.

    \snippet examples/graphicsview/diagramscene/diagramscene.cpp 8
    
    The \c DiagramTextItem is editable when the
    Qt::TextEditorInteraction flag is set, else it is movable by the
    mouse. We always want the text to be drawn on top of the other
    items in the scene, so we set the value to a number higher
    than other items in the scene.

    \snippet examples/graphicsview/diagramscene/diagramscene.cpp 9

    We are in MoveItem mode if we get to the default switch; we
    can then call the QGraphicsScene implementation, which
    handles movement of items with the mouse. We make this call even
    if we are in another mode making it possible to add an item and
    then keep the mouse button pressed down and start moving 
    the item. In the case of text items, this is not possible as they
    do not propagate mouse events when they are editable.

    This is the \c mouseMoveEvent() function:
    
    \snippet examples/graphicsview/diagramscene/diagramscene.cpp 10

    We must draw the line if we are in InsertMode and the mouse button
    is pressed down (the line is not 0). As discussed in \c
    mousePressEvent() the line is drawn from the position the mouse
    was pressed to the current position of the mouse.

    If we are in MoveItem mode, we call the QGraphicsScene
    implementation, which handles movement of items.

    In the \c mouseReleaseEvent() function we need to check if an arrow
    should be added to the scene:

    \snippet examples/graphicsview/diagramscene/diagramscene.cpp 11
    
    First we need to get the items (if any) under the line's start
    and end points. The line itself is the first item at these points,
    so we remove it from the lists. As a precaution, we check if the
    lists are empty, but this should never happen.

    \snippet examples/graphicsview/diagramscene/diagramscene.cpp 12

    Now we check if there are two different \c DiagramItems under
    the lines start and end points. If there are we can create an \c
    Arrow with the two items. The arrow is then added to each item and
    finally the scene. The arrow must be updated to adjust its start
    and end points to the items. We set the z-value of the arrow to
    -1000.0 because we always want it to be drawn under the items.

    \snippet examples/graphicsview/diagramscene/diagramscene.cpp 13

    Here is the \c isItemChange() function:

    \snippet examples/graphicsview/diagramscene/diagramscene.cpp 14

    The scene has single selection, i.e., only one item can be
    selected at any given time. The foreach will then loop one time
    with the selected item or none if no item is selected. \c
    isItemChange() is used to check whether a selected item exists
    and also is of the specified diagram \a type.

    \section1 DiagramItem Class Definition


    \snippet examples/graphicsview/diagramscene/diagramitem.h 0

    The \c DiagramItem represents a flowchart shape in the \c
    DiagramScene. It inherits QGraphicsPolygonItem and has a polygon
    for each shape. The enum DiagramType has a value for each of the
    flowchart shapes.
    
    The class has a list of the arrows that are connected to it.
    This is necessary because only the item knows when it is being
    moved (with the \c itemChanged() function) at which time the
    arrows must be updated. The item can also draw itself onto a
    QPixmap with the \c image() function. This is used for the tool
    buttons in \c MainWindow, see \c createColorToolButtonIcon() in
    \c MainWindow.

    The Type enum is a unique identifier of the class. It is used by 
    \c qgraphicsitem_cast(), which does dynamic casts of graphics
    items. The UserType constant is the minimum value a custom
    graphics item type can be.

    \section1 DiagramItem Class Implementation


    We start with a look at the constructor:

    \snippet examples/graphicsview/diagramscene/diagramitem.cpp 0

    In the constructor we create the items polygon according to
    \a diagramType. \l{QGraphicsItem}s are not movable or selectable
    by default, so we must set these properties.

    Here is the \c removeArrow() function:

    \snippet examples/graphicsview/diagramscene/diagramitem.cpp 1

    \c removeArrow() is used to remove \c Arrow items when they
    or \c DiagramItems they are connected to are removed from the
    scene.

    Here is the \c removeArrows() function:

    \snippet examples/graphicsview/diagramscene/diagramitem.cpp 2

    This function is called when the item is removed from the scene
    and removes all arrows that are connected to this item. The arrow
    must be removed from the \c arrows list of both its start and end
    item.

    Here is the \c addArrow() function:
    
    \snippet examples/graphicsview/diagramscene/diagramitem.cpp 3

    This function simply adds the \a arrow to the items \c arrows list.

    Here is the \c image() function:

    \snippet examples/graphicsview/diagramscene/diagramitem.cpp 4

    This function draws the polygon of the item onto a QPixmap. In
    this example we use this to create icons for the tool buttons in
    the tool box.

    Here is the \c contextMenuEvent() function:

    \snippet examples/graphicsview/diagramscene/diagramitem.cpp 5

    We show the context menu. As right mouse clicks, which shows the
    menu, don't select items by default we set the item selected with
    \l{QGraphicsItem::}{setSelected()}. This is necessary since an
    item must be selected to change its elevation with the
    \c bringToFront and \c sendToBack actions.

    This is the implementation of \c itemChange():

    \snippet examples/graphicsview/diagramscene/diagramitem.cpp 6

    If the item has moved, we need to update the positions of the
    arrows connected to it. The implementation of QGraphicsItem does
    nothing, so we just return \a value.

    \section1 DiagramTextItem Class Definition

    The \c TextDiagramItem class inherits QGraphicsTextItem and
    adds the possibility to move editable text items. Editable
    QGraphicsTextItems are designed to be fixed in place and editing
    starts when the user single clicks on the item. With \c
    DiagramTextItem the editing starts with a double click leaving
    single click available to interact with and move it.

    \snippet examples/graphicsview/diagramscene/diagramtextitem.h 0

    We use \c itemChange() and \c focusOutEvent() to notify the
    \c DiagramScene when the text item loses focus and gets selected.

    We reimplement the functions that handle mouse events to make it
    possible to alter the mouse behavior of QGraphicsTextItem.

    \section1 DiagramTextItem Implementation
    
    We start with the constructor:

    \snippet examples/graphicsview/diagramscene/diagramtextitem.cpp 0

    We simply set the item movable and selectable, as these flags are
    off by default.

    Here is the \c itemChange() function:

    \snippet examples/graphicsview/diagramscene/diagramtextitem.cpp 1

    When the item is selected we emit the selectedChanged signal. The
    \c MainWindow uses this signal to update the widgets that display
    font properties to the font of the selected text item.

    Here is the \c focusOutEvent() function:

    \snippet examples/graphicsview/diagramscene/diagramtextitem.cpp 2

    \c DiagramScene uses the signal emitted when the text item looses
    focus to remove the item if it is empty, i.e., it contains no
    text. 

    This is the implementation of \c mouseDoubleClickEvent():

    \snippet examples/graphicsview/diagramscene/diagramtextitem.cpp 5

    When we receive a double click event, we make the item editable by calling
    QGraphicsTextItem::setTextInteractionFlags(). We then forward the
    double-click to the item itself.

    \section1 Arrow Class Definition

    The \c Arrow class is a graphics item that connects two \c
    DiagramItems. It draws an arrow head to one of the items. To
    achieve this the item needs to paint itself and also re implement
    methods used by the graphics scene to check for collisions and
    selections. The class inherits QGraphicsLine item, and draws the
    arrowhead and moves with the items it connects.

    \snippet examples/graphicsview/diagramscene/arrow.h 0

    The item's color can be set with \c setColor().

    \c boundingRect() and \c shape() are reimplemented 
    from QGraphicsLineItem and are used by the scene
    to check for collisions and selections.

    Calling \c updatePosition() causes the arrow to recalculate its
    position and arrow head angle. \c paint() is reimplemented so that
    we can paint an arrow rather than just a line between items.

    \c myStartItem and \c myEndItem are the diagram items that the
    arrow connects. The arrow is drawn with its head to the end item.
    \c arrowHead is a polygon with three vertices's we use to draw the
    arrow head.

    \section1 Arrow Class Implementation

    The constructor of the \c Arrow class looks like this:

    \snippet examples/graphicsview/diagramscene/arrow.cpp 0

    We set the start and end diagram items of the arrow. The arrow
    head will be drawn where the line intersects the end item.

    Here is the \c boundingRect() function:

    \snippet examples/graphicsview/diagramscene/arrow.cpp 1

    We need to reimplement this function because the arrow is
    larger than the bounding rectangle of the QGraphicsLineItem. The
    graphics scene uses the bounding rectangle to know which regions
    of the scene to update. 

    Here is the \c shape() function:

    \snippet examples/graphicsview/diagramscene/arrow.cpp 2

    The shape function returns a QPainterPath that is the exact
    shape of the item. The QGraphicsLineItem::shape() returns a path
    with a line drawn with the current pen, so we only need to add
    the arrow head. This function is used to check for collisions and
    selections with the mouse. 

    Here is the \c updatePosition() slot:

    \snippet examples/graphicsview/diagramscene/arrow.cpp 3

    This slot updates the arrow by setting the start and end
    points of its line to the center of the items it connects. 

    Here is the \c paint() function:

    \snippet examples/graphicsview/diagramscene/arrow.cpp 4

    If the start and end items collide we do not draw the arrow; the
    algorithm we use to find the point the arrow should be drawn at
    may fail if the items collide.

    We first set the pen and brush we will use for drawing the arrow.

    \snippet examples/graphicsview/diagramscene/arrow.cpp 5

    We then need to find the position at which to draw the
    arrowhead.  The head should be drawn where the line and the end
    item intersects. This is done by taking the line between each
    point in the polygon and check if it intersects with the line of
    the arrow. Since the line start and end points are set to the
    center of the items the arrow line should intersect one and only
    one of the lines of the polygon. Note that the points in the
    polygon are relative to the local coordinate system of the item.
    We must therefore add the position of the end item to make the
    coordinates relative to the scene. 

    \snippet examples/graphicsview/diagramscene/arrow.cpp 6

    We calculate the angle between the x-axis and the line of the
    arrow. We need to turn the arrow head to this angle so that it
    follows the direction of the arrow. If the angle is negative we
    must turn the direction of the arrow.

    We can then calculate the three points of the arrow head polygon.
    One of the points is the end of the line, which now is the
    intersection between the arrow line and the end polygon. Then we
    clear the \c arrowHead polygon from the previous calculated arrow
    head and set these new points.

    \snippet examples/graphicsview/diagramscene/arrow.cpp 7

    If the line is selected, we draw two dotted lines that are
    parallel with the line of the arrow. We do not use the default
    implementation, which uses \l{QGraphicsItem::}{boundingRect()}
    because the QRect bounding rectangle is considerably larger than
    the line.
*/