110309_qgis_diagrams_2.diff

Marco Hugentobler, 2011-03-09 08:27 AM

Download (70.5 KB)

View differences:

src/app/qgslabelpropertydialog.cpp (Arbeitskopie)
18 18
#include "qgslabelpropertydialog.h"
19 19
#include "qgsmaplayerregistry.h"
20 20
#include "qgsmaprenderer.h"
21
#include "qgsvectorlayer.h"
21 22
#include <QColorDialog>
22 23
#include <QFontDialog>
23 24

  
src/app/qgsmaptoollabel.cpp (Arbeitskopie)
280 280
    pos = mCurrentLabelPos.cornerPoints.at( 0 );
281 281
  }
282 282

  
283
  //alignment always center/center and rotation 0 for diagrams
284
  if( mCurrentLabelPos.isDiagram )
285
  {
286
    pos.setX( pos.x() + mCurrentLabelPos.labelRect.width() / 2.0 );
287
    pos.setY( pos.y() + mCurrentLabelPos.labelRect.height() / 2.0 );
288
    return true;
289
  }
290

  
283 291
  //adapt pos depending on data defined alignment
284 292
  QString haliString, valiString;
285 293
  currentAlignment( haliString, valiString );
......
356 364
    return false;
357 365
  }
358 366

  
359
  if ( !layerIsMoveable( vlayer, xCol, yCol ) )
367
  if( mCurrentLabelPos.isDiagram )
360 368
  {
369
    if( !diagramMoveable( vlayer, xCol, yCol ) )
370
    {
371
      return false;
372
    }
373
  }
374
  else if ( !labelMoveable( vlayer, xCol, yCol ) )
375
  {
361 376
    return false;
362 377
  }
363 378

  
......
374 389
  return true;
375 390
}
376 391

  
377
bool QgsMapToolLabel::layerIsMoveable( const QgsMapLayer* ml, int& xCol, int& yCol ) const
392
bool QgsMapToolLabel:: diagramMoveable( const QgsMapLayer* ml, int& xCol, int& yCol ) const
378 393
{
379 394
  const QgsVectorLayer* vlayer = dynamic_cast<const QgsVectorLayer*>( ml );
395
  if( vlayer && vlayer->diagramRenderer() )
396
  {
397
    QgsDiagramLayerSettings dls = vlayer->diagramLayerSettings();
398
    if( dls.xPosColumn >= 0 && dls.yPosColumn >= 0 )
399
    {
400
      xCol = dls.xPosColumn;
401
      yCol = dls.yPosColumn;
402
      return true;
403
    }
404
  }
405
  return false;
406
}
407

  
408
bool QgsMapToolLabel::labelMoveable( const QgsMapLayer* ml, int& xCol, int& yCol ) const
409
{
410
  const QgsVectorLayer* vlayer = dynamic_cast<const QgsVectorLayer*>( ml );
380 411
  if ( !vlayer || !vlayer->isEditable() )
381 412
  {
382 413
    return false;
src/app/qgsmaptoollabel.h (Arbeitskopie)
31 31
    QgsMapToolLabel( QgsMapCanvas* canvas );
32 32
    ~QgsMapToolLabel();
33 33

  
34
    /**Returns true if layer move can be applied to a layer
34
    /**Returns true if label move can be applied to a layer
35 35
        @param xCol out: index of the attribute for data defined x coordinate
36 36
        @param yCol out: index of the attribute for data defined y coordinate
37 37
        @return true if labels of layer can be moved*/
38
    bool layerIsMoveable( const QgsMapLayer* ml, int& xCol, int& yCol ) const;
38
    bool labelMoveable( const QgsMapLayer* ml, int& xCol, int& yCol ) const;
39
    /**Returns true if diagram move can be applied to a layer
40
        @param xCol out: index of the attribute for data defined x coordinate
41
        @param yCol out: index of the attribute for data defined y coordinate
42
        @return true if labels of layer can be moved*/
43
    bool diagramMoveable( const QgsMapLayer* ml, int& xCol, int& yCol ) const;
39 44

  
40 45
  protected:
41 46
    QgsRubberBand* mLabelRubberBand;
src/app/qgsvectorlayerproperties.h (Arbeitskopie)
106 106
    void on_pbnSelectEditForm_clicked();
107 107
    void on_tabWidget_currentChanged( int idx );
108 108
    void on_buttonBox_helpRequested() { QgsContextHelp::run( metaObject()->className() ); }
109
    void on_mAddCategoryPushButton_clicked();
110
    void on_mRemoveCategoryPushButton_clicked();
111
    void on_mDiagramFontButton_clicked();
112
    void on_mFixedSizeCheckBox_stateChanged( int state );
113
    void on_mFindMaximumValueButton_clicked();
114
    void on_mBackgroundColorButton_clicked();
109 115

  
110 116
    void enableLabelOptions( bool theFlag );
111 117
    void addAttribute();
......
120 126
    void on_mButtonAddJoin_clicked();
121 127
    void on_mButtonRemoveJoin_clicked();
122 128

  
129
    /**Set color for diagram category*/
130
    void handleDiagramItemDoubleClick( QTreeWidgetItem * item, int column );
131

  
123 132
  signals:
124 133

  
125 134
    /** emitted when changes to layer were saved to update legend */
......
164 173
    QMap<int, QgsVectorLayer::RangeData> mRanges;
165 174
    QMap<int, QPair<QString, QString> > mCheckedStates;
166 175

  
176
    QFont mDiagramFont;
177

  
167 178
    void updateButtons();
168 179
    void loadRows();
169 180
    void setRow( int row, int idx, const QgsField &field );
170 181

  
182
    void initDiagramTab();
183

  
171 184
    /**Requests all overlay plugis from the plugin registry. Useful for inserting their dialogs as new tabs*/
172 185
    QList<QgsVectorOverlayPlugin*> overlayPlugins() const;
173 186

  
src/app/qgsvectorlayerproperties.cpp (Arbeitskopie)
28 28
#include "qgscontexthelp.h"
29 29
#include "qgscontinuouscolordialog.h"
30 30
#include "qgscoordinatetransform.h"
31
#include "qgsdiagram.h"
32
#include "qgsdiagramrendererv2.h"
31 33
#include "qgsfieldcalculator.h"
32 34
#include "qgsgraduatedsymboldialog.h"
33 35
#include "qgslabeldialog.h"
......
53 55
#include <QFile>
54 56
#include <QFileDialog>
55 57
#include <QFileInfo>
58
#include <QFontDialog>
56 59
#include <QSettings>
57 60
#include <QComboBox>
58 61
#include <QCheckBox>
59 62
#include <QHeaderView>
63
#include <QColorDialog>
60 64

  
61 65
#include "qgsrendererv2propertiesdialog.h"
62 66
#include "qgsstylev2.h"
......
142 146
    addJoinToTreeWidget( joins[i] );
143 147
  }
144 148

  
149
  initDiagramTab();
150

  
145 151
  //for each overlay plugin create a new tab
146 152
  int position;
147 153
  QList<QgsVectorOverlayPlugin*> overlayPluginList = overlayPlugins();
......
678 684

  
679 685
  }
680 686

  
687
  //apply diagram settings
688
  if( !mDisplayDiagramsCheckBox->isChecked() )
689
  {
690
    layer->setDiagramRenderer( 0 );
691
  }
692
  else
