void PieDiagram::shuffleLabels( QRectF* textBoundingRect ) { // things that could be improved here: // - use a variable number (chosen using angle information) of neighbors to check // - try harder to arrange the labels to look nice // ideas: // - leave labels that don't collide alone (only if they their offset is zero) // - use a graphics view for collision detection LabelPaintCache& lpc = d->labelPaintCache; const int n = lpc.paintReplay.size(); bool modified = false; qreal direction = 5.0; QVector< qreal > offsets; offsets.fill( 0.0, n ); for ( bool lastRoundModified = true; lastRoundModified; ) { lastRoundModified = false; for ( int i = 0; i < n; i++ ) { const int neighborsToCheck = qMax( 10, lpc.paintReplay.size() - 1 ); const int minComp = wraparound( i - neighborsToCheck / 2, n ); const int maxComp = wraparound( i + ( neighborsToCheck + 1 ) / 2, n ); QPainterPath& path = lpc.paintReplay[ i ].labelArea; for ( int j = minComp; j != maxComp; j = wraparound( j + 1, n ) ) { if ( i == j ) { continue; } QPainterPath& otherPath = lpc.paintReplay[ j ].labelArea; while ( ( offsets[ i ] + direction > 0 ) && otherPath.intersects( path ) ) { #ifdef SHUFFLE_DEBUG qDebug() << "collision involving" << j << "and" << i << " -- n =" << n; TextAttributes ta = lpc.paintReplay[ i ].attrs.textAttributes(); ta.setPen( QPen( Qt::white ) ); lpc.paintReplay[ i ].attrs.setTextAttributes( ta ); #endif uint slice = lpc.paintReplay[ i ].index.column(); qreal angle = DEGTORAD( d->startAngles[ slice ] + d->angleLens[ slice ] / 2.0 ); qreal dx = cos( angle ) * direction; qreal dy = -sin( angle ) * direction; offsets[ i ] += direction; path.translate( dx, dy ); lastRoundModified = true; } } } direction *= -1.07; // this can "overshoot", but avoids getting trapped in local minimums modified = modified || lastRoundModified; } if ( modified ) { for ( int i = 0; i < lpc.paintReplay.size(); i++ ) { *textBoundingRect |= lpc.paintReplay[ i ].labelArea.boundingRect(); } } }
void MainWindow::on_paintValuesCB_toggled( bool checked ) { const int colCount = m_lines->model()->columnCount(); for ( int iColumn = 0; iColumn<colCount; ++iColumn ) { DataValueAttributes a = m_lines->dataValueAttributes( iColumn ); a.setVisible( true ); TextAttributes ta = a.textAttributes(); ta.setRotation( 0 ); ta.setFont( QFont( "Comic", 10 ) ); ta.setPen( m_lines->brush( iColumn ).color() ); ta.setVisible( checked ); a.setTextAttributes( ta ); m_lines->setDataValueAttributes( iColumn, a); } }
void markPeak(Plotter* p, const QModelIndex& peak, quint64 cost, const KColorScheme& scheme) { QBrush brush = p->model()->data(peak, DatasetBrushRole).value<QBrush>(); QColor outline = brush.color(); QColor foreground = scheme.foreground().color(); QBrush background = scheme.background(); DataValueAttributes dataAttributes = p->dataValueAttributes(peak); dataAttributes.setDataLabel(prettyCost(cost)); dataAttributes.setVisible(true); dataAttributes.setShowRepetitiveDataLabels(true); dataAttributes.setShowOverlappingDataLabels(false); FrameAttributes frameAttrs = dataAttributes.frameAttributes(); QPen framePen(outline); framePen.setWidth(2); frameAttrs.setPen(framePen); frameAttrs.setVisible(true); dataAttributes.setFrameAttributes(frameAttrs); MarkerAttributes a = dataAttributes.markerAttributes(); a.setMarkerSize(QSizeF(7, 7)); a.setPen(outline); a.setMarkerStyle(KChart::MarkerAttributes::MarkerDiamond); a.setVisible(true); dataAttributes.setMarkerAttributes(a); TextAttributes txtAttrs = dataAttributes.textAttributes(); txtAttrs.setPen(foreground); txtAttrs.setFontSize(Measure(12)); dataAttributes.setTextAttributes(txtAttrs); BackgroundAttributes bkgAtt = dataAttributes.backgroundAttributes(); bkgAtt.setBrush(background); bkgAtt.setVisible(true); dataAttributes.setBackgroundAttributes(bkgAtt); p->setDataValueAttributes(peak, dataAttributes); }
MainWindow::MainWindow( QWidget* parent ) : QWidget( parent ) { setupUi( this ); QHBoxLayout* chartLayout = new QHBoxLayout( chartFrame ); m_chart = new Chart(); m_chart->setGlobalLeading( 10, 10, 10, 10 ); chartLayout->addWidget( m_chart ); hSBar->setVisible( false ); vSBar->setVisible( false ); m_model.loadFromCSV( ":/data" ); // Set up the diagram m_lines = new BarDiagram(); m_lines->setModel( &m_model ); // create and position axis CartesianAxis *topAxis = new CartesianAxis( m_lines ); CartesianAxis *leftAxis = new CartesianAxis ( m_lines ); RulerAttributes rulerAttr = topAxis->rulerAttributes(); rulerAttr.setTickMarkPen( 0.9999999, QPen( Qt::red ) ); rulerAttr.setTickMarkPen( 2.0, QPen( Qt::green ) ); rulerAttr.setTickMarkPen( 3.0, QPen( Qt::blue ) ); rulerAttr.setShowMinorTickMarks(true); //rulerAttr.setShowMajorTickMarks(false); topAxis->setRulerAttributes( rulerAttr ); CartesianAxis *rightAxis = new CartesianAxis ( m_lines ); CartesianAxis *bottomAxis = new CartesianAxis ( m_lines ); topAxis->setPosition ( CartesianAxis::Top ); leftAxis->setPosition ( CartesianAxis::Left ); rightAxis->setPosition ( CartesianAxis::Right ); bottomAxis->setPosition ( CartesianAxis::Bottom ); // set the margin that should be used between the displayed labels and the ticks to zero #if 0 RulerAttributes ra = bottomAxis->rulerAttributes(); ra.setLabelMargin(0); bottomAxis->setRulerAttributes( ra ); #endif // show a red frame around the bottom axis #if 0 FrameAttributes fa( bottomAxis->frameAttributes() ); fa.setPen( QPen(QBrush(QColor("#ff0000")),1.0) ); fa.setVisible( true ); bottomAxis->setFrameAttributes( fa ); #endif // set axis titles topAxis->setTitleText ( "Abscissa color configured top position" ); leftAxis->setTitleText ( "left Ordinate: fonts configured" ); rightAxis->setTitleText ( "right Ordinate: default settings" ); bottomAxis->setTitleText ( "Abscissa Bottom" ); topAxis->setTitleSize(1.1); topAxis->setTitleSpace(.4); // configure titles text attributes TextAttributes taTop ( topAxis->titleTextAttributes () ); taTop.setPen( QPen( Qt::red ) ); topAxis->setTitleTextAttributes ( taTop ); TextAttributes taLeft ( leftAxis->titleTextAttributes () ); taLeft.setRotation( 180 ); Measure me( taLeft.fontSize() ); me.setValue( me.value() * 0.8 ); taLeft.setFontSize( me ); // Set the following to 1, to hide the left axis title // - no matter if a title text is set or not #if 0 taLeft.setVisible( false ); #endif leftAxis->setTitleTextAttributes ( taLeft ); TextAttributes taBottom ( bottomAxis->titleTextAttributes () ); taBottom.setPen( QPen( Qt::blue ) ); bottomAxis->setTitleTextAttributes ( taBottom ); // configure labels text attributes TextAttributes taLabels( topAxis->textAttributes() ); taLabels.setPen( QPen( Qt::darkGreen ) ); taLabels.setRotation( 90 ); topAxis->setTextAttributes( taLabels ); leftAxis->setTextAttributes( taLabels ); bottomAxis->setTextAttributes( taLabels ); // Set the following to 0, to see the default Abscissa labels // (== X headers, as read from the data file) #if 1 // configure labels and their shortened versions QStringList daysOfWeek; daysOfWeek << "M O N D A Y" << "Tuesday" << "Wednesday" << "Thursday" << "Friday" ; topAxis->setLabels( daysOfWeek ); QStringList shortDays; shortDays << "MON" << "Tue" << "Wed" << "Thu" << "Fri"; topAxis->setShortLabels( shortDays ); QStringList bottomLabels; bottomLabels << "Team A" << "Team B" << "Team C"; bottomAxis->setLabels( bottomLabels ); QStringList shortBottomLabels; shortBottomLabels << "A" << "B"; bottomAxis->setShortLabels( shortBottomLabels ); #endif // add axis m_lines->addAxis( topAxis ); m_lines->addAxis( leftAxis ); m_lines->addAxis( rightAxis ); m_lines->addAxis( bottomAxis ); // assign diagram to chart view m_chart->coordinatePlane()->replaceDiagram( m_lines ); }