Exemple #1
0
/** Draws the label using the specificed painter & x/y-offsets */
void MLabelObject::draw( QPainter* p, int xoffset, int yoffset )
{
    QFont font( fontFamily, fontSize, fontWeight, fontItalic );
    QPen textPen( foregroundColor, 0, QPen::NoPen );

    int tf;

    // Set the offsets
    int xcalc = xpos + xoffset;
    int ycalc = ypos + yoffset;

    // Draw the base
    drawBase( p, xoffset, yoffset );

    // Set the font
    p->setFont( font );
    QFontMetrics fm = p->fontMetrics();

    // Set the text alignment flags

    // Horizontal
    switch ( hAlignment )
    {
    case MLabelObject::Left:
        tf = QPainter::AlignLeft;
        break;
    case MLabelObject::Center:
        tf = QPainter::AlignHCenter;
        break;
    case MLabelObject::Right:
        tf = QPainter::AlignRight;
    }

    // Vertical
    switch ( vAlignment )
    {
    case MLabelObject::Top:
        tf = tf | QPainter::AlignTop;
        break;
    case MLabelObject::Bottom:
        tf = tf | QPainter::AlignBottom;
        break;
    case MLabelObject::Middle:
        tf = tf | QPainter::AlignVCenter;
    }

    // Word wrap
    if ( wordWrap )
        tf = tf | QPainter::WordBreak;

    // Draw the text
    p->setPen( textPen );
    p->drawText( xcalc + xMargin, ycalc + yMargin,
                 width - xMargin, height - yMargin,
                 tf, text );
}
Exemple #2
0
// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
// ---- paint
// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
void Shape::paint( QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget )
{
	QPen textPen( getTextColor() );
	
	painter->setPen( textPen );
	painter->drawText
	(
		option->rect.x() + option->rect.width ()/2 - QFontMetricsF(painter->font()).width ( getText() )/2, 
		option->rect.y() + option->rect.height()/2 + QFontMetricsF(painter->font()).height(           )/3,
		getText()
	);
}
Exemple #3
0
void LogView::createHeader() {
    _headerScene->clear();
    _hourScene->clear();

    QSize size = headerSizeHint();

    QLinearGradient grad(0, 0, 0, size.height());
    int dark = 210;
    grad.setColorAt(1, QColor(dark, dark, dark));
    grad.setColorAt(0.7, QColor(dark + 20, dark + 20, dark + 20));
    grad.setColorAt(0, Qt::white);
    QBrush background(grad);
    QPen pen(QColor(220, 220, 220));
    QSize sizeHint = _logScene->viewSizeHint();
    _headerScene->addRect(0, 0, sizeHint.width() + verticalScrollBar()->width() + 200, size.height() + 1, pen, background)->setZValue(0);

    int columnSize = _logScene->dayWidth();

    DateTime startDate = _logScene->startDate().addDays(-1);
    DateTime today;
    today.setHour(0);
    today.setMin(0);
    today.setSecs(0);
    for (int x = 0; x < _logScene->totalDays(); x++) {
        QPen textPen(Qt::black);
        QGraphicsSimpleTextItem* text = _headerScene->addSimpleText(startDate.addDays(1).toQDateTime().toString("dd-MMM"), QFont("Arial", 8));
        text->setPos((x * columnSize + 2) + 50, 3);
        text->setVisible(true);
//        text->setPen(textPen);
        text->setZValue(1);
        if (startDate == today) {
            _todayPos = (x * columnSize + 2);
        }
        startDate = startDate.addDays(1);
    }
    _headerView.setMaximumHeight(headerSizeHint().height());

    for (int x = 0; x < 24; x++) {
        _hourScene->addRect(0, x*BLOCKSIZE, 50, BLOCKSIZE, pen, background)->setZValue(0);
        std::stringstream ss;
        ss << x << ":00";
        QGraphicsSimpleTextItem* text = _hourScene->addSimpleText(ss.str().c_str());
        text->setPos(10, (x * BLOCKSIZE) + 10);
        text->setVisible(true);
//        text->setPen(textPen);
        text->setZValue(1);
    }
    _hourView.setScene(_hourScene);
    _hourView.setMaximumWidth(50);
}
void FramesWeightFrame::drawWeights()
{
  if(!offscreen) return;

  QPainter p(offscreen);
  QColor boxColor = QColor("#5c4179");

  p.fillRect(0, 0, frames_count*FrameBarWidth, TrackHeight, boxColor);

  //emphasize the first frame if it's T-pose
  if(_anim->isFirstFrameTPose())
    p.fillRect(0, 0, FrameBarWidth, TrackHeight, QColor("#84365D"));

  double hFactor = ((double)TrackHeight) / 100.0;
  QColor barColor("#999999");

  for(int i=0; i<frames_count; i++)
  {
    int barHeight = (int)(frameWeights[i] * hFactor);
    if(i==weightedFrame)
      p.fillRect(i*FrameBarWidth +1, TrackHeight-barHeight, FrameBarWidth-2, barHeight, QColor("#0080ff"));
    else
      p.fillRect(i*FrameBarWidth +1, TrackHeight-barHeight, FrameBarWidth-2, barHeight, barColor);

    if(weightedFrame!=-1)
    {
      int w = frameWeights[weightedFrame];
      QPen textPen(QColor("#f8f8f8"));
      QFont f ("Arial", 11, QFont::Normal);
      p.setPen(textPen);
      p.setFont(f);

     //for some galactic reason the center alignment doesn't work as expected, so must be done manually
      if(w==100)
        p.drawText(weightedFrame*FrameBarWidth-FrameBarWidth, TrackHeight-TextSize,
                   FrameBarWidth*3, TextSize, Qt::AlignJustify, QString::number(w));
      else if(w<10)
        p.drawText(weightedFrame*FrameBarWidth, TrackHeight-TextSize,
                   FrameBarWidth, TextSize, Qt::AlignJustify, QString::number(w));
      else    //10-99
        p.drawText(weightedFrame*FrameBarWidth-(FrameBarWidth/2), TrackHeight-TextSize,
                   FrameBarWidth*2, TextSize, Qt::AlignJustify, QString::number(w));
    }
  }
}
void dialogAnalog::initPixmap(QSize size)
{
	// resize the pixmap
	//	complete it
	// Draw plot
	QPainter painter;
    int heightPerField = size.height() / NbBits;
	
	lastPixmap=QPixmap( size.width(), size.height() );
	lastPixmap.fill(Qt::black);
	painter.begin(&lastPixmap);
	
    // set font ------------------------------------------------------------------------------------
    QFont textFont;
    textFont.setPixelSize(heightPerField / 2);
    painter.setFont(textFont);

    // set the needed pens -------------------------------------------------------------------------
	QPen linePen(QColor(100,100,100));
    QPen textPen(QColor(255, 255, 255));
    QPen gridPen(QColor(100, 100, 100));
    QColor greenColor(Qt::green);
    QPen dataPen(greenColor);

	// draw the fields and the text ----------------------------------------------------------------
    {
        int current = heightPerField;
        for (int i = 0; i < (NbBits - 1); i++)
        {
            painter.setPen(linePen);
            painter.drawLine(0, current, size.width(), current);
            
            painter.setPen(textPen);
            QString lbl = QString::number(i+1);
            if (currentlabels.contains(i+1)) lbl += "-"+currentlabels[i+1];
            painter.drawText(10, current - heightPerField / 3, lbl);
            current += heightPerField;
        }
        painter.setPen(textPen);
        painter.drawText(10, current - 15, QString::number(NbBits));
    }

	painter.end();
}
Exemple #6
0
void SceneGraphConnection::paint(QPainter* painter)
{
    painter->setRenderHints(QPainter::Antialiasing, true);
    
    if(!m_selected){
        if(m_type == In)
            m_connFillBrush = QBrush(QColor(DESELECTED_IN_CONNECTOR_COLOR));
        else
            m_connFillBrush = QBrush(QColor(DESELECTED_OUT_CONNECTOR_COLOR));
    } else {
        m_connFillBrush = QBrush(QColor(SELECTED_CONNECTOR_COLOR));
    }
   
    painter->setBrush(m_connFillBrush);

    // text block 
    if(m_type == In)
        painter->drawRect(CONNECTION_WIDTH+2,0,width(),height());
    else
        painter->drawRect(0,0,width()-CONNECTION_WIDTH,height());
 
    QPen textPen(QColor(NODE_TEXT_COLOR),2);
    QFont textFont("DejaVuSans",7);
    painter->setPen(textPen);
    painter->setFont(textFont);
    if(m_type == In) {
        painter->drawText(QRect(CONNECTION_WIDTH+2,0,NODE_WIDTH/2,height()),Qt::AlignLeft|Qt::AlignVCenter,m_name);
    } else {
        painter->drawText(QRect(0,0,(NODE_WIDTH/2)-2,height()),Qt::AlignRight|Qt::AlignVCenter,m_name);
    }


    if(m_type == In) {
        painter->drawRect(0,0,CONNECTION_WIDTH,CONNECTION_HEIGHT);
    } else {
        painter->drawRect(NODE_WIDTH/2,0,CONNECTION_WIDTH,CONNECTION_HEIGHT);
    }

}
/*!
  Draw an entry on the legend

  \param painter Qt Painter
  \param plotItem Plot item, represented by the entry
  \param data Attributes of the legend entry
  \param rect Bounding rectangle for the entry
 */