693
  {
694
    QgsDiagram* diagram = 0;
695
    if( mDiagramTypeComboBox->currentText() == tr("Text diagram") )
696
    {
697
      diagram = new QgsTextDiagram();
698
    }
699
    else if( mDiagramTypeComboBox->currentText() == tr("Pie chart") )
700
    {
701
      diagram = new QgsPieDiagram();
702
    }
703

  
704
    QgsDiagramSettings ds;
705
    ds.font = mDiagramFont;
706
    QList<QColor> categoryColors;
707
    QList<int> categoryAttributes;
708
    for( int i = 0; i < mDiagramAttributesTreeWidget->topLevelItemCount(); ++i )
709
    {
710
      categoryColors.append( mDiagramAttributesTreeWidget->topLevelItem( i )->background( 1 ).color() );
711
      categoryAttributes.append( mDiagramAttributesTreeWidget->topLevelItem( i )->data(0, Qt::UserRole ).toInt() );
712
    }
713
    ds.categoryColors = categoryColors;
714
    ds.categoryIndices = categoryAttributes;
715
    ds.size = QSizeF( mDiagramSizeSpinBox->value(), mDiagramSizeSpinBox->value() );
716
    ds.backgroundColor = mBackgroundColorButton->color();
717

  
718
    QgsDiagramRendererV2* r = 0;
719
    if( mFixedSizeCheckBox->isChecked() )
720
    {
721
      QgsSingleCategoryDiagramRenderer* dr = new QgsSingleCategoryDiagramRenderer();
722
      dr->setDiagram( diagram );
723
      dr->setDiagramSettings( ds );
724
      layer->setDiagramRenderer( dr );
725
    }
726
    else
727
    {
728
      QgsLinearlyInterpolatedDiagramRenderer* dr = new QgsLinearlyInterpolatedDiagramRenderer();
729
      dr->setLowerValue( 0.0 );
730
      dr->setLowerSize( QSizeF( 0.0, 0.0 ) );
731
      dr->setUpperValue( mValueLineEdit->text().toDouble() );
732
      dr->setUpperSize( QSizeF( mSizeSpinBox->value(), mSizeSpinBox->value() ) );
733
      dr->setClassificationAttribute( mSizeAttributeComboBox->itemData( mSizeAttributeComboBox->currentIndex() ).toInt() );
734
      dr->setDiagram( diagram );
735
      dr->setDiagramSettings( ds );
736
      layer->setDiagramRenderer( dr );
737
    }
738

  
739
    QgsDiagramLayerSettings dls;
740
    dls.dist = mDiagramDistanceSpinBox->value();
741
    dls.priority = mPrioritySlider->value();
742
    dls.xPosColumn = mDataDefinedXComboBox->itemData( mDataDefinedXComboBox->currentIndex() ).toInt();
743
    dls.yPosColumn = mDataDefinedYComboBox->itemData( mDataDefinedYComboBox->currentIndex() ).toInt();
744
    dls.placement = (QgsDiagramLayerSettings::Placement)mPlacementComboBox->itemData( mPlacementComboBox->currentIndex() ).toInt();
745
    if( mLineOptionsComboBox->isEnabled() )
746
    {
747
      dls.placementFlags = (QgsDiagramLayerSettings::LinePlacementFlags)mLineOptionsComboBox->itemData( mLineOptionsComboBox->currentIndex() ).toInt();
748
    }
749
    layer->setDiagramLayerSettings( dls );
750
  }
751

  
752

  
681 753
  //apply overlay dialogs
682 754
  for ( QList<QgsApplyDialog*>::iterator it = mOverlayDialogs.begin(); it != mOverlayDialogs.end(); ++it )
