libyui-qt  2.47.1.1
YQBarGraph.cc
1 /*
2  Copyright (C) 2000-2012 Novell, Inc
3  This library is free software; you can redistribute it and/or modify
4  it under the terms of the GNU Lesser General Public License as
5  published by the Free Software Foundation; either version 2.1 of the
6  License, or (at your option) version 3.0 of the License. This library
7  is distributed in the hope that it will be useful, but WITHOUT ANY
8  WARRANTY; without even the implied warranty of MERCHANTABILITY or
9  FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
10  License for more details. You should have received a copy of the GNU
11  Lesser General Public License along with this library; if not, write
12  to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
13  Floor, Boston, MA 02110-1301 USA
14 */
15 
16 
17 /*-/
18 
19  File: YQBarGraph.cc
20 
21  Author: Stefan Hundhammer <sh@suse.de>
22 
23 /-*/
24 
25 
26 #define YUILogComponent "qt-ui"
27 #include <yui/YUILog.h>
28 
29 #include <algorithm>
30 #include <qpainter.h>
31 #include <qnamespace.h>
32 
33 #include "utf8.h"
34 #include "YQUI.h"
35 #include "YQBarGraph.h"
36 
37 
38 #define YQBarGraphOuterMargin YQWidgetMargin
39 #define YQBarGraphLabelHorizontalMargin 1
40 #define YQBarGraphLabelVerticalMargin 2
41 #define YQBarGraphMinWidth 80
42 #define YQBarGraphMinHeight 30
43 
44 using std::max;
45 
46 // a helper function, takes std::pair as a param and compares
47 // its key (int) to the second param - true if less
48 inline bool in_segment (pair <int, QString> seg, int cmp)
49 {
50  return seg.first < cmp;
51 }
52 
53 YQBarGraph::YQBarGraph( YWidget * parent )
54  : QFrame( (QWidget *) parent->widgetRep() )
55  , YBarGraph( parent )
56 {
57  setWidgetRep( this );
58 }
59 
60 
62 {
63  // NOP
64 }
65 
66 
67 void
69 {
70  QFrame::update(); // triggers drawContents()
71 }
72 
73 bool
74 YQBarGraph::event ( QEvent *event)
75 {
76  if (event->type() == QEvent::ToolTip) {
77  QHelpEvent *helpEvent = static_cast<QHelpEvent *>(event);
78 
79  // Ook, I know this is write-only piece of code, but it basically means this:
80  // Traverse map from the rear end, looking for the lower bound of the segment the
81  // mouse pointer is in, using in_segment function as comparison
82  map<int, QString>::reverse_iterator lbound =
83  find_if( toolTips.rbegin(), toolTips.rend(), bind2nd( ptr_fun(in_segment), helpEvent->x()));
84 
85  if (lbound != toolTips.rend())
86  QToolTip::showText(helpEvent->globalPos(), lbound->second );
87  }
88  return QWidget::event(event);
89 
90 }
91 
92 void
94 {
95  QFrame::paintEvent( paintEvent );
96 
97  QPainter painter( this );
98 
99  unsigned nextDefaultColor = 0;
100  int totalWidth = contentsRect().width() - 2*YQBarGraphOuterMargin;
101  int segHeight = contentsRect().height() - 2*YQBarGraphOuterMargin;
102  int x_off = YQBarGraphOuterMargin;
103  int y_off = YQBarGraphOuterMargin;
104  int valueTotal = 0;
105  QFontMetrics fm = painter.fontMetrics();
106 
107  toolTips.clear();
108 
109  for ( int i=0; i < segments(); i++ )
110  valueTotal += segment(i).value();
111 
112  if ( valueTotal == 0 ) // Avoid division by zero
113  return;
114 
115  for ( int i=0; i < segments(); i++ )
116  {
117  const YBarGraphSegment & seg = segment(i);
118  int segWidth = ( (long) totalWidth * seg.value() ) / valueTotal;
119  int stringWidth = 0;
120 
121  if ( i == segments()-1 )
122  {
123  // Compensate for rounding errors:
124  // The last segment gets all leftover pixels from the previous ones.
125 
126  segWidth = totalWidth - x_off + YQBarGraphOuterMargin;
127  }
128 
129 
130  //
131  // Fill the segment
132  //
133 
134  YColor segmentColor = seg.segmentColor();
135  YColor textColor = seg.textColor();
136 
137  if ( segmentColor.isUndefined() || textColor.isUndefined() )
138  {
139  // If any of the colors is undefined, use the next default color
140  // for both so some contrast is ensured.
141 
142  segmentColor = defaultSegmentColor( nextDefaultColor );
143  textColor = defaultTextColor ( nextDefaultColor++ );
144  }
145 
146  painter.setBrush( QColor( segmentColor.red(),
147  segmentColor.green(),
148  segmentColor.blue() ) );
149  painter.setPen( Qt::NoPen );
150  painter.drawRect( x_off, y_off, segWidth+2, segHeight+2 );
151 
152 
153  //
154  // Draw the label
155  //
156 
157  painter.setPen( Qt::SolidLine );
158  painter.setPen( QColor( textColor.red(),
159  textColor.green(),
160  textColor.blue() ) );
161 
162  QString txt = fromUTF8( seg.label() );
163 
164  if ( txt.contains( "%1" ) )
165  txt = txt.arg( seg.value() ); // substitute variable
166 
167  stringWidth = fm.size(0,txt).width();
168 
169  // draw the text only if it fits the current segment width ...
170  if (stringWidth < segWidth)
171  {
172  painter.drawText( x_off + YQBarGraphLabelHorizontalMargin,
173  y_off + YQBarGraphLabelVerticalMargin,
174  segWidth - 2 * YQBarGraphLabelHorizontalMargin + 1,
175  segHeight - 2 * YQBarGraphLabelVerticalMargin + 1,
176  Qt::AlignCenter, txt );
177  }
178 
179  // ... but always make it available via tooltip
180  toolTips.insert(make_pair( x_off, txt));
181 
182  // Prepare for the next segment
183 
184  x_off += segWidth;
185  }
186 }
187 
188 
189 YColor
191 {
192  // use color from qproperty defined in qss
193  QColor color;
194  QStringList colors = _backgroundColors.split(",");
195 
196  if ( colors.size() > 0 )
197  {
198  color = colors[index % colors.size()];
199  if ( color.isValid() )
200  return YColor( color.red(), color.green(), color.blue() );
201  }
202 
203  // use default color if color is not defined in qss
204  switch( index % 8 )
205  {
206  case 0: return YColor( 0, 0, 128 ); // dark blue
207  case 1: return YColor( 64, 200, 255 ); // medium blue
208  case 2: return YColor( 255, 255, 255 ); // white
209  case 3: return YColor( 0, 153, 153 ); // cadet blue
210  case 4: return YColor( 150, 255, 255 ); // cyan
211  case 5: return YColor( 100, 100, 100 ); // medium grey
212  case 6: return YColor( 0, 200, 100 ); // medium green
213  case 7: return YColor( 0, 100, 76 ); // dark green
214  }
215 
216  return YColor( 255, 255, 255 ); // just to make gcc happy
217 }
218 
219 
220 YColor
222 {
223  // use color from qproperty defined in qss
224 
225  QColor color;
226  QStringList colors = _foregroundColors.split(",");
227 
228  if ( colors.size() > 0 )
229  {
230  color = colors[index % colors.size()];
231  if (color.isValid() )
232  return YColor( color.red(), color.green(), color.blue() );
233  }
234 
235  // use default color if color is not defined in qss
236  YColor black = YColor( 0, 0, 0 );
237  YColor white = YColor( 255, 255, 255 );
238 
239  switch( index % 8 )
240  {
241  case 0: return white;
242  case 1: return black;
243  case 2: return black;
244  case 3: return black;
245  case 4: return black;
246  case 5: return white;
247  case 6: return black;
248  case 7: return white;
249  }
250 
251  return black; // just to make gcc happy
252 }
253 
254 
255 void
256 YQBarGraph::setEnabled( bool enabled )
257 {
258  QFrame::setEnabled( enabled );
259  YWidget::setEnabled( enabled );
260 }
261 
262 
263 int
265 {
266  int width = 0;
267  QFontMetrics metrics = fontMetrics();
268 
269  for ( int i=0; i < segments(); i++ )
270  {
271  QString txt = fromUTF8( segment(i).label() );
272 
273  if ( txt.contains( "%1" ) )
274  txt = txt.arg( segment(i).value() );
275 
276  QSize segSize = metrics.size( 0, txt );
277  width += segSize.width();
278  }
279 
280  width += 2 * YQBarGraphLabelHorizontalMargin;
281  width += frameWidth();
282  width += 2 * YQBarGraphOuterMargin;
283  width = max( width, YQBarGraphMinWidth );
284 
285  return width;
286 }
287 
288 
289 int
291 {
292  int height = YQBarGraphMinHeight;
293  QFontMetrics metrics = fontMetrics();
294 
295  for ( int i=0; i < segments(); i++ )
296  {
297  QString txt = fromUTF8( segment(i).label() );
298 
299  if ( txt.contains( "%1" ) )
300  txt = txt.arg( segment(i).value() );
301 
302  QSize segSize = metrics.size( 0, txt );
303  height = max( height, segSize.height() );
304  }
305 
306  height += 2 * YQBarGraphLabelVerticalMargin;
307  height += frameWidth();
308  height += 2 * YQBarGraphOuterMargin;
309  height = max( height, YQBarGraphMinHeight );
310 
311  return height;
312 }
313 
314 
315 void
316 YQBarGraph::setSize( int newWidth, int newHeight )
317 {
318  resize( newWidth, newHeight );
319 }
320 
321 QString YQBarGraph::getBackgroundColors()
322 {
323  return _backgroundColors;
324 }
325 
326 void YQBarGraph::setBackgroundColors( QString colors )
327 {
328  _backgroundColors = colors;
329 }
330 
331 QString YQBarGraph::getForegroundColors()
332 {
333  return _foregroundColors;
334 }
335 
336 void YQBarGraph::setForegroundColors( QString colors )
337 {
338  _foregroundColors = colors;
339 }
340 
341 
342 
343 #include "YQBarGraph.moc"
YColor defaultSegmentColor(unsigned index)
Return one from a set of default segment background colors.
Definition: YQBarGraph.cc:190
YQBarGraph(YWidget *parent)
Constructor.
Definition: YQBarGraph.cc:53
virtual ~YQBarGraph()
Destructor.
Definition: YQBarGraph.cc:61
virtual int preferredWidth()
Preferred width of the widget.
Definition: YQBarGraph.cc:264
YColor defaultTextColor(unsigned index)
Return one from a set of default text colors.
Definition: YQBarGraph.cc:221
virtual void doUpdate()
Perform a visual update on the screen.
Definition: YQBarGraph.cc:68
virtual void setSize(int newWidth, int newHeight)
Set the new size of the widget.
Definition: YQBarGraph.cc:316
virtual void paintEvent(QPaintEvent *painter)
Draw the contents.
Definition: YQBarGraph.cc:93
virtual int preferredHeight()
Preferred height of the widget.
Definition: YQBarGraph.cc:290
virtual void setEnabled(bool enabled)
Set enabled/disabled state.
Definition: YQBarGraph.cc:256