File indexing completed on 2024-04-28 05:41:39

0001 /*
0002     This file is part of KCachegrind.
0003 
0004     SPDX-FileCopyrightText: 2002-2016 Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
0005 
0006     SPDX-License-Identifier: GPL-2.0-only
0007 */
0008 
0009 /**
0010  * A Widget for visualizing hierarchical metrics as areas.
0011  * The API is similar to QListView.
0012  *
0013  * This file defines the following classes:
0014  *  DrawParams, RectDrawing, TreeMapItem, TreeMapWidget
0015  *
0016  * DrawParams/RectDrawing allows reusing of TreeMap drawing
0017  * functions in other widgets.
0018  */
0019 
0020 #ifndef TREEMAP_H
0021 #define TREEMAP_H
0022 
0023 #include <QString>
0024 #include <QWidget>
0025 #include <QPixmap>
0026 #include <QColor>
0027 #include <QStringList>
0028 #include <QPaintEvent>
0029 #include <QKeyEvent>
0030 #include <QContextMenuEvent>
0031 #include <QMouseEvent>
0032 
0033 class QMenu;
0034 class TreeMapWidget;
0035 class TreeMapItem;
0036 class TreeMapItemList;
0037 
0038 
0039 /**
0040  * Drawing parameters for an object.
0041  * A Helper Interface for RectDrawing.
0042  */
0043 class DrawParams
0044 {
0045 public:
0046     /**
0047      * Positions for drawing into a rectangle.
0048      *
0049      * The specified position assumes no rotation.
0050      * If there is more than one text for one position, it is put
0051      * nearer to the center of the item.
0052      *
0053      * Drawing at top positions cuts free space from top,
0054      * drawing at bottom positions cuts from bottom.
0055      * Default usually gives positions clockwise according to field number.
0056      */
0057     enum Position { TopLeft, TopCenter, TopRight,
0058                     BottomLeft, BottomCenter, BottomRight,
0059                     Default, Unknown};
0060 
0061     // no constructor as this is an abstract class
0062     virtual ~DrawParams() {}
0063 
0064     virtual QString  text(int) const = 0;
0065     virtual QPixmap  pixmap(int) const = 0;
0066     virtual Position position(int) const = 0;
0067     // 0: no limit, negative: leave at least -maxLines() free
0068     virtual int      maxLines(int) const { return 0; }
0069     // allow breaking up content into multiple lines?
0070     virtual bool     allowBreak(int) const { return true; }
0071     // truncate or show nothing if space not enough?
0072     virtual bool     allowTruncation(int) const { return true; }
0073     virtual int      fieldCount() const { return 0; }
0074 
0075     virtual QColor   backColor() const { return Qt::white; }
0076     virtual const QFont& font() const = 0;
0077 
0078     virtual bool selected() const { return false; }
0079     virtual bool current() const { return false; }
0080     virtual bool shaded() const { return true; }
0081     virtual bool rotated() const { return false; }
0082     virtual bool drawFrame() const { return true; }
0083 };
0084 
0085 
0086 /*
0087  * DrawParam with attributes stored
0088  */
0089 class StoredDrawParams: public DrawParams
0090 {
0091 public:
0092     StoredDrawParams();
0093     explicit StoredDrawParams(const QColor& c,
0094                               bool selected = false, bool current = false);
0095 
0096     // getters
0097     QString  text(int) const override;
0098     QPixmap  pixmap(int) const override;
0099     Position position(int) const override;
0100     int      maxLines(int) const override;
0101     int      fieldCount() const override { return _field.size(); }
0102 
0103     QColor   backColor() const override { return _backColor; }
0104     bool selected() const override { return _selected; }
0105     bool current() const override { return _current; }
0106     bool shaded() const override { return _shaded; }
0107     bool rotated() const override { return _rotated; }
0108     bool drawFrame() const override { return _drawFrame; }
0109 
0110     const QFont& font() const override;
0111 
0112     // attribute setters
0113     void setField(int f, const QString& t, const QPixmap& pm = QPixmap(),
0114                   Position p = Default, int maxLines = 0);
0115     void setText(int f, const QString&);
0116     void setPixmap(int f, const QPixmap&);
0117     void setPosition(int f, Position);
0118     void setMaxLines(int f, int);
0119     void setBackColor(const QColor& c) { _backColor = c; }
0120     void setSelected(bool b) { _selected = b; }
0121     void setCurrent(bool b) { _current = b; }
0122     void setShaded(bool b) { _shaded = b; }
0123     void setRotated(bool b) { _rotated = b; }
0124     void drawFrame(bool b) { _drawFrame = b; }
0125 
0126 protected:
0127     QColor _backColor;
0128     bool _selected :1;
0129     bool _current :1;
0130     bool _shaded :1;
0131     bool _rotated :1;
0132     bool _drawFrame :1;
0133 
0134 private:
0135     // resize field array if needed to allow to access field <f>
0136     void ensureField(int f);
0137 
0138     struct Field {
0139         QString text;
0140         QPixmap pix;
0141         Position pos;
0142         int maxLines;
0143     };
0144 
0145     QVector<Field> _field;
0146 };
0147 
0148 
0149 /* State for drawing on a rectangle.
0150  *
0151  * Following drawing functions are provided:
0152  * - background drawing with shading and 3D frame
0153  * - successive pixmap/text drawing at various positions with wrap-around
0154  *   optimized for minimal space usage (e.g. if a text is drawn at top right
0155  *   after text on top left, the same line is used if space allows)
0156  *
0157  */
0158 class RectDrawing
0159 {
0160 public:
0161     explicit RectDrawing(const QRect&);
0162     ~RectDrawing();
0163 
0164     // The default DrawParams object used.
0165     DrawParams* drawParams();
0166     // we take control over the given object (i.e. delete at destruction)
0167     void setDrawParams(DrawParams*);
0168 
0169     // draw on a given QPainter, use this class as info provider per default
0170     void drawBack(QPainter*, DrawParams* dp = nullptr);
0171     /* Draw field at position() from pixmap()/text() with maxLines().
0172      * Returns true if something was drawn
0173      */
0174     bool drawField(QPainter*, int f, DrawParams* dp = nullptr);
0175 
0176     // resets rectangle for free space
0177     void setRect(const QRect&);
0178 
0179     // Returns the rectangle area still free of text/pixmaps after
0180     // a number of drawText() calls.
0181     QRect remainingRect(DrawParams* dp = nullptr);
0182 
0183 private:
0184     int _usedTopLeft, _usedTopCenter, _usedTopRight;
0185     int _usedBottomLeft, _usedBottomCenter, _usedBottomRight;
0186     QRect _rect;
0187 
0188     // temporary
0189     int _fontHeight;
0190     QFontMetrics* _fm;
0191     DrawParams* _dp;
0192 };
0193 
0194 
0195 class TreeMapItemList: public QList<TreeMapItem*>
0196 {
0197 public:
0198     TreeMapItem* commonParent();
0199 };
0200 
0201 
0202 /**
0203  * Base class of items in TreeMap.
0204  *
0205  * This class supports an arbitrary number of text() strings
0206  * positioned counterclock-wise starting at TopLeft. Each item
0207  * has its own static value(), sum() and sorting(). The
0208  * splitMode() and borderWidth() is taken from a TreeMapWidget.
0209  *
0210  * If you want more flexibility, reimplement TreeMapItem and
0211  * override the corresponding methods. For dynamic creation of child
0212  * items on demand, reimplement children().
0213  */
0214 class TreeMapItem: public StoredDrawParams
0215 {
0216 public:
0217 
0218     /**
0219      * Split direction for nested areas:
0220      *  AlwaysBest: Choose split direction for every subitem according to
0221      *              longest side of rectangle left for drawing
0222      *  Best:       Choose split direction for all subitems of an area
0223      *              depending on longest side
0224      *  HAlternate: Horizontal at top;  alternate direction on depth step
0225      *  VAlternate: Vertical at top; alternate direction on depth step
0226      *  Horizontal: Always horizontal split direction
0227      *  Vertical:   Always vertical split direction
0228      */
0229     enum SplitMode { Bisection, Columns, Rows,
0230                      AlwaysBest, Best,
0231                      HAlternate, VAlternate,
0232                      Horizontal, Vertical };
0233 
0234     explicit TreeMapItem(TreeMapItem* parent = nullptr, double value = 1.0 );
0235     TreeMapItem(TreeMapItem* parent, double value,
0236                 const QString& text1, const QString& text2 = QString(),
0237                 const QString& text3 = QString(), const QString& text4 = QString());
0238     ~TreeMapItem() override;
0239 
0240     bool isChildOf(TreeMapItem*);
0241 
0242     TreeMapItem* commonParent(TreeMapItem* item);
0243 
0244     // force a redraw of this item
0245     void redraw();
0246 
0247     // delete all children
0248     void clear();
0249 
0250     // force new child generation & refresh
0251     void refresh();
0252 
0253     // call in a reimplemented items() method to check if already called
0254     // after a clear(), this will return false
0255     bool initialized();
0256 
0257     /**
0258      * Adds an item to a parent.
0259      * When no sorting is used, the item is appended (drawn at bottom).
0260      * This is only needed if the parent was not already specified in the
0261      * construction of the item.
0262      */
0263     void addItem(TreeMapItem*);
0264 
0265     /**
0266      * Returns a list of text strings of specified text number,
0267      * from root up to this item.
0268      */
0269     QStringList path(int) const;
0270 
0271     /**
0272      * Depth of this item. This is the distance to root.
0273      */
0274     int depth() const;
0275 
0276     /**
0277      * Parent Item
0278      */
0279     TreeMapItem* parent() const { return _parent; }
0280 
0281     /**
0282      * Temporary rectangle used for drawing this item the last time.
0283      * This is internally used to map from a point to an item.
0284      */
0285     void setItemRect(const QRect& r) { _rect = r; }
0286     void clearItemRect();
0287     const QRect& itemRect() const { return _rect; }
0288     int width() const { return _rect.width(); }
0289     int height() const { return _rect.height(); }
0290 
0291     /**
0292      * Temporary rectangle list of free space of this item.
0293      * Used internally to enable tooltip.
0294      */
0295     void clearFreeRects();
0296     const QList<QRect>& freeRects() const { return _freeRects; }
0297     void addFreeRect(const QRect& r);
0298 
0299     /**
0300      * Temporary child item index of the child that was current() recently.
0301      */
0302     int index() const { return _index; }
0303     void setIndex(int i) { _index = i; }
0304 
0305 
0306     /**
0307      * TreeMap widget this item is put in.
0308      */
0309     TreeMapWidget* widget() const { return _widget; }
0310 
0311     void setParent(TreeMapItem* p);
0312     void setWidget(TreeMapWidget* w) { _widget = w; }
0313     void setSum(double s) { _sum = s; }
0314     void setValue(double s) { _value = s; }
0315 
0316     virtual double sum() const;
0317     virtual double value() const;
0318     // replace "Default" position with setting from TreeMapWidget
0319     Position position(int) const override;
0320     const QFont& font() const override;
0321     virtual bool isMarked(int) const;
0322 
0323     virtual int borderWidth() const;
0324 
0325     /**
0326      * Returns the text number after that sorting is done or
0327      * -1 for no sorting, -2 for value() sorting (default).
0328      * If ascending != 0, a bool value is written at that location
0329      * to indicate if sorting should be ascending.
0330      */
0331     virtual int sorting(bool* ascending) const;
0332 
0333     /**
0334      * Set the sorting for child drawing.
0335      *
0336      * Default is no sorting: @p textNo = -1
0337      * For value() sorting, use @p textNo = -2
0338      *
0339      * For fast sorting, set this to -1 before child insertions and call
0340      * again after inserting all children.
0341      */
0342     void setSorting(int textNo, bool ascending = true);
0343 
0344     /**
0345      * Resort according to the already set sorting.
0346      *
0347      * This has to be done if the sorting base changes (e.g. text or values
0348      * change). If this is only true for the children of this item, you can
0349      * set the recursive parameter to false.
0350      */
0351     void resort(bool recursive = true);
0352 
0353     virtual SplitMode splitMode() const;
0354     virtual int rtti() const;
0355     // not const as this can create children on demand
0356     virtual TreeMapItemList* children();
0357 
0358 protected:
0359     TreeMapItemList* _children;
0360     double _sum, _value;
0361 
0362 private:
0363     TreeMapWidget* _widget;
0364     TreeMapItem* _parent;
0365 
0366     int _sortTextNo;
0367     bool _sortAscending;
0368 
0369     // temporary layout
0370     QRect _rect;
0371     QList<QRect> _freeRects;
0372     int _depth;
0373 
0374     // temporary self value (when using level skipping)
0375     double _unused_self;
0376 
0377     // index of last active subitem
0378     int _index;
0379 };
0380 
0381 
0382 /**
0383  * Class for visualization of a metric of hierarchically
0384  * nested items as 2D areas.
0385  */
0386 class TreeMapWidget: public QWidget
0387 {
0388     Q_OBJECT
0389 
0390 public:
0391 
0392     /**
0393      * Same as in QListBox/QListView
0394      */
0395     enum SelectionMode { Single, Multi, Extended, NoSelection };
0396 
0397     /* The widget gets owner of the base item */
0398     explicit TreeMapWidget(TreeMapItem* base, QWidget* parent=nullptr);
0399     ~TreeMapWidget() override;
0400 
0401     /**
0402      * Returns the TreeMapItem filling out the widget space
0403      */
0404     TreeMapItem* base() const { return _base; }
0405 
0406     /**
0407      * Returns a reference to the current widget font.
0408      */
0409     const QFont& currentFont() const;
0410 
0411     /**
0412      * Returns the area item at position x/y, independent from any
0413      * maxSelectDepth setting.
0414      */
0415     TreeMapItem* item(int x, int y) const;
0416 
0417     /**
0418      * Returns the nearest item with a visible area; this
0419      * can be the given item itself.
0420      */
0421     TreeMapItem* visibleItem(TreeMapItem*) const;
0422 
0423     /**
0424      * Returns the item possible for selection. this returns the
0425      * given item itself or a parent thereof,
0426      * depending on setting of maxSelectDepth().
0427      */
0428     TreeMapItem* possibleSelection(TreeMapItem*) const;
0429 
0430     /**
0431      * Selects or unselects an item.
0432      * In multiselection mode, the constrain that a selected item
0433      * has no selected children or parents stays true.
0434      */
0435     void setSelected(TreeMapItem*, bool selected = true);
0436 
0437     /**
0438      * Switches on the marking @p markNo. Marking 0 switches off marking.
0439      * This is mutually exclusive to selection, and is automatically
0440      * switched off when selection is changed (also by the user).
0441      * Marking is visually the same as selection, and is based on
0442      * TreeMapItem::isMarked(@c markNo).
0443      * This enables to programmatically show multiple selected items
0444      * at once even in single selection mode.
0445      */
0446     void setMarked(int markNo = 1, bool redraw = true);
0447 
0448     /**
0449      * Clear selection of all selected items which are children of
0450      * parent. When parent == 0, clears whole selection
0451      * Returns true if selection changed.
0452      */
0453     bool clearSelection(TreeMapItem* parent = nullptr);
0454 
0455     /**
0456      * Selects or unselects items in a range.
0457      * This is needed internally for Shift-Click in Extended mode.
0458      * Range means for a hierarchical widget:
0459      * - select/unselect i1 and i2 according selected
0460      * - search common parent of i1 and i2, and select/unselect the
0461      *   range of direct children between but excluding the child
0462      *   leading to i1 and the child leading to i2.
0463      */
0464     void setRangeSelection(TreeMapItem* i1,
0465                            TreeMapItem* i2, bool selected);
0466 
0467     /**
0468      * Sets the current item.
0469      * The current item is mainly used for keyboard navigation.
0470      */
0471     void setCurrent(TreeMapItem*, bool kbd=false);
0472 
0473     /**
0474      * Set the maximal depth a selected item can have.
0475      * If you try to select a item with higher depth, the ancestor holding
0476      * this condition is used.
0477      *
0478      * See also possibleSelection().
0479      */
0480     void setMaxSelectDepth(int d) { _maxSelectDepth = d; }
0481 
0482 
0483     void setSelectionMode(SelectionMode m) { _selectionMode = m; }
0484 
0485     /**
0486      * for setting/getting global split direction
0487      */
0488     void setSplitMode(TreeMapItem::SplitMode m);
0489     TreeMapItem::SplitMode splitMode() const;
0490     // returns true if string was recognized
0491     bool setSplitMode(const QString&);
0492     QString splitModeString() const;
0493 
0494 
0495     /*
0496    * Shading of rectangles enabled ?
0497    */
0498     void setShadingEnabled(bool s);
0499     bool isShadingEnabled() const { return _shading; }
0500 
0501     /* Setting for a whole depth level: draw 3D frame (default) or solid */
0502     void drawFrame(int d, bool b);
0503     bool drawFrame(int d) const { return (d<4)?_drawFrame[d]:true; }
0504 
0505     /* Setting for a whole depth level: draw items (default) or transparent */
0506     void setTransparent(int d, bool b);
0507     bool isTransparent(int d) const { return (d<4)?_transparent[d]:false; }
0508 
0509     /**
0510      * Items usually have a size proportional to their value().
0511      * With @p width, you can give the minimum width
0512      * of the resulting rectangle to still be drawn.
0513      * For space not used because of to small items, you can specify
0514      * with @p reuseSpace if the background should shine through or
0515      * the space will be used to enlarge the next item to be drawn
0516      * at this level.
0517      */
0518     void setVisibleWidth(int width, bool reuseSpace = false);
0519 
0520     /**
0521      * If a children value() is almost the parents sum(),
0522      * it can happen that the border to be drawn for visibility of
0523      * nesting relations takes to much space, and the
0524      * parent/child size relation can not be mapped to a correct
0525      * area size relation.
0526      *
0527      * Either
0528      * (1) Ignore the incorrect drawing, or
0529      * (2) Skip drawing of the parent level altogether.
0530      */
0531     void setSkipIncorrectBorder(bool enable = true);
0532     bool skipIncorrectBorder() const { return _skipIncorrectBorder; }
0533 
0534     /**
0535      * Maximal nesting depth
0536      */
0537     void setMaxDrawingDepth(int d);
0538     int maxDrawingDepth() const { return _maxDrawingDepth; }
0539 
0540     /**
0541      * Minimal area for rectangles to draw
0542      */
0543     void setMinimalArea(int area);
0544     int minimalArea() const { return _minimalArea; }
0545 
0546     /* defaults for text attributes */
0547     QString defaultFieldType(int) const;
0548     QString defaultFieldStop(int) const;
0549     bool    defaultFieldVisible(int) const;
0550     bool    defaultFieldForced(int) const;
0551     DrawParams::Position defaultFieldPosition(int) const;
0552 
0553     /**
0554      * Set the type name of a field.
0555      * This is important for the visualization menu generated
0556      * with visualizationMenu()
0557      */
0558     void setFieldType(int, const QString&);
0559     QString fieldType(int) const;
0560 
0561     /**
0562      * Stop drawing at item with name
0563      */
0564     void setFieldStop(int, const QString&);
0565     QString fieldStop(int) const;
0566 
0567     /**
0568      * Should the text with number textNo be visible?
0569      * This is only done if remaining space is enough to allow for
0570      * proportional size constrains.
0571      */
0572     void setFieldVisible(int, bool);
0573     bool fieldVisible(int) const;
0574 
0575     /**
0576      * Should the drawing of the name into the rectangle be forced?
0577      * This enables drawing of the name before drawing subitems, and
0578      * thus destroys proportional constrains.
0579      */
0580     void setFieldForced(int, bool);
0581     bool fieldForced(int) const;
0582 
0583     /**
0584      * Set the field position in the area. See TreeMapItem::Position
0585      */
0586     void setFieldPosition(int, DrawParams::Position);
0587     DrawParams::Position fieldPosition(int) const;
0588     void setFieldPosition(int, const QString&);
0589     QString fieldPositionString(int) const;
0590 
0591     /**
0592      * Do we allow the texts to be rotated by 90 degrees for better fitting?
0593      */
0594     void setAllowRotation(bool);
0595     bool allowRotation() const { return _allowRotation; }
0596 
0597     void setBorderWidth(int w);
0598     int borderWidth() const { return _borderWidth; }
0599 
0600     /**
0601      * Populate given menu with option items.
0602      * The added items are automatically connected to handlers.
0603      */
0604     void addSplitDirectionItems(QMenu*);
0605 
0606     TreeMapWidget* widget() { return this; }
0607     TreeMapItem* current() const { return _current; }
0608     TreeMapItemList selection() const { return _selection; }
0609     bool isSelected(TreeMapItem* i) const;
0610     int maxSelectDepth() const { return _maxSelectDepth; }
0611     SelectionMode selectionMode() const { return _selectionMode; }
0612 
0613     /**
0614      * Return tooltip string to show for a item (can be rich text)
0615      * Default implementation gives lines with "text0 (text1)" going to root.
0616      */
0617     virtual QString tipString(TreeMapItem* i) const;
0618 
0619     /**
0620      * Redraws an item with all children.
0621      * This takes changed values(), sums(), colors() and text() into account.
0622      */
0623     void redraw(TreeMapItem*);
0624     void redraw() { redraw(_base); }
0625 
0626     /**
0627      * Resort all TreeMapItems. See TreeMapItem::resort().
0628      */
0629     void resort() { _base->resort(true); }
0630 
0631     // internal
0632     void drawTreeMap();
0633 
0634     // used internally when items are destroyed
0635     void deletingItem(TreeMapItem*);
0636 
0637 protected Q_SLOTS:
0638     void splitActivated(QAction*);
0639 
0640 Q_SIGNALS:
0641     void selectionChanged();
0642     void selectionChanged(TreeMapItem*);
0643 
0644     /**
0645      * This signal is emitted if the current item changes.
0646      * If the change is done because of keyboard navigation,
0647      * the @p keyboard is set to true
0648      */
0649     void currentChanged(TreeMapItem*, bool keyboard);
0650     void clicked(TreeMapItem*);
0651     void returnPressed(TreeMapItem*);
0652     void doubleClicked(TreeMapItem*);
0653     void rightButtonPressed(TreeMapItem*, const QPoint &);
0654     void contextMenuRequested(TreeMapItem*, const QPoint &);
0655 
0656 protected:
0657     void mousePressEvent( QMouseEvent * ) override;
0658     void contextMenuEvent( QContextMenuEvent * ) override;
0659     void mouseReleaseEvent( QMouseEvent * ) override;
0660     void mouseMoveEvent( QMouseEvent * ) override;
0661     void mouseDoubleClickEvent( QMouseEvent * ) override;
0662     void keyPressEvent( QKeyEvent* ) override;
0663     void paintEvent( QPaintEvent * ) override;
0664     void fontChange( const QFont& );
0665     bool event(QEvent *event) override;
0666 
0667 private:
0668     TreeMapItemList diff(TreeMapItemList&, TreeMapItemList&);
0669     // returns true if selection changed
0670     TreeMapItem* setTmpSelected(TreeMapItem*, bool selected = true);
0671     TreeMapItem* setTmpRangeSelection(TreeMapItem* i1,
0672                                       TreeMapItem* i2, bool selected);
0673     bool isTmpSelected(TreeMapItem* i);
0674 
0675     void drawItem(QPainter* p, TreeMapItem*);
0676     void drawItems(QPainter* p, TreeMapItem*);
0677     bool horizontal(TreeMapItem* i, const QRect& r);
0678     void drawFill(TreeMapItem*,QPainter* p, const QRect& r);
0679     void drawFill(TreeMapItem*,QPainter* p, const QRect& r,
0680                   TreeMapItemList* list, int idx, int len, bool goBack);
0681     bool drawItemArray(QPainter* p, TreeMapItem*, const QRect& r, double,
0682                        TreeMapItemList* list, int idx, int len, bool);
0683     bool resizeAttr(int);
0684 
0685     void addSplitAction(QMenu*, const QString&, int);
0686 
0687     TreeMapItem* _base;
0688     TreeMapItem *_current, *_pressed, *_lastOver, *_oldCurrent;
0689     int _maxSelectDepth, _maxDrawingDepth;
0690 
0691     // attributes for field, per textNo
0692     struct FieldAttr {
0693         QString type, stop;
0694         bool visible, forced;
0695         DrawParams::Position pos;
0696     };
0697     QVector<FieldAttr> _attr;
0698 
0699     SelectionMode _selectionMode;
0700     TreeMapItem::SplitMode _splitMode;
0701     int _visibleWidth, _stopArea, _minimalArea, _borderWidth;
0702     bool _reuseSpace, _skipIncorrectBorder, _drawSeparators, _shading;
0703     bool _allowRotation;
0704     bool _transparent[4], _drawFrame[4];
0705     TreeMapItem * _needsRefresh;
0706     TreeMapItemList _selection;
0707     int _markNo;
0708 
0709     // temporary selection while dragging, used for drawing
0710     // most of the time, _selection == _tmpSelection
0711     TreeMapItemList _tmpSelection;
0712     bool _inShiftDrag, _inControlDrag;
0713 
0714     // temporary widget font metrics while drawing
0715     QFont _font;
0716     int _fontHeight;
0717 
0718     // back buffer pixmap
0719     QPixmap _pixmap;
0720 };
0721 
0722 #endif