683 755
  {
......
1243 1315
  mJoinTreeWidget->takeTopLevelItem( mJoinTreeWidget->indexOfTopLevelItem( currentJoinItem ) );
1244 1316
}
1245 1317

  
1318
void QgsVectorLayerProperties::handleDiagramItemDoubleClick( QTreeWidgetItem * item, int column )
1319
{
1320
  if ( column == 1 ) //change color
1321
  {
1322
    QColor newColor = QColorDialog::getColor();
1323
    if ( newColor.isValid() )
1324
    {
1325
      item->setBackground( 1, QBrush( newColor ) );
1326
    }
1327
  }
1328
}
1329

  
1246 1330
void QgsVectorLayerProperties::useNewSymbology()
1247 1331
{
1248 1332
  int res = QMessageBox::question( this, tr( "Symbology" ),
......
1338 1422
{
1339 1423
  labelOptionsFrame->setEnabled( theFlag );
1340 1424
}
1425

  
1426
void QgsVectorLayerProperties::on_mAddCategoryPushButton_clicked()
1427
{
1428
  QTreeWidgetItem *newItem = new QTreeWidgetItem( mDiagramAttributesTreeWidget );
1429
  newItem->setText( 0, mDiagramAttributesComboBox->currentText() );
1430
  newItem->setData( 0, Qt::UserRole, mDiagramAttributesComboBox->itemData( mDiagramAttributesComboBox->currentIndex() ) );
1431

  
1432
  //set initial color for diagram category
1433
  int red = 1 + ( int )( 255.0 * rand() / ( RAND_MAX + 1.0 ) );
1434
  int green = 1 + ( int )( 255.0 * rand() / ( RAND_MAX + 1.0 ) );
1435
  int blue = 1 + ( int )( 255.0 * rand() / ( RAND_MAX + 1.0 ) );
1436
  QColor randomColor( red, green, blue );
1437
  newItem->setBackground( 1, QBrush( randomColor ) );
1438
  mDiagramAttributesTreeWidget->addTopLevelItem( newItem );
1439
}
1440

  
1441
void QgsVectorLayerProperties::on_mRemoveCategoryPushButton_clicked()
1442
{
1443
  QTreeWidgetItem* currentItem = mDiagramAttributesTreeWidget->currentItem();
1444
  if ( currentItem )
1445
  {
1446
    delete currentItem;
1447
  }
1448
}
1449

  
1450
void QgsVectorLayerProperties::on_mDiagramFontButton_clicked()
1451
{
1452
  bool ok;
1453
  mDiagramFont = QFontDialog::getFont( &ok, mDiagramFont );
1454
}
1455

  
1456
void QgsVectorLayerProperties::on_mFixedSizeCheckBox_stateChanged( int state )
1457
{
1458
  mDiagramSizeSpinBox->setEnabled( state == Qt::Checked );
1459

  
1460
  //enable / disable all widget in the scaling layout
1461
  mLinearlyScalingLabel->setEnabled( state != Qt::Checked );
1462
  QWidget* currentWidget = 0;
1463
  for( int i = 0; i < mLinearlyScalingLayout->count(); ++i )
1464
  {
1465
    currentWidget = mLinearlyScalingLayout->itemAt( i )->widget();
1466
    if( currentWidget )
1467
    {
1468
      currentWidget->setEnabled( state != Qt::Checked );
1469
    }
1470
  }
1471
}
1472

  
1473
void QgsVectorLayerProperties::on_mFindMaximumValueButton_clicked()
1474
{
1475
  //get maximum value from provider (ignoring not-commited edits)
1476
  if ( layer )
1477
  {
1478
    QgsVectorDataProvider* provider = layer->dataProvider();
1479
    if ( provider )
1480
    {
1481
      mValueLineEdit->setText( provider->maximumValue( mSizeAttributeComboBox->itemData( mSizeAttributeComboBox->currentIndex() ).toInt() ).toString());
1482
    }
1483
  }
1484
}
1485

  
1486
void QgsVectorLayerProperties::on_mBackgroundColorButton_clicked()
1487
{
1488
  QColor newColor = QColorDialog::getColor( mBackgroundColorButton->color(), 0, tr("Background color"), QColorDialog::ShowAlphaChannel);
1489
  if( newColor.isValid() )
1490
  {
1491
    mBackgroundColorButton->setColor( newColor );
1492
  }
1493
}
1494

  
1495
void QgsVectorLayerProperties::initDiagramTab()
1496
{
1497
  if( !layer )
1498
  {
1499
    mDiagramPage->setEnabled( false );
1500
  }
1501

  
1502
  QGis::GeometryType layerType = layer->geometryType();
1503
  if( layerType == QGis::UnknownGeometry || layerType == QGis::NoGeometry )
1504
  {
1505
    mDiagramPage->setEnabled( false );
1506
  }
1507

  
1508
  //insert placement options
1509

  
1510
  if( layerType == QGis::Point || layerType == QGis::Polygon )
1511
  {
1512
    mPlacementComboBox->addItem( tr("AroundPoint"), 0 );
1513
    mPlacementComboBox->addItem( tr("OverPoint"), 1 );
1514
  }
1515

  
1516
  if( layerType == QGis::Line || layerType == QGis::Polygon )
1517
  {
1518
    mPlacementComboBox->addItem( tr("Line"), 2 );
1519
    mPlacementComboBox->addItem( tr("Horizontal"), 3 );
1520
  }
1521

  
1522
  if( layerType == QGis::Polygon )
1523
  {
1524
    mPlacementComboBox->addItem( tr("Free"), 4 );
1525
  }
1526

  
1527
  if( layerType == QGis::Line )
1528
  {
1529
    mLineOptionsComboBox->addItem( tr("On line"), 1);
1530
    mLineOptionsComboBox->addItem( tr("Above line"), 2);
1531
    mLineOptionsComboBox->addItem( tr("Below Line"), 4);
1532
    mLineOptionsComboBox->addItem( tr("Map orientation"), 8);
1533
  }
1534
  else
1535
  {
1536
    mLineOptionsComboBox->setEnabled( false );
1537
  }
1538

  
1539
  mDiagramTypeComboBox->addItem( tr("Pie chart") );
1540
  mDiagramTypeComboBox->addItem( tr("Text diagram") );
1541

  
1542
  //insert all attributes into the combo boxes
1543
  const QgsFieldMap& layerFields = layer->pendingFields();
1544
  QgsFieldMap::const_iterator fieldIt = layerFields.constBegin();
1545
  for(; fieldIt != layerFields.constEnd(); ++fieldIt )
1546
  {
1547
    mDiagramAttributesComboBox->addItem( fieldIt.value().name(), fieldIt.key() );
1548
    if( fieldIt.value().type() != QVariant::String )
1549
    {
1550
      mSizeAttributeComboBox->addItem( fieldIt.value().name(), fieldIt.key() );
1551
    }
1552
  }
1553

  
1554
  mDataDefinedXComboBox->addItem( tr("None"), -1 );
1555
  for( fieldIt = layerFields.constBegin(); fieldIt != layerFields.constEnd(); ++fieldIt )
1556
  {
1557
    mDataDefinedXComboBox->addItem( fieldIt.value().name(), fieldIt.key() );
1558
  }
1559
  mDataDefinedYComboBox->addItem( tr("None"), -1 );
1560
  for( fieldIt = layerFields.constBegin(); fieldIt != layerFields.constEnd(); ++fieldIt )
1561
  {
1562
    mDataDefinedYComboBox->addItem( fieldIt.value().name(), fieldIt.key() );
1563
  }
1564

  
1565
  const QgsDiagramRendererV2* dr = layer->diagramRenderer();
1566
  if( !dr )
1567
  {
1568
    mDisplayDiagramsCheckBox->setChecked( false );
1569
    mFixedSizeCheckBox->setChecked( true );
1570

  
1571
    //insert reasonable default for placement
1572
    switch( layerType )
1573
    {
1574
      case QGis::Point:
1575
        mPlacementComboBox->setCurrentIndex( mPlacementComboBox->findData( 1 ));
1576
        break;
1577
      case QGis::Line:
1578
        mPlacementComboBox->setCurrentIndex( mPlacementComboBox->findData( 3 ));
1579
        mLineOptionsComboBox->setCurrentIndex( mLineOptionsComboBox->findData( 2 ) );
1580
        break;
1581
      case QGis::Polygon:
1582
        mPlacementComboBox->setCurrentIndex( mPlacementComboBox->findData( 1 ));
1583
        break;
1584
    }
1585
    mBackgroundColorButton->setColor( QColor( 255, 255, 255, 255 ) );
1586
  }
1587
  else
1588
  {
1589
    mDisplayDiagramsCheckBox->setChecked( true );
1590

  
1591
    //single category renderer or interpolated one?
1592
    mFixedSizeCheckBox->setChecked( dr->rendererName() == "SingleCategory" );
1593

  
1594
    //assume single category or linearly interpolated diagram renderer for now
1595
    QList<QgsDiagramSettings> settingList = dr->diagramSettings();
1596
    if( settingList.size() > 0 )
1597
    {
1598
      mDiagramFont = settingList.at(0).font;
1599
      QSizeF size = settingList.at(0).size;
1600
      mBackgroundColorButton->setColor( settingList.at( 0 ).backgroundColor );
1601
      mDiagramSizeSpinBox->setValue( ( size.width() + size.height() ) / 2.0 );
1602

  
1603
      QList< QColor > categoryColors = settingList.at(0).categoryColors;
1604
      QList< int > categoryIndices = settingList.at(0).categoryIndices;
1605
      QList< int >::const_iterator catIt = categoryIndices.constBegin();
1606
      QList< QColor >::const_iterator coIt = categoryColors.constBegin();
1607
      for(;catIt != categoryIndices.constEnd(); ++catIt, ++coIt )
1608
      {
1609
        QTreeWidgetItem *newItem = new QTreeWidgetItem( mDiagramAttributesTreeWidget );
1610
        newItem->setText( 0, layer->pendingFields()[*catIt].name() );
1611
        newItem->setData( 0, Qt::UserRole, *catIt );
1612
        newItem->setBackground( 1, QBrush( *coIt ) );
1613
      }
1614
    }
1615

  
1616
    if( dr->rendererName() == "LinearlyInterpolated" )
1617
    {
1618
      const QgsLinearlyInterpolatedDiagramRenderer* lidr = dynamic_cast<const QgsLinearlyInterpolatedDiagramRenderer*>( dr );
1619
      if( lidr )
1620
      {
1621
        mDiagramSizeSpinBox->setEnabled( false );
1622
        mValueLineEdit->setText( QString::number( lidr->upperValue() ) );
1623
        mSizeSpinBox->setValue( ( lidr->upperSize().width() + lidr->upperSize().height() ) / 2 );
1624
        mSizeAttributeComboBox->setCurrentIndex( mSizeAttributeComboBox->findData( lidr->classificationAttribute() ) );
1625
      }
1626
    }
1627

  
1628
    QgsDiagramLayerSettings dls = layer->diagramLayerSettings();
1629
    mDiagramDistanceSpinBox->setValue( dls.dist );
1630
    mPrioritySlider->setValue( dls.priority );
1631
    mDataDefinedXComboBox->setCurrentIndex( mDataDefinedXComboBox->findData( dls.xPosColumn ) );
1632
    mDataDefinedYComboBox->setCurrentIndex( mDataDefinedYComboBox->findData( dls.yPosColumn ) );
1633
    mPlacementComboBox->setCurrentIndex( mPlacementComboBox->findData( dls.placement ) );
1634
    mLineOptionsComboBox->setCurrentIndex( mLineOptionsComboBox->findData( dls.placementFlags ) );
1635

  
1636
    if( dr->diagram() )
1637
    {
1638
      QString diagramName = dr->diagram()->diagramName();
1639
      if( diagramName == "Text" )
1640
      {
1641
        mDiagramTypeComboBox->setCurrentIndex( mDiagramTypeComboBox->findText( tr("Text diagram") ) );
1642
      }
1643
      else if( diagramName == "Pie" )
1644
      {
1645
        mDiagramTypeComboBox->setCurrentIndex( mDiagramTypeComboBox->findText( tr("Pie chart") ) );
1646
      }
1647
    }
1648
  }
1649
  QObject::connect( mDiagramAttributesTreeWidget, SIGNAL( itemDoubleClicked ( QTreeWidgetItem*, int ) ), this, SLOT( handleDiagramItemDoubleClick(QTreeWidgetItem*,int) ) );
1650
}
src/app/qgsmaptoolmovelabel.cpp (Arbeitskopie)
40 40
  }
41 41

  
42 42
  QgsMapLayer* layer = QgsMapLayerRegistry::instance()->mapLayer( mCurrentLabelPos.layerID );
43
  if ( !layer )
43
  if ( !layer || !layer->isEditable() )
44 44
  {
45 45
    return;
46 46
  }
47 47

  
48 48
  int xCol, yCol;
49
  if ( layerIsMoveable( layer, xCol, yCol ) )
49
  if ( labelMoveable( layer, xCol, yCol ) || diagramMoveable( layer, xCol, yCol ) )
50 50
  {
51 51
    mStartPointMapCoords = toMapCoordinates( e->pos() );
52 52
    mClickOffsetX = mStartPointMapCoords.x() - mCurrentLabelPos.labelRect.xMinimum();
src/app/qgisapp.cpp (Arbeitskopie)
5554 5554
  for ( QMap<QString, QgsMapLayer*>::iterator it = layers.begin(); it != layers.end(); it++ )
5555 5555
  {
5556 5556
    QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( it.value() );
5557
    if ( !vlayer || !vlayer->isEditable() || vlayer->customProperty( "labeling" ).toString() != QString( "pal" ) )
5557
    if ( !vlayer || !vlayer->isEditable() ||
5558
         (!vlayer->diagramRenderer() && vlayer->customProperty( "labeling" ).toString() != QString( "pal" ) ) )
5558 5559
      continue;
5559 5560

  
5560 5561
    int colX, colY, colAng;
5561 5562
    enableMove =
5562 5563
      enableMove ||
5563 5564
      ( qobject_cast<QgsMapToolMoveLabel*>( mMapTools.mMoveLabel ) &&
5564
        qobject_cast<QgsMapToolMoveLabel*>( mMapTools.mMoveLabel )->layerIsMoveable( vlayer, colX, colY ) );
5565
        ( qobject_cast<QgsMapToolMoveLabel*>( mMapTools.mMoveLabel )->labelMoveable( vlayer, colX, colY )
5566
        || qobject_cast<QgsMapToolMoveLabel*>( mMapTools.mMoveLabel )->diagramMoveable( vlayer, colX, colY) )
5567
        );
5565 5568

  
5566 5569
    enableRotate =
5567 5570
      enableRotate ||
src/plugins/grass/qgsgrassedittools.cpp (Arbeitskopie)
22 22
#include "qgisinterface.h"
23 23
#include "qgslogger.h"
24 24
#include "qgsmapcanvas.h"
25
#include "qgsvectorlayer.h"
25 26
#include "qgsvertexmarker.h"
26 27

  
27 28
#include <QMouseEvent>
src/analysis/interpolation/qgsinterpolator.cpp (Arbeitskopie)
17 17

  
18 18
#include "qgsinterpolator.h"
19 19
#include "qgsvectordataprovider.h"
20
#include "qgsvectorlayer.h"
20 21
#include "qgsgeometry.h"
21 22

  
22 23
QgsInterpolator::QgsInterpolator( const QList<LayerData>& layerData ): mDataIsCached( false ), mLayerData( layerData )
src/gui/qgsmaptip.cpp (Arbeitskopie)
16 16
#include <qgsmapcanvas.h>
17 17
#include <qgsmaplayer.h>
18 18
#include <qgsvectordataprovider.h>
19
#include <qgsvectorlayer.h>
19 20
#include <qgsfield.h>
20 21

  
21 22
// Qt includes
src/core/qgsmaprenderer.h (Arbeitskopie)
39 39
class QgsVectorLayer;
40 40
class QgsFeature;
41 41

  
42
struct QgsDiagramLayerSettings;
43

  
42 44
struct CORE_EXPORT QgsLabelPosition
43 45
{
44
  QgsLabelPosition( int id, double r, const QVector< QgsPoint >& corners, const QgsRectangle& rect, double w, double h, const QString& layer, bool upside_down ):
45
      featureId( id ), rotation( r ), cornerPoints( corners ), labelRect( rect ), width( w ), height( h ), layerID( layer ), upsideDown( upside_down ) {}
46
  QgsLabelPosition(): featureId( -1 ), rotation( 0 ), labelRect( QgsRectangle() ), width( 0 ), height( 0 ), layerID( "" ), upsideDown( false ) {}
46
  QgsLabelPosition( int id, double r, const QVector< QgsPoint >& corners, const QgsRectangle& rect, double w, double h, const QString& layer, bool upside_down, bool diagram = false ):
47
      featureId( id ), rotation( r ), cornerPoints( corners ), labelRect( rect ), width( w ), height( h ), layerID( layer ), upsideDown( upside_down ), isDiagram( diagram ) {}
48
  QgsLabelPosition(): featureId( -1 ), rotation( 0 ), labelRect( QgsRectangle() ), width( 0 ), height( 0 ), layerID( "" ), upsideDown( false ), isDiagram( false ) {}
47 49
  int featureId;
48 50
  double rotation;
49 51
  QVector< QgsPoint > cornerPoints;
......
52 54
  double height;
53 55
  QString layerID;
54 56
  bool upsideDown;
57
  bool isDiagram;
55 58
};
56 59

  
57 60
/** Labeling engine interface.
......
70 73
    //! called when starting rendering of a layer
71 74
    //! @note: this method was added in version 1.6
72 75
    virtual int prepareLayer( QgsVectorLayer* layer, QSet<int>& attrIndices, QgsRenderContext& ctx ) = 0;
76
    //! adds a diagram layer to the labeling engine
77
    virtual int addDiagramLayer( QgsVectorLayer* layer, QgsDiagramLayerSettings& s ){};
73 78
    //! called for every feature
74 79
    virtual void registerFeature( QgsVectorLayer* layer, QgsFeature& feat, const QgsRenderContext& context = QgsRenderContext() ) = 0;
80
    //! called for every diagram feature
81
    virtual void registerDiagramFeature( QgsVectorLayer* layer, QgsFeature& feat, const QgsRenderContext& context = QgsRenderContext() ){};
75 82
    //! called when the map is drawn and labels should be placed
76 83
    virtual void drawLabeling( QgsRenderContext& context ) = 0;
77 84
    //! called when we're done with rendering
src/core/qgspallabeling.cpp (Arbeitskopie)
38 38
#include <QTime>
39 39
#include <QPainter>
40 40

  
41
#include "qgsdiagram.h"
42
#include "qgsdiagramrendererv2.h"
41 43
#include "qgslabelsearchtree.h"
42 44
#include <qgslogger.h>
43 45
#include <qgsvectorlayer.h>
......
54 56
class QgsPalGeometry : public PalGeometry
55 57
{
56 58
  public:
57
    QgsPalGeometry( int id, QString text, GEOSGeometry* g ): mG( g ), mText( text ), mId( id ), mInfo( NULL )
59
    QgsPalGeometry( int id, QString text, GEOSGeometry* g ): mG( g ), mText( text ), mId( id ), mInfo( NULL ), mIsDiagram( false )
58 60
    {
59 61
      mStrId = QByteArray::number( id );
60 62
    }
......
100 102
    const QMap< QgsPalLayerSettings::DataDefinedProperties, QVariant >& dataDefinedValues() const { return mDataDefinedValues; }
101 103
    void addDataDefinedValue( QgsPalLayerSettings::DataDefinedProperties p, QVariant v ) { mDataDefinedValues.insert( p, v ); }
102 104

  
105
    void setIsDiagram( bool d ) { mIsDiagram = d; }
106
    bool isDiagram() const { return mIsDiagram; }
107

  
108
    void addDiagramAttribute( int index, QVariant value ){ mDiagramAttributes.insert( index, value ); }
109
    const QgsAttributeMap& diagramAttributes(){ return mDiagramAttributes; }
110

  
103 111
  protected:
104 112
    GEOSGeometry* mG;
105 113
    QString mText;
106 114
    QByteArray mStrId;
107 115
    int mId;
108 116
    LabelInfo* mInfo;
117
    bool mIsDiagram;
109 118
    /**Stores attribute values for data defined properties*/
110 119
    QMap< QgsPalLayerSettings::DataDefinedProperties, QVariant > mDataDefinedValues;
120

  
121
    /**Stores attribute values for diagram rendering*/
122
    QgsAttributeMap mDiagramAttributes;
111 123
};
112 124

  
113 125
// -------------
......
414 426
  labelY = qAbs( ptSize.y() - ptZero.y() );
415 427
}
416 428

  
417

  
418 429
void QgsPalLayerSettings::registerFeature( QgsFeature& f, const QgsRenderContext& context )
419 430
{
420 431
  QString labelText = f.attributeMap()[fieldIndex].toString();
......
743 754
  return 1; // init successful
744 755
}
745 756

  
757
int QgsPalLabeling::addDiagramLayer( QgsVectorLayer* layer, QgsDiagramLayerSettings& s )
758
{
759
  Layer* l = mPal->addLayer( layer->id().append("d").toLocal8Bit().data(), -1, -1, pal::Arrangement(s.placement), METER, s.priority, s.obstacle, true, true );
760
  l->setArrangementFlags( s.placementFlags );
746 761

  
762
  s.palLayer = l;
763
  if ( mMapRenderer->hasCrsTransformEnabled() )
764
    s.ct = new QgsCoordinateTransform( layer->srs(), mMapRenderer->destinationSrs() );
765
  else
766
    s.ct = NULL;
767
  s.xform = mMapRenderer->coordinateTransform();
768
  mActiveDiagramLayers.insert( layer, s );
769
  return 1;
770
}
771

  
747 772
void QgsPalLabeling::registerFeature( QgsVectorLayer* layer, QgsFeature& f, const QgsRenderContext& context )
748 773
{
749 774
  QgsPalLayerSettings& lyr = mActiveLayers[layer];
750 775
  lyr.registerFeature( f, context );
751 776
}
752 777

  
778
void QgsPalLabeling::registerDiagramFeature( QgsVectorLayer* layer, QgsFeature& feat, const QgsRenderContext& context )
779
{
780
  //get diagram layer settings, diagram renderer
781
  QHash<QgsVectorLayer*, QgsDiagramLayerSettings>::iterator layerIt = mActiveDiagramLayers.find( layer );
782
  if( layerIt == mActiveDiagramLayers.constEnd() )
783
  {
784
    return;
785
  }
753 786

  
787
  //convert geom to geos
788
  QgsGeometry* geom = feat.geometry();
789

  
790
  if ( layerIt.value().ct ) // reproject the geometry if necessary
791
  {
792
    geom->transform( *(layerIt.value().ct) );
793
  }
794

  
795
  GEOSGeometry* geos_geom = geom->asGeos();
796
  if ( geos_geom == 0 )
797
  {
798
    return; // invalid geometry
799
  }
800

  
801
  //create PALGeometry with diagram = true
802
  QgsPalGeometry* lbl = new QgsPalGeometry( feat.id(), "", GEOSGeom_clone( geos_geom ) );
803
  lbl->setIsDiagram( true );
804

  
805
  // record the created geometry - it will be deleted at the end.
806
  layerIt.value().geometries.append( lbl );
807

  
808
  double diagramWidth = 0;
809
  double diagramHeight = 0;
810
  QgsDiagramRendererV2* dr = layerIt.value().renderer;
811
  if( dr )
812
  {
813
    QSizeF diagSize = dr->sizeMapUnits( feat.attributeMap(), context );
814
    if( diagSize.isValid() )
815
    {
816
      diagramWidth = diagSize.width();
817
      diagramHeight= diagSize.height();
818
    }
819

  
820
    //append the diagram attributes to lbl
821
    QList<int> diagramAttrib = dr->diagramAttributes();
822
    QList<int>::const_iterator diagAttIt = diagramAttrib.constBegin();
823
    for(; diagAttIt != diagramAttrib.constEnd(); ++diagAttIt )
824
    {
825
      lbl->addDiagramAttribute( *diagAttIt, feat.attributeMap()[*diagAttIt] );
826
    }
827
  }
828

  
829
  // register feature to the layer
830
  int ddColX = layerIt.value().xPosColumn;
831
  int ddColY = layerIt.value().yPosColumn;
832
  double ddPosX = 0.0;
833
  double ddPosY = 0.0;
834
  bool ddPos = (ddColX >= 0 && ddColY >= 0);
835
  if( ddPos )
836
  {
837
    bool posXOk, posYOk;
838
    //data defined diagram position is always centered
839
    ddPosX = feat.attributeMap()[ddColX].toDouble( &posXOk )- diagramWidth / 2.0;
840
    ddPosY = feat.attributeMap()[ddColY].toDouble( &posYOk )- diagramHeight / 2.0;
841
    if( !posXOk || !posYOk )
842
    {
843
      ddPos = false;
844
    }
845
  }
846

  
847
  try
848
  {
849
    if ( !layerIt.value().palLayer->registerFeature( lbl->strId(), lbl, diagramWidth, diagramHeight, "", ddPosX, ddPosY, ddPos ) )
850
    {
851
      return;
852
    }
853
  }
854
  catch ( std::exception* e )
855
  {
856
    QgsDebugMsg( QString( "Ignoring feature %1 due PAL exception: " ).arg( feat.id() ) + QString::fromLatin1( e->what() ) );
857
    return;
858
  }
859

  
860
  pal::Feature* palFeat = layerIt.value().palLayer->getFeature( lbl->strId() );
861
  QgsPoint ptZero = layerIt.value().xform->toMapCoordinates( 0, 0 );
862
  QgsPoint ptOne = layerIt.value().xform->toMapCoordinates( 1, 0 );
863
  palFeat->setDistLabel( qAbs( ptOne.x() - ptZero.x() ) * layerIt.value().dist );
864
}
865

  
866

  
754 867
void QgsPalLabeling::init( QgsMapRenderer* mr )
755 868
{
756 869
  mMapRenderer = mr;
......
779 892
  mPal->setPolyP( mCandPolygon );
780 893

  
781 894
  mActiveLayers.clear();
895
  mActiveDiagramLayers.clear();
782 896
}
783 897

  
784 898
void QgsPalLabeling::exit()
......
867 981
  std::list<LabelPosition*>::iterator it = labels->begin();
