Logo Search packages:      
Sourcecode: koffice version File versions

void KDChartAxesPainter::paintAxes ( QPainter *  painter,
KDChartTableDataBase data 
) [protected, virtual, inherited]

Paints the actual axes areas.

Parameters:
painter the QPainter onto which the chart should be painted
data the data that will be displayed as a chart

Reimplemented from KDChartPainter.

Definition at line 417 of file KDChartAxesPainter.cpp.

References KDChartAxisParams::AXIS_GRID_AUTO_LINEWIDTH, KDChartAxisParams::AXIS_LABELS_AUTO_LEAVEOUT, KDChartAxisParams::axisFirstLabelText(), KDChartAxisParams::axisGridColor(), KDChartAxisParams::axisGridLineWidth(), KDChartAxisParams::axisGridStyle(), KDChartAxisParams::axisGridSubColor(), KDChartAxisParams::axisGridSubLineWidth(), KDChartAxisParams::axisGridSubStyle(), KDChartAxisParams::axisLabelsColor(), KDChartAxisParams::axisLabelsDateTimeFormat(), KDChartAxisParams::axisLabelsDontAutoRotate(), KDChartAxisParams::axisLabelsDontShrinkFont(), KDChartAxisParams::axisLabelsFont(), KDChartAxisParams::axisLabelsFontUseRelSize(), KDChartAxisParams::axisLabelsRotation(), KDChartAxisParams::axisLabelsTouchEdges(), KDChartAxisParams::axisLabelsVisible(), KDChartAxisParams::axisLabelTexts(), KDChartAxisParams::axisLastLabelText(), KDChartAxisParams::axisLineColor(), KDChartAxisParams::axisLineVisible(), KDChartAxisParams::axisLineWidth(), KDChartParams::axisParams(), KDChartAxisParams::axisShowGrid(), KDChartAxisParams::axisShowSubDelimiters(), KDChartAxisParams::axisTrueLineWidth(), KDChartAxisParams::axisType(), KDChartAxisParams::axisValueLeaveOut(), KDChartAxisParams::axisVisible(), KDChartAxisParams::axisZeroLineColor(), KDChartAxisParams::axisZeroLineStartX(), KDChartAxisParams::axisZeroLineStartY(), KDChartParams::barChartSubType(), KDChartParams::chartType(), KDChartParams::globalLeadingLeft(), KDChartAxisParams::hasAxisFirstLabelText(), KDChartAxisParams::hasAxisLastLabelText(), KDChartParams::optimizeOutputForScreen(), KDChartAxisParams::trueAxisDelta(), KDChartAxisParams::trueAxisDeltaPixels(), and KDChartAxisParams::trueAxisLow().