void QwtPlotLegendItem::drawLegendData( QPainter *painter,
    const QwtPlotItem *plotItem, const QwtLegendData &data, 
    const QRectF &rect ) const
{
    Q_UNUSED( plotItem );

    const int m = d_data->itemMargin;
    const QRectF r = rect.toRect().adjusted( m, m, -m, -m );

    painter->setClipRect( r, Qt::IntersectClip );

    int titleOff = 0;

    const QwtGraphic graphic = data.icon();
    if ( !graphic.isEmpty() )
    {
        QRectF iconRect( r.topLeft(), graphic.defaultSize() );

        iconRect.moveCenter( 
            QPoint( iconRect.center().x(), rect.center().y() ) );

        graphic.render( painter, iconRect, Qt::KeepAspectRatio );

        titleOff += iconRect.width() + d_data->itemSpacing;
    }

    const QwtText text = data.title();
    if ( !text.isEmpty() )
    {
        painter->setPen( textPen() );
        painter->setFont( font() );

        const QRectF textRect = r.adjusted( titleOff, 0, 0, 0 );
        text.draw( painter, textRect );
    }
}
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;
}
Exemple #9
0
void PieView::paintEvent(QPaintEvent *event)
{
    QItemSelectionModel *selections = selectionModel();
    QStyleOptionViewItem option = viewOptions();
    QStyle::State state = option.state;

    QBrush background = option.palette.base();
    QPen foreground(option.palette.color(QPalette::WindowText));
    QPen textPen(option.palette.color(QPalette::Text));
    QPen highlightedPen(option.palette.color(QPalette::HighlightedText));

    QPainter painter(viewport());
    painter.setRenderHint(QPainter::Antialiasing);

    painter.fillRect(event->rect(), background);
    painter.setPen(foreground);

    // Viewport rectangles
    QRect pieRect = QRect(margin, margin, pieSize, pieSize);
    QPoint keyPoint = QPoint(totalSize - horizontalScrollBar()->value(),
                             margin - verticalScrollBar()->value());

    if (validItems > 0) {

        painter.save();
        painter.translate(pieRect.x() - horizontalScrollBar()->value(),
                          pieRect.y() - verticalScrollBar()->value());
        painter.drawEllipse(0, 0, pieSize, pieSize);
        double startAngle = 0.0;
        int row;

        for (row = 0; row < model()->rowCount(rootIndex()); ++row) {

            QModelIndex index = model()->index(row, 1, rootIndex());
            double value = model()->data(index).toDouble();

            if (value > 0.0) {
                double angle = 360*value/totalValue;

                QModelIndex colorIndex = model()->index(row, 0, rootIndex());
                QColor color = QColor(model()->data(colorIndex,
                                Qt::DecorationRole).toString());

                if (currentIndex() == index)
                    painter.setBrush(QBrush(color, Qt::Dense4Pattern));
                else if (selections->isSelected(index))
                    painter.setBrush(QBrush(color, Qt::Dense3Pattern));
                else
                    painter.setBrush(QBrush(color));

                painter.drawPie(0, 0, pieSize, pieSize, int(startAngle*16),
                                int(angle*16));

                startAngle += angle;
            }
        }
        painter.restore();

        int keyNumber = 0;

        for (row = 0; row < model()->rowCount(rootIndex()); ++row) {

            QModelIndex index = model()->index(row, 1, rootIndex());
            double value = model()->data(index).toDouble();

            if (value > 0.0) {
                QModelIndex labelIndex = model()->index(row, 0, rootIndex());

                QStyleOptionViewItem option = viewOptions();
                option.rect = visualRect(labelIndex);
                if (selections->isSelected(labelIndex))
                    option.state |= QStyle::State_Selected;
                if (currentIndex() == labelIndex)
                    option.state |= QStyle::State_HasFocus;
                itemDelegate()->paint(&painter, option, labelIndex);

                keyNumber++;
            }
        }
    }
}
void PipelineFlowChart::paintEvent(QPaintEvent *e)
{
  if(m_StageNames.empty())
    return;

  QPainter p(this);

  p.fillRect(rect(), Qt::transparent);

  p.setRenderHint(QPainter::Antialiasing, true);

  const QRectF totalRect = totalAreaRect();
  const QRectF box0Rect = boxRect(0);

  const qreal radius = qMin(MaxBoxCornerRadius, box0Rect.height() * BoxCornerRadiusFraction);

  const qreal arrowY = totalRect.y() + totalRect.height() / 2;

  QColor base = palette().color(QPalette::Base);
  QColor baseText = palette().color(QPalette::Text);
  QColor inactiveWin = palette().color(QPalette::Inactive, QPalette::Dark);
  QColor inactiveWinText = palette().color(QPalette::Inactive, QPalette::WindowText);
  QColor tooltip = palette().color(QPalette::ToolTipBase);
  QColor tooltipText = palette().color(QPalette::ToolTipText);

  QPen pen(baseText);
  QPen selectedPen(Qt::red);

  int num = numGaps();
  for(int i = 0; i < num; i++)
  {
    if(!m_StageFlows[i] || !m_StageFlows[i + 1])
      continue;

    float right = totalRect.x() + (i + 1) * (box0Rect.width() + boxMargin());
    float left = right - boxMargin();

    p.setBrush(baseText);
    drawArrow(p, pen, ArrowHeadSize, arrowY, left, right);
  }

  num = numItems();
  for(int i = 0; i < num; i++)
  {
    QRectF boxrect = boxRect(i);

    QBrush backBrush(base);
    QPen textPen(baseText);
    QPen outlinePen = pen;

    if(!stageEnabled(i))
    {
      backBrush.setColor(inactiveWin);
      textPen.setColor(inactiveWinText);
    }

    if(i == m_HoverStage)
    {
      backBrush.setColor(tooltip);
      textPen.setColor(tooltipText);
    }

    if(i == m_SelectedStage)
    {
      outlinePen = selectedPen;
    }

    outlinePen.setWidthF(BoxBorderWidth);

    p.setPen(outlinePen);
    p.setBrush(backBrush);
    p.drawRoundedRect(boxrect, radius, radius);

    QTextOption opts(Qt::AlignCenter);
    opts.setWrapMode(QTextOption::NoWrap);

    QString s = m_StageNames[i];

    QRectF reqBox = p.boundingRect(QRectF(0, 0, 1, 1), m_StageNames[i], opts);

    if(reqBox.width() + BoxLabelMargin > (float)boxrect.width())
      s = m_StageAbbrevs[i];

    p.setPen(textPen);
    p.drawText(boxrect, s, opts);
  }
}
void BpDocument::composeGraphBasics( Graph *g,
    bool isLineGraph, EqVar *xVar, EqVar *yVar, EqVar *zVar,
    int curves, GraphAxleParms *xParms, GraphAxleParms *yParms )
{
    //--------------------------------------------------------------------------
    // Set the logical fonts and colors here
    //--------------------------------------------------------------------------

    // Axis text fonts.
    QFont  textFont( property()->string( "graphTextFontFamily" ),
                    property()->integer( "graphTextFontSize" ) );
    QPen   textPen( property()->color( "graphTextFontColor" ) );

    QFont  axleFont( textFont );
    QColor axleColor( property()->color( "graphAxleColor" ) );
    QPen   axlePen( axleColor,
                property()->integer( "graphAxleWidth" ), Qt::SolidLine );
    QPen   gridPen( property()->color( "graphGridColor" ),
                property()->integer( "graphGridWidth" ), Qt::SolidLine );

    // Title fonts and colors.
    QFont  subTitleFont( property()->string( "graphSubtitleFontFamily" ),
                    property()->integer( "graphSubtitleFontSize" ) );
    QColor subTitleColor( property()->color( "graphSubtitleFontColor" ) );

    QFont  titleFont( property()->string( "graphTitleFontFamily" ),
                    property()->integer( "graphTitleFontSize" ) );
    QColor titleColor( property()->color( "graphTitleFontColor" ) );

    // Background and canvas colors.
    QBrush worldBg( property()->color( "graphBackgroundColor" ),
                Qt::SolidPattern );
    QBrush canvasBg( "white", SolidPattern );
    QPen   canvasBox( "black", 1, NoPen );

    //--------------------------------------------------------------------------
    // Create the graph canvas, world, and decoration.
    //--------------------------------------------------------------------------

    // Get the x- and y-axle parameters
    double xValMin    = xParms->m_axleMin;
    double xValMax    = xParms->m_axleMax;
    double xMajorStep = xParms->m_majorStep;
    int    xDec       = xParms->m_decimals;

    double yValMin    = yParms->m_axleMin;
    double yValMax    = yParms->m_axleMax;
    double yMajorStep = yParms->m_majorStep;
    int    yDec       = yParms->m_decimals;

    // Graph title and subtitle.
    QString qStr = m_eqTree->m_eqCalc->docDescriptionStore().stripWhiteSpace();
    //if ( qStr.isNull() || qStr.isEmpty() )
    //{
    //  translate( qStr, "BpDocument:NoRunDescription" );
    //}
    g->setTitle( qStr, titleFont, titleColor );

    if ( property()->boolean( "graphTitleActive" ) )
    {
        QString text("");
        translate( text, "BpDocument:Graphs:By" );
        qStr = *(yVar->m_label) + "\n" + text + " " + *(xVar->m_label);
        if ( curves > 1 && isLineGraph && zVar )
        {
            translate( text, "BpDocument:Graphs:And" );
            qStr += "\n" + text + " " + *(zVar->m_label);
        }
        g->setSubTitle( qStr, subTitleFont, subTitleColor );
    }

    // Use portrait orientation (assuming screen output, not printer).
    g->setCanvasRotation( 0.0 );
    g->setCanvasScale( 1.0, 1.0 );
    // NOTE: to change the graph location or size,
    // we must manipulate the m_composer->graph() args!
    g->setCanvas(
        m_screenSize->m_marginLeft,     // upper left X pixel
        m_screenSize->m_marginTop,      // upper left Y pixel
        m_screenSize->m_bodyWd,         // graph canvas width in pixels
        m_screenSize->m_bodyHt,         // graph canvas height in pixels
        0                               // graph border in pixels
    );

    // Canvas background and box.
    g->setCanvasBg( canvasBg );
    g->setCanvasBox( canvasBox );

    // Make the world coordinate system 20% larger than the data range.
    g->setWorld(
        xValMin - 0.2 * (xValMax-xValMin),  // canvas WORLD left coordinate
        yValMin - 0.2 * (yValMax-yValMin),  // canvas WORLD bottom coordinate
        xValMax + 0.1 * (xValMax-xValMin),  // canvas WORLD right coordinate
        yValMax + 0.1 * (yValMax-yValMin)   // canvas WORLD top coordinate
    );

    // Provide a colored background for the graph area.
    g->setWorldBg(
        xValMin,                        // colored bg WORLD left coordinate
        yValMin,                        // colored bg WORLD bottom coordinate
        xValMax,                        // colored bg WORLD right coordinate
        yValMax,                        // colored bg WORLD top coordinate
        worldBg                         // brush color and pattern
    );

    //--------------------------------------------------------------------------
    // Create a bottom axle with endpoints in WORLD coordinates (not AXLE).
    // This has all elements of an axle EXCEPT a minor grid and subtitle.
    //--------------------------------------------------------------------------

    GraphAxle *b = g->addGraphAxle(
        xValMin,                        // axle's min scale (NOT WORLD) value
        xValMax,                        // axle's max scale (NOT WORLD) value
        axlePen                         // axle line pen (color, width, style)
    );

    b->setWorld(
        xValMin,                        // axle's start WORLD x coordinate
        yValMin,                        // axle's start WORLD y coordinate
        xValMax,                        // axle's end WORLD x coordinate
        yValMin                         // axle's end WORLD y coordinate
    );

    // Line graph bottom axles need labels and tic marks.
    if ( isLineGraph )
    {
        b->setMajorLabels(
            axleFont,                   // label font
            axleColor,                  // font color
            xDec                        // decimal places (-1 mean no label)
        );

        b->setMajorTics(
            GraphAxleBottom,                 // side of axle to draw tic marks
            xValMin,                    // first tic mark location in AXLE units
            xValMax,                    // last tic mark location in AXLE units
            xMajorStep,                 // tic spacing in AXLE units
            0.05 * (yValMax-yValMin),   // tic mark length in Y WORLD units
            axlePen                     // tic pen (color, width, style)
        );

        b->setMinorTics(
            GraphAxleBottom,                 // side of axle to draw tic marks
            xValMin,                    // first tic mark location in AXLE units
            xValMax,                    // last tic mark location in AXLE units
            0.50 * xMajorStep,          // tic spacing in AXLE units
            0.03 * (yValMax-yValMin),   // tic mark length in Y WORLD units
            axlePen                     // tic pen (color, width, style)
        );

        b->setMajorGrid(
            gridPen,                    // grid pen color, width, style
            (yValMax-yValMin)           // length in Y WORLD units !!
        );

        // Don't show the units for ratio variables.
        qStr = *(xVar->m_label) + " " + xVar->displayUnits(true);
        b->setTitle(
            qStr,                       // axle title string
            GraphAxleBottom,                 // axle side to write the string
            axleFont,                   // axle title font
            axleColor                   // axle title color
        );
    }
    // Bar graphs just need the title.
    else
    {
        b->setTitle(
            *(xVar->m_label),           // axle title string
            GraphAxleBottom,                 // axle side to write the string
            axleFont,                   // axle title font
            axleColor                   // axle title color
        );
    }

    //--------------------------------------------------------------------------
    // Create a top axle with endpoints in WORLD coordinates (not AXLE)
    // Same as bottom axle EXCEPT no tic labels or axle label
    //--------------------------------------------------------------------------

    // Line graph top axles need tic marks.
    if ( isLineGraph )
    {
        GraphAxle *t = g->addGraphAxle(
            xValMin,                    // axle's min scale (NOT WORLD) value
            xValMax,                    // axle's max scale (NOT WORLD) value
            axlePen                     // axle line pen (color, width, style)
        );

        t->setWorld(
            xValMin,                    // axle's start WORLD x coordinate
            yValMax,                    // axle's start WORLD y coordinate
            xValMax,                    // axle's end WORLD x coordinate
            yValMax                     // axle's end WORLD y coordinate
        );

        if ( false )
        t->setMajorTics(
            GraphAxleTop,                    // side of axle to draw tic marks
            xValMin,                    // first tic mark location in AXLE units
            xValMax,                    // last tic mark location in AXLE units
            xMajorStep,                 // tic spacing in AXLE units
            0.05 * (yValMax-yValMin),   // tic mark length in WORLD units
            axlePen                     // tic pen (color, width, style)
        );

        if ( false )
        t->setMinorTics(
            GraphAxleTop,                    // side of axle to draw tic marks
            xValMin,                    // first tic mark location in AXLE units
            xValMax,                    // last tic mark location in AXLE units
            0.50 * xMajorStep,          // tic spacing in AXLE units
            0.03 * (yValMax-yValMin),   // tic mark length in WORLD units
            axlePen                     // tic pen (color, width, style)
        );
    }

    //--------------------------------------------------------------------------
    // Create a left axle with endpoints in WORLD coordinates (not AXLE)
    // This has all elements of an axle EXCEPT a minor grid and subtitle
    //--------------------------------------------------------------------------

    GraphAxle *l = g->addGraphAxle(
        yValMin,                        // axle's min scale (NOT WORLD) value
        yValMax,                        // axle's max scale (NOT WORLD) value
        axlePen                         // axle line pen (color, width, style)
    );

    l->setWorld(
        xValMin,                        // axle's start WORLD x coordinate
        yValMin,                        // axle's start WORLD y coordinate
        xValMin,                        // axle's end WORLD x coordinate
        yValMax                         // axle's end WORLD y coordinate
    );

    l->setMajorLabels(
        axleFont,                       // label font
        axleColor,                      // font color
        yDec                            // decimal places (-1 mean no label)
    );

    l->setMajorTics(
        GraphAxleLeft,                       // side of axle to draw tic marks
        yValMin,                        // first tic mark location in AXLE units
        yValMax,                        // last tic mark location in AXLE units
        yMajorStep,                     // tic spacing in AXLE units
        0.04 * (xValMax-xValMin),       // tic mark length in X WORLD units
        axlePen                         // tic pen (color, width, style)
    );

    l->setMinorTics(
        GraphAxleLeft,                       // side of axle to draw tic marks
        yValMin,                        // first tic mark location in AXLE units
        yValMax,                        // last tic mark location in AXLE units
        0.50 * yMajorStep,              // tic spacing in AXLE units
        0.02 * (xValMax-xValMin),       // tic mark length in X WORLD units
        axlePen                         // tic pen (color, width, style)
    );

    l->setMajorGrid(
        gridPen,                        // grid pen color, width, style
        (xValMax-xValMin)               // length in X axis WORLD units !!
    );

    // Don't show the units for fraction or ratio variables.
    qStr = *(yVar->m_label) + " " + yVar->displayUnits(true);
    l->setTitle(
        qStr,                           // axle title string
        GraphAxleLeft,                  // axle side to write the string
        axleFont,                       // axle title font
        axleColor                       // axle title font color
    );

    //--------------------------------------------------------------------------
    // Create a right axle with endpoints in WORLD coordinates (not AXLE)
    // Same as the left axle EXCEPT no tic labels or axle label.
    //--------------------------------------------------------------------------

    GraphAxle *r = g->addGraphAxle(
        yValMin,                        // axle's min scale (NOT WORLD) value
        yValMax,                        // axle's max scale (NOT WORLD) value
        axlePen                         // axle line pen (color, width, style)
    );

    r->setWorld(
        xValMax,                        // axle's start WORLD x coordinate
        yValMin,                        // axle's start WORLD y coordinate
        xValMax,                        // axle's end WORLD x coordinate
        yValMax                         // axle's end WORLD y coordinate
    );

    if ( false )
    r->setMajorTics(
        GraphAxleRight,                      // side of axle to draw tic marks
        yValMin,                        // first tic mark location in AXLE units
        yValMax,                        // last tic mark location in AXLE units
        yMajorStep,                     // tic spacing in AXLE units
        0.04 * (xValMax-xValMin),       // tic mark length in X WORLD units
        axlePen                         // tic pen (color, width, style)
    );

    if ( false )
    r->setMinorTics(
        GraphAxleLeft,                       // side of axle to draw tic marks
        yValMin,                        // first tic mark location in AXLE units
        yValMax,                        // last tic mark location in AXLE units
        0.50 * yMajorStep,              // tic spacing in AXLE units
        0.02 * (xValMax-xValMin),       // tic mark length in X WORLD units
        axlePen                         // tic pen (color, width, style)
    );

    return;
}
void BpDocument::composeBarGraph( int yid, EqVar *xVar, EqVar *yVar,
        GraphAxleParms *xParms, GraphAxleParms *yParms )
{
    //--------------------------------------------------------------------------
    // 1: Set up fonts, pens, and colors used by this graph
    //--------------------------------------------------------------------------

    // Graph fonts.
    QFont textFont( property()->string( "graphTextFontFamily" ),
                    property()->integer( "graphTextFontSize" ) );
    QColor textColor( property()->color( "graphTextFontColor" ) );
    QPen textPen( textColor );

    // How many colors are requested?
    QString colorName( property()->color( "graphBarColor" ) );
    int colors = 1;
    if ( colorName == "rainbow" )
    {
        colors = property()->integer( "graphRainbowColors" );
    }
    // Allocate number of requested colors.
    QColor *color = new QColor [colors];
    checkmem( __FILE__, __LINE__, color, "QColor color", colors );
    int colorId = 0;
    // If only 1 color...
    if ( colors == 1 )
    {
        color[0].setNamedColor( colorName );
    }
    // else if rainbow colors are requested.
    else
    {
        // \todo - add some code to check conflicts with graphBackgroundColor
        // and graphGridColor (if graphGridWidth > 0 ).
        int hue = 0;
        for ( colorId = 0;
              colorId < colors;
              colorId++ )
        {
            color[colorId].setHsv( hue, 255, 255);
            hue += 360 / colors;
        }
        colorId = 0;
    }
    // Setup bar brush and color
    QBrush barBrush( color[colorId], Qt::SolidPattern );

    //--------------------------------------------------------------------------
    // 2: Create the graph and its text and axles.
    //--------------------------------------------------------------------------

    // Initialize graph and variables
    Graph g;
    int bars  = ( tableRows() < graphMaxBars )
              ? tableRows()
              : graphMaxBars ;
    int vStep = tableVars();

    // Draw thew basic graph (axis and text)
    composeGraphBasics( &g, false, xVar, yVar, 0, bars, xParms, yParms );

    //--------------------------------------------------------------------------
    // 3: Add the bars.
    //--------------------------------------------------------------------------

    // Each bar occupies 2/3 of its x range, plus a 1/3 padding on right.
    double xMin = xParms->m_axleMin;
    double xMax = xParms->m_axleMax;
    double xMinorStep = ( xMax - xMin ) / (double) ( 3 * bars + 1 );
    double xMajorStep = 3. * xMinorStep;

    // Create each data bar and add it to the graph.
    double x0, x1, y0, y1, xl;
    double yl = 0.;
    double rotation = 0.;
    QString label;
    int row, vid;
    for ( row = 0, vid = yid;
          row < bars;
          row++, vid += vStep )
    {
        x0 = xMin + xMinorStep + row * xMajorStep;
        x1 = xMin + ( row + 1 ) * xMajorStep;
        y0 = yParms->m_axleMin;
        y1 = tableVal( vid );
        xl = 0.5 * (x0 + x1) ;

        // If we're out of colors, start over.
        if ( colorId >= colors )
        {
            colorId = 0;
        }

        // Set the bar brush to this color.
        barBrush.setColor( color[colorId++] );

        // Create the graph bar.
        GraphBar *bar = g.addGraphBar( x0, y0, x1, y1, barBrush, textPen );

        // Create the bar label.
        int iid = (int) tableRow( row );
        label = xVar->m_itemList->itemName( iid );
        bar->setGraphBarLabel( label, xl, yl, textFont, textColor, rotation );
    }

    //--------------------------------------------------------------------------
    // 4: Add an output page on which to draw the graph.
    //--------------------------------------------------------------------------

    // Create a separate page for this graph.
    QString text("");
    translate( text, "BpDocument:Graphs:By" );
    label = QString( "%1 %2 %3" )
        .arg( *(yVar->m_label) )
        .arg( text )
        .arg( *(xVar->m_label) );
    startNewPage( label, TocBarGraph );

    // This is how we save the graph and its composer.
    m_composer->graph( g,
        m_pageSize->m_marginLeft
            + m_pageSize->m_bodyWd * property()->real( "graphXOffset" ),
        m_pageSize->m_marginTop
            + m_pageSize->m_bodyHt * property()->real( "graphYOffset" ),
        m_pageSize->m_bodyWd * property()->real( "graphScaleWidth" ),
        m_pageSize->m_bodyHt * property()->real( "graphScaleHeight" )
    );

    // Be polite and stop the composer.
    m_composer->end();
    delete[] color;
    return;
}
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;
}
Exemple #14
0
void CtrlDisAsmView::paintEvent(QPaintEvent *)
{
	QPainter painter(this);
	painter.setBrush(Qt::white);
	painter.setPen(Qt::white);
	painter.drawRect(rect());

	struct branch
	{
		int src,dst,srcAddr;
		bool conditional;
	};
	branch branches[256];
	int numBranches=0;

	int width = rect().width();
	int numRows=(rect().height()/rowHeight);

	QColor bgColor(0xFFFFFFFF);
	QPen nullPen(bgColor);
	QPen currentPen(QColor(0,0,0));
	QPen selPen(QColor(0xFF808080));
	QPen condPen(QColor(0xFFFF3020));

	QBrush lbr;
	lbr.setColor(bgColor);
	QBrush currentBrush(QColor(0xFFFFEfE8));
	QBrush pcBrush(QColor(0xFF70FF70));

	QFont normalFont("Arial", 10);
	QFont boldFont("Arial", 10);
	QFont alignedFont("Monospace", 10);
	alignedFont.setStyleHint(QFont::Monospace);
	boldFont.setBold(true);
	painter.setFont(normalFont);


	QImage breakPoint(":/resources/breakpoint.ico");
	int i;
	curAddress&=~(align-1);

	align=(debugger->getInstructionSize(0));
	for (i=0; i<=numRows; i++)
	{
		unsigned int address=curAddress + (i-(numRows/2))*align;

		int rowY1 = rect().top() + rowHeight*i;
		int rowY2 = rect().top() + rowHeight*i + rowHeight - 1;

		lbr.setColor((unsigned int)marker == address ? QColor(0xFFFFEEE0) : QColor(debugger->getColor(address)));
		QColor bg = lbr.color();
		painter.setBrush(currentBrush);
		painter.setPen(nullPen);
		painter.drawRect(0,rowY1,16-1,rowY2-rowY1);

		if (selecting && address == (unsigned int)selection)
			painter.setPen(selPen);
		else
		{
			if(i==numRows/2)
				painter.setPen(currentPen);
			else
				painter.setPen(bg);
		}
		painter.setBrush(QBrush(bg));

		if (address == debugger->getPC())
		{
			painter.setBrush(pcBrush);
		}

		painter.drawRect(16,rowY1,width-16-1,rowY2-rowY1);
		painter.setBrush(currentBrush);
		QPen textPen(QColor(halfAndHalf(bg.rgba(),0)));
		painter.setPen(textPen);
		painter.setFont(alignedFont);
		painter.drawText(17,rowY1-3+rowHeight,QString("%1").arg(address,8,16,QChar('0')));
		painter.setFont(normalFont);
		textPen.setColor(QColor(0xFF000000));
		painter.setPen(textPen);
		if (debugger->isAlive())
		{
			const char *dizz = debugger->disasm(address, align);
			char dis[512];
			strcpy(dis, dizz);
			char *dis2 = strchr(dis,'\t');
			char desc[256]="";
			if (dis2)
			{
				*dis2=0;
				dis2++;
				const char *mojs=strstr(dis2,"->$");
				if (mojs)
				{
					for (int i=0; i<8; i++)
					{
						bool found=false;
						for (int j=0; j<22; j++)
						{
							if (mojs[i+3]=="0123456789ABCDEFabcdef"[j])
								found=true;
						}
						if (!found)
						{
							mojs=0;
							break;
						}
					}
				}
				if (mojs)
				{
					int offs;
					sscanf(mojs+3,"%08x",&offs);
					branches[numBranches].src=rowY1 + rowHeight/2;
					branches[numBranches].srcAddr=address/align;
					branches[numBranches].dst=(int)(rowY1+((s64)offs-(s64)address)*rowHeight/align + rowHeight/2);
					branches[numBranches].conditional = (dis[1]!=0); //unconditional 'b' branch
					numBranches++;
					const char *t = debugger->getDescription(offs).c_str();
					if (memcmp(t,"z_",2)==0)
						t+=2;
					if (memcmp(t,"zz_",3)==0)
						t+=3;
					sprintf(desc,"-->%s", t);
					textPen.setColor(QColor(0xFF600060));
					painter.setPen(textPen);
				}
				else
				{
					textPen.setColor(QColor(0xFF000000));
					painter.setPen(textPen);
				}
				painter.drawText(149,rowY1-3+rowHeight,QString(dis2));
			}
			textPen.setColor(QColor(0xFF007000));
			painter.setPen(textPen);
			painter.setFont(boldFont);
			painter.drawText(84,rowY1-3+rowHeight,QString(dis));
			painter.setFont(normalFont);
			if (desc[0]==0)
			{
				const char *t = debugger->getDescription(address).c_str();
				if (memcmp(t,"z_",2)==0)
					t+=2;
				if (memcmp(t,"zz_",3)==0)
					t+=3;
				strcpy(desc,t);
			}
			if (memcmp(desc,"-->",3) == 0)
			{
				textPen.setColor(QColor(0xFF0000FF));
				painter.setPen(textPen);
			}
			else
			{
				textPen.setColor(halfAndHalf(halfAndHalf(bg.rgba(),0),bg.rgba()));
				painter.setPen(textPen);
			}
			if (strlen(desc))
				painter.drawText(std::max(280,width/3+190),rowY1-3+rowHeight,QString(desc));
			if (debugger->isBreakpoint(address))
			{
				painter.drawImage(2,rowY1+2,breakPoint);
			}
		}
	}
	for (i=0; i<numBranches; i++)
	{
		painter.setPen(branches[i].conditional ? condPen : currentPen);
		int x=280+(branches[i].srcAddr%9)*8;
		QPoint curPos(x-2,branches[i].src);

		if (branches[i].dst<rect().bottom()+200 && branches[i].dst>-200)
		{
			painter.drawLine(curPos, QPoint(x+2,branches[i].src));
			curPos = QPoint(x+2,branches[i].src);
			painter.drawLine(curPos, QPoint(x+2,branches[i].dst));
			curPos = QPoint(x+2,branches[i].dst);
			painter.drawLine(curPos, QPoint(x-4,branches[i].dst));

			curPos = QPoint(x,branches[i].dst-4);
			painter.drawLine(curPos, QPoint(x-4,branches[i].dst));
			curPos = QPoint(x-4,branches[i].dst);
			painter.drawLine(curPos, QPoint(x+1,branches[i].dst+5));
		}
		else
		{
			painter.drawLine(curPos, QPoint(x+4,branches[i].src));
		}
	}
}
/** Draws the label using the specificed painter & x/y-offsets */
void MLabelObject::draw(QPainter* p, int xoffset, int yoffset){
    QFont font(fontFamily, fontSize, fontWeight, fontItalic);
    QPen textPen(foregroundColor, 0, QPen::NoPen);

    int tf;

        // Set the offsets
    int xcalc = xpos + xoffset;
    int ycalc = ypos + yoffset;

        // Draw the base
    drawBase(p, xoffset, yoffset);

        // Set the font
    p->setFont(font);
    QFontMetrics fm = p->fontMetrics();

        // Set the text alignment flags

        // Horizontal
    switch(hAlignment){
        case MLabelObject::Left:
            tf = QPainter::AlignLeft;
            break;
        case MLabelObject::Center:
            tf = QPainter::AlignHCenter;
            break;
        case MLabelObject::Right:
	    tf = QPainter::AlignRight;
    }

        // Vertical
    switch(vAlignment){
        case MLabelObject::Top:
            tf = tf | QPainter::AlignTop;
            break;
        case MLabelObject::Bottom:
            tf = tf | QPainter::AlignBottom;
            break;
        case MLabelObject::Middle:
	    tf = tf | QPainter::AlignVCenter;
    }

        // Word wrap
    if(wordWrap) tf = tf | QPainter::WordBreak;

        // Draw the text
    p->setPen(textPen);
    QString newtext = text;
    newtext.replace( QRegExp( "<br>", false ), QString( "\n" ) );
    p->drawText(xcalc + xMargin, ycalc + yMargin,
                width - xMargin, height - yMargin,
                tf, newtext);

        // leave this in place - possible use for other tags
        //
//          // ----------------------------------------
//          // look for line breaks (<br>)
//          // ----------------------------------------

//      int idx = 0;
//      int ysub = ycalc;
//      int line_height = height;
//      int len = text.length();
//      int line_len = len;
//      QString sep = "<br>";
//      int len_sep = sep.length();
//      while ( idx < len )
//      {
//          int eol = text.find( sep, idx, FALSE );
//          if ( eol < 0 )
//              eol = len;
        
//          line_len = eol - idx;

//              // draw the line and determine the space used.
//          QRect brect = p->boundingRect(xcalc + xMargin, ysub + yMargin,
//                                        width - xMargin, line_height - yMargin,
//                                        tf, text.mid( idx, line_len ), line_len);
//          p->drawText( xcalc + xMargin, ysub + yMargin,
//                       width - xMargin, line_height - yMargin,
//                       tf, text.mid( idx, line_len ), line_len );

//              // substract the vert space used.
//          ysub += brect.height();
//          line_height -= brect.height();
        
//              // nothing more
//          if ( eol == len )
//              break;
//          else
//              idx = eol + len_sep;
//      }
}
void BpDocument::composeFireCharacteristicsDiagram( void )
{
    // Surface Module must be active and using fuel model inputs
    PropertyDict *prop = m_eqTree->m_propDict;
    if ( ! prop->boolean( "surfaceModuleActive" )
      || ! prop->boolean( "surfaceCalcFireCharacteristicsDiagram" ) )
    {
        return;
    }

    // Graph fonts.
    QFont  textFont( property()->string( "graphTextFontFamily" ),
                     property()->integer( "graphTextFontSize" ) );
    QColor textColor( property()->color( "graphTextFontColor" ) );
    QPen   textPen( textColor );
    QFont  subTitleFont( property()->string( "graphSubtitleFontFamily" ),
                    property()->integer( "graphSubtitleFontSize" ) );
    QColor subTitleColor( property()->color( "graphSubtitleFontColor" ) );

    // Open the result file
    QString resultFile = m_eqTree->m_resultFile;
    FILE *fptr = 0;
    if ( ! ( fptr = fopen( resultFile.latin1(), "r" ) ) )
    // This code block should never be executed!
    {
        QString text("");
        translate( text, "BpDocument:FireCharacteristicsDiagram:NoLogOpen",
            resultFile );
        error( text );
        return;
    }
    // Allocate ros and hpua data arrays
    int rows  = tableRows();
    int cols  = tableCols();
    int cells = rows * cols;
    double *hpua = new double[ cells ];
    checkmem( __FILE__, __LINE__, hpua, "double hpua", cells );
    double *ros = new double[ cells ];
    checkmem( __FILE__, __LINE__, ros, "double ros", cells );
    // Set the variable names we're looking for
    const char* hpuaName = "vSurfaceFireHeatPerUnitArea";
    const char* rosName = "vSurfaceFireSpreadAtHead";
    if ( prop->boolean( "surfaceConfSpreadDirInput" ) )
    {
        rosName = "vSurfaceFireSpreadAtVector";
    }
    // Read and store the ros and hpua values
    char   buffer[1024], varName[128], varUnits[128];
    int    row, col, cell;
    double value;
    double rosMax = 0.0;
    double hpuaMax = 0.0;
    while ( fgets( buffer, sizeof(buffer), fptr ) )
    {
        if ( strncmp( buffer, "CELL", 4 ) == 0 )
        {
            if ( strstr( buffer, hpuaName ) )
            {
                sscanf( buffer, "CELL %d %d %s cont %lf %s",
                    &row, &col, varName, &value, varUnits );
                cell = ( col - 1 ) + ( cols * ( row - 1) );
                if ( ( hpua[ cell ] = value ) > hpuaMax )
                {
                    hpuaMax = value;
                }
            }
            else if ( strstr( buffer, rosName ) )
            {
                sscanf( buffer, "CELL %d %d %s cont %lf %s",
                    &row, &col, varName, &value, varUnits );
                cell = ( col - 1 ) + ( cols * ( row - 1) );
                if ( ( ros[ cell ] = value ) > rosMax )
                {
                    rosMax = value;
                }
            }
        }
    }
    fclose( fptr );

    // Get variable pointers
    EqVar *hpuaVar = m_eqTree->m_varDict->find( "vSurfaceFireHeatPerUnitArea" );
    EqVar *rosVar = m_eqTree->m_varDict->find( "vSurfaceFireSpreadAtHead" );
    EqVar *fliVar = m_eqTree->m_varDict->find( "vSurfaceFireLineIntAtHead" );
    EqVar *flVar = m_eqTree->m_varDict->find( "vSurfaceFireFlameLengAtHead" );

    // Conversion factor
    double flFactor, fliFactor, rosFactor, hpuaFactor, offset;
    appSiUnits()->conversionFactorOffset(
        flVar->m_nativeUnits, flVar->m_displayUnits, &flFactor, &offset );
    appSiUnits()->conversionFactorOffset(
        fliVar->m_nativeUnits, fliVar->m_displayUnits, &fliFactor, &offset );
    appSiUnits()->conversionFactorOffset(
        hpuaVar->m_nativeUnits, hpuaVar->m_displayUnits, &hpuaFactor, &offset );
    appSiUnits()->conversionFactorOffset(
        rosVar->m_nativeUnits, rosVar->m_displayUnits, &rosFactor, &offset );

    // Determine which of four different chart scales to use
    static const int Scales = 4;
    static double RosScale[Scales] = { 100., 200., 400., 800. };        // ft/min
    static double HpuaScale[Scales] = { 2000., 4000., 8000., 16000. };  // Btu/ft2
    double rosScale = 0.;       // Max y-axis ros
    double hpuaScale = 0.;      // Max x-axis hpua
    int scale;
    for ( scale=0; scale<Scales; scale++ )
    {
        if ( rosMax < ( rosScale = RosScale[ scale ] ) )
        {
            break;
        }
    }
    for ( scale=0; scale<Scales; scale++ )
    {
        if ( hpuaMax < ( hpuaScale = HpuaScale[scale] ) )
        {
            break;
        }
    }
    // Set axis maximums to appropriate predefined scale in display units
    rosMax  = rosFactor * rosScale;
    hpuaMax = hpuaFactor * hpuaScale;
    double ratio = rosMax / hpuaMax;

    // Create the graph
    Graph  graph;
    GraphLine *graphLine;
    GraphMarker *graphMarker;
    static const int Points = 100;
    double l_x[Points];
    double l_y[Points];

    // Draw the four standard hauling chart fli-fl levels
    static const int Lines = 4;
    static const double Fli[Lines] = { 100., 500., 1000., 2000. };  // Btu/ft/s
    static const double Fl[Lines] = { 4., 8., 11., 15. };           // ft

    // Create the hauling chart lines
    // Put Fireline Int label 65% of the way along the HPUA axis (display units)
    double  xPosFli = 0.65 * hpuaMax;
    // Put Flame Length label 85% of the way along the HPUA axis (display units)
    double  xPosFl  = 0.85 * hpuaMax;
    // Fireline Int and Flame Length label Y positions (display units)
    double  yPosFl[Lines], yPosFli[Lines];
    // Icon locations (in display units)
    double xIcon[Lines+1], yIcon[Lines+1];
    double diff, minDiff;
    QString label;
    QPen    redPen( "red", 1 );
    QColor  blackColor( "black" );
    int     alignCenter = Qt::AlignHCenter | Qt::AlignVCenter;
    // Fireline intensity - flame length curves
    int     line, point;
    for ( line = 0; line < Lines; line++ )
    {
        minDiff = 999999999.;
        for ( point = 0; point < Points; point++ )
        {
            // Hpua value in native units (Btu/ft2)
            l_x[point] = ( (point+1) * hpuaScale ) / (double) Points;
            // Ros value in native units (ft/min)
            l_y[point] = 60. * Fli[line] / l_x[point];
            // Convert to display units
            l_x[point] *= hpuaFactor;
            l_y[point] *= rosFactor;
            // Check for curve inflection point (for icon placement)
            if ( ( diff = fabs( l_y[point]/l_x[point] - ratio ) ) < minDiff )
            {
                minDiff = diff;
                xIcon[line+1] = l_x[point];
                yIcon[line+1] = l_y[point];
            }
        }
        // Create a graph line (with its own copy of the data).
        graphLine = graph.addGraphLine( Points, l_x, l_y, redPen );

        // Fireline intensity label
        label = QString( "%1" ).arg( ( Fli[line] * fliFactor ), 0, 'f', 0 );
        yPosFli[line] = rosFactor * ( 60. * Fli[line] / ( xPosFli / hpuaFactor ) );
        graph.addGraphMarker( xPosFli, yPosFli[line], label, textFont,
            blackColor, alignCenter );

        // Flame length label
        label = QString( "%1" ).arg( ( Fl[line] * flFactor ), 0, 'f', 0 );
        yPosFl[line] = rosFactor * ( 60. * Fli[line] / ( xPosFl / hpuaFactor ) );
        graph.addGraphMarker( xPosFl, yPosFl[line], label, textFont,
            blackColor, alignCenter );
    } // Next line

    // Fireline intensity label and units
    translate( label, "BpDocument:FireCharacteristicsDiagram:FLI" );
    graph.addGraphMarker( xPosFli, ( yPosFli[Lines-1] + 0.10 * rosMax ),
        label, textFont, blackColor, alignCenter );
    graph.addGraphMarker( xPosFli, ( yPosFli[Lines-1] + 0.05 * rosMax ),
        fliVar->m_displayUnits, textFont, blackColor, alignCenter );

    // Flame length label and units
    translate( label, "BpDocument:FireCharacteristicsDiagram:FL" );
    graph.addGraphMarker( xPosFl, ( yPosFl[Lines-1] + 0.10 * rosMax ),
        label, textFont, blackColor, alignCenter );
    graph.addGraphMarker( xPosFl, ( yPosFl[Lines-1] + 0.05 * rosMax ),
        flVar->m_displayUnits, textFont, blackColor, alignCenter );

    // Add icons
    QPixmap pixmap[Lines];
    pixmap[0] = QPixmap( fireman_xpm );
    pixmap[1] = QPixmap( dozer_xpm );
    pixmap[2] = QPixmap( torchtree_xpm );
    pixmap[3] = QPixmap( mtnfire_xpm );
    xIcon[0] = yIcon[0] = 0.0;
    for ( line=0; line<Lines; line++ )
    {
        graphMarker = graph.addGraphMarker(
            xIcon[line] + ( 0.5 * ( xIcon[line+1] - xIcon[line] ) ),
            yIcon[line] + ( 0.5 * ( yIcon[line+1] - yIcon[line] ) ),
            "", textFont, blackColor, alignCenter );
        graphMarker->setGraphMarkerPixmap( pixmap[line] );
    }

    // Finally, add a marker for each output result
    QColor  bluePen( "blue" );
    for ( cell=0; cell<cells; cell++ )
    {
        //fprintf( stderr, "%02d: %3.2f  %3.2f\n", i, hpua[i], ros[i] );
        graph.addGraphMarker( hpua[cell], ros[cell],
            QString( "%1" ).arg( cell + 1 ), textFont, bluePen, alignCenter );
    }
    // Compose the graph
    EqVar *zVar = 0;
    GraphAxleParms xParms( 0.0, hpuaMax, 11 );
    GraphAxleParms yParms( 0.0, rosMax, 11 );
    composeGraphBasics( &graph, true, hpuaVar, rosVar, zVar, Lines,
        &xParms, &yParms );

    // Create a separate page for this graph.
    translate( label, "BpDocument:FireCharacteristicsDiagram:Caption" );
    graph.setSubTitle( label, subTitleFont, subTitleColor );
    startNewPage( label, TocHaulChart );

    // This is how we save the graph and its composer.
    m_composer->graph( graph,
        m_pageSize->m_marginLeft
            + m_pageSize->m_bodyWd * property()->real( "graphXOffset" ),
        m_pageSize->m_marginTop
            + m_pageSize->m_bodyHt * property()->real( "graphYOffset" ),
        m_pageSize->m_bodyWd * property()->real( "graphScaleWidth" ),
        m_pageSize->m_bodyHt * property()->real( "graphScaleHeight" )
    );
    // Be polite and stop the composer.
    m_composer->end();
    delete[] ros;   ros  = 0;
    delete[] hpua;  hpua = 0;
    return;
}
Exemple #17
0
void ColorGridView::paintEvent(QPaintEvent *event)
{
    // To make it clear, we do not use delegate at all
    //    QItemSelectionModel *selections = selectionModel();
    QStyleOptionViewItem option = viewOptions();
    QStyle::State state = option.state;

    QBrush background = option.palette.base();
    QPen foreground(option.palette.color(QPalette::WindowText));
    QPen textPen(option.palette.color(QPalette::Text));
    QPen highlightedPen(option.palette.color(QPalette::HighlightedText));

    QPainter painter(viewport());
    // close anti aliasing to make it more clear
    //        painter.setRenderHint(QPainter::Antialiasing);

    painter.fillRect(event->rect(), background);
    painter.setPen(Qt::white);
    QBrush brush;
    brush.setTextureImage(backgroundImg);
    painter.setBrush(brush);

    painter.translate(margin - horizontalScrollBar()->value(),
                      margin - verticalScrollBar()->value());
    for(int i = 0; i<gridCount; ++i){
        for(int j=0; j<gridCount; ++j){
            painter.drawImage(i*(gridMargin+gridWidth),j*(gridMargin+gridWidth),
                              backgroundImg);
        }
    }

    if( !model() )return;
    for (int row = 0; row < model()->rowCount(rootIndex()); ++row) {
        for(int column = 0; column < model()->columnCount(rootIndex()); ++column)
        {
            QModelIndex index = model()->index(row, column, rootIndex());
            QColor color = model()->data(index).value<QColor>();

            int j = index.row();
            int i = index.column();
            if(color.isValid()){
                //draw white background to prevent disturbings of background if transparent color
                painter.setBrush(Qt::white);
                painter.drawRect(i*(gridMargin+gridWidth),j*(gridMargin+gridWidth),
                                 gridWidth,gridWidth);
                painter.setBrush(color);
                painter.drawRect(i*(gridMargin+gridWidth),j*(gridMargin+gridWidth),
                                 gridWidth,gridWidth);
            }
        }
    }
    QModelIndexList list = selectedIndexes();
    if( !list.isEmpty() ){
        QModelIndex index = list.at(0);
        //        Qt::ItemFlags flags = index.flags();
        //        if(flags.testFlag(QItemSelectionModel::Select)){
        painter.setPen(textPen);
        //        }
        //        if(flags.testFlag(QItemSelectionModel::Toggle)){
        //            painter.setPen(highlightedPen);
        //        }
        int row = index.row();
        int column = index.column();
        //        QPointF start(column*(gridMargin+gridWidth),row*(gridMargin+gridWidth));
        //        QRadialGradient gradient(start+QPointF(gridWidth/2,gridWidth/2),0.1,start+QPointF(gridWidth,gridWidth));
        //        gradient.setColorAt(0.5,Qt::transparent);
        //        gradient.setColorAt(1.0,Qt::black);
        //        foreground = QPen(Qt::black);

        //        QBrush brush(gradient);
        //        brush.setStyle(Qt::RadialGradientPattern);
        painter.setBrush(Qt::NoBrush);
        //        painter.setBrush(brush);
        painter.drawRect(column*(gridMargin+gridWidth),row*(gridMargin+gridWidth),
                         gridWidth,gridWidth);
    }
}
void BpDocument::composeLineGraph( int yid, EqVar *xVar, EqVar *yVar,
    EqVar *zVar, GraphAxleParms *xParms, GraphAxleParms *yParms )
{
    //--------------------------------------------------------------------------
    // 1: Set up fonts, pens, and colors used by this graph
    //--------------------------------------------------------------------------

    // Graph fonts
    QFont  textFont( property()->string( "graphTextFontFamily" ),
                    property()->integer( "graphTextFontSize" ) );
    QColor textColor( property()->color( "graphTextFontColor" ) );
    QPen   textPen( textColor );
    // How many colors are requested?
    QString colorName( property()->color( "graphLineColor" ) );
    int colors = 1;
    if ( colorName == "rainbow" )
    {
        colors = property()->integer( "graphRainbowColors" );
    }
    // Allocate number of requested colors.
    QColor *color = new QColor [colors];
    checkmem( __FILE__, __LINE__, color, "QColor color", colors );
    int colorId = 0;
    // If only 1 color...
    if ( colors == 1 )
    {
        color[0].setNamedColor( colorName );
    }
    // else if rainbow colors are requested...
    else
    {
        // todo - add some code to check conflicts with graphBackgroundColor
        // and graphGridColor (if graphGridWidth > 0 ).
        int hue = 0;
        for ( colorId = 0;
              colorId < colors;
              colorId++ )
        {
            color[colorId].setHsv( hue, 255, 255);
            hue += 360 / colors;
        }
        colorId = 0;
    }
    // Set up line width and color
    int lineWidth = property()->integer( "graphLineWidth" );
    QPen pen( color[0], lineWidth, SolidLine );

    //--------------------------------------------------------------------------
    // 2: Create the graph and add its curves.
    //--------------------------------------------------------------------------

    // Initialize graph and variables
    Graph      g;
    GraphLine *line[graphMaxLines];
    double     l_x[graphMaxSteps];
    double     l_y[graphMaxSteps];
    int        curves = ( tableCols() < graphMaxLines )
                  ? ( tableCols() )
                  : ( graphMaxLines );
    int        points = tableRows();
    int        vStep  = tableCols() * tableVars();

    // Loop for each zVar family curve value in this graph (or at least once!).
    // Note that zVar count is in tableCols(), e.g. each column stores a curve,
    // and zVar values are in tableCol( col ).
    int col, vid;
    for ( col = 0;
          col < curves;
          col++ )
    {
        // tableVal[] offset of first y-value for this curve.
        vid = yid + col * tableVars();
        // Set up the y[point] array for this curve.
        // Note number of points is in tableRows() and
        // point x values are in tableRow( point ).
        for ( int point = 0;
              point < points;
              point++ )
        {
            l_x[point] = tableRow( point );
            l_y[point] = tableVal( vid );
            vid += vStep;
        }
        // If we're out of colors, start over.
        if ( colorId >= colors )
        {
            colorId = 0;
        }
        // Create a graph line (with its own copy of the data).
        pen.setColor( color[colorId++] );
        line[col] = g.addGraphLine( points, l_x, l_y, pen );
    } // Next z-variable curve.

    //--------------------------------------------------------------------------
    // 3: Add curve labels if there is more than 1 curve.
    //--------------------------------------------------------------------------

    QString label;
    if ( curves > 1 )
    {
        colorId = 0;

#define GRAPH_LABEL_METHOD_1

#ifdef GRAPH_LABEL_METHOD_1
        // Label x array index step size between labels
        int j1 = points / curves;
        if ( j1 < 1 )
        {
            j1 = 1;
        }
        // Label x array index offset
        int j0 = j1 / 2;
#endif
        double xLabel, yLabel;
        int idx;
        // Loop for each z-variable curve.
        for ( col = 0;
              col < curves;
              col++ )
        {
            // Get a new color for the curve.
            if ( colorId >= colors )
            {
                colorId = 0;
            }
            // Set the curve label.
            if ( zVar->isDiscrete() )
            {
                int iid = (int) tableCol( col );
                label = zVar->m_itemList->itemName( iid );
            }
            else if ( zVar->isContinuous() )
            {
				int decimals = zVar->m_displayDecimals;
                label.sprintf( "%1.*f",
                    zVar->m_displayDecimals, tableCol( col ) );
				// Remove all trailing zeros
				while ( decimals && label.endsWith( "0" ) )
				{
					label = label.left( label.length()-1 );
					decimals--;
				}
            }

#ifdef GRAPH_LABEL_METHOD_1
            // Determine an x-axis index for the label position.
            idx = ( j0 + col * j1 ) % points;
            xLabel = line[col]->m_x[idx];
            yLabel = line[col]->m_y[idx];
#endif

#ifdef GRAPH_LABEL_METHOD_2
            // NEW LABEL POSITIONING METHOD STARTS HERE
            // Find the x position where this variable has the maximum y
            // clearance
            // Loop for each x value for this curve
            idx = 0;
            double dMax = 0;
            double dir  = 1.;
            double yMin = yParms->m_axleMin;
            double yMax = yParms->m_axleMax;
            for ( int row=1; row<tableRows()-1; row++ )
            {
                // Find vertical clearance above and below this x point
                double y0 = m_eqTree->getResult( row, col, yid );
                // Don't consider locations outside the viewport
                if ( y0 < yMin || y0 > yMax )
                {
                    continue;
                }
                double below = y0 - yMin;
                double above = yMax - y0;
                double dist, y1;
                // Loop for each family member curve
                for ( int c=0; c<curves; c++ )
                {
                    // Skip self
                    if ( c == col )
                    {
                        continue;
                    }
                    y1 = m_eqTree->getResult( row, c, yid );
                    y1 = ( y1 < yMax ) ? y1 : yMax;
                    y1 = ( y1 > yMin ) ? y1 : yMin;
                    // Shrink vertical clearance above and below this x point?
                    if ( y0 <= y1 )
                    {
                        dist = y1 - y0;
                        above = ( dist < above ) ? dist : above;
                    }
                    else
                    {
                        dist = y0 - y1;
                        below = ( dist < below ) ? dist : below;
                    }
                }
                // Is this the maximum vertical clearance so far?
                if ( above + below > dMax )
                {
                    dMax = above + below;
                    idx  = row;
                    dir  = ( above > below ) ? 1. : -1;
                }
            }
            xLabel = line[col]->m_x[idx];
            double offset = dir * 0.02 * ( yMax - yMin );
            yLabel = line[col]->m_y[idx] + offset;
#endif
            // Set the label text, font, color, and position.
            line[col]->setGraphLineLabel( label, xLabel, yLabel, textFont,
                QColor( color[colorId++] ) );
        } // Next curve.

        // Add a z-variable label to the graph.
        label = *(zVar->m_label);
        if ( zVar->isContinuous() )
        {
            label = *(zVar->m_label) + "\n" + zVar->displayUnits(true);
        }
        g.setMultipleCurveLabel( label );
    }

    //--------------------------------------------------------------------------
    // 4: Compose the graph and add an output page to draw it onto
    //--------------------------------------------------------------------------

    composeGraphBasics( &g, true, xVar, yVar, zVar, curves, xParms, yParms );

    // Create a separate output page for this graph.
    QString text("");
    translate( text, "BpDocument:Graphs:By" );
    label = *(yVar->m_label) + " " + text + " " + *(xVar->m_label);
    if ( curves > 1 )
    {
        translate( text, "BpDocument:Graphs:And" );
        label += " " + text + " " + *(zVar->m_label);
    }
    startNewPage( label, TocLineGraph );

    // This is how we save the graph and its composer.
    m_composer->graph( g,
        m_pageSize->m_marginLeft
            + m_pageSize->m_bodyWd * property()->real( "graphXOffset" ),
        m_pageSize->m_marginTop
            + m_pageSize->m_bodyHt * property()->real( "graphYOffset" ),
        m_pageSize->m_bodyWd * property()->real( "graphScaleWidth" ),
        m_pageSize->m_bodyHt * property()->real( "graphScaleHeight" )
    );

    // Be polite and stop the composer.
    m_composer->end();
    delete[] color;
    return;
}