868 982
  for ( ; it != labels->end(); ++it )
869 983
  {
984
    QgsPalGeometry* palGeometry = dynamic_cast< QgsPalGeometry* >(( *it )->getFeaturePart()->getUserGeometry() );
985
    if ( !palGeometry )
986
    {
987
      continue;
988
    }
989

  
990
    if( palGeometry->isDiagram() )
991
    {
992
      //render diagram
993
      QHash<QgsVectorLayer*, QgsDiagramLayerSettings>::iterator dit = mActiveDiagramLayers.begin();
994
      for ( dit = mActiveDiagramLayers.begin(); dit != mActiveDiagramLayers.end(); ++dit )
995
      {
996
        if ( dit.key() && dit.key()->id().append("d") == ( *it )->getLayerName() )
997
        {
998
          QgsPoint outPt = xform->transform( (*it)->getX(), (*it)->getY() );
999
          dit.value().renderer->renderDiagram( palGeometry->diagramAttributes(), context, QPointF( outPt.x(), outPt.y() ) );
1000
        }
1001
      }
1002

  
1003
      //insert into label search tree to manipulate position interactively
1004
      if ( mLabelSearchTree )
1005
      {
1006
        //for diagrams, remove the additional 'd' at the end of the layer id
1007
        QString layerId = (*it )->getLayerName();
1008
        layerId.chop( 1 );
1009
        mLabelSearchTree->insertLabel( *it,  QString( palGeometry->strId() ).toInt(), layerId, true );
1010
      }
1011
      continue;
1012
    }
1013

  
870 1014
    const QgsPalLayerSettings& lyr = layer(( *it )->getLayerName() );
871 1015
    QFont fontForLabel = lyr.textFont;
872 1016
    QColor fontColor = lyr.textColor;
873 1017
    double bufferSize = lyr.bufferSize;
874 1018
    QColor bufferColor = lyr.bufferColor;
875 1019

  
876
    QgsPalGeometry* palGeometry = dynamic_cast< QgsPalGeometry* >(( *it )->getFeaturePart()->getUserGeometry() );
877
    if ( !palGeometry )
878
    {
879
      continue;
880
    }
881

  
882 1020
    //apply data defined settings for the label
883 1021
    //font size
884 1022
    QVariant dataDefinedSize = palGeometry->dataDefinedValues().value( QgsPalLayerSettings::Size );
......
969 1107
      delete *git;
970 1108
    lyr.geometries.clear();
971 1109
  }