{
    if ( !painter || !data || 0 == params() )
        return ;



    const bool bMultiRowBarChart = KDChartParams::Bar == params()->chartType() &&
                                   KDChartParams::BarMultiRows == params()->barChartSubType();



    double areaWidthP1000 = _logicalWidth / 1000.0;
    double areaHeightP1000 = _logicalHeight / 1000.0;
    double averageValueP1000 = QMIN(areaWidthP1000, areaHeightP1000);//( areaWidthP1000 + areaHeightP1000 ) / 2.0;
    // length of little delimiter-marks indicating axis scaling
    double delimLen;

    calculateAllAxesLabelTextsAndCalcValues( data, areaWidthP1000, areaHeightP1000, delimLen );

    
    // Now the labels are known, so let us paint the axes...
    painter->save();
    painter->setPen( Qt::NoPen );

    bool screenOutput = params()->optimizeOutputForScreen();
    uint iAxis;

    for ( iAxis = 0; iAxis < KDCHART_MAX_AXES; ++iAxis ){
        internal__KDChart__CalcValues& cv = calcVal[iAxis];
        if( cv.processThisAxis ){

            const KDChartAxisParams & para = params()->axisParams( iAxis );

            internal__KDChart__CalcValues& cv = calcVal[iAxis];

            const QColor labelsColor( para.axisLabelsColor() );

            // for debugging:
            //painter->fillRect(para.axisTrueAreaRect(), Qt::yellow);

            uint lineWidth = 0 <= para.axisLineWidth()
                ? para.axisLineWidth()
                : -1 * static_cast < int > ( para.axisLineWidth()
                        * averageValueP1000 );
            ( ( KDChartAxisParams& ) para ).setAxisTrueLineWidth( lineWidth );

            uint gridLineWidth
                = ( KDChartAxisParams::AXIS_GRID_AUTO_LINEWIDTH
                        == para.axisGridLineWidth() )
                ? lineWidth
                : (   ( 0 <= para.axisGridLineWidth() )
                        ? para.axisGridLineWidth()
                        : -1 * static_cast < int > ( para.axisGridLineWidth()
                            * averageValueP1000 ) );

            uint gridSubLineWidth
                = ( KDChartAxisParams::AXIS_GRID_AUTO_LINEWIDTH
                        == para.axisGridSubLineWidth() )
                ? lineWidth
                : (   ( 0 <= para.axisGridSubLineWidth() )
                        ? para.axisGridSubLineWidth()
                        : -1 * static_cast < int > ( para.axisGridSubLineWidth()
                            * averageValueP1000 ) );

            // Magic to find out axis scaling factors and labels text height
            // =============================================================
            //                                             - khz, 02/24/2001
            //
            // 1st Calculate the axis label texts height regarding to
            //     user-defined per-axis settings.
            //
            // 2nd This height is given to calculateLabelTexts() to
            //     calculate the delimiter and sub-delimiter distances as
            //     well as the axis scaling factors.
            //     If neccessary and possible the short replacement strings
            //     are taken that might have been specified by the user.
            //     - see KDChartAxisParams::setAxisLabelStringLists() -
            //
            // 3rd Before displaying the texts we make sure they fit into
            //     their space, if needed we will do the following
            //     in order to avoid clipping of text parts:
            //
            //     (a) ABSCISSA axes only: rotate the texts in 5° steps
            //                             until they are drawn vertically
            //
            //     (b) further reduce the texts' font height down to 6pt
            //         .
            //
            // If the texts *still* don't fit into their space, we are lost
            // and they will be clipped. Such is live.
            //
            // Why all this?
            //
            // Because I do not believe in axis areas growing and shrinking
            // regarding to long or short label texts: start such behaviour
            // and become mad.
            //
            // Better plan: ask the user to specify a way how to abbreviate
            //              label texts (e.g. by writing "200" instead
            //              of that wide and unreadable  "200,000.00")
            //
            //
            //   F E A T U R E   P L A N N E D   F O R   F U T U R E . . .
            //
            //

            // Note: The labels-touch-edges flag may have been set to true
            //       inside the calculateLabelTexts() function.
            bool bTouchEdges = para.axisLabelsTouchEdges();

            // NOTE: The steady-value-calc flag may have been set to true
            //       inside the calculateLabelTexts() function
            //       by a special setAxisLabelTextParams() call,
            //       therefor we do not store its value before calling that function.
            if( cv.bLogarithmic )
                cv.nSubDelimFactor = 0.1;

            const double nUsableAxisHeight = cv.pTextsH;
            const double nUsableAxisWidth  = cv.pTextsW;

            const bool isHorizontalAxis
                = (KDChartAxisParams::AxisPosBottom == cv.basicPos) ||
                (KDChartAxisParams::AxisPosTop    == cv.basicPos);

            QStringList* labelTexts = ( QStringList* ) para.axisLabelTexts();
            uint nLabels = ( 0 != labelTexts )
                ? labelTexts->count()
                : 0;
            // start point of 1st delimiter on the axis-line == grid-start
            QPoint p1( cv.orig );
            // end point of 1st delimiter near the label text
            QPoint p2( cv.orig );
            // end point of small sub-delimiter
            QPoint p2a( cv.orig );
            // start point of 1st grid-line (beginnig at the axis)
            QPoint pGA( cv.orig );
            // end point of 1st grid-line at the other side of the chart
            QPoint pGZ( cv.orig );
            // start point of zero-line, this is often identical with p1
            // but will be different in case of shifted zero-line
            const int aGapX = axisGapX(iAxis);
            const int aGapY = axisGapY(iAxis);
            double axisZeroLineStartX = p1.x() - cv.pXDelimDeltaFaktor * aGapX;
            double axisZeroLineStartY = p1.y() - cv.pYDelimDeltaFaktor * aGapY;

            p2.setX( static_cast<int>( p2.x()  + cv.pXDelimDeltaFaktor * delimLen ) );
            p2.setY(  static_cast<int>(p2.y()  + cv.pYDelimDeltaFaktor * delimLen ) );
            p2a.setX( static_cast<int>(p2a.x() + cv.pXDelimDeltaFaktor * delimLen * 2 / 3 ) );
            p2a.setY( static_cast<int>(p2a.y() + cv.pYDelimDeltaFaktor * delimLen * 2 / 3 ) );

            pGA.setX( static_cast<int>(pGZ.x() - cv.pXDelimDeltaFaktor * aGapX ) );
            pGA.setY( static_cast<int>(pGZ.y() - cv.pYDelimDeltaFaktor * aGapY ) );
            pGZ.setX( static_cast<int>(pGZ.x() - cv.pXDelimDeltaFaktor
                                                 * (_dataRect.width() - 1 + aGapX) ) );
            pGZ.setY( static_cast<int>(pGZ.y() - cv.pYDelimDeltaFaktor 
                                                 * (_dataRect.height() - 1 + aGapY) ) );

            if ( nLabels ) {
                // Sometimes the first or last labels partially reach out of
                // their axis area: we allow this
                const bool oldClippingFlag = painter->hasClipping();
                painter->setClipping( false );

                if( para.hasAxisFirstLabelText() )
                    labelTexts->first() = para.axisFirstLabelText();
                if( para.hasAxisLastLabelText() )
                    labelTexts->last() = para.axisLastLabelText();

                const double pXDelta = cv.pXDeltaFactor * cv.pDelimDelta;
                const double pYDelta = cv.pYDeltaFactor * cv.pDelimDelta;

                // draw label texts and delimiters and grid
                painter->setPen( QPen( para.axisLineColor(),
                                 lineWidth ) );

                const QString formatDT = cv.isDateTime
                    ? para.axisLabelsDateTimeFormat()
                    : QString();

                // calculate font size
                const double minTextHeight = 7.0;
                if ( minTextHeight > cv.nTxtHeight )
                    cv.nTxtHeight = minTextHeight;
                QFont actFont( para.axisLabelsFont() );
                if ( para.axisLabelsFontUseRelSize() ) {
                    actFont.setPointSizeFloat( cv.nTxtHeight );
                }
                painter->setFont( actFont );
                QFontMetrics fm( actFont );

                int nLeaveOut = 0;
                int nRotation = 0;

                // Draw simple string labels
                // or calculate and draw nice Date/Time ruler?
                QString commonDtHeader;
                if( cv.autoDtLabels ){
                    cv.textAlign = Qt::AlignCenter;
                    //qDebug(dtLow.toString("\nd.MM.yyyy  -  h:mm:ss" ));
                    //qDebug(dtHigh.toString( "d.MM.yyyy  -  h:mm:ss" ));
                    const QDate& dLow  = cv.dtLow.date();
                    const QTime& tLow  = cv.dtLow.time();
                    const QDate& dHigh = cv.dtHigh.date();
                    const QTime& tHigh = cv.dtHigh.time();
                    bool sameYear   = dLow.year() == dHigh.year();
                    bool sameMonth  = sameYear   && (dLow.month()  == dHigh.month() );
                    bool sameDay    = sameMonth  && (dLow.day()    == dHigh.day()   );
                    bool sameHour   = sameDay    && (tLow.hour()   == tHigh.hour()  );
                    bool sameMinute = sameHour   && (tLow.minute() == tHigh.minute());
                    bool sameSecond = sameMinute && (tLow.second() == tHigh.second());
                    if( sameDay ){
                        commonDtHeader = QString::number( dLow.day() )
                            + ". "
#if COMPAT_QT_VERSION >= 0x030000
                            + QDate::longMonthName( dLow.month() )
#else
                            + dLow.monthName( dLow.month() )
#endif
                            + ' '
                            + QString::number( dLow.year() );
                        if( sameHour ){
                            commonDtHeader += "  /  "
                                + QString::number( tLow.hour() )
                                + ':';
                            if( sameMinute ){
                                if( 10 > tLow.minute() )
                                    commonDtHeader += '0';
                                commonDtHeader += QString::number( tLow.minute() )
                                    + ':';
                                if( sameSecond ){
                                    if( 10 > tLow.second() )
                                        commonDtHeader += '0';
                                    commonDtHeader += QString::number( tLow.second() );
                                    //
                                    // " Huston, we have a problem! "
                                    //
                                    // Currently we don't support milli secs
                                    // since they will not fit into a double
                                    // when looking at years...
                                    //
                                    // This will be improved in release 2.0.
                                    //                     (khz, 2002/07/12)
                                }
                                else
                                    commonDtHeader += "00";
                            }
                            else
                                commonDtHeader += "00";
                        }
                    }else if( sameMonth )
#if COMPAT_QT_VERSION >= 0x030000
                        commonDtHeader = QDate::longMonthName( dLow.month() )
#else
                            commonDtHeader = dLow.monthName( dLow.month() )
#endif
                            + ' '
                            + QString::number( dLow.year() );
                    else if( sameYear )
                        commonDtHeader = QString::number( dLow.year() );
                    //if( !commonDtHeader.isEmpty() )
                    //    qDebug(commonDtHeader);
                }else{
                    // make sure all label texts fit into their space
                    // by rotating and/or shrinking the texts
                    // or by leaving out some of the labels
                    QRegion unitedRegions;

                    const bool tryLeavingOut =
                        ( para.axisValueLeaveOut()
                          == KDChartAxisParams::AXIS_LABELS_AUTO_LEAVEOUT )
                        || ( 0 < para.axisValueLeaveOut() );
                    if( tryLeavingOut ) {
                        if( para.axisValueLeaveOut()
                                == KDChartAxisParams::AXIS_LABELS_AUTO_LEAVEOUT )
                            nLeaveOut = 0;
                        else
                            nLeaveOut = para.axisValueLeaveOut();
                    }
                    else
                        nLeaveOut = 0;
                    int stepWidthLeaveOut = nLeaveOut+1;
                    int iStepsLeaveOut = 0;

                    const bool tryShrinking = !para.axisLabelsDontShrinkFont();
                    const double nInitialTxtHeight = cv.nTxtHeight;

                    const bool tryRotating = isHorizontalAxis
                        && !para.axisLabelsDontAutoRotate();
                    const int nInitialRotation = (    (360 >  para.axisLabelsRotation())
                            && (270 <= para.axisLabelsRotation()) )
                        ? para.axisLabelsRotation()
                        : 0;
                    nRotation = nInitialRotation;

                    bool textsDontFitIntoArea;
                    bool textsOverlapping;
                    bool textsMatching;
                    do {
                        textsDontFitIntoArea = false;
                        textsOverlapping = false;
                        textsMatching = true;
                        // test if all texts match without mutually overlapping
                        unitedRegions = QRegion();
                        int align = nRotation
                            ? (Qt::AlignRight | Qt::AlignVCenter) // adjusting for rotation
                            : cv.textAlign;
                        QPoint anchor(200,200);
                        int iLeaveOut = 0;
                        double iLabel=0.0;
                        for ( QStringList::Iterator it = labelTexts->begin();
                                it != labelTexts->end();
                                ++it ) {
                            iLabel += 1.0;
                            if( iLeaveOut < nLeaveOut ) {
                                ++iLeaveOut;
                            } else {
                                iLeaveOut = 0;
                                anchor.setX(
                                        static_cast < int > ( p2.x() + pXDelta * (iLabel - 0.5) ) );
                                anchor.setY(
                                        static_cast < int > ( p2.y() + pYDelta * (iLabel - 0.5) ) );
                                QString text;
                                if( cv.isDateTime ){
#if COMPAT_QT_VERSION >= 0x030000
                                    QDateTime dt( QDateTime::fromString( *it,
                                                Qt::ISODate ) );
                                    text = dt.toString( formatDT );
#else
                                    QDateTime dt( dateTimeFromString( *it ) );
                                    text = dt.toString();
#endif
                                }else{
                                    text = *it;
                                }
                                KDDrawTextRegionAndTrueRect infosKDD =
                                    KDDrawText::measureRotatedText( painter,
                                            nRotation,
                                            anchor,
                                            text,
                                            0,
                                            align,
                                            &fm,
                                            false,
                                            false,
                                            15 );
                                if( infosKDD.region.boundingRect().left()
                                        < params()->globalLeadingLeft()+1 ){
                                    textsMatching = false;
                                    textsDontFitIntoArea = true;
                                    //qDebug("too wide");
                                    break;
                                }
                                else{
                                    QRegion sectReg( infosKDD.region.intersect( unitedRegions ) );
                                    if ( sectReg.isEmpty() )
                                        unitedRegions = unitedRegions.unite( infosKDD.region );
                                    else {
                                        textsMatching = false;
                                        textsOverlapping = true;
                                        //qDebug("label regions are intersecting");
                                        break;
                                    }
                                }
                            }
                        }
                        /*if(!iAxis){
                          qDebug("nTxtHeight: "+QString::number(nTxtHeight)+"   nRotation: "+QString::number(nRotation)+
                          "   matching: "+QString(textsMatching ? "TRUE":"FALSE"));
                          }*/
                        if( isHorizontalAxis ) {
                            if( nUsableAxisHeight < unitedRegions.boundingRect().height() ){
                                textsMatching = false;
                                textsDontFitIntoArea = true;
                                //qDebug("too high");
                            }
                        } else {
                            if( nUsableAxisWidth < unitedRegions.boundingRect().width() ){
                                //qDebug("textsMatching: %s",textsMatching ? "TRUE" : "FALSE");
                                textsMatching = false;
                                textsDontFitIntoArea = true;
                                //qDebug("too wide");
                            }
                            //else qDebug("not too wide");
                        }
                        if(!iAxis){
                          /*if(textsMatching){
                            qDebug("\n--------------------------");
                            qDebug("MATCHING: nTxtHeight: "+QString::number(cv.nTxtHeight)+"   nRotation: "+QString::number(nRotation));
                            qDebug("--------------------------");
                          }else{
                            qDebug("\n--------------------------");
                            qDebug("N O T   MATCHING: nTxtHeight: "+QString::number(cv.nTxtHeight)+"   nRotation: "+QString::number(nRotation));
                            qDebug("--------------------------");
                          }*/
                        }
                        if( !textsMatching ) {
                            bool rotatingDoesNotHelp = false;
                            // step 1: In case of labels being too wide
                            //         to fit into the available space
                            //         we try to rotate the texts in 5° steps.
                            //         This is done for Abscissa axes only.
                            if ( tryRotating ) {
                                //qDebug("try rotating");
                                // The following is designed for horizontal axes
                                // since we currently don't support label rotating
                                // on vertical axes.             (khz, 2002/08/15)
                                if( textsDontFitIntoArea  ){
                                    if( nRotation != nInitialRotation ){
                                      textsDontFitIntoArea = false;
                                      nRotation = nInitialRotation;
                                    }
                                    rotatingDoesNotHelp = true;
                                }
                                else{
                                    if( nRotation ) {
                                        if( 270 < nRotation ) {
                                            nRotation -= 5;
                                            if( 270 > nRotation )
                                                nRotation = 270; // drawing vertically now
                                        } else {
                                            if( nInitialRotation )
                                                nRotation = nInitialRotation;
                                            else
                                                nRotation = 0; // reset rotation to ZERO°
                                            rotatingDoesNotHelp = true;
                                        }
                                    } else {
                                        if( nInitialRotation )
                                            nRotation = nInitialRotation;
                                        else
                                            nRotation = 350; // (re-)start rotating with -10°
                                    }
                                }
                            }
                            if ( !tryRotating || rotatingDoesNotHelp ) {

                                // step 2: In case of labels being too wide and
                                //         rotating them did not help or is forbidden
                                //         we try to reduce the font size.
                                if ( tryShrinking && (minTextHeight < cv.nTxtHeight) ) {
                                    cv.nTxtHeight -= 1.0;
                                    if ( minTextHeight > cv.nTxtHeight )
                                        cv.nTxtHeight = minTextHeight;
                                } else {

                                    // step 3: In case reducing the font size is not possible
                                    //         any further (or is not allowed at all) we try
                                    //         to leave out some of the labels.
                                    if(    tryLeavingOut
                                        && textsOverlapping
                                        && (nLeaveOut+1 < static_cast < int > ( nLabels )) ) {
                                        ++iStepsLeaveOut;
                                        //if(!iAxis)qDebug("iStepsLeaveOut: %i", iStepsLeaveOut);
                                        nLeaveOut =
                                            iStepsLeaveOut*stepWidthLeaveOut - 1;
                                        if( tryShrinking )
                                            cv.nTxtHeight = nInitialTxtHeight;
                                    }
                                    else
                                        break;
                                }
                                if( tryShrinking ) {
                                    actFont.setPointSizeFloat( cv.nTxtHeight );
                                    //if(!iAxis)qDebug("axis: %i    cv.nTxtHeight: %f", iAxis, cv.nTxtHeight);
                                    painter->setFont( actFont );
                                    fm = QFontMetrics( actFont );
                                }
                            }
                        }
                    } while( !textsMatching );

                    if( nRotation ){
                        // The following is designed for horizontal axes
                        // since we currently don't support label rotating
                        // on vertical axes.             (khz, 2002/08/15)
                        //int oldVert = textAlign & (Qt::AlignTop | Qt::AlignBottom);
                        //int steepness = abs(270-nRotation);
                        //bool steep = (30 > steepness);
                        cv.textAlign = Qt::AlignRight | Qt::AlignVCenter;  // adjusting for rotation
                        /*textAlign = Qt::AlignRight |
                          ( steep ? Qt::AlignVCenter : oldVert);*/
                        //int dx = pXDelta / 2 - steep ? (nTxtHeight / 4) : 0;
                        double dx = (pXDelta / 2) - (cv.nTxtHeight / 4);
                        double dy = /*steep ? 0 : */(cv.nTxtHeight / 2.0);
                        cv.pTextsX += dx;
                        cv.pTextsY += dy;
                    }
                    /*
                       QBrush oldBrush = painter->brush();
                       QRegion oldReg = painter->clipRegion();//QPainter::CoordPainter);
                       painter->setBrush(Qt::Dense4Pattern);
                       painter->setClipRegion(unitedRegions);//,QPainter::CoordPainter);
                       painter->drawRect(0,0,2000,1500);
                       painter->setClipRegion(oldReg);//,QPainter::CoordPainter);
                       painter->setBrush(oldBrush);
                       */
                    /*if(!iAxis){
                      qDebug("==========================");
                      qDebug("nTxtHeight: "+QString::number(nTxtHeight)+"   nRotation: "+QString::number(nRotation));
                      qDebug(textsMatching ? "matching":"not matching");
                      }*/
                }

                painter->setFont( actFont );
                fm = QFontMetrics( actFont );

                // set colour of grid pen
                QPen gridPen, leaveOutGridPen;
                if( para.axisShowGrid() && !bMultiRowBarChart )
                    gridPen.setColor( para.axisGridColor() );

                bool bDrawAdditionalSubGridLine = false;
                double pGXMicroAdjust = 0.0;
                double pGYMicroAdjust = 0.0;
                if ( !bTouchEdges ) {
                    // adjust the data values pos
                    p1.setX( static_cast<int>( p1.x() + pXDelta / 2 ) );
                    p1.setY( static_cast<int>( p1.y() + pYDelta / 2 ) );
                    p2.setX( static_cast<int>( p2.x() + pXDelta / 2 ) );
                    p2.setY( static_cast<int>( p2.y() + pYDelta / 2 ) );
                    // adjust the short delimiter lines pos
                    p2a.setX( static_cast<int>( p2a.x() + pXDelta / 2 ) );
                    p2a.setY( static_cast<int>( p2a.y() + pYDelta / 2 ) );
                    // adjust grid lines pos
                    bDrawAdditionalSubGridLine =
                        isHorizontalAxis && !
                        params()->axisParams(
                                KDChartAxisParams::AxisPosRight ).axisVisible() &&
                        !bMultiRowBarChart;
                    pGA.setX( static_cast<int>( pGA.x() + pXDelta / 2 ) );
                    pGA.setY( static_cast<int>( pGA.y() + pYDelta / 2 ) );
                    pGZ.setX( static_cast<int>( pGZ.x() + pXDelta / 2 ) );
                    pGZ.setY( static_cast<int>( pGZ.y() + pYDelta / 2 ) );
                    // fine-tune grid line pos for grid of vertical axis
                    if( KDChartAxisParams::AxisTypeNORTH == para.axisType() ) {
                        pGXMicroAdjust = cv.pXDeltaFactor * lineWidth / 2.0;
                        pGYMicroAdjust = cv.pYDeltaFactor * lineWidth / 2.0;
                    }
                }
                double x1, y1, x2, y2, xGA, yGA, xGZ, yGZ,
                p1X, p1Y, p2X, p2Y, pGAX, pGAY, pGZX, pGZY, xT, yT;
                if (    !cv.autoDtLabels
                        && 0.0 != cv.nSubDelimFactor
                        && para.axisShowSubDelimiters()
                        && para.axisLabelsVisible()
                        && !nLeaveOut ) {
                    QPen pen( para.axisLineColor(), static_cast<int>( 0.5 * lineWidth ) );
                    uint penWidth = pen.width();
                    bool bOk = true;

                    if( cv.bLogarithmic )
                        cv.nSubDelimFactor = 0.1;

                    while ( fabs( ( pXDelta + pYDelta ) * cv.nSubDelimFactor / 6.0 )
                            <= 1.0 + penWidth
                            && bOk ) {
                        if ( 0 < penWidth ) {
                            --penWidth;
                            pen.setWidth( penWidth );
                        }else{
                            if( cv.bLogarithmic ){
                                break; // there is nothing we can do: we allways
                                // want 10 sub-delims per logarithmic step
                            }else{
                                if ( 0.5 != cv.nSubDelimFactor ) {
                                    // emercency: reduce number of sub-scaling
                                    // delimiters
                                    cv.nSubDelimFactor = 0.5;
                                } else
                                    bOk = false;
                            }
                        }
                    }
                    if ( bOk ) {
                        x1 = p1.x();
                        y1 = p1.y();
                        x2 = p2a.x();
                        y2 = p2a.y();
                        xGA = pGA.x();
                        yGA = pGA.y();
                        xGZ = pGZ.x();
                        yGZ = pGZ.y();
                        p1X = x1;
                        p1Y = y1;
                        p2X = x2;
                        p2Y = y2;
                        pGAX = xGA;
                        pGAY = yGA;
                        pGZX = xGZ;
                        pGZY = yGZ;

                        // set up grid pen for drawing the sub-grid lines
                        const QPen oldGridPen( gridPen );
                        if ( para.axisShowGrid() ) {
                            gridPen.setColor( para.axisGridSubColor() );
                            gridPen.setWidth( gridSubLineWidth );
                            gridPen.setStyle( para.axisGridSubStyle() );
                        }
                        const QPen oldPen( painter->pen() );
                        painter->setPen( pen );
                        double nSubDelim = ( labelTexts->count() - 1 )
                            / cv.nSubDelimFactor;
                        modf( nSubDelim, &nSubDelim );
                        double pXSubDelimDelta = pXDelta * cv.nSubDelimFactor;
                        double pYSubDelimDelta = pYDelta * cv.nSubDelimFactor;

                        int logarithCnt = 1;
                        double xLogarithOffs = 0;
                        double yLogarithOffs = 0;

                        for ( double iDelim = 1.0;
                                iDelim <= nSubDelim + 1.0;
                                iDelim += 1.0, logarithCnt++ ) {
                            if ( cv.bLogarithmic )
                            {
                                if ( logarithCnt == 11 )
                                {
                                    xLogarithOffs +=
                                        pXDelta * log10( 10*cv.nSubDelimFactor*10 );
                                    yLogarithOffs +=
                                        pYDelta * log10( 10*cv.nSubDelimFactor*10 );
                                    logarithCnt=1;
                                }

                                pXSubDelimDelta =
                                    pXDelta * log10( 10*cv.nSubDelimFactor*logarithCnt );
                                pYSubDelimDelta =
                                    pYDelta * log10( 10*cv.nSubDelimFactor*logarithCnt );
                            }

                            if ( para.axisShowGrid() && !bMultiRowBarChart) {
                                // draw the sub grid line
                                saveDrawLine( *painter,
                                              QPoint( static_cast<int>( pGAX ), static_cast<int>( pGAY ) ),
                                              QPoint( static_cast<int>( pGZX ), static_cast<int>( pGZY ) ),
                                              gridPen );
                                if( cv.bLogarithmic ){
                                    pGAX = xGA + pXSubDelimDelta + xLogarithOffs;
                                    pGAY = yGA + pYSubDelimDelta + yLogarithOffs;
                                    pGZX = xGZ + pXSubDelimDelta + xLogarithOffs;
                                    pGZY = yGZ + pYSubDelimDelta + yLogarithOffs;
                                }else{
                                    pGAX = xGA + iDelim * pXSubDelimDelta;
                                    pGAY = yGA + iDelim * pYSubDelimDelta;
                                    pGZX = xGZ + iDelim * pXSubDelimDelta;
                                    pGZY = yGZ + iDelim * pYSubDelimDelta;
                                }
                            }
                            // draw the short delimiter line
                            painter->drawLine( QPoint( static_cast<int>( p1X ), static_cast<int>( p1Y ) ),
                                               QPoint( static_cast<int>( p2X ), static_cast<int>( p2Y ) ) );

                            if( cv.bLogarithmic ){
                                p1X = x1 + pXSubDelimDelta + xLogarithOffs;
                                p1Y = y1 + pYSubDelimDelta + yLogarithOffs;
                                p2X = x2 + pXSubDelimDelta + xLogarithOffs;
                                p2Y = y2 + pYSubDelimDelta + yLogarithOffs;
                            }else{
                                p1X = x1 + iDelim * pXSubDelimDelta;
                                p1Y = y1 + iDelim * pYSubDelimDelta;
                                p2X = x2 + iDelim * pXSubDelimDelta;
                                p2Y = y2 + iDelim * pYSubDelimDelta;
                            }
                        }
                        // draw additional sub grid line
                        if( bDrawAdditionalSubGridLine
                                && para.axisShowGrid() ) {
                            saveDrawLine( *painter,
                                          QPoint( static_cast<int>( pGAX ), static_cast<int>( pGAY ) ),
                                          QPoint( static_cast<int>( pGZX ), static_cast<int>( pGZY ) ), gridPen );
                        }
                        painter->setPen( oldPen );
                        gridPen = oldGridPen;
                    }
                }
                x1 = p1.x();
                y1 = p1.y();
                x2 = p2.x();
                y2 = p2.y();
                xGA = pGA.x();
                yGA = pGA.y();
                xGZ = pGZ.x();
                yGZ = pGZ.y();
                p1X = x1;
                p1Y = y1;
                p2X = x2;
                p2Y = y2;
                pGAX = xGA;
                pGAY = yGA;
                pGZX = xGZ;
                pGZY = yGZ;
                xT = cv.pTextsX;
                yT = cv.pTextsY;
                // set up grid pen for drawing the normal grid lines
                if ( para.axisShowGrid() ) {
                    gridPen.setWidth( gridLineWidth );
                    gridPen.setStyle( para.axisGridStyle() );
                    // if axis not visible draw the 1st grid line too
                    if( !para.axisLineVisible() )
                        saveDrawLine( *painter, cv.orig, cv.dest, gridPen );
                }
                if( nLeaveOut ) {
                    leaveOutGridPen = gridPen;
                    leaveOutGridPen.setWidth( gridLineWidth / 2 );
                    leaveOutGridPen.setStyle( Qt::DotLine );
                }
                //  =========================================================
                //  ||  The labels and delimiters and grid printing loops  ||
                //  =========================================================
                //
                double iLabel = 0.0;
                if( cv.autoDtLabels )
                {
                    /*
                       qDebug("\ndtLow: %i %i %i    %i:%i:%i",
                       dtLow.date().year(),
                       dtLow.date().month(),
                       dtLow.date().day(),
                       dtLow.time().hour(),
                       dtLow.time().minute(),
                       dtLow.time().second());
                       qDebug("dtHigh: %i %i %i    %i:%i:%i",
                       dtHigh.date().year(),
                       dtHigh.date().month(),
                       dtHigh.date().day(),
                       dtHigh.time().hour(),
                       dtHigh.time().minute(),
                       dtHigh.time().second());
                       */
                    int pXD = static_cast <int> (cv.pXDelimDeltaFaktor * 1.25 * (cv.nTxtHeight+4));
                    int pYD = static_cast <int> (cv.pYDelimDeltaFaktor * 1.25 * (cv.nTxtHeight+4));
                    int orgXD = pXD;
                    int orgYD = pYD;
                    cv.pTextsW = fabs( (0.0 == pXDelta) ? pXD : pXDelta );
                    cv.pTextsH = fabs( (0.0 == pYDelta) ? pYD : pYDelta );

                    // make sure leftmost little rectangle border is straight below the left axis
                    x1--;

                    double pSecX     = x1;
                    double pSecY     = y1;
                    bool   secPaint= false;
                    double pMinX     = x1;
                    double pMinY     = y1;
                    bool   minPaint= false;
                    double pHourX    = x1;
                    double pHourY    = y1;
                    bool   hourPaint= false;
                    double pDayX     = x1;
                    double pDayY     = y1;
                    bool   dayPaint= false;
                    /* khz: currently not used
                       double pWeekX    = x1;
                       double pWeekY    = y1;
                       bool   weekPaint= false;
                       */
                    double pMonthX   = x1;
                    double pMonthY   = y1;
                    bool   monthPaint= false;
                    /*double pQuarterX = x1;
                      double pQuarterY = y1;
                      bool   minPaint= false;
                      */
                    double pYearX    = x1;
                    double pYearY    = y1;
                    bool   yearPaint= false;

                    double pXYDelta = fabs( pXDelta ) + fabs( pYDelta );

                    if( 0.0 == para.trueAxisDeltaPixels() )
                        ( ( KDChartAxisParams& ) para ).setTrueAxisDeltaPixels( QMIN(_logicalWidth, _logicalHeight) / 150 );

                    if( !commonDtHeader.isEmpty() ){
                        QPen oldPen( painter->pen() );
                        painter->setPen( QPen( labelsColor ) );
                        painter->drawText( static_cast<int>( x1 + 4.0 * pXD ),
                                           static_cast<int>( y1 + 4.0 * pYD ),
                                commonDtHeader );
                        painter->setPen( oldPen );
                    }
                    bool dtGoDown = cv.dtLow > cv.dtHigh;
                    int  mult = dtGoDown ? -1 : 1;
                    const QDateTime& startDt = dtGoDown ? cv.dtHigh : cv.dtLow;

                    ( ( KDChartAxisParams& ) para ).setAxisDtLowPos( x1, y1 );
                    // adjust stored dt-low and scale settings
                    ( ( KDChartAxisParams& ) para ).setTrueAxisDtLow( startDt );
                    ( ( KDChartAxisParams& ) para ).setTrueAxisDtScale( cv.dtDeltaScale );

                    int gridDX = pGZ.x() - pGA.x();
                    int gridDY = pGZ.y() - pGA.y();
                    if ( para.axisShowGrid() ) {
                        gridPen.setColor( para.axisGridColor() );
                        gridPen.setWidth( gridLineWidth );
                        gridPen.setStyle( para.axisGridStyle() );
                    }
                    QPen subGridPen(    gridPen.color(), 1, para.axisGridStyle() );
                    QPen subSubGridPen( gridPen.color(), 1, para.axisGridSubStyle() );
                    QPen pen = subGridPen;

                    QDateTime dt(    startDt );
                    QDateTime newDt( startDt );
                    for( uint i=1; i <= nLabels; ++i ){
                        switch( cv.dtDeltaScale ) {
                            case KDChartAxisParams::ValueScaleSecond:
                                dtAddSecs( dt, 1 * mult, newDt );
                                break;
                            case KDChartAxisParams::ValueScaleMinute:
                                dtAddSecs( dt, 60 * mult, newDt );
                                break;
                            case KDChartAxisParams::ValueScaleHour:
                                dtAddSecs( dt, 3600 * mult, newDt );
                                break;
                            case KDChartAxisParams::ValueScaleDay:
                                dtAddDays( dt, 1 * mult, newDt );
                                break;
                            case KDChartAxisParams::ValueScaleWeek:
                                dtAddDays( dt, 7 * mult, newDt );
                                break;
                            case KDChartAxisParams::ValueScaleMonth:
                                dtAddMonths( dt,1 * mult, newDt );
                                break;
                            case KDChartAxisParams::ValueScaleQuarter:
                                dtAddMonths( dt,3 * mult, newDt );
                                break;
                            case KDChartAxisParams::ValueScaleYear:
                                dtAddYears( dt, 1 * mult, newDt );
                                break;
                            default:
                                dtAddDays( dt, 1 * mult, newDt );
                                break;
                        }
                        const QDateTime& testDt
                            = dtGoDown
                            ? (   ( newDt < cv.dtLow )
                                    ? cv.dtLow
                                    : newDt )
                            : (   ( newDt > cv.dtHigh )
                                    ? cv.dtHigh
                                    : newDt );
                        /*
                           qDebug("    dt: %i %i %i    %i:%i:%i",
                           newDt.date().year(),newDt.date().month(),newDt.date().day(),
                           newDt.time().hour(),newDt.time().minute(),newDt.time().second());
                           qDebug("testDt: %i %i %i    %i:%i:%i",
                           testDt.date().year(),testDt.date().month(),testDt.date().day(),
                           testDt.time().hour(),testDt.time().minute(),testDt.time().second());
                           */
                        bool endLoop = (i == nLabels) || (&testDt != &newDt);

                        secPaint = ( KDChartAxisParams::ValueScaleSecond >= cv.dtDeltaScale ) &&
                            ( testDt.time().second() != dt.time().second() ||
                              ( endLoop && ((pSecX != x1) || (pSecY != y1))));
                        minPaint = ( KDChartAxisParams::ValueScaleMinute >= cv.dtDeltaScale ) &&
                            ( testDt.time().minute() != dt.time().minute() ||
                              ( endLoop && ((pMinX != x1) || (pMinY != y1))));
                        hourPaint = ( KDChartAxisParams::ValueScaleHour >= cv.dtDeltaScale ) &&
                            ( testDt.time().hour() != dt.time().hour() ||
                              ( endLoop && ((pHourX != x1) || (pHourY != y1))));
                        dayPaint = ( KDChartAxisParams::ValueScaleDay >= cv.dtDeltaScale ) &&
                            ( testDt.date().day() != dt.date().day() ||
                              ( endLoop && ((pDayX != x1) || (pDayY != y1))));
                        /* khz: currently not used
                           weekPaint = ( KDChartAxisParams::ValueScaleWeek >= cv.dtDeltaScale ) &&
                           ( testDt.date().week() != dt.date().week() ||
                           ( endLoop && ((pWeekX != x1) || (pWeekY != y1))));
                           */
                        monthPaint = ( KDChartAxisParams::ValueScaleMonth >= cv.dtDeltaScale ) &&
                            ( testDt.date().month() != dt.date().month() ||
                              ( endLoop && ((pMonthX != x1) || (pMonthY != y1))));
                        yearPaint = ( KDChartAxisParams::ValueScaleYear >= cv.dtDeltaScale ) &&
                            ( testDt.date().year() != dt.date().year() ||
                              ( endLoop && ((pYearX != x1) || (pYearY != y1))));

                        p1X = x1 + iLabel * pXDelta;
                        p1Y = y1 + iLabel * pYDelta;
                        p2X = p1X + pXDelta;
                        p2Y = p1Y + pYDelta;
                        pXD = orgXD;
                        pYD = orgYD;

                        if( endLoop ){
                            ( ( KDChartAxisParams& ) para ).setAxisDtHighPos( p1X, p1Y );
                            // adjust stored dt-high settings
                            ( ( KDChartAxisParams& ) para ).setTrueAxisDtHigh( dt );
                        }
                        pen = subGridPen;
                        /*
                        // old code: just draw the seconds without any tests
                        // (not wise to do that when supporting sec1000
                        //  and the like some day...)
                        if( newDt.time().second() != dt.time().second() ){
                        painter->drawLine( QPoint( p1X, p1Y ), QPoint( p1X+pXD, p1Y+pYD ) );
                        painter->drawLine( QPoint( p1X+pXD, p1Y+pYD ),
                        QPoint( p1X+pXD + pXDelta, p1Y+pYD + pYDelta ) );
                        painter->drawText( p1X+pXD-orgXD, p1Y+pYD-orgYD,
                        pTextsW, pTextsH,
                        textAlign | Qt::DontClip,
                        QString::number( dt.time().second() ) );
                        pXD += orgXD;
                        pYD += orgYD;
                        }
                        */
                        if( secPaint ){
                            painter->drawLine( QPoint( static_cast<int>( pSecX+pXD ),
                                                       static_cast<int>( pSecY+pYD ) ),
                                               QPoint( static_cast<int>( p2X + pXD ),
                                                       static_cast<int>( p2Y + pYD ) ) );
                            if( (pXDelta/2.0 < p2X - pSecX) || (pYDelta/2.0 < p2Y - pSecY) ){
                                QPen oldPen( painter->pen() );
                                painter->setPen( QPen( labelsColor ) );
                                painter->drawText( static_cast<int>( pSecX+pXD-orgXD ),
                                                   static_cast<int>( pSecY+pYD-orgYD ),
                                                   static_cast<int>( fabs((0.0 == pXDelta) ? cv.pTextsW : (p2X - pSecX))),
                                                   static_cast<int>(fabs((0.0 == pYDelta) ? cv.pTextsH : (p2Y - pSecY))),
                                        cv.textAlign | Qt::DontClip,
                                        QString::number( dt.time().second() ) );
                                painter->setPen( oldPen );
                                if ( para.axisShowGrid() ){

                                    saveDrawLine( *painter,
                                                  QPoint( static_cast<int>( pSecX ),
                                                          static_cast<int>( pSecY ) ),
                                                  QPoint( static_cast<int>( pSecX + gridDX ),
                                                          static_cast<int>( pSecY + gridDY ) ),
                                            pen );
                                    pen = gridPen;
                                }
                                if( !minPaint || pMinX != pSecX || pMinY != pSecY ){
                                    painter->drawLine( QPoint( static_cast<int>( pSecX ),
                                                               static_cast<int>( pSecY ) ),
                                                       QPoint( static_cast<int>( pSecX+pXD ),
                                                               static_cast<int>( pSecY+pYD ) ) );
                                }
                            }
                            if( endLoop && !minPaint )
                                painter->drawLine( QPoint( static_cast<int>( p2X ),
                                                           static_cast<int>( p2Y ) ),
                                                   QPoint( static_cast<int>( p2X+pXD ),
                                                           static_cast<int>( p2Y+pYD ) ) );
                            pSecX = p1X + pXDelta;
                            pSecY = p1Y + pYDelta;
                            pXD += orgXD;
                            pYD += orgYD;
                        }
                        if( minPaint ){
                            painter->drawLine( QPoint( static_cast<int>( pMinX+pXD ),
                                                       static_cast<int>( pMinY+pYD ) ),
                                               QPoint( static_cast<int>( p2X + pXD ),
                                                       static_cast<int>( p2Y + pYD ) ) );
                            if( (pXDelta/2.0 < p2X - pMinX) || (pYDelta/2.0 < p2Y - pMinY) ){
                                QPen oldPen( painter->pen() );
                                painter->setPen( QPen( labelsColor ) );
                                painter->drawText( static_cast<int>( pMinX+pXD-orgXD ),
                                                   static_cast<int>( pMinY+pYD-orgYD ),
                                                   static_cast<int>( fabs((0.0 == pXDelta) ? cv.pTextsW : (p2X - pMinX)) ),
                                                   static_cast<int>( fabs((0.0 == pYDelta) ? cv.pTextsH : (p2Y - pMinY)) ),
                                                   cv.textAlign | Qt::DontClip,
                                                   QString::number( dt.time().minute() ) );
                                painter->setPen( oldPen );
                                if ( para.axisShowGrid() ){
                                    if( !secPaint && 10 < pXYDelta  ){
                                        saveDrawLine( *painter,
                                                      QPoint( static_cast<int>( pMinX+pXDelta/2 ),
                                                              static_cast<int>( pMinY+pYDelta/2 ) ),
                                                      QPoint( static_cast<int>( pMinX+pXDelta/2 + gridDX ),
                                                              static_cast<int>( pMinY+pYDelta/2 + gridDY ) ),
                                                      subSubGridPen );
                                    }
                                    saveDrawLine( *painter,
                                                  QPoint( static_cast<int>( pMinX ),
                                                          static_cast<int>( pMinY ) ),
                                                  QPoint( static_cast<int>( pMinX + gridDX ),
                                                          static_cast<int>( pMinY + gridDY ) ),
                                                  pen );
                                    pen = gridPen;
                                }
                                if( !hourPaint || pHourX != pMinX || pHourY != pMinY ){
                                    painter->drawLine( QPoint( static_cast<int>( pMinX ),
                                                               static_cast<int>( pMinY ) ),
                                                       QPoint( static_cast<int>( pMinX+pXD ),
                                                               static_cast<int>( pMinY+pYD ) ) );
                                }
                            }
                            if( endLoop && !hourPaint )
                                painter->drawLine( QPoint( static_cast<int>( p2X ),
                                                           static_cast<int>( p2Y ) ),
                                                   QPoint( static_cast<int>( p2X+pXD ),
                                                           static_cast<int>( p2Y+pYD ) ) );
                            pMinX = p1X + pXDelta;
                            pMinY = p1Y + pYDelta;
                            pXD += orgXD;
                            pYD += orgYD;
                        }
                        if( hourPaint ){
                            painter->drawLine( QPoint( static_cast<int>( pHourX+pXD ),
                                                       static_cast<int>( pHourY+pYD ) ),
                                               QPoint( static_cast<int>( p2X + pXD ),
                                                       static_cast<int>( p2Y + pYD ) ) );
                            /*
                               qDebug("line");
                               qDebug("pXDelta / 2.0 : %f", pXDelta/2.0);
                               qDebug("p2X - pHourX  : %f", p2X - pHourX);
                               */
                            if( (pXDelta/2.0 < p2X - pHourX) || (pYDelta/2.0 < p2Y - pHourY) ){
                                /*
                                   qDebug("pHourX              %f", pHourX          );
                                   qDebug("      +pXD          %i",        pXD      );
                                   qDebug("          -orgXD    %i",            orgXD);
                                   qDebug("pHourY              %f", pHourY          );
                                   qDebug("      +pYD          %i",        pYD      );
                                   qDebug("          -orgYD    %i",            orgYD);
                                   */
                                QPen oldPen( painter->pen() );
                                painter->setPen( QPen( labelsColor ) );
                                painter->drawText( static_cast<int>( pHourX+pXD-orgXD ),
                                                   static_cast<int>( pHourY+pYD-orgYD ),
                                                   static_cast<int>( fabs((0.0 == pXDelta) ? cv.pTextsW : (p2X - pHourX))),
                                                   static_cast<int>( fabs((0.0 == pYDelta) ? cv.pTextsH : (p2Y - pHourY))),
                                                   cv.textAlign | Qt::DontClip,
                                                   QString::number( dt.time().hour() ) );
                                painter->setPen( oldPen );
                                if ( para.axisShowGrid() ){
                                    if( !minPaint && 10 < pXYDelta  ){
                                        saveDrawLine( *painter,
                                                      QPoint( static_cast<int>( pHourX+pXDelta/2 ),
                                                              static_cast<int>( pHourY+pYDelta/2 ) ),
                                                      QPoint( static_cast<int>( pHourX+pXDelta/2 + gridDX ),
                                                              static_cast<int>( pHourY+pYDelta/2 + gridDY ) ),
                                                      subSubGridPen );
                                    }
                                    saveDrawLine( *painter,
                                                  QPoint( static_cast<int>( pHourX ),
                                                          static_cast<int>( pHourY ) ),
                                                  QPoint( static_cast<int>( pHourX + gridDX ),
                                                          static_cast<int>( pHourY + gridDY ) ),
                                                  pen );
                                    pen = gridPen;
                                }
                                if( !dayPaint || pDayX != pHourX || pDayY != pHourY ){
                                    painter->drawLine( QPoint( static_cast<int>( pHourX ),
                                                               static_cast<int>( pHourY ) ),
                                                       QPoint( static_cast<int>( pHourX+pXD ),
                                                               static_cast<int>( pHourY+pYD ) ) );
                                }
                            }
                            if( endLoop && !dayPaint )
                                painter->drawLine( QPoint( static_cast<int>( p2X ),
                                                           static_cast<int>( p2Y ) ),
                                                   QPoint( static_cast<int>( p2X+pXD ),
                                                           static_cast<int>( p2Y+pYD ) ) );
                            pHourX = p1X + pXDelta;
                            pHourY = p1Y + pYDelta;
                            pXD += orgXD;
                            pYD += orgYD;
                        }
                        if( dayPaint ){
                            painter->drawLine( QPoint( static_cast<int>( pDayX+pXD ),
                                                       static_cast<int>( pDayY+pYD ) ),
                                               QPoint( static_cast<int>( p2X + pXD ),
                                                       static_cast<int>( p2Y + pYD ) ) );
                            if( (pXDelta/2.0 < p2X - pDayX) || (pYDelta/2.0 < p2Y - pDayY) ){
                                QPen oldPen( painter->pen() );
                                painter->setPen( QPen( labelsColor ) );
                                painter->drawText( static_cast<int>( pDayX+pXD-orgXD ),
                                                   static_cast<int>( pDayY+pYD-orgYD ),
                                                   static_cast<int>( fabs((0.0 == pXDelta) ? cv.pTextsW : (p2X - pDayX)) ),
                                                   static_cast<int>( fabs((0.0 == pYDelta) ? cv.pTextsH : (p2Y - pDayY)) ),
                                        cv.textAlign | Qt::DontClip,
                                        QString::number( dt.date().day() ) );
                                painter->setPen( oldPen );
                                /* khz: currently not used
                                   if( !weekPaint || pWeekX != pDayX || pWeekY != pDayY )
                                   */
                                if ( para.axisShowGrid() ){
                                    if( !hourPaint && 10 < pXYDelta  ){
                                        saveDrawLine( *painter,
                                                      QPoint( static_cast<int>( pDayX+pXDelta/2 ),
                                                              static_cast<int>( pDayY+pYDelta/2 ) ),
                                                      QPoint( static_cast<int>( pDayX+pXDelta/2 + gridDX ),
                                                              static_cast<int>( pDayY+pYDelta/2 + gridDY ) ),
                                                subSubGridPen );
                                    }
                                    saveDrawLine( *painter,
                                                  QPoint( static_cast<int>( pDayX ),
                                                          static_cast<int>( pDayY ) ),
                                                  QPoint( static_cast<int>( pDayX + gridDX ),
                                                          static_cast<int>( pDayY + gridDY ) ),
                                            pen );
                                    pen = gridPen;
                                }
                                if( !monthPaint || pMonthX != pDayX || pMonthY != pDayY ){
                                    painter->drawLine( QPoint( static_cast<int>( pDayX ),
                                                               static_cast<int>( pDayY ) ),
                                                       QPoint( static_cast<int>( pDayX+pXD ),
                                                               static_cast<int>( pDayY+pYD ) ) );
                                }
                            }
                            /* khz: currently not used
                               if( endLoop && !weekPaint )
                               */
                            if( endLoop && !monthPaint )
                                painter->drawLine( QPoint( static_cast<int>( p2X ),
                                                           static_cast<int>( p2Y ) ),
                                                   QPoint( static_cast<int>( p2X+pXD ),
                                                           static_cast<int>( p2Y+pYD ) ) );
                            pDayX = p1X + pXDelta;
                            pDayY = p1Y + pYDelta;
                            pXD += orgXD;
                            pYD += orgYD;
                        }
                        /* khz: currently unused
                           if( weekPaint ){
                           painter->drawLine( QPoint( pWeekX+pXD, pWeekY+pYD ),
                           QPoint( p2X + pXD, p2Y + pYD ) );
                           if( (pXDelta/2.0 < p2X - pWeekX) || (pYDelta/2.0 < p2Y - pWeekY) ){
                           QPen oldPen( painter->pen() );
                           painter->setPen( QPen( labelsColor ) );
                           painter->drawText( pWeekX+pXD-orgXD, pWeekY+pYD-orgYD,
                           painter->setPen( oldPen );
                           fabs((0.0 == pXDelta) ? pTextsW : (p2X - pWeekX)),
                           fabs((0.0 == pYDelta) ? pTextsH : (p2Y - pWeekY)),
                           textAlign | Qt::DontClip,
                           QString::number( dt.date().week() ) );
                           if ( para.axisShowGrid() ){
                           if( !dayPaint && 40 < pXYDelta  ){
                        // draw 7 lines:
                        //saveDrawLine( *painter,
                        //            QPoint( pWeekX+pXDelta/2,
                        //                    pWeekY+pYDelta/2 ),
                        //            QPoint( pWeekX+pXDelta/2 + gridDX,
                        //                    pWeekY+pYDelta/2 + gridDY ),
                        //            subSubGridPen );
                        }
                        saveDrawLine( *painter,
                        QPoint( pWeekX,
                        pWeekY ),
                        QPoint( pWeekX + gridDX,
                        pWeekY + gridDY ),
                        pen );
                        pen = gridPen;
                        }
                        if( !monthPaint || pMonthX != pDayX || pMonthY != pDayY ){
                        painter->drawLine( QPoint( pWeekX, pWeekY ), QPoint( pWeekX+pXD, pWeekY+pYD ) );
                        }
                        }
                        if( endLoop && !monthPaint )
                        painter->drawLine( QPoint( p2X, p2Y ), QPoint( p2X+pXD, p2Y+pYD ) );
                        pWeekX = p1X + pXDelta;
                        pWeekY = p1Y + pYDelta;
                        pXD += orgXD;
                        pYD += orgYD;
                        }
                        */
                        if( monthPaint ){
                            painter->drawLine( QPoint( static_cast<int>( pMonthX+pXD ),
                                                       static_cast<int>( pMonthY+pYD ) ),
                                               QPoint( static_cast<int>( p2X + pXD ),
                                                       static_cast<int>( p2Y + pYD ) ) );
                            if( (pXDelta/2.0 < p2X - pMonthX) || (pYDelta/2.0 < p2Y - pMonthY) ){
                                QPen oldPen( painter->pen() );
                                painter->setPen( QPen( labelsColor ) );
                                painter->drawText( static_cast<int>( pMonthX+pXD-orgXD ),
                                                   static_cast<int>( pMonthY+pYD-orgYD ),
                                                   static_cast<int>( fabs((0.0 == pXDelta) ? cv.pTextsW : (p2X - pMonthX)) ),
                                                   static_cast<int>( fabs((0.0 == pYDelta) ? cv.pTextsH : (p2Y - pMonthY)) ),
                                        cv.textAlign | Qt::DontClip,
                                        QString::number( dt.date().month() ) );
                                painter->setPen( oldPen );
                                if ( para.axisShowGrid() ){
                                    /* khz: currently unused
                                       if( !weekPaint &&
                                       && 10 < pXYDelta  ){
                                       saveDrawLine( *painter,
                                       QPoint( pMonthX+pXDelta/2,
                                       pMonthY+pYDelta/2 ),
                                       QPoint( pMonthX+pXDelta/2 + gridDX,
                                       pMonthY+pYDelta/2 + gridDY ),
                                       subSubGridPen );
                                       }
                                       */
                                    saveDrawLine( *painter,
                                                  QPoint( static_cast<int>( pMonthX ),
                                                          static_cast<int>( pMonthY ) ),
                                                  QPoint( static_cast<int>( pMonthX + gridDX ),
                                                          static_cast<int>( pMonthY + gridDY ) ),
                                            pen );
                                    pen = gridPen;
                                }
                                if( !yearPaint || pYearX != pMonthX || pYearY != pMonthY ){
                                    painter->drawLine( QPoint( static_cast<int>( pMonthX ),
                                                               static_cast<int>( pMonthY ) ),
                                                       QPoint( static_cast<int>( pMonthX+pXD ),
                                                               static_cast<int>( pMonthY+pYD ) ) );
                                }
                            }
                            if( endLoop && !yearPaint )
                                painter->drawLine( QPoint( static_cast<int>( p2X ),
                                                           static_cast<int>( p2Y ) ),
                                                   QPoint( static_cast<int>( p2X+pXD ),
                                                           static_cast<int>( p2Y+pYD ) ) );
                            pMonthX = p1X + pXDelta;
                            pMonthY = p1Y + pYDelta;
                            pXD += orgXD;
                            pYD += orgYD;
                        }
                        if( yearPaint ){
                            painter->drawLine( QPoint( static_cast<int>( pYearX+pXD ),
                                                       static_cast<int>( pYearY+pYD  ) ),
                                               QPoint( static_cast<int>( p2X + pXD ),
                                                       static_cast<int>( p2Y + pYD ) ) );
                            if( (pXDelta/2.0 < p2X - pYearX) || (pYDelta/2.0 < p2Y - pYearY) ){
                                QPen oldPen( painter->pen() );
                                painter->setPen( QPen( labelsColor ) );
                                painter->drawText( static_cast<int>( pYearX+pXD-orgXD ),
                                                   static_cast<int>( pYearY+pYD-orgYD ),
                                                   static_cast<int>( fabs((0.0 == pXDelta) ? cv.pTextsW : (p2X - pYearX)) ),
                                                   static_cast<int>( fabs((0.0 == pYDelta) ? cv.pTextsH : (p2Y - pYearY)) ),
                                        cv.textAlign | Qt::DontClip,
                                        QString::number( dt.date().year() ) );
                                painter->setPen( oldPen );
                                if ( para.axisShowGrid() ){
                                    if( !monthPaint && 10 < pXYDelta  ){
                                        saveDrawLine( *painter,
                                                      QPoint( static_cast<int>( pYearX+pXDelta/2 ),
                                                              static_cast<int>( pYearY+pYDelta/2 ) ),
                                                      QPoint( static_cast<int>( pYearX+pXDelta/2 + gridDX ),
                                                              static_cast<int>( pYearY+pYDelta/2 + gridDY ) ),
                                                subSubGridPen );
                                    }
                                    saveDrawLine( *painter,
                                                  QPoint( static_cast<int>( pYearX ),
                                                          static_cast<int>( pYearY ) ),
                                                  QPoint( static_cast<int>( pYearX + gridDX ),
                                                          static_cast<int>( pYearY + gridDY ) ),
                                            pen );
                                    pen = gridPen;
                                }
                                painter->drawLine( QPoint( static_cast<int>( pYearX ),
                                                           static_cast<int>( pYearY ) ),
                                                   QPoint( static_cast<int>( pYearX+pXD ),
                                                           static_cast<int>( pYearY+pYD ) ) );
                            }
                            if( endLoop )
                                painter->drawLine( QPoint( static_cast<int>( p2X ),
                                                           static_cast<int>( p2Y ) ),
                                                   QPoint( static_cast<int>( p2X+pXD ),
                                                           static_cast<int>( p2Y+pYD ) ) );
                            pYearX = p1X + pXDelta;
                            pYearY = p1Y + pYDelta;
                            pXD += orgXD;
                            pYD += orgYD;
                        }
                        if( &testDt != &newDt )
                            break;
                        dt = newDt;
                        iLabel += 1.0;
                    }
                }else{
                    int iLeaveOut = nLeaveOut;

                    QString label;
                    for ( QStringList::Iterator labelIter = labelTexts->begin();
                          labelIter != labelTexts->end();
                          ++labelIter ) {
                        QDateTime dt;
                        if( cv.isDateTime ){
#if COMPAT_QT_VERSION >= 0x030000
                            dt = QDateTime::fromString( *labelIter,
                                    Qt::ISODate );
                            label = dt.toString( formatDT );
#else
                            dt = dateTimeFromString( *labelIter );
                            label = dt.toString();
#endif
                        }else{
                            label = *labelIter;
                        }

                        if( iLeaveOut < nLeaveOut )
                            ++iLeaveOut;
                        else
                            iLeaveOut = 0;
                        if ( para.axisShowGrid() && !bMultiRowBarChart ) {
                            if( !iLeaveOut )
                                // draw the main grid line
                                saveDrawLine( *painter,
                                              QPoint( static_cast<int>( pGAX - pGXMicroAdjust ),
                                                      static_cast<int>( pGAY - pGYMicroAdjust ) ),
                                              QPoint( static_cast<int>( pGZX - pGXMicroAdjust ),
                                                      static_cast<int>( pGZY - pGYMicroAdjust ) ),
                                              gridPen );
                            else if( para.axisShowSubDelimiters() )
                                // draw a thin sub grid line instead of main line
                                saveDrawLine( *painter,
                                              QPoint( static_cast<int>( pGAX - pGXMicroAdjust ),
                                                      static_cast<int>( pGAY - pGYMicroAdjust ) ),
                                              QPoint( static_cast<int>( pGZX - pGXMicroAdjust ),
                                                      static_cast<int>( pGZY - pGYMicroAdjust ) ),
                                              leaveOutGridPen );
                        }
                        if ( para.axisLabelsVisible() ) {
                            if( !iLeaveOut ) {
                                painter->drawLine( QPoint( static_cast<int>( p1X ),
                                                           static_cast<int>( p1Y ) ),
                                                   QPoint( static_cast<int>( p2X ),
                                                           static_cast<int>( p2Y ) ) );
                                QPen oldPen( painter->pen() );
                                painter->setPen( QPen( labelsColor ) );
                                if(    para.axisLabelsDontShrinkFont()
                                        && isHorizontalAxis
                                        && (Qt::AlignHCenter == (cv.textAlign & Qt::AlignHCenter)) ) {
                                    double w = fm.width( label ) + 4.0;
                                    double x0 = cv.pTextsX + cv.pTextsW / 2.0;
                                    painter->drawText( static_cast<int>( x0 - w / 2.0 ),
                                                       static_cast<int>( cv.pTextsY ),
                                                       static_cast<int>( w ),
                                                       static_cast<int>( cv.pTextsH ),
                                                       cv.textAlign, label );
                                } else {
                                    if( nRotation )
                                        KDDrawText::drawRotatedText(
                                                painter,
                                                nRotation,
                                                QPoint( static_cast<int>( cv.pTextsX ),
                                                        static_cast<int>( cv.pTextsY ) ),
                                                label,
                                                0,
                                                cv.textAlign,
                                                false,
                                                &fm,
                                                screenOutput,screenOutput,0,
                                                screenOutput );
                                    else {
                                        painter->drawText( static_cast<int>( cv.pTextsX ),
                                                           static_cast<int>( cv.pTextsY ),
                                                           static_cast<int>( cv.pTextsW ),
                                                           static_cast<int>( cv.pTextsH ),
                                                           cv.textAlign | Qt::DontClip,
                                                           label );
                                        // show test rect:
                                        //painter->drawRect(cv.pTextsX,cv.pTextsY,nUsableAxisWidth,nUsableAxisHeight);
                                    }
                                }
                                painter->setPen( oldPen );
                            }
                        }
                        /* // for debugging:
                           painter->drawRoundRect(pTextsX,pTextsY,pTextsW,pTextsH);
                           */

                        if( cv.isDateTime ){
                            if( labelTexts->begin() == labelIter ){
                                ((KDChartAxisParams&)para).setAxisDtLowPos(
                                                                           pGAX - pGXMicroAdjust,
                                                                           pGAY - pGYMicroAdjust );
                                // adjust stored dt-low settings
                                ( ( KDChartAxisParams& ) para ).setTrueAxisDtLow( dt );
                            }else{
                                ((KDChartAxisParams&)para).setAxisDtHighPos(
                                                                            pGAX - pGXMicroAdjust,
                                                                            pGAY - pGYMicroAdjust );
                                // adjust stored dt-high settings
                                ( ( KDChartAxisParams& ) para ).setTrueAxisDtHigh( dt );
                            }
                        }

                        iLabel += 1.0;
                        p1X = x1 + iLabel * pXDelta;
                        p1Y = y1 + iLabel * pYDelta;
                        p2X = x2 + iLabel * pXDelta;
                        p2Y = y2 + iLabel * pYDelta;
                        cv.pTextsX = xT + iLabel * pXDelta;
                        cv.pTextsY = yT + iLabel * pYDelta;
                        pGAX = xGA + iLabel * pXDelta;
                        pGAY = yGA + iLabel * pYDelta;
                        pGZX = xGZ + iLabel * pXDelta;
                        pGZY = yGZ + iLabel * pYDelta;
                    }
                }


                // adjust zero-line start, if not starting at origin
                if ( cv.bSteadyCalc && (0.0 != para.trueAxisLow()) ) {
                    double x = p1.x();
                    double y = p1.y();
                    double mult = para.trueAxisLow() / para.trueAxisDelta();
                    x -= mult * pXDelta;
                    y -= mult * pYDelta;
                    axisZeroLineStartX = x;
                    axisZeroLineStartY = y;
                    //qDebug( "axisZeroLineStartX %f,  axisZeroLineStartY %f",
                    //        axisZeroLineStartX, axisZeroLineStartY );
                }

                painter->setClipping( oldClippingFlag );
            } // if( nLabels )

            // draw zero-line (Ok, this might be overwritten by axes
            //  cause those are drawn after all labels and grid and
            //  zero-line(s) has been painted, see code below, starting
            // with "// draw all the axes".
            if ( cv.bSteadyCalc && !cv.isDateTime ) {
                ( ( KDChartAxisParams& ) para ).setAxisZeroLineStart( axisZeroLineStartX, axisZeroLineStartY );
                double axisZeroLineStart;
                int minCoord, maxCoord;
                double xFactor, yFactor;
                switch( cv.basicPos ){
                    case KDChartAxisParams::AxisPosLeft:
                        xFactor =  1.0;
                        yFactor =  0.0;
                        axisZeroLineStart = axisZeroLineStartY;
                        minCoord = QMIN( cv.orig.y(), cv.dest.y() );
                        maxCoord = QMAX( cv.orig.y(), cv.dest.y() );
                        break;
                    case KDChartAxisParams::AxisPosRight:
                        xFactor = -1.0;
                        yFactor =  0.0;
                        axisZeroLineStart = axisZeroLineStartY;
                        minCoord = QMIN( cv.orig.y(), cv.dest.y() );
                        maxCoord = QMAX( cv.orig.y(), cv.dest.y() );
                        break;
                    case KDChartAxisParams::AxisPosTop:
                        xFactor =  0.0;
                        yFactor =  1.0;
                        axisZeroLineStart = axisZeroLineStartX;
                        minCoord = QMIN( cv.orig.x(), cv.dest.x() );
                        maxCoord = QMAX( cv.orig.x(), cv.dest.x() );
                        break;
                    case KDChartAxisParams::AxisPosBottom:
                        xFactor =  0.0;
                        yFactor = -1.0;
                        axisZeroLineStart = axisZeroLineStartX;
                        minCoord = QMIN( cv.orig.x(), cv.dest.x() );
                        maxCoord = QMAX( cv.orig.x(), cv.dest.x() );
                        break;
                    default:
                        xFactor =  0.0;
                        yFactor =  0.0;
                        axisZeroLineStart = 0.0;
                        minCoord = 0;
                        maxCoord = 0;
                }
                if( axisZeroLineStart >= minCoord &&
                        axisZeroLineStart <= maxCoord ){
                    QPoint pZ0( static_cast<int>( para.axisZeroLineStartX() ),
                                static_cast<int>( para.axisZeroLineStartY() ) );
                    QPoint pZ(  static_cast<int>( para.axisZeroLineStartX()
                                + xFactor * _dataRect.width() ),
                                static_cast<int>( para.axisZeroLineStartY()
                                + yFactor * _dataRect.height() ) );
                    //qDebug("------");
                    saveDrawLine( *painter,
                            pZ0,
                            pZ,
                            QPen( para.axisZeroLineColor(),
                                lineWidth ) );
                }
            }
        }
    }

    // draw all the axes lines
    for( iAxis = 0; iAxis < KDCHART_MAX_AXES; ++iAxis ){
        internal__KDChart__CalcValues& cv = calcVal[iAxis];
        const KDChartAxisParams & para = params()->axisParams( iAxis );
        if( cv.processThisAxis && para.axisLineVisible() ){
            painter->setPen( QPen( para.axisLineColor(),
                             para.axisTrueLineWidth() ) );
            painter->drawLine( calcVal[iAxis].orig, calcVal[iAxis].dest );
        }
    }

    painter->restore();
}


Generated by  Doxygen 1.6.0   Back to index