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