972
  // labeling is done: clear the active layers hashtable
973
// mActiveLayers.clear();
974 1110

  
1111
  //delete all allocated geometries for diagrams
1112
  QHash<QgsVectorLayer*, QgsDiagramLayerSettings>::iterator dIt = mActiveDiagramLayers.begin();
1113
  for(; dIt != mActiveDiagramLayers.end(); ++dIt )
1114
  {
1115
    QgsDiagramLayerSettings& dls = dIt.value();
1116
    for ( QList<QgsPalGeometry*>::iterator git = dls.geometries.begin(); git != dls.geometries.end(); ++git )
1117
    {
1118
      delete *git;
1119
    }
1120
    dls.geometries.clear();
1121
  }
975 1122
}
976 1123

  
977 1124
QList<QgsLabelPosition> QgsPalLabeling::labelsAtPosition( const QgsPoint& p )
src/core/qgsrendercontext.h (Arbeitskopie)
41 41
    //getters
42 42

  
43 43
    QPainter* painter() {return mPainter;}
44
    const QPainter* constPainter() const { return mPainter; }
44 45

  
45 46
    const QgsCoordinateTransform* coordinateTransform() const {return mCoordTransform;}
46 47

  
src/core/qgspallabeling.h (Arbeitskopie)
23 23

  
24 24
class QFontMetricsF;
25 25
class QPainter;
26
class QgsGeometry;
26 27
class QgsMapRenderer;
27 28
class QgsRectangle;
28 29
class QgsCoordinateTransform;
29 30
class QgsLabelSearchTree;
31
struct QgsDiagramLayerSettings;
30 32

  
31 33
#include <QString>
32 34
#include <QFont>
33 35
#include <QColor>
36
#include <QHash>
34 37
#include <QList>
35 38
#include <QRectF>
36 39

  
......
45 48
class QgsFeature;
46 49
#include "qgspoint.h"
47 50

  
48
#include "qgsvectorlayer.h" // definition of QgsLabelingEngineInterface
51
#include "qgsmaprenderer.h" // definition of QgsLabelingEngineInterface
49 52

  
50 53
class QgsPalGeometry;
54
class QgsVectorLayer;
51 55

  
52 56
class CORE_EXPORT QgsPalLayerSettings
53 57
{
......
195 199
    virtual bool willUseLayer( QgsVectorLayer* layer );
196 200
    //! hook called when drawing layer before issuing select()
197 201
    virtual int prepareLayer( QgsVectorLayer* layer, QSet<int>& attrIndices, QgsRenderContext& ctx );
202
    //! adds a diagram layer to the labeling engine
203
    virtual int addDiagramLayer( QgsVectorLayer* layer, QgsDiagramLayerSettings& s );
198 204
    //! hook called when drawing for every feature in a layer
199 205
    virtual void registerFeature( QgsVectorLayer* layer, QgsFeature& feat, const QgsRenderContext& context = QgsRenderContext() );
206
    virtual void registerDiagramFeature( QgsVectorLayer* layer, QgsFeature& feat, const QgsRenderContext& context = QgsRenderContext() );
200 207
    //! called when the map is drawn and labels should be placed
201 208
    virtual void drawLabeling( QgsRenderContext& context );
202 209
    //! called when we're done with rendering
......
220 227
  protected:
221 228
    // hashtable of layer settings, being filled during labeling
222 229
    QHash<QgsVectorLayer*, QgsPalLayerSettings> mActiveLayers;
230
    // hashtable of active diagram layers
231
    QHash<QgsVectorLayer*, QgsDiagramLayerSettings> mActiveDiagramLayers;
223 232
    QgsPalLayerSettings mInvalidLayerSettings;
224 233

  
225 234
    QgsMapRenderer* mMapRenderer;
src/core/qgslabelsearchtree.h (Arbeitskopie)
44 44

  
45 45
    /**Inserts label position. Does not take ownership of labelPos
46 46
      @return true in case of success*/
47
    bool insertLabel( LabelPosition* labelPos, int featureId, const QString& layerName );
47
    bool insertLabel( LabelPosition* labelPos, int featureId, const QString& layerName, bool diagram = false );
48 48

  
49 49
  private:
50 50
    RTree<QgsLabelPosition*, double, 2, double> mSpatialIndex;
src/core/qgsvectorlayer.cpp (Arbeitskopie)
112 112
    mLabelOn( false ),
113 113
    mVertexMarkerOnlyForSelection( false ),
114 114
    mFetching( false ),
115
    mJoinBuffer( 0 )
115
    mJoinBuffer( 0 ),
116
    mDiagramRenderer( 0 )
116 117
{
117 118
  mActions = new QgsAttributeAction( this );
118 119

  
......
755 756
      mRendererV2->renderFeature( fet, rendererContext, -1, sel, drawMarker );
756 757

  
757 758
      // labeling - register feature
758
      if ( labeling && mRendererV2->symbolForFeature( fet ) != NULL )
759
        rendererContext.labelingEngine()->registerFeature( this, fet, rendererContext );
759
      if( mRendererV2->symbolForFeature( fet ) != NULL )
760
      {
761
        if ( labeling )
762
        {
763
          rendererContext.labelingEngine()->registerFeature( this, fet, rendererContext );
764
        }
765
        if( mDiagramRenderer )
766
        {
767
          rendererContext.labelingEngine()->registerDiagramFeature( this, fet, rendererContext );
768
        }
769
      }
760 770

  
761 771
      if ( mEditable )
762 772
      {
......
822 832
    }
823 833
    features[sym].append( fet );
824 834

  
825
    if ( labeling && mRendererV2->symbolForFeature( fet ) != NULL )
826
      rendererContext.labelingEngine()->registerFeature( this, fet, rendererContext );
835
    if( mRendererV2->symbolForFeature( fet ) != NULL )
836
    {
837
      if ( labeling )
838
      {
839
        rendererContext.labelingEngine()->registerFeature( this, fet, rendererContext );
840
      }
841
      if( mDiagramRenderer )
842
      {
843
        rendererContext.labelingEngine()->registerDiagramFeature( this, fet, rendererContext );
844
      }
845
    }
827 846

  
828 847
    if ( mEditable )
829 848
    {
......
950 969
    }
951 970

  
952 971
    bool labeling = false;
953
    if ( rendererContext.labelingEngine() )
954
    {
955
      QSet<int> attrIndex;
956
      if ( rendererContext.labelingEngine()->prepareLayer( this, attrIndex, rendererContext ) )
957
      {
958
        QSet<int>::const_iterator attIt = attrIndex.constBegin();
959
        for ( ; attIt != attrIndex.constEnd(); ++attIt )
960
        {
961
          if ( !attributes.contains( *attIt ) )
962
          {
963
            attributes << *attIt;
964
          }
965
        }
966
        labeling = true;
967
      }
968
    }
972
    //register label and diagram layer to the labeling engine
973
    prepareLabelingAndDiagrams( rendererContext, attributes, labeling );
969 974

  
970 975
    select( attributes, rendererContext.extent() );
971 976

  
......
1012 1017
    QgsAttributeList attributes = mRenderer->classificationAttributes();
1013 1018

  
1014 1019
    bool labeling = false;
1015
    if ( rendererContext.labelingEngine() )
1016
    {
1017
      QSet<int> attrIndex;
1018
      if ( rendererContext.labelingEngine()->prepareLayer( this, attrIndex, rendererContext ) )
1019
      {
1020
        QSet<int>::const_iterator attIt = attrIndex.constBegin();
1021
        for ( ; attIt != attrIndex.constEnd(); ++attIt )
1022
        {
1023
          if ( !attributes.contains( *attIt ) )
1024
          {
1025
            attributes << *attIt;
1026
          }
1027
        }
1028
        labeling = true;
1029
      }
1030
    }
1020
    prepareLabelingAndDiagrams( rendererContext, attributes, labeling );
1031 1021

  
1032 1022
    select( attributes, rendererContext.extent() );
1033 1023

  
......
1093 1083
        //double scale = rendererContext.scaleFactor() /  markerScaleFactor;
1094 1084
        drawFeature( rendererContext, fet, &marker );
1095 1085

  
1096
        if ( labeling && mRenderer->willRenderFeature( &fet ) )
1086
        if( mRenderer->willRenderFeature( &fet ) )
1097 1087
        {
1098
          rendererContext.labelingEngine()->registerFeature( this, fet, rendererContext );
1088
          if ( labeling )
1089
          {
1090
            rendererContext.labelingEngine()->registerFeature( this, fet, rendererContext );
1091
          }
1092
          if( mDiagramRenderer )
1093
          {
1094
            rendererContext.labelingEngine()->registerDiagramFeature( this, fet, rendererContext );
1095
          }
1099 1096
        }
1100

  
1101 1097
        ++featureCount;
1102 1098
      }
1103 1099
    }
