00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "qgsdetaileditemdelegate.h"
00020 #include "qgsdetaileditemwidget.h"
00021 #include "qgsdetaileditemdata.h"
00022 #include <QPainter>
00023 #include <QFont>
00024 #include <QFontMetrics>
00025 #include <QStyleOptionViewItem>
00026 #include <QModelIndex>
00027 #include <QCheckBox>
00028 #include <QLinearGradient>
00029 QgsDetailedItemDelegate::QgsDetailedItemDelegate( QObject * parent ) :
00030 QAbstractItemDelegate( parent ),
00031 mpWidget( new QgsDetailedItemWidget() ),
00032 mpCheckBox( new QCheckBox() )
00033
00034 {
00035
00036 mpCheckBox->resize( mpCheckBox->sizeHint().height(), mpCheckBox->sizeHint().height() );
00037 setVerticalSpacing( 3 );
00038 setHorizontalSpacing( 5 );
00039 }
00040
00041 QgsDetailedItemDelegate::~QgsDetailedItemDelegate()
00042 {
00043 delete mpCheckBox;
00044 delete mpWidget;
00045 }
00046
00047 void QgsDetailedItemDelegate::paint( QPainter * thepPainter,
00048 const QStyleOptionViewItem & theOption,
00049 const QModelIndex & theIndex ) const
00050 {
00051
00052 thepPainter->save();
00053 if ( qVariantCanConvert<QgsDetailedItemData>( theIndex.data( Qt::UserRole ) ) )
00054 {
00055 QgsDetailedItemData myData =
00056 qVariantValue<QgsDetailedItemData>( theIndex.data( Qt::UserRole ) );
00057 if ( myData.isRenderedAsWidget() )
00058 {
00059 paintAsWidget( thepPainter, theOption, myData );
00060 }
00061 else
00062 {
00063 paintManually( thepPainter, theOption, myData );
00064 }
00065 }
00066 thepPainter->restore();
00067 }
00068
00069
00070
00071 QSize QgsDetailedItemDelegate::sizeHint(
00072 const QStyleOptionViewItem & theOption,
00073 const QModelIndex & theIndex ) const
00074 {
00075 if ( qVariantCanConvert<QgsDetailedItemData>( theIndex.data( Qt::UserRole ) ) )
00076 {
00077 QgsDetailedItemData myData =
00078 qVariantValue<QgsDetailedItemData>( theIndex.data( Qt::UserRole ) );
00079 if ( myData.isRenderedAsWidget() )
00080 {
00081 return QSize( 378, mpWidget->height() );
00082 }
00083 else
00084 {
00085
00086 return QSize( 50, height( theOption, myData ) );
00087
00088 }
00089 }
00090 else
00091 {
00092 return QSize( 50, 50 );
00093 }
00094 }
00095
00096 void QgsDetailedItemDelegate::paintManually( QPainter * thepPainter,
00097 const QStyleOptionViewItem & theOption,
00098 const QgsDetailedItemData theData ) const
00099 {
00100
00101
00102
00103
00104 mpCheckBox->setChecked( theData.isChecked() );
00105 mpCheckBox->setEnabled( theData.isEnabled() );
00106 QPixmap myCbxPixmap( mpCheckBox->size() );
00107 mpCheckBox->render( &myCbxPixmap );
00108
00109
00110
00111
00112
00113 QFontMetrics myTitleMetrics( titleFont( theOption ) );
00114 QFontMetrics myDetailMetrics( detailFont( theOption ) );
00115 int myTextStartX = theOption.rect.x() + horizontalSpacing();
00116 int myTextStartY = theOption.rect.y() + verticalSpacing();
00117 int myHeight = myTitleMetrics.height() + verticalSpacing();
00118
00119
00120
00121
00122 if ( theOption.state & QStyle::State_Selected )
00123 {
00124 drawHighlight( theOption, thepPainter, height( theOption, theData ) );
00125 thepPainter->setPen( theOption.palette.highlightedText().color() );
00126 }
00127 else
00128 {
00129 thepPainter->setPen( theOption.palette.text().color() );
00130 }
00131
00132
00133
00134
00135
00136 if ( theData.isCheckable() )
00137 {
00138 thepPainter->drawPixmap( theOption.rect.x(),
00139 theOption.rect.y() + mpCheckBox->height(),
00140 myCbxPixmap );
00141 myTextStartX = theOption.rect.x() + myCbxPixmap.width() + horizontalSpacing();
00142 }
00143
00144
00145
00146 bool myIconFlag = false;
00147 QPixmap myDecoPixmap = theData.icon();
00148 if ( !myDecoPixmap.isNull() )
00149 {
00150 thepPainter->drawPixmap( myTextStartX,
00151 myTextStartY + ( myDecoPixmap.height() / 2 ),
00152 myDecoPixmap );
00153 myTextStartX += myDecoPixmap.width() + horizontalSpacing();
00154 }
00155
00156
00157
00158 myTextStartY += myHeight / 2;
00159 thepPainter->setFont( titleFont( theOption ) );
00160 thepPainter->drawText( myTextStartX,
00161 myTextStartY,
00162 theData.title() );
00163
00164
00165
00166 thepPainter->setFont( detailFont( theOption ) );
00167 if ( myIconFlag )
00168 {
00169 myTextStartY += verticalSpacing();
00170 }
00171 else
00172 {
00173 myTextStartY += myDetailMetrics.height() + verticalSpacing();
00174 }
00175 QStringList myList =
00176 wordWrap( theData.detail(), myDetailMetrics, theOption.rect.width() - myTextStartX );
00177 QStringListIterator myLineWrapIterator( myList );
00178 while ( myLineWrapIterator.hasNext() )
00179 {
00180 QString myLine = myLineWrapIterator.next();
00181 thepPainter->drawText( myTextStartX,
00182 myTextStartY,
00183 myLine );
00184 myTextStartY += myDetailMetrics.height() - verticalSpacing();
00185 }
00186 }
00187
00188
00189 void QgsDetailedItemDelegate::paintAsWidget( QPainter * thepPainter,
00190 const QStyleOptionViewItem & theOption,
00191 const QgsDetailedItemData theData ) const
00192 {
00193
00194 mpWidget->setChecked( theData.isChecked() );
00195 mpWidget->setData( theData );
00196 mpWidget->resize( theOption.rect.width(), mpWidget->height() );
00197 mpWidget->setAutoFillBackground( true );
00198
00199 mpWidget->repaint();
00200 if ( theOption.state & QStyle::State_Selected )
00201 {
00202 drawHighlight( theOption, thepPainter, height( theOption, theData ) );
00203 }
00204 QPixmap myPixmap = QPixmap::grabWidget( mpWidget );
00205 thepPainter->drawPixmap( theOption.rect.x(),
00206 theOption.rect.y(),
00207 myPixmap );
00208 }
00209
00210 void QgsDetailedItemDelegate::drawHighlight( const QStyleOptionViewItem &theOption,
00211 QPainter * thepPainter,
00212 int theHeight ) const
00213 {
00214 QColor myColor1 = theOption.palette.highlight().color();
00215 QColor myColor2 = myColor1;
00216 myColor2 = myColor2.lighter( 110 );
00217 QLinearGradient myGradient( QPointF( 0, theOption.rect.y() ),
00218 QPointF( 0, theOption.rect.y() + theHeight ) );
00219 myGradient.setColorAt( 0, myColor1 );
00220 myGradient.setColorAt( 0.1, myColor2 );
00221 myGradient.setColorAt( 0.5, myColor1 );
00222 myGradient.setColorAt( 0.9, myColor2 );
00223 myGradient.setColorAt( 1, myColor2 );
00224 thepPainter->fillRect( theOption.rect, QBrush( myGradient ) );
00225 }
00226
00227 int QgsDetailedItemDelegate::height( const QStyleOptionViewItem & theOption,
00228 const QgsDetailedItemData theData ) const
00229 {
00230 QFontMetrics myTitleMetrics( titleFont( theOption ) );
00231 QFontMetrics myDetailMetrics( detailFont( theOption ) );
00232
00233 int myHeight = myTitleMetrics.height() + verticalSpacing();
00234
00235 QStringList myList = wordWrap( theData.detail(),
00236 myDetailMetrics,
00237 theOption.rect.width() - ( mpCheckBox->width() + horizontalSpacing() ) );
00238 myHeight += ( myList.count() + 1 ) * ( myDetailMetrics.height() - verticalSpacing() );
00239 return myHeight;
00240 }
00241
00242
00243 QFont QgsDetailedItemDelegate::detailFont( const QStyleOptionViewItem &theOption ) const
00244 {
00245 QFont myFont = theOption.font;
00246 return myFont;
00247 }
00248
00249 QFont QgsDetailedItemDelegate::titleFont( const QStyleOptionViewItem &theOption ) const
00250 {
00251 QFont myTitleFont = detailFont( theOption );
00252 myTitleFont.setBold( true );
00253 myTitleFont.setPointSize( myTitleFont.pointSize() );
00254 return myTitleFont;
00255 }
00256
00257
00258 QStringList QgsDetailedItemDelegate::wordWrap( QString theString,
00259 QFontMetrics theMetrics,
00260 int theWidth ) const
00261 {
00262 if ( theString.isEmpty() ) return QStringList();
00263 if ( 50 >= theWidth ) return QStringList() << theString;
00264
00265
00266
00267 QStringList myList;
00268 QString myCumulativeLine = "";
00269 QString myStringToPreviousSpace = "";
00270 int myPreviousSpacePos = 0;
00271 for ( int i = 0; i < theString.count(); ++i )
00272 {
00273 QChar myChar = theString.at( i );
00274 if ( myChar == QChar( ' ' ) )
00275 {
00276 myStringToPreviousSpace = myCumulativeLine;
00277 myPreviousSpacePos = i;
00278 }
00279 myCumulativeLine += myChar;
00280 if ( theMetrics.width( myCumulativeLine ) >= theWidth )
00281 {
00282
00283
00284
00285 myList << myStringToPreviousSpace.trimmed();
00286 i = myPreviousSpacePos;
00287 myStringToPreviousSpace = "";
00288 myCumulativeLine = "";
00289 }
00290 }
00291
00292 if ( !myCumulativeLine.trimmed().isEmpty() )
00293 {
00294 myList << myCumulativeLine.trimmed();
00295 }
00296
00297
00298
00299
00300 return myList;
00301
00302 }
00303
00304
00305
00306 int QgsDetailedItemDelegate::verticalSpacing() const
00307 {
00308 return mVerticalSpacing;
00309 }
00310
00311
00312 void QgsDetailedItemDelegate::setVerticalSpacing( int theValue )
00313 {
00314 mVerticalSpacing = theValue;
00315 }
00316
00317
00318 int QgsDetailedItemDelegate::horizontalSpacing() const
00319 {
00320 return mHorizontalSpacing;
00321 }
00322
00323
00324 void QgsDetailedItemDelegate::setHorizontalSpacing( int theValue )
00325 {
00326 mHorizontalSpacing = theValue;
00327 }