int TitleHeight() const { QFontMetrics titleMetrics( mTitleFont ); return titleMetrics.ascent() - titleMetrics.descent(); }
void BpDocument::composeTable3( int vid, EqVar *rowVar, EqVar *colVar ) { // START THE STANDARD PREAMBLE USED BY ALL TABLE COMPOSITION FUNCTIONS. // WIN98 requires that we actually create a font here and use it for // font metrics rather than using the widget's font. QFont subTitleFont( property()->string( "tableSubtitleFontFamily" ), property()->integer( "tableSubtitleFontSize" ) ); QPen subTitlePen( property()->color( "tableSubtitleFontColor" ) ); QFontMetrics subTitleMetrics( subTitleFont ); QFont textFont( property()->string( "tableTextFontFamily" ), property()->integer( "tableTextFontSize" ) ); QPen textPen( property()->color( "tableTextFontColor" ) ); QFontMetrics textMetrics( textFont ); QFont titleFont( property()->string( "tableTitleFontFamily" ), property()->integer( "tableTitleFontSize" ) ); QPen titlePen( property()->color( "tableTitleFontColor" ) ); QFontMetrics titleMetrics( titleFont ); QFont valueFont( property()->string( "tableValueFontFamily" ), property()->integer( "tableValueFontSize" ) ); QPen valuePen( property()->color( "tableValueFontColor" ) ); QFontMetrics valueMetrics( valueFont ); bool doRowBg = property()->boolean( "tableRowBackgroundColorActive" ); QBrush rowBrush( property()->color( "tableRowBackgroundColor" ), Qt::SolidPattern ); QString text(""); // Store pixel resolution into local variables. double yppi = m_screenSize->m_yppi; double xppi = m_screenSize->m_xppi; double m_padWd = m_pageSize->m_padWd; // Determine the height of the various display fonts. double textHt, titleHt, valueHt, rowHt, x0, x1; textHt = ( textMetrics.lineSpacing() + m_screenSize->m_padHt ) / yppi; titleHt = ( titleMetrics.lineSpacing() + m_screenSize->m_padHt ) / yppi; valueHt = ( valueMetrics.lineSpacing() + m_screenSize->m_padHt ) / yppi; rowHt = ( textHt > valueHt ) ? textHt : valueHt; // END THE STANDARD PREAMBLE USED BY ALL TABLE COMPOSITION FUNCTIONS. // Determine the number of rows we can display on a page. int rowsPerPage = (int) ( ( m_pageSize->m_bodyHt - 5. * titleHt - 4. * textHt ) / rowHt ); // Number of pages the table requires to accomodate all the rows. int pagesLong = 1 + (int) ( tableRows() / rowsPerPage ); // Arrays to hold the output values' column information. // Page on which the output value column appears. int *colPage = new int[ tableCols() ]; checkmem( __FILE__, __LINE__, colPage, "int colPage", tableCols() ); // Horizontal position of each output value column. double *colXPos = new double[ tableCols() ]; checkmem( __FILE__, __LINE__, colXPos, "double colXPos", tableCols() ); // Column header text. QString *colText = new QString[ tableCols() ]; checkmem( __FILE__, __LINE__, colText, "double colText", tableCols() ); // Prescription shading? bool doRx = property()->boolean( "tableShading" ); bool doBlank = property()->boolean( "tableShadingBlank" ); // Determine the row variable's (left-most) column width. int row, iid, cell; double len; QString qStr; // Start wide enough to hold the variable name and units. double rowWd = m_padWd + ( (double) headerWidth( rowVar, textMetrics ) / xppi ); // Enlarge it to hold the fattest row value. m_rowDecimals = 0; for ( row = 0; row < tableRows(); row++ ) { if ( rowVar->isDiscrete() ) { iid = (int) tableRow( row ); qStr = rowVar->m_itemList->itemName( iid ) + "MMM"; } else if ( rowVar->isContinuous() ) { // CDB DECIMALS MOD if ( false ) { qStr.sprintf( "%1.*fMMM", rowVar->m_displayDecimals, tableRow( row ) ); } else { // Start with 6 decimals for this row value int decimals = 6; qStr.sprintf( "%1.*f", decimals, tableRow( row ) ); // Remove all trailing zeros while ( qStr.endsWith( "0" ) ) { qStr = qStr.left( qStr.length()-1 ); decimals--; } // Update m_rowDecimals digits m_rowDecimals = ( decimals > m_rowDecimals ) ? decimals : m_rowDecimals; qStr.append( "MWM" ); } } len = (double) textMetrics.width( qStr ) / xppi; if ( len > rowWd ) { rowWd = len; } } // Find the fattest output value for this table variable. int col; int out = vid; EqVar *outVar = tableVar(vid); double colWd = 0; for ( row = 0; row < tableRows(); row++ ) { for ( col = 0; col < tableCols(); col++ ) { if ( outVar->isDiscrete() ) { iid = (int) tableVal( out ); qStr = outVar->m_itemList->itemName( iid ) + "WM"; } else if ( outVar->isContinuous() ) { qStr.sprintf( "%1.*fWM", outVar->m_displayDecimals, tableVal( out ) ); } len = (double) textMetrics.width( qStr ) / xppi; if ( len > colWd ) { colWd = len; } out += tableVars(); } // Next table column. } // Next table row. // Set the column header value text. m_colDecimals = 0; for ( col = 0; col < tableCols(); col++ ) { if ( colVar->isDiscrete() ) { iid = (int) tableCol( col ); colText[col] = colVar->m_itemList->itemName( iid ); } else if ( colVar->isContinuous() ) { // CDB DECIMALS MOD if ( false ) { colText[col].sprintf( " %1.*f", colVar->m_displayDecimals, tableCol( col ) ); } else { // Start with 6 decimals for this row value int decimals = 6; colText[col].sprintf( " %1.*f", decimals, tableCol( col ) ); // Remove all trailing zeros while ( colText[col].endsWith( "0" ) ) { colText[col] = colText[col].left( colText[col].length()-1 ); decimals--; } // Update Decimals digits m_colDecimals = ( decimals > m_colDecimals ) ? decimals : m_colDecimals; } } // Expand the column width to accomodate the header value text? len = (double) textMetrics.width( colText[col] ) / xppi; if ( len > colWd ) { colWd = len; } } // Next table column. // CDB DECIMALS MOD for ( col = 0; col < tableCols(); col++ ) { if ( colVar->isContinuous() ) { colText[col].sprintf( " %1.*f", m_colDecimals, tableCol( col ) ); } } // Add padding between each column. colWd += m_padWd; // Determine each column's position on each page. int pagesWide = 1; // Horizontal position of first column on the first page. double xpos = m_pageSize->m_bodyLeft + rowWd + 2. * m_padWd; for ( col = 0; col < tableCols(); col++ ) { // If past the right page edge, start a new page. if ( xpos + colWd > m_pageSize->m_bodyRight ) { // The table page width has just increased. pagesWide++; // This will be the first column on the new page. xpos = m_pageSize->m_bodyLeft + rowWd + 2. * m_padWd; } // Store the page and position of this output variable's column. colXPos[col] = xpos; colPage[col] = pagesWide; // Update the position pointer. xpos += ( 2. * m_padWd + colWd ); } // Determine the column title width (inches). double colTitleWd = textMetrics.width( *(colVar->m_label) ) / xppi; if ( ( textMetrics.width( colVar->m_displayUnits ) / xppi ) > colTitleWd ) { colTitleWd = textMetrics.width( colVar->m_displayUnits ) / xppi; } colTitleWd += ( 2. * m_padWd ); // Determine an offset shift to center each pageAcross. double *shift = new double[ pagesWide + 1 ]; checkmem( __FILE__, __LINE__, shift, "double shift", pagesWide + 1 ); for ( col = 0; col < tableCols(); col++ ) { // Table must be at least this wide. double minLeft = m_pageSize->m_bodyLeft + rowWd + 2. * m_padWd + colTitleWd; // Does it need to be wider to accomodate this column? if ( colXPos[col] + colWd > minLeft ) { minLeft = colXPos[col] + colWd; } // Just the last column of each page finally gets stored in shift[]. shift[colPage[col]] = 0.5 * ( m_pageSize->m_bodyRight - minLeft ); } // Start drawing the table. double yPos, s, bgLeft, bgRight, rightEdge, leftEdge; int i; // Loop for each page down. int thisPage = 1; for ( int pageDown = 1; pageDown <= pagesLong; pageDown++ ) { // Loop for each page across. for ( int pageAcross = 1; pageAcross <= pagesWide; pageAcross++, thisPage++ ) { // Table title indicates the table portion translate( text, "BpDocument:Table:PageOf", *(tableVar(vid)->m_label), QString( "%1" ).arg( thisPage ), QString( "%1" ).arg( pagesLong * pagesWide ) ); // Start a new page startNewPage( text, TocTable ); yPos = m_pageSize->m_marginTop + titleHt; // Draw a map of where we are. composePageMap( ( 2. * titleHt - 0.1 ), pagesLong, pagesWide, pagesLong, pagesWide, 1, 1, pageDown-1, pageAcross-1 ); // Display the table title::description m_composer->font( titleFont ); // use tableTitleFont m_composer->pen( titlePen ); // use tableTitleFontColor qStr = m_eqTree->m_eqCalc->docDescriptionStore().stripWhiteSpace(); m_composer->text( m_pageSize->m_marginLeft, yPos, // start at UL corner m_pageSize->m_bodyWd, titleHt,// width and height Qt::AlignVCenter|Qt::AlignHCenter, // center alignement qStr ); // display description yPos += titleHt; // Display the table title::variable m_composer->font( subTitleFont ); // use tableSubtitleFont m_composer->pen( subTitlePen ); // use tableSubtitleFontColor qStr = *(outVar->m_label); if ( outVar->isContinuous() ) { qStr = *(outVar->m_label) + " " + outVar->displayUnits(true); } m_composer->text( m_pageSize->m_marginLeft, yPos, // start at UL corner m_pageSize->m_bodyWd, titleHt,// width and height Qt::AlignVCenter|Qt::AlignHCenter, // center alignment qStr ); // table variable name yPos += titleHt; // Display the table title::portion //m_composer->text( // m_pageSize->m_marginLeft, yPos, // m_pageSize->m_bodyWd, titleHt, // Qt::AlignVCenter|Qt::AlignHCenter, // portion ); //yPos += titleHt; yPos += titleHt; // Everything else on this page is shifted s = shift[pageAcross]; // Determine left and right edges of the table. leftEdge = -1; for ( col = 0; col < tableCols(); col++ ) { if ( pageAcross == colPage[col] ) { rightEdge = colXPos[col] + colWd + s; if ( leftEdge < 0. ) { leftEdge = colXPos[col] + s; } } } // Must be at least wide enough to accomodate column header text. if ( rightEdge < leftEdge + colTitleWd ) { rightEdge = leftEdge + colTitleWd; } bgLeft = m_pageSize->m_marginLeft + s - m_padWd ; bgRight = rightEdge - leftEdge + rowWd + 4 * m_padWd ; // Display a colored row column header background? if ( doRowBg ) { m_composer->fill( bgLeft, yPos, bgRight, 3 * textHt, rowBrush ); } // Display the row column header0. m_composer->font( textFont ); // use tableTextFont m_composer->pen( textPen ); // use tableTextFontColor m_composer->text( m_pageSize->m_marginLeft + s, yPos, rowWd, textHt, Qt::AlignVCenter|Qt::AlignLeft, *(rowVar->m_hdr0) ); // Display the row column header1. m_composer->text( m_pageSize->m_marginLeft + s, yPos + textHt, rowWd, textHt, Qt::AlignVCenter|Qt::AlignLeft, *(rowVar->m_hdr1) ); // Display the row column units. m_composer->text( m_pageSize->m_marginLeft + s, yPos + 2. * textHt, rowWd, textHt, Qt::AlignVCenter|Qt::AlignLeft, rowVar->displayUnits() ); // Display the row column header underline // only if we are not coloring row backgrounds. int skipLines = 3; if ( ! doRowBg ) { m_composer->line( m_pageSize->m_marginLeft + s, yPos + 3.5 * textHt, m_pageSize->m_marginLeft + rowWd + s, yPos + 3.5 * textHt ); skipLines = 4; } // Display the output column headers. for ( col = 0; col < tableCols(); col++ ) { if ( pageAcross == colPage[col] ) { // Display the output column units. m_composer->text( colXPos[col] + s, yPos + 2. * textHt, colWd, textHt, Qt::AlignVCenter|Qt::AlignRight, colText[col] ); // Display the output column underline. if ( ! doRowBg ) { m_composer->line( colXPos[col] + s, yPos + 3.5 * textHt, colXPos[col] + colWd + s, yPos + 3.5 * textHt ); } } } // Display a centered column variable name and units header. m_composer->text( leftEdge, yPos, ( rightEdge - leftEdge ), textHt, Qt::AlignVCenter|Qt::AlignHCenter, *(colVar->m_label) ); if ( colVar->isContinuous() ) { m_composer->text( leftEdge, yPos + textHt, ( rightEdge - leftEdge ), textHt, Qt::AlignVCenter|Qt::AlignHCenter, colVar->displayUnits() ); } // If there are previous columns, display a visual cue. if ( pageAcross > 1 ) { for ( i = 0; i < 3; i++ ) { m_composer->text( 0, ( yPos + i * textHt ), ( m_pageSize->m_marginLeft + s - m_padWd ), textHt, Qt::AlignVCenter|Qt::AlignRight, "<" ); } } // If there are subsequent column pages, display a visual clue. if ( pageAcross < pagesWide ) { for ( i = 0; i < 3; i++ ) { m_composer->text( ( rightEdge + m_padWd ), ( yPos + i * textHt ), ( m_pageSize->m_pageWd - rightEdge ), textHt, Qt::AlignVCenter|Qt::AlignLeft, ">" ); } } // Set vertical start of rows. yPos += skipLines * textHt; // Determine the rows range to display on this page. int rowFrom = ( pageDown - 1 ) * rowsPerPage; int rowThru = pageDown * rowsPerPage - 1; if ( rowThru >= tableRows() ) { rowThru = tableRows() - 1; } // Determine the columns range to display on this page. int colFrom = -1; int colThru = 0; for ( col = 0; col < tableCols(); col++ ) { if ( colPage[col] == pageAcross ) { if ( colFrom == -1 ) { colFrom = col; } colThru = col; } } // Loop for each row on this page. bool doThisRowBg = false; for ( row = rowFrom; row <= rowThru; row++ ) { // Display a colored row background? if ( doRowBg && doThisRowBg ) { m_composer->fill( bgLeft, yPos, bgRight, textHt, rowBrush ); } doThisRowBg = ! doThisRowBg; // Left-most (row variable) column value. if ( rowVar->isDiscrete() ) { iid = (int) tableRow( row ); qStr = rowVar->m_itemList->itemName( iid ); } else if ( rowVar->isContinuous() ) { // CDB DECIMALS MOD if ( false ) { qStr.sprintf( "%1.*f", rowVar->m_displayDecimals, tableRow( row ) ); } else { qStr.sprintf( "%1.*f", m_rowDecimals, tableRow( row ) ); } } m_composer->font( textFont ); // use tableTextFont m_composer->pen( textPen ); // use tableTextFontColor m_composer->text( m_pageSize->m_marginLeft + s, yPos, rowWd, textHt, Qt::AlignVCenter|Qt::AlignLeft, qStr ); // Loop for each column value on this page. m_composer->font( valueFont ); // use tableValueFont m_composer->pen( valuePen ); // use tableValueFontColor out = vid + colFrom * tableVars() + row * tableCols() * tableVars(); for ( col = colFrom; col <= colThru; col++ ) { // Determine whether to hatch this cell cell = col + row * tableCols(); bool hatch = doRx && ! tableInRx( cell ); // Discrete variables use their item name. if ( outVar->isDiscrete() ) { iid = (int) tableVal( out ); qStr = outVar->m_itemList->itemName( iid ); } // Continuous variables use the current display units format. else if ( outVar->isContinuous() ) { qStr.sprintf( " %1.*f", outVar->m_displayDecimals, tableVal( out ) ); } // Display the output value. if ( hatch && doBlank ) { // draw nothing } else { m_composer->text( colXPos[col] + s, yPos, colWd, textHt, Qt::AlignVCenter|Qt::AlignRight, qStr ); } out += tableVars(); // RX hatching if ( hatch && ! doBlank && ! outVar->isDiagram() ) { x0 = colXPos[col] + s - m_padWd; x1 = colXPos[col] + s + m_padWd + colWd; m_composer->line( x0, yPos, x1, ( yPos + textHt ) ); m_composer->line( x0, ( yPos + textHt ), x1, yPos ); } } // Next table output variable. yPos += rowHt; } // Next table row. } // Next pageAcross. } // Next pageDown. // Be polite and stop the composer. m_composer->end(); // Clean up and return. delete[] colPage; delete[] colXPos; delete[] colText; delete[] shift; return; }
void BpDocument::composeTable1( void ) { // START THE STANDARD PREAMBLE USED BY ALL TABLE COMPOSITION FUNCTIONS. // WIN98 requires that we actually create a font here and use it for // font metrics rather than using the widget's font. QFont textFont( property()->string( "tableTextFontFamily" ), property()->integer( "tableTextFontSize" ) ); QPen textPen( property()->color( "tableTextFontColor" ) ); QFontMetrics textMetrics( textFont ); QFont titleFont( property()->string( "tableTitleFontFamily" ), property()->integer( "tableTitleFontSize" ) ); QPen titlePen( property()->color( "tableTitleFontColor" ) ); QFontMetrics titleMetrics( titleFont ); QFont valueFont( property()->string( "tableValueFontFamily" ), property()->integer( "tableValueFontSize" ) ); QPen valuePen( property()->color( "tableValueFontColor" ) ); QFontMetrics valueMetrics( valueFont ); // Store pixel resolution into local variables. double yppi = m_screenSize->m_yppi; double xppi = m_screenSize->m_xppi; double textHt, titleHt, valueHt; textHt = ( textMetrics.lineSpacing() + m_screenSize->m_padHt ) / yppi; titleHt = ( titleMetrics.lineSpacing() + m_screenSize->m_padHt ) / yppi; valueHt = ( valueMetrics.lineSpacing() + m_screenSize->m_padHt ) / yppi; // END THE STANDARD PREAMBLE USED BY ALL TABLE COMPOSITION FUNCTIONS QString results(""); translate( results, "BpDocument:Table:Results" ); // Determine variable label, value, and units minimum column widths. int nameWdPixels = 0; int resultWdPixels = 0; int unitsWdPixels = 0; int vid, len; QString qStr; EqVar *varPtr; // Loop for each output variable. for ( vid = 0; vid < tableVars(); vid++ ) { varPtr = tableVar(vid); // Label width. len = textMetrics.width( *(varPtr->m_label) ); if ( len > nameWdPixels ) { nameWdPixels = len; } // Units width. len = textMetrics.width( varPtr->m_displayUnits ); if ( len > unitsWdPixels ) { unitsWdPixels = len; } // Value width. if ( varPtr->isContinuous() ) { qStr.sprintf( "%1.*f", varPtr->m_displayDecimals, tableVal(vid) ); len = valueMetrics.width( qStr ); if ( len > resultWdPixels ) { resultWdPixels = len; } } else if ( varPtr->isDiscrete() ) { int iid = (int) tableVal(vid); qStr = varPtr->m_itemList->itemName(iid); len = valueMetrics.width( varPtr->m_itemList->itemName(iid) ); if ( len > resultWdPixels ) { resultWdPixels = len; } } } // Add padding for differences in screen and printer font sizes int wmPad = textMetrics.width( "WM" ); unitsWdPixels += wmPad; nameWdPixels += wmPad; resultWdPixels += valueMetrics.width( "WM" ); // If the name is too wide for the page, reduce the name field width. if ( ( nameWdPixels + unitsWdPixels + resultWdPixels + 2 * m_screenSize->m_padWd ) > m_screenSize->m_bodyWd ) { nameWdPixels = m_screenSize->m_bodyWd - resultWdPixels - unitsWdPixels - 2 * m_screenSize->m_padWd; } // Convert name and units widths from pixels to inches. double resultWd = (double) resultWdPixels / xppi; double nameWd = (double) nameWdPixels / xppi; double unitsWd = (double) unitsWdPixels / xppi; // Determine offset (inches) required to horizontally center the table. double offsetX = ( m_screenSize->m_bodyWd - nameWdPixels - resultWdPixels - ( unitsWdPixels - wmPad ) - 2 * m_screenSize->m_padWd ) / ( 2. * xppi ); // Determine column offsets. double nameColX = m_pageSize->m_marginLeft + offsetX; double resultColX = nameColX + nameWd + m_pageSize->m_padWd; double unitsColX = resultColX + resultWd + m_pageSize->m_padWd; // Open the composer and start with a new page. startNewPage( results, TocListOut ); double yPos = m_pageSize->m_marginTop + titleHt; // Print the table header. m_composer->font( titleFont ); // use tableTitleFont m_composer->pen( titlePen ); // use tableTitleFontColor qStr = m_eqTree->m_eqCalc->docDescriptionStore().stripWhiteSpace(); //if ( qStr.isNull() || qStr.isEmpty() ) //{ // translate( qStr, "BpDocument:NoRunDescription" ); //} m_composer->text( m_pageSize->m_marginLeft, yPos, // start at UL corner m_pageSize->m_bodyWd, titleHt, // width and height Qt::AlignVCenter|Qt::AlignCenter, // center alignment qStr ); // display description yPos += titleHt; // Draw each output variable on its own line. m_composer->font( textFont ); m_composer->pen( textPen ); for ( vid = 0; vid < tableVars(); vid++ ) { varPtr = tableVar(vid); if ( varPtr->isDiagram() ) { continue; } // Get the next y position. if ( ( yPos += textHt ) > m_pageSize->m_bodyEnd ) { startNewPage( results, TocBlank ); yPos = m_pageSize->m_marginTop; } // Write the variable name. m_composer->font( textFont ); // use tableTextFont m_composer->pen( textPen ); // use tableTextFontColor qStr = *(varPtr->m_label); // display label text m_composer->text( nameColX, yPos, // start at UL corner nameWd, textHt, // width and height Qt::AlignVCenter|Qt::AlignLeft, // left justified qStr ); // display label text // Continuous variable value and units. if ( varPtr->isContinuous() ) { qStr.sprintf( "%1.*f", varPtr->m_displayDecimals, tableVal(vid) ); m_composer->font( valueFont ); // use tableValueFont m_composer->pen( valuePen ); // use tableValueFontColor m_composer->text( resultColX, yPos, // start at UL corner resultWd, valueHt, // width and height Qt::AlignVCenter|Qt::AlignRight, // right justified qStr ); // display value text m_composer->font( textFont ); // use tableTextFont m_composer->pen( textPen ); // use tableTextFontColor m_composer->text( unitsColX, yPos, // start at UL corner unitsWd, textHt, // width and height Qt::AlignVCenter|Qt::AlignLeft, // left justified varPtr->displayUnits() ); // display units text } // Discrete variable value name else if ( varPtr->isDiscrete() ) { int id = (int) tableVal(vid); m_composer->font( valueFont ); // use tableValueFont m_composer->pen( valuePen ); // use tableValueFontColor m_composer->text( resultColX, yPos, // start at UL corner resultWd, valueHt, // width and height Qt::AlignVCenter|Qt::AlignRight, // right justify varPtr->m_itemList->itemName(id) ); // display item name } } // Write any prescription results if ( false && property()->boolean( "tableShading" ) ) { // Get the next y position. if ( ( yPos += textHt ) > m_pageSize->m_bodyEnd ) { startNewPage( results, TocBlank ); yPos = m_pageSize->m_marginTop; } // Write the prescription label m_composer->font( textFont ); // use tableTextFont m_composer->pen( textPen ); // use tableTextFontColor translate( qStr, "BpDocument:Results:RxVar:Label" ); m_composer->text( nameColX, yPos, // start at UL corner nameWd, textHt, // width and height Qt::AlignVCenter|Qt::AlignLeft, // left justified qStr ); // display label text // Write the result translate( qStr, tableInRx(0) ? "BpDocument:Results:RxVar:Yes" : "BpDocument:Results:RxVar:No" ); m_composer->font( valueFont ); // use tableValueFont m_composer->pen( valuePen ); // use tableValueFontColor m_composer->text( resultColX, yPos, // start at UL corner resultWd, valueHt, // width and height Qt::AlignVCenter|Qt::AlignRight, // right justify qStr ); // display item name } // Be polite and stop the composer. m_composer->end(); // Write the spreadsheet files composeTable1Spreadsheet(); composeTable1Html(); return; }
void GetNewStuffDelegate::paint( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const { QStyleOptionViewItemV4 opt = option; initStyleOption( &opt, index ); QApplication::style()->drawPrimitive( QStyle::PE_PanelItemViewItem, &opt, painter, opt.widget ); painter->setRenderHint( QPainter::Antialiasing ); QFont titleFont = opt.font; titleFont.setBold( true ); titleFont.setPointSize( titleFont.pointSize() + 2 ); QFontMetrics titleMetrics( titleFont ); QFont authorFont = opt.font; authorFont.setItalic( true ); authorFont.setPointSize( authorFont.pointSize() - 1 ); QFontMetrics authorMetrics( authorFont ); QFont descFont = authorFont; descFont.setItalic( false ); QFontMetrics descMetrics( descFont ); QFont installFont = opt.font; installFont.setPointSize( installFont.pointSize() - 1 ); QFontMetrics installMetrics( descFont ); const int height = opt.rect.height(); const int center = height / 2 + opt.rect.top(); // Pixmap QPixmap p = index.data( Qt::DecorationRole ).value< QPixmap >(); const int pixmapWidth = height - 2*PADDING; QRect pixmapRect( PADDING, PADDING + opt.rect.top(), pixmapWidth, pixmapWidth ); if ( p.isNull() ) // default image... TODO p = m_defaultCover; else p = p.scaled( pixmapRect.size(), Qt::KeepAspectRatio, Qt::SmoothTransformation ); painter->drawPixmap( pixmapRect, p ); // Go from right edge now, stars, install button, and downloaded info // install / status button AtticaManager::ResolverState state = static_cast< AtticaManager::ResolverState >( index.data( GetNewStuffModel::StateRole ).toInt() ); QString actionText; switch( state ) { case AtticaManager::Uninstalled: actionText = tr( "Install" ); break; case AtticaManager::Installing: actionText = tr( "Installing" ); break; case AtticaManager::Upgrading: actionText = tr( "Upgrading" ); break; case AtticaManager::Failed: actionText = tr( "Failed" ); break; case AtticaManager::Installed: actionText = tr( "Uninstall" ); break; case AtticaManager::NeedsUpgrade: actionText = tr( "Upgrade" ); break; } const int btnWidth = m_widestTextWidth + 7; const int leftEdge = opt.rect.width() - PADDING - btnWidth - 3; const QRect btnRect( leftEdge, center - ( installMetrics.height() + 4 ) / 2, btnWidth, installMetrics.height() + 4 ); m_cachedButtonRects[ QPair<int, int>(index.row(), index.column()) ] = btnRect; QPen saved = painter->pen(); painter->setPen( opt.palette.color( QPalette::Active, QPalette::AlternateBase ) ); QPainterPath btnPath; const int radius = 3; //btnPath.addRoundedRect( btnRect, 3, 3 ); // draw top half gradient const int btnCenter = btnRect.bottom() - ( btnRect.height() / 2 ); btnPath.moveTo( btnRect.left(), btnCenter ); btnPath.lineTo( btnRect.left(), btnRect.top() + radius ); btnPath.quadTo( QPoint( btnRect.topLeft() ), QPoint( btnRect.left() + radius, btnRect.top() ) ); btnPath.lineTo( btnRect.right() - radius, btnRect.top() ); btnPath.quadTo( QPoint( btnRect.topRight() ), QPoint( btnRect.right(), btnRect.top() + radius ) ); btnPath.lineTo( btnRect.right(),btnCenter ); btnPath.lineTo( btnRect.left(), btnCenter ); QLinearGradient g; g.setColorAt( 0, QColor(54, 127, 211) ); g.setColorAt( 0.5, QColor(43, 104, 182) ); //painter->setPen( bg.darker() ); painter->fillPath( btnPath, g ); //painter->drawPath( btnPath ); btnPath = QPainterPath(); btnPath.moveTo( btnRect.left(), btnCenter ); btnPath.lineTo( btnRect.left(), btnRect.bottom() - radius ); btnPath.quadTo( QPoint( btnRect.bottomLeft() ), QPoint( btnRect.left() + radius, btnRect.bottom() ) ); btnPath.lineTo( btnRect.right() - radius, btnRect.bottom() ); btnPath.quadTo( QPoint( btnRect.bottomRight() ), QPoint( btnRect.right(), btnRect.bottom() - radius ) ); btnPath.lineTo( btnRect.right(), btnCenter ); btnPath.lineTo( btnRect.left(), btnCenter ); g.setColorAt( 0, QColor(34, 85, 159) ); g.setColorAt( 0.5, QColor(35, 79, 147) ); painter->fillPath( btnPath, g ); painter->setFont( installFont ); painter->drawText( btnRect, Qt::AlignCenter, actionText ); painter->setPen( saved ); // rating stars int rating = index.data( GetNewStuffModel::RatingRole ).toInt(); const int ratingWidth = 5 * ( m_ratingStarPositive.width() + PADDING_BETWEEN_STARS ); int runningEdge = ( btnRect.right() - btnRect.width() / 2 ) - ratingWidth / 2; for ( int i = 1; i < 6; i++ ) { QRect r( runningEdge, btnRect.top() - m_ratingStarPositive.height() - PADDING, m_ratingStarPositive.width(), m_ratingStarPositive.height() ); if ( i == 1 ) m_cachedStarRects[ QPair<int, int>(index.row(), index.column()) ] = r; const bool userHasRated = index.data( GetNewStuffModel::UserHasRatedRole ).toBool(); if ( !userHasRated && // Show on-hover animation if the user hasn't rated it yet, and is hovering over it m_hoveringOver > -1 && m_hoveringItem == index ) { if ( i <= m_hoveringOver ) // positive star painter->drawPixmap( r, m_onHoverStar ); else painter->drawPixmap( r, m_ratingStarNegative ); } else { if ( i <= rating ) // positive or rated star { if ( userHasRated ) painter->drawPixmap( r, m_onHoverStar ); else painter->drawPixmap( r, m_ratingStarPositive ); } else painter->drawPixmap( r, m_ratingStarNegative ); } runningEdge += m_ratingStarPositive.width() + PADDING_BETWEEN_STARS; } // downloaded num times, underneath button QString count = tr( "%1 downloads" ).arg( index.data( GetNewStuffModel::DownloadCounterRole ).toInt() ); const QRect countRect( btnRect.left(), btnRect.bottom() + PADDING, btnRect.width(), opt.rect.bottom() - PADDING - btnRect.bottom() ); QFont countFont = descFont; countFont.setPointSize( countFont.pointSize() - 2 ); countFont.setBold( true ); painter->setFont( countFont ); painter->drawText( countRect, Qt::AlignCenter | Qt::TextWordWrap, count ); // author and version QString author = index.data( GetNewStuffModel::AuthorRole ).toString(); const int authorWidth = authorMetrics.width( author ); const int topTextLine = opt.rect.top() + PADDING; const QRect authorRect( btnRect.x() - 3*PADDING - authorWidth, topTextLine, authorWidth + 6, authorMetrics.height() ); painter->setFont( authorFont ); painter->drawText( authorRect, Qt::AlignCenter, author ); const QRect versionRect = authorRect.translated( 0, authorRect.height() ); QString version = index.data( GetNewStuffModel::VersionRole ).toString(); painter->drawText( versionRect, Qt::AlignCenter, version ); // title QString title = index.data( Qt::DisplayRole ).toString(); const int rightTitleEdge = authorRect.left() - PADDING; const int leftTitleEdge = pixmapRect.right() + PADDING; const QRect textRect( leftTitleEdge, topTextLine, rightTitleEdge - leftTitleEdge, versionRect.bottom() - opt.rect.top() - PADDING ); painter->setFont( titleFont ); painter->drawText( textRect, Qt::AlignVCenter | Qt::AlignLeft, title ); // description QString desc = index.data( GetNewStuffModel::DescriptionRole ).toString(); const int descWidth = btnRect.left() - leftTitleEdge - PADDING; const QRect descRect( leftTitleEdge, versionRect.bottom(), descWidth, opt.rect.bottom() - versionRect.bottom() + PADDING ); painter->setFont( descFont ); painter->drawText( descRect, Qt::AlignLeft | Qt::TextWordWrap, desc ); }