......
1304 1300
  }
1305 1301
}
1306 1302

  
1303
void QgsVectorLayer::setDiagramRenderer( QgsDiagramRendererV2* r )
1304
{
1305
  delete mDiagramRenderer;
1306
  mDiagramRenderer = r;
1307
}
1308

  
1307 1309
QGis::GeometryType QgsVectorLayer::geometryType() const
1308 1310
{
1309 1311
  if ( mDataProvider )
......
2938 2940
      QgsDebugMsg( "calling readXML" );
2939 2941
      mLabel->readXML( labelattributesnode );
2940 2942
    }
2943

  
2944
    //diagram renderer and diagram layer settings
2945
    delete mDiagramRenderer; mDiagramRenderer = 0;
2946
    QDomElement singleCatDiagramElem = node.firstChildElement( "SingleCategoryDiagramRenderer" );
2947
    if( !singleCatDiagramElem.isNull() )
2948
    {
2949
      mDiagramRenderer = new QgsSingleCategoryDiagramRenderer();
2950
      mDiagramRenderer->readXML( singleCatDiagramElem );
2951
    }
2952
    QDomElement linearDiagramElem = node.firstChildElement( "LinearlyInterpolatedDiagramRenderer" );
2953
    if( !linearDiagramElem.isNull() )
