libyui-qt
2.43.5
|
00001 /* 00002 Copyright (C) 2000-2012 Novell, Inc 00003 This library is free software; you can redistribute it and/or modify 00004 it under the terms of the GNU Lesser General Public License as 00005 published by the Free Software Foundation; either version 2.1 of the 00006 License, or (at your option) version 3.0 of the License. This library 00007 is distributed in the hope that it will be useful, but WITHOUT ANY 00008 WARRANTY; without even the implied warranty of MERCHANTABILITY or 00009 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 00010 License for more details. You should have received a copy of the GNU 00011 Lesser General Public License along with this library; if not, write 00012 to the Free Software Foundation, Inc., 51 Franklin Street, Fifth 00013 Floor, Boston, MA 02110-1301 USA 00014 */ 00015 00016 00017 /*-/ 00018 00019 File: YQBarGraph.cc 00020 00021 Author: Stefan Hundhammer <sh@suse.de> 00022 00023 /-*/ 00024 00025 00026 #define YUILogComponent "qt-ui" 00027 #include <yui/YUILog.h> 00028 00029 #include <algorithm> 00030 #include <qpainter.h> 00031 #include <qnamespace.h> 00032 00033 #include "utf8.h" 00034 #include "YQUI.h" 00035 #include "YQBarGraph.h" 00036 00037 00038 #define YQBarGraphOuterMargin YQWidgetMargin 00039 #define YQBarGraphLabelHorizontalMargin 1 00040 #define YQBarGraphLabelVerticalMargin 2 00041 #define YQBarGraphMinWidth 80 00042 #define YQBarGraphMinHeight 30 00043 00044 using std::max; 00045 00046 // a helper function, takes std::pair as a param and compares 00047 // its key (int) to the second param - true if less 00048 inline bool in_segment (pair <int, QString> seg, int cmp) 00049 { 00050 return seg.first < cmp; 00051 } 00052 00053 YQBarGraph::YQBarGraph( YWidget * parent ) 00054 : QFrame( (QWidget *) parent->widgetRep() ) 00055 , YBarGraph( parent ) 00056 { 00057 setWidgetRep( this ); 00058 } 00059 00060 00061 YQBarGraph::~YQBarGraph() 00062 { 00063 // NOP 00064 } 00065 00066 00067 void 00068 YQBarGraph::doUpdate() 00069 { 00070 QFrame::update(); // triggers drawContents() 00071 } 00072 00073 bool 00074 YQBarGraph::event ( QEvent *event) 00075 { 00076 if (event->type() == QEvent::ToolTip) { 00077 QHelpEvent *helpEvent = static_cast<QHelpEvent *>(event); 00078 00079 // Ook, I know this is write-only piece of code, but it basically means this: 00080 // Traverse map from the rear end, looking for the lower bound of the segment the 00081 // mouse pointer is in, using in_segment function as comparison 00082 map<int, QString>::reverse_iterator lbound = 00083 find_if( toolTips.rbegin(), toolTips.rend(), bind2nd( ptr_fun(in_segment), helpEvent->x())); 00084 00085 if (lbound != toolTips.rend()) 00086 QToolTip::showText(helpEvent->globalPos(), lbound->second ); 00087 } 00088 return QWidget::event(event); 00089 00090 } 00091 00092 void 00093 YQBarGraph::paintEvent( QPaintEvent* paintEvent ) 00094 { 00095 QFrame::paintEvent( paintEvent ); 00096 00097 QPainter painter( this ); 00098 00099 unsigned nextDefaultColor = 0; 00100 int totalWidth = contentsRect().width() - 2*YQBarGraphOuterMargin; 00101 int segHeight = contentsRect().height() - 2*YQBarGraphOuterMargin; 00102 int x_off = YQBarGraphOuterMargin; 00103 int y_off = YQBarGraphOuterMargin; 00104 int valueTotal = 0; 00105 QFontMetrics fm = painter.fontMetrics(); 00106 00107 toolTips.clear(); 00108 00109 for ( int i=0; i < segments(); i++ ) 00110 valueTotal += segment(i).value(); 00111 00112 if ( valueTotal == 0 ) // Avoid division by zero 00113 return; 00114 00115 for ( int i=0; i < segments(); i++ ) 00116 { 00117 const YBarGraphSegment & seg = segment(i); 00118 int segWidth = ( (long) totalWidth * seg.value() ) / valueTotal; 00119 int stringWidth = 0; 00120 00121 if ( i == segments()-1 ) 00122 { 00123 // Compensate for rounding errors: 00124 // The last segment gets all leftover pixels from the previous ones. 00125 00126 segWidth = totalWidth - x_off + YQBarGraphOuterMargin; 00127 } 00128 00129 00130 // 00131 // Fill the segment 00132 // 00133 00134 YColor segmentColor = seg.segmentColor(); 00135 YColor textColor = seg.textColor(); 00136 00137 if ( segmentColor.isUndefined() || textColor.isUndefined() ) 00138 { 00139 // If any of the colors is undefined, use the next default color 00140 // for both so some contrast is ensured. 00141 00142 segmentColor = defaultSegmentColor( nextDefaultColor ); 00143 textColor = defaultTextColor ( nextDefaultColor++ ); 00144 } 00145 00146 painter.setBrush( QColor( segmentColor.red(), 00147 segmentColor.green(), 00148 segmentColor.blue() ) ); 00149 painter.setPen( Qt::NoPen ); 00150 painter.drawRect( x_off, y_off, segWidth+2, segHeight+2 ); 00151 00152 00153 // 00154 // Draw the label 00155 // 00156 00157 painter.setPen( Qt::SolidLine ); 00158 painter.setPen( QColor( textColor.red(), 00159 textColor.green(), 00160 textColor.blue() ) ); 00161 00162 QString txt = fromUTF8( seg.label() ); 00163 00164 if ( txt.contains( "%1" ) ) 00165 txt = txt.arg( seg.value() ); // substitute variable 00166 00167 stringWidth = fm.size(0,txt).width(); 00168 00169 // draw the text only if it fits the current segment width ... 00170 if (stringWidth < segWidth) 00171 { 00172 painter.drawText( x_off + YQBarGraphLabelHorizontalMargin, 00173 y_off + YQBarGraphLabelVerticalMargin, 00174 segWidth - 2 * YQBarGraphLabelHorizontalMargin + 1, 00175 segHeight - 2 * YQBarGraphLabelVerticalMargin + 1, 00176 Qt::AlignCenter, txt ); 00177 } 00178 00179 // ... but always make it available via tooltip 00180 toolTips.insert(make_pair( x_off, txt)); 00181 00182 // Prepare for the next segment 00183 00184 x_off += segWidth; 00185 } 00186 } 00187 00188 00189 YColor 00190 YQBarGraph::defaultSegmentColor( unsigned index ) 00191 { 00192 switch( index % 8 ) 00193 { 00194 case 0: return YColor( 0, 0, 128 ); // dark blue 00195 case 1: return YColor( 64, 200, 255 ); // medium blue 00196 case 2: return YColor( 255, 255, 255 ); // white 00197 case 3: return YColor( 0, 153, 153 ); // cadet blue 00198 case 4: return YColor( 150, 255, 255 ); // cyan 00199 case 5: return YColor( 100, 100, 100 ); // medium grey 00200 case 6: return YColor( 0, 200, 100 ); // medium green 00201 case 7: return YColor( 0, 100, 76 ); // dark green 00202 } 00203 00204 return YColor( 255, 255, 255 ); // just to make gcc happy 00205 } 00206 00207 00208 YColor 00209 YQBarGraph::defaultTextColor( unsigned index ) 00210 { 00211 YColor black = YColor( 0, 0, 0 ); 00212 YColor white = YColor( 255, 255, 255 ); 00213 00214 switch( index % 8 ) 00215 { 00216 case 0: return white; 00217 case 1: return black; 00218 case 2: return black; 00219 case 3: return black; 00220 case 4: return black; 00221 case 5: return white; 00222 case 6: return black; 00223 case 7: return white; 00224 } 00225 00226 return black; // just to make gcc happy 00227 } 00228 00229 00230 void 00231 YQBarGraph::setEnabled( bool enabled ) 00232 { 00233 QFrame::setEnabled( enabled ); 00234 YWidget::setEnabled( enabled ); 00235 } 00236 00237 00238 int 00239 YQBarGraph::preferredWidth() 00240 { 00241 int width = 0; 00242 QFontMetrics metrics = fontMetrics(); 00243 00244 for ( int i=0; i < segments(); i++ ) 00245 { 00246 QString txt = fromUTF8( segment(i).label() ); 00247 00248 if ( txt.contains( "%1" ) ) 00249 txt = txt.arg( segment(i).value() ); 00250 00251 QSize segSize = metrics.size( 0, txt ); 00252 width += segSize.width(); 00253 } 00254 00255 width += 2 * YQBarGraphLabelHorizontalMargin; 00256 width += frameWidth(); 00257 width += 2 * YQBarGraphOuterMargin; 00258 width = max( width, YQBarGraphMinWidth ); 00259 00260 return width; 00261 } 00262 00263 00264 int 00265 YQBarGraph::preferredHeight() 00266 { 00267 int height = YQBarGraphMinHeight; 00268 QFontMetrics metrics = fontMetrics(); 00269 00270 for ( int i=0; i < segments(); i++ ) 00271 { 00272 QString txt = fromUTF8( segment(i).label() ); 00273 00274 if ( txt.contains( "%1" ) ) 00275 txt = txt.arg( segment(i).value() ); 00276 00277 QSize segSize = metrics.size( 0, txt ); 00278 height = max( height, segSize.height() ); 00279 } 00280 00281 height += 2 * YQBarGraphLabelVerticalMargin; 00282 height += frameWidth(); 00283 height += 2 * YQBarGraphOuterMargin; 00284 height = max( height, YQBarGraphMinHeight ); 00285 00286 return height; 00287 } 00288 00289 00290 void 00291 YQBarGraph::setSize( int newWidth, int newHeight ) 00292 { 00293 resize( newWidth, newHeight ); 00294 } 00295 00296 00297 00298 #include "YQBarGraph.moc"