2954
    {
2955
      mDiagramRenderer = new QgsLinearlyInterpolatedDiagramRenderer();
2956
      mDiagramRenderer->readXML( linearDiagramElem );
2957
    }
2958

  
2959
    if( mDiagramRenderer )
2960
    {
2961
      QDomElement diagramSettingsElem = node.firstChildElement( "DiagramLayerSettings" );
2962
      if( !diagramSettingsElem.isNull() )
2963
      {
2964
        mDiagramLayerSettings.readXML( diagramSettingsElem );
2965
      }
2966
    }
2941 2967
  }
2942 2968

  
2943 2969
  // process the attribute actions
......
3110 3136
    }
3111 3137

  
3112 3138
    mLabel->writeXML( node, doc );
3139

  
3140
    if( mDiagramRenderer )
3141
    {
3142
      mDiagramRenderer->writeXML( mapLayerNode, doc );
3143
      mDiagramLayerSettings.writeXML( mapLayerNode, doc );
3144
    }
3113 3145
  }
3114 3146

  
3115 3147
  //edit types
......
5132 5164
  map.insert( newIndex, it.value() );
5133 5165
  map.remove( oldIndex );
5134 5166
}
5167

  
5168
void QgsVectorLayer::prepareLabelingAndDiagrams( QgsRenderContext& rendererContext, QgsAttributeList& attributes, bool& labeling )
5169
{
5170
  if ( rendererContext.labelingEngine() )
5171
    {
5172
      QSet<int> attrIndex;
5173
      if ( rendererContext.labelingEngine()->prepareLayer( this, attrIndex, rendererContext ) )
5174
      {
5175
        QSet<int>::const_iterator attIt = attrIndex.constBegin();
5176
        for ( ; attIt != attrIndex.constEnd(); ++attIt )
5177
        {
5178
          if ( !attributes.contains( *attIt ) )
5179
          {
5180
            attributes << *attIt;
5181
          }
5182
        }
5183
        labeling = true;
5184
      }
5185

  
5186
      //register diagram layers
5187
      if( mDiagramRenderer )
5188
      {
5189
        mDiagramLayerSettings.renderer = mDiagramRenderer;
5190
        rendererContext.labelingEngine()->addDiagramLayer( this, mDiagramLayerSettings );
5191
        //add attributes needed by the diagram renderer
5192
        QList<int> att = mDiagramRenderer->diagramAttributes();
5193
        QList<int>::const_iterator attIt = att.constBegin();
5194
        for(; attIt != att.constEnd(); ++attIt )
5195
        {
5196
          if( !attributes.contains( *attIt ) )
5197
          {
5198
            attributes << *attIt;
5199
          }
5200
        }
5201
        //and the ones needed for data defined diagram positions
5202
        if( mDiagramLayerSettings.xPosColumn >= 0 && !attributes.contains( mDiagramLayerSettings.xPosColumn ) )
5203
        {
5204
          attributes << mDiagramLayerSettings.xPosColumn;
5205
        }
5206
        if( mDiagramLayerSettings.yPosColumn >= 0 && !attributes.contains( mDiagramLayerSettings.yPosColumn ) )
5207
        {
5208
          attributes << mDiagramLayerSettings.yPosColumn;
5209
        }
5210
      }
5211
    }
5212
}
src/core/qgsdiagram.h (Revision 0)
1
#ifndef QGSDIAGRAM_H
2
#define QGSDIAGRAM_H
3

  
4
#include "qgsfeature.h"
5
#include <QPen>
6

  
7
class QPainter;
8
class QPointF;
9
struct QgsDiagramSettings;
10

  
11
class QgsRenderContext;
12

  
13
/**Base class for all diagram types*/
14
class QgsDiagram
15
{
16
  public:
17
    /**Draws the diagram at the given position (in pixel coordinates)*/
18
    virtual void renderDiagram( const QgsAttributeMap& att, QgsRenderContext& c, const QgsDiagramSettings& s, const QPointF& position ) = 0;
19
    virtual QString diagramName() const = 0;
20
};
21

  
22
class QgsTextDiagram: public QgsDiagram
23
{
24
  public:
25
    enum Shape
26
    {
27
      Circle = 0,
28
      Rectangle,
29
      Triangle
30
    };
31

  
32
    enum Orientation
33
    {
34
      Horizontal = 0,
35
      Vertical
36
    };
37

  
38
    QgsTextDiagram();
39
    ~QgsTextDiagram();
40
    void renderDiagram( const QgsAttributeMap& att, QgsRenderContext& c, const QgsDiagramSettings& s, const QPointF& position );
41

  
42
    QString diagramName() const { return "Text"; }
43

  
44
  private:
45
    Orientation mOrientation;
46
    Shape mShape;
47
    QBrush mBrush; //transparent brush
48
    QPen mPen;
49

  
50
    /**Calculates intersection points between a line and an ellipse
51
      @return intersection points*/
52
    void lineEllipseIntersection( const QPointF& lineStart, const QPointF& lineEnd, const QPointF& ellipseMid, double r1, double r2, QList<QPointF>& result ) const;
53
};
54

  
55
class QgsPieDiagram: public QgsDiagram
56
{
57
  public:
58
    QgsPieDiagram();
59
    ~QgsPieDiagram();
60

  
61
    void renderDiagram( const QgsAttributeMap& att, QgsRenderContext& c, const QgsDiagramSettings& s, const QPointF& position );
62
    QString diagramName() const { return "Pie"; }
63

  
64
  private:
65
    QBrush mCategoryBrush;
66
    QPen mPen;
67
};
68

  
69
#endif // QGSDIAGRAM_H
src/core/qgsdiagram.cpp (Revision 0)
1
#include "qgsdiagram.h"
2
#include "qgsdiagramrendererv2.h"
3
#include "qgsrendercontext.h"
4

  
5
#include <QPainter>
6

  
7
QgsTextDiagram::QgsTextDiagram(): mOrientation( Vertical ), mShape( Circle )
8
{
9
  mPen.setWidthF( 2.0 );
10
  mPen.setColor( QColor( 0, 0, 0 ) );
11
  mPen.setCapStyle( Qt::FlatCap );
12
  mBrush.setStyle( Qt::SolidPattern );
13
}
14

  
15
QgsTextDiagram::~QgsTextDiagram()
16
{
17
}
18

  
19
void QgsTextDiagram::renderDiagram( const QgsAttributeMap& att, QgsRenderContext& c, const QgsDiagramSettings& s, const QPointF& position )
20
{
21
  QPainter* p = c.painter();
22
  if ( !p )
23
  {
24
    return;
25
  }
26

  
27
  //convert from mm to painter units
28
  double w = s.size.width() * c.scaleFactor();
29
  double h = s.size.height() * c.scaleFactor();
30

  
31
  double baseX = position.x();
32
  double baseY = position.y() - h;
33

  
34
  QList<QPointF> textPositions; //midpoints for text placement
35
  int nCategories = s.categoryIndices.size();
36
  for( int i = 0; i < nCategories; ++i )
37
  {
38
    if( mOrientation == Horizontal )
39
    {
40
      textPositions.push_back( QPointF( baseX + (w / nCategories) * i + w / nCategories / 2.0 , baseY + h / 2.0 ) );
41
    }
42
    else //vertical
43
    {
44
      textPositions.push_back( QPointF( baseX + w / 2.0, baseY + h / nCategories * i + w / nCategories / 2.0 ) );
45
    }
46
  }
47

  
48
  mPen.setColor( QColor( 0, 0, 0 ) );
49
  p->setPen( mPen );
50
  mBrush.setColor( s.backgroundColor );
51
  p->setBrush( mBrush );
52
  p->setFont( s.font );
53

  
54
  //draw shapes
55
  QPointF center( baseX + w / 2.0, baseY + h / 2.0 );
56
  double r1 = w / 2.0; double r2 = h / 2.0;
57
  QList<QPointF> intersect; //intersections between shape and separation lines
58

  
59
  switch( mShape )
60
  {
61
    case Circle:
62
    p->drawEllipse( baseX, baseY, w, h );
63
    //draw separator lines
64
    for( int i = 1; i < nCategories; ++i )
65
    {
66
      if( mOrientation == Horizontal )
67
      {
68
        lineEllipseIntersection( QPointF( baseX + w / nCategories * i, baseY ), QPointF( baseX + w / nCategories * i, baseY + h ), center, r1, r2, intersect );
69
      }
70
      else //vertical
71
      {
72
        lineEllipseIntersection( QPointF( baseX, baseY + h / nCategories * i ), QPointF( baseX + w, baseY + h / nCategories * i), center, r1, r2, intersect );
73
      }
74
      if( intersect.size() > 1 )
75
      {
76
        p->drawLine( intersect.at(0), intersect.at(1) );
77
      }
78
    }
79
    break;
80
    case Rectangle:
81
    break;
82
    case Triangle:
83
    default:
84
    break;
85
  }
86

  
87
  //draw text
88
  p->setFont( s.font );
89
  QFontMetricsF fontMetrics( s.font );
90

  
91
  for( int i = 0; i < textPositions.size(); ++i )
92
  {
93
    QString val = att[ s.categoryIndices.at( i ) ].toString();
94
    //find out dimensions
95
    double textHeight = fontMetrics.height();
96
    double textWidth = fontMetrics.width( val );
97
    mPen.setColor( s.categoryColors.at( i ) );
98
    p->setPen( mPen );
99
    QPointF position = textPositions.at( i );
100
    p->drawText( QPointF( position.x() - textWidth / 2.0, position.y() + textHeight / 2.0 ), val );
101
  }
102
}
103

  
104
void QgsTextDiagram::lineEllipseIntersection( const QPointF& lineStart, const QPointF& lineEnd, const QPointF& ellipseMid, double r1, double r2, QList<QPointF>& result ) const
105
{
106
  result.clear();
107

  
108
  double rrx = r1 * r1;
109
  double rry = r2 * r2;
110
  double x21 = lineEnd.x() - lineStart.x();
111
  double y21 = lineEnd.y() - lineStart.y();
112
  double x10 = lineStart.x() - ellipseMid.x();
113
  double y10 = lineStart.y() - ellipseMid.y();
114
  double a = x21*x21/rrx+y21*y21/rry;
115
  double b = x21*x10/rrx+y21*y10/rry;
116
  double c = x10*x10/rrx+y10*y10/rry;
117
  double d = b*b-a*(c-1);
118
  if( d > 0 )
119
  {
120
    double e = sqrt( d );
121
    double u1 = (-b-e)/a;
122
    double u2 = (-b+e)/a;
123
    //work with a tolerance of 0.00001 because of limited numerical precision
124
    if( -0.00001 <= u1 && u1 < 1.00001 )
125
    {
126
      result.push_back( QPointF( lineStart.x() + x21 * u1, lineStart.y() + y21 * u1 ) );
127
    }
128
    if( -0.00001 <= u2 && u2 <= 1.00001 )
129
    {
130
      result.push_back( QPointF( lineStart.x() + x21 * u2, lineStart.y() + y21 * u2 ) );
131
    }
132
  }
133
}
134

  
135
QgsPieDiagram::QgsPieDiagram()
136
{
137
  mCategoryBrush.setStyle( Qt::SolidPattern );
138
  mPen.setStyle( Qt::NoPen );
139
}
140

  
141
QgsPieDiagram::~QgsPieDiagram()
142
{
143
}
144

  
145
void QgsPieDiagram::renderDiagram( const QgsAttributeMap& att, QgsRenderContext& c, const QgsDiagramSettings& s, const QPointF& position )
146
{
147
  QPainter* p = c.painter();
148
  if ( !p )
149
  {
150
    return;
151
  }
152

  
153
  //get sum of values
154
  QList<double> values;
155
  double currentVal = 0;
156
  double valSum = 0;
157

  
158
  QList<int>::const_iterator catIt = s.categoryIndices.constBegin();
159
  for(; catIt != s.categoryIndices.constEnd(); ++catIt )
160
  {
161
    currentVal = att[*catIt].toDouble();
162
    values.push_back( currentVal );
163
    valSum += currentVal;
164
  }
165

  
166
  //draw the slices
167
  double totalAngle = 0;
168
  double currentAngle;
169

  
170
  //convert from mm to painter units
171
  double w = s.size.width() * c.scaleFactor();
172
  double h = s.size.height() * c.scaleFactor();
173

  
174
  double baseX = position.x();
175
  double baseY = position.y() - h;
176

  
177
  p->setPen( mPen );
178
  QList<double>::const_iterator valIt = values.constBegin();
179
  QList< QColor >::const_iterator colIt = s.categoryColors.constBegin();
180
  for(; valIt != values.constEnd(); ++valIt, ++colIt )
181
  {
182
    currentAngle =  *valIt / valSum * 360 * 16;
183
    mCategoryBrush.setColor( *colIt );
184
    p->setBrush( mCategoryBrush );
185
    p->drawPie( baseX, baseY, w, h, totalAngle, currentAngle );
186
    totalAngle += currentAngle;
187
  }
188
}
src/core/qgsvectorlayer.h (Arbeitskopie)
25 25
#include <QStringList>
26 26

  
27 27
#include "qgis.h"
28
#include "qgsdiagramrendererv2.h"
28 29
#include "qgsmaplayer.h"
29 30
#include "qgsfeature.h"
30 31
#include "qgssnapper.h"
......
48 49
class QgsSingleSymbolRendererV2;
49 50
class QgsRectangle;
50 51
class QgsVectorLayerJoinBuffer;
51

  
52 52
class QgsFeatureRendererV2;
53 53

  
54 54
typedef QList<int> QgsAttributeList;
......
208 208
    /** Sets the renderer. If a renderer is already present, it is deleted */
209 209
    void setRenderer( QgsRenderer * r );
210 210

  
211
    /** Sets diagram rendering object (takes ownership) */
212
    void setDiagramRenderer( QgsDiagramRendererV2* r );
213
    const QgsDiagramRendererV2* diagramRenderer() const { return mDiagramRenderer; }
214

  
215
    void setDiagramLayerSettings( const QgsDiagramLayerSettings& s ) { mDiagramLayerSettings = s; }
216
    QgsDiagramLayerSettings diagramLayerSettings() const { return mDiagramLayerSettings; }
217

  
211 218
    /** Return renderer V2.
212 219
     * @note added in 1.4 */
213 220
    QgsFeatureRendererV2* rendererV2();
......
804 811
    /**Updates an index in an attribute map to a new value (usually necessary because of a join operation)*/
805 812
    void updateAttributeMapIndex( QgsAttributeMap& map, int oldIndex, int newIndex ) const;
806 813

  
814
    /**Registers label and diagram layer
815
      @param attList attributes needed for labeling and diagrams will be added to the list
816
      @param labeling out: true if there will be labeling (ng) for this layer*/
817
    void prepareLabelingAndDiagrams( QgsRenderContext& rendererContext, QgsAttributeList& attributes, bool& labeling );
818

  
807 819
  private:                       // Private attributes
808 820

  
809 821
    /** Update threshold for drawing features as they are read. A value of zero indicates
......
931 943

  
932 944
    //stores information about joined layers
933 945
    QgsVectorLayerJoinBuffer* mJoinBuffer;
946

  
947
    //diagram rendering object. 0 if diagram drawing is disabled
948
    QgsDiagramRendererV2* mDiagramRenderer;
949

  
... This diff was truncated because it exceeds the maximum size that can be displayed.