⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 qgscomposervectorlegend.cpp

📁 一个非常好的GIS开源新版本
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/***************************************************************************                         qgscomposervectorlegend.cpp                             -------------------    begin                : January 2005    copyright            : (C) 2005 by Radim Blazek    email                : blazek@itc.it ***************************************************************************//*************************************************************************** *                                                                         * *   This program is free software; you can redistribute it and/or modify  * *   it under the terms of the GNU General Public License as published by  * *   the Free Software Foundation; either version 2 of the License, or     * *   (at your option) any later version.                                   * *                                                                         * ***************************************************************************/#include "qgscomposervectorlegend.h"#include "qgscomposermap.h"#include "qgscontinuouscolorrenderer.h"#include "qgsmapcanvas.h"#include "qgsmaplayer.h"#include "qgsproject.h"#include "qgsrenderer.h"#include "qgssymbol.h"#include "qgsvectorlayer.h"#include <QFontDialog>#include <QPainter>#include <Q3PopupMenu>#include <QGraphicsScene>#include <iostream>#include <vector>QgsComposerVectorLegend::QgsComposerVectorLegend ( QgsComposition *composition, int id,                                               int x, int y, int fontSize )    : QWidget(composition), QGraphicsRectItem(x,y,10,10,0){  setupUi(this);  //std::cout << "QgsComposerVectorLegend::QgsComposerVectorLegend()" << std::endl;  mComposition = composition;  mId  = id;  mMapCanvas = mComposition->mapCanvas();  init();  // Font and pen  if(fontSize < 10){    fontSize = 10;  }  mFont.setPointSize ( fontSize );      // Set map to the first available if any  std::vector<QgsComposerMap*> maps = mComposition->maps();  if ( maps.size() > 0 ) {    mMap = maps[0]->id();  }  // Calc size and cache  recalculate();  // Add to scene  mComposition->canvas()->addItem(this);  QGraphicsRectItem::show();  QGraphicsRectItem::update();       writeSettings();}QgsComposerVectorLegend::QgsComposerVectorLegend ( QgsComposition *composition, int id )     : QGraphicsRectItem(0,0,10,10,0){    //std::cout << "QgsComposerVectorLegend::QgsComposerVectorLegend()" << std::endl;    setupUi(this);    mComposition = composition;    mId  = id;    mMapCanvas = mComposition->mapCanvas();    init();    readSettings();    // Calc size and cache    recalculate();    // Add to scene    mComposition->canvas()->addItem(this);    QGraphicsRectItem::show();    QGraphicsRectItem::update();}void QgsComposerVectorLegend::init ( void ) {    mSelected = false;    mNumCachedLayers = 0;    mTitle = tr("Legend");    mMap = 0;    mNextLayerGroup = 1;    mFrame = true;    // Cache    mCacheUpdated = false;    // Rectangle    QGraphicsRectItem::setZValue(50);//    setActive(true);    // Layers list view    mLayersListView->setColumnText(0,tr("Layers"));    mLayersListView->addColumn(tr("Group"));    mLayersListView->setSorting(-1);    mLayersListView->setResizeMode(Q3ListView::AllColumns);    mLayersListView->setSelectionMode(Q3ListView::Extended);    mLayersPopupMenu = new Q3PopupMenu( );    mLayersPopupMenu->insertItem( tr("Combine selected layers"), this, SLOT(groupLayers()) );    connect ( mLayersListView, SIGNAL(clicked(Q3ListViewItem *)),                          this, SLOT(layerChanged(Q3ListViewItem *)));    connect ( mLayersListView, SIGNAL(rightButtonClicked(Q3ListViewItem *, const QPoint &, int)),                     this, SLOT( showLayersPopupMenu(Q3ListViewItem *, const QPoint &, int)) );    // Plot style    setPlotStyle ( QgsComposition::Preview );        // Preview style    mPreviewMode = Render;    mPreviewModeComboBox->insertItem ( tr("Cache"), Cache );    mPreviewModeComboBox->insertItem ( tr("Render"), Render );    mPreviewModeComboBox->insertItem ( tr("Rectangle"), Rectangle );    mPreviewModeComboBox->setCurrentItem ( mPreviewMode );    connect ( mComposition, SIGNAL(mapChanged(int)), this, SLOT(mapChanged(int)) ); }QgsComposerVectorLegend::~QgsComposerVectorLegend(){  //std::cerr << "QgsComposerVectorLegend::~QgsComposerVectorLegend()" << std::endl;}#define FONT_WORKAROUND_SCALE 10QRectF QgsComposerVectorLegend::render ( QPainter *p ){  //std::cout << "QgsComposerVectorLegend::render p = " << p << std::endl;  // Painter can be 0, create dummy to avoid many if below  QPainter *painter = NULL;  QPixmap *pixmap = NULL;  if ( p ) {    painter = p;  } else {    pixmap = new QPixmap(1,1);    painter = new QPainter( pixmap );  }  //std::cout << "mComposition->scale() = " << mComposition->scale() << std::endl;  // Font size in canvas units  float titleSize = 25.4 * mComposition->scale() * mTitleFont.pointSizeFloat() / 72;  float sectionSize = 25.4 * mComposition->scale() * mSectionFont.pointSizeFloat() / 72;  float size = 25.4 * mComposition->scale() * mFont.pointSizeFloat() / 72;  //std::cout << "font sizes = " << titleSize << " " << sectionSize << " " << size << std::endl;  // Create fonts   QFont titleFont ( mTitleFont );  QFont sectionFont ( mSectionFont );  QFont font ( mFont );  titleFont.setPointSizeFloat ( titleSize );  sectionFont.setPointSizeFloat ( sectionSize );  font.setPointSizeFloat ( size );  // Not sure about Style Strategy, QFont::PreferMatch?  titleFont.setStyleStrategy ( (QFont::StyleStrategy) (QFont::PreferOutline | QFont::PreferAntialias) );  sectionFont.setStyleStrategy ( (QFont::StyleStrategy) (QFont::PreferOutline | QFont::PreferAntialias) );  font.setStyleStrategy ( (QFont::StyleStrategy) (QFont::PreferOutline | QFont::PreferAntialias) );  QFontMetricsF titleMetrics ( titleFont );  QFontMetricsF sectionMetrics ( sectionFont );  QFontMetricsF metrics ( font );  if ( plotStyle() == QgsComposition::Postscript) //do we need seperate PostScript rendering settings?  {    // Fonts sizes for Postscript rendering    double psTitleSize = titleMetrics.ascent() * 72.0 / mComposition->resolution(); //What??    double psSectionSize = sectionMetrics.ascent() * 72.0 / mComposition->resolution();    double psSize = metrics.ascent() * 72.0 / mComposition->resolution();    titleFont.setPointSizeFloat ( psTitleSize * FONT_WORKAROUND_SCALE );    sectionFont.setPointSizeFloat ( psSectionSize * FONT_WORKAROUND_SCALE );    font.setPointSizeFloat ( psSize * FONT_WORKAROUND_SCALE );  }  else  {    titleFont.setPointSizeFloat ( titleSize * FONT_WORKAROUND_SCALE );    sectionFont.setPointSizeFloat ( sectionSize * FONT_WORKAROUND_SCALE );    font.setPointSizeFloat ( size * FONT_WORKAROUND_SCALE );  }  double x, y;  // Legend title  -if we do this later, we can center it  y = mMargin + titleMetrics.height();  painter->setPen ( mPen );  painter->setFont ( titleFont );  painter->save(); //Save the painter state so we can undo the scaling later  painter->scale(1./FONT_WORKAROUND_SCALE, 1./FONT_WORKAROUND_SCALE); //scale the painter to work around the font bug  painter->drawText( QPointF(2 * mMargin * FONT_WORKAROUND_SCALE, y * FONT_WORKAROUND_SCALE), mTitle );  painter->restore();  //used to keep track of total width and height   double width = 4 * mMargin + titleMetrics.width ( mTitle );   double height = mMargin + mSymbolSpace + titleMetrics.height(); // mSymbolSpace?  // Layers  QgsComposerMap *map = mComposition->map ( mMap ); //Get the map from the composition by ID number  if ( map ) {     std::map<int,int> doneGroups;          int nlayers = mMapCanvas->layerCount();    for ( int i = nlayers - 1; i >= 0; i-- ) {      QgsMapLayer *layer = mMapCanvas->getZpos(i);//      if ( !layer->visible() ) continue; // skip non-visible layers      if ( layer->type() != QgsMapLayer::VECTOR ) continue; //skip raster layers      QString layerId = layer->getLayerID();//      if( ! layerOn(layerId) ) continue; //does this need to go away?      int group = layerGroup ( layerId );      if ( group > 0 ) {         if ( doneGroups.find(group) != doneGroups.end() ) {          continue;         } else {          doneGroups.insert(std::make_pair(group,1));        }      }      // Make list of all layers in the group and count section items      std::vector<int> groupLayers; // vector of layers      std::vector<double> itemHeights; // maximum item sizes      std::vector<QString> itemLabels; // item labels      int sectionItemsCount = 0;      QString sectionTitle;      for ( int j = nlayers - 1; j >= 0; j-- )      {        QgsMapLayer *layer2 = mMapCanvas->getZpos(j);//        if ( !layer2->visible() ) continue;        if ( layer2->type() != QgsMapLayer::VECTOR ) continue;	              QString layerId2 = layer2->getLayerID();        if( ! layerOn(layerId2) ) continue;	            int group2 = layerGroup ( layerId2 );	            QgsVectorLayer *vector = dynamic_cast <QgsVectorLayer*> (layer2);        const QgsRenderer *renderer = vector->renderer();        if ( (group > 0 && group2 == group) || ( group == 0 && j == i )  ) {          groupLayers.push_back(j);          QList<QgsSymbol*> symbols = renderer->symbols();          if ( sectionTitle.length() == 0 ) {            sectionTitle = layer2->name();          }        		            if ( symbols.size() > sectionItemsCount ) {            sectionItemsCount = symbols.size();            itemHeights.resize(sectionItemsCount);            itemLabels.resize(sectionItemsCount);           }          double widthScale = map->widthScale() * mComposition->scale();          if ( plotStyle() == QgsComposition::Preview && mPreviewMode == Render ) {            widthScale *= mComposition->viewScale();          }		          double scale = map->symbolScale() * mComposition->scale();          int icnt = 0;          for ( QList<QgsSymbol*>::iterator it = symbols.begin(); it != symbols.end(); ++it ) {		            QgsSymbol* sym = (*it);	                  // height            if ( itemHeights[icnt] < mSymbolHeight ) { // init first              itemHeights[icnt] = mSymbolHeight;            }            QPixmap pic = QPixmap::fromImage(sym->getPointSymbolAsImage(widthScale, false));            double h = scale * pic.height();            if ( h > itemHeights[icnt] ) {              itemHeights[icnt] = h;            }            if ( itemLabels[icnt].length() == 0 ) {              if ( sym->label().length() > 0 ) {		            itemLabels[icnt] = sym->label();              } else {		            itemLabels[icnt] = sym->lowerValue();                if (sym->upperValue().length() > 0)                  itemLabels[icnt] += " - " + sym->upperValue();              }            }		              icnt++;          }        }      }      //std::cout << "group size = " << groupLayers.size() << std::endl;      //std::cout << "sectionItemsCount = " << sectionItemsCount << std::endl;      // Section title       if ( sectionItemsCount > 1 )      {        height += mSymbolSpace;        x = 2*mMargin;        y = height + sectionMetrics.height();        painter->setPen ( mPen );        painter->setFont ( sectionFont );        painter->save(); //Save the painter state so we can undo the scaling later        painter->scale(1./FONT_WORKAROUND_SCALE, 1./FONT_WORKAROUND_SCALE); //scale the painter to work around the font bug        painter->drawText(QPointF(x * FONT_WORKAROUND_SCALE, y * FONT_WORKAROUND_SCALE), sectionTitle );        painter->restore();        double w = 3*mMargin + sectionMetrics.width( sectionTitle );        if ( w > width ) width = w;        height += sectionMetrics.height();        height += (1.5*mSymbolSpace);      }      // Draw all layers in group       double groupStartHeight = height;      for ( int j = groupLayers.size()-1; j >= 0; j-- )      {	    std::cout << "layer = " << groupLayers[j] << std::endl;	    double localHeight = groupStartHeight;		    layer = mMapCanvas->getZpos(groupLayers[j]);	    QgsVectorLayer *vector = dynamic_cast <QgsVectorLayer*> (layer);	    const QgsRenderer *renderer = vector->renderer();	    // Get a list of the symbols from the renderer - some renderers can have several symbols	    QList<QgsSymbol*> symbols = renderer->symbols();	    int icnt = 0;	    for ( QList<QgsSymbol*>::iterator it = symbols.begin(); it != symbols.end(); ++it ) {          localHeight += mSymbolSpace;          double symbolHeight = itemHeights[icnt];          QgsSymbol* sym = (*it);	              QPen pen = sym->pen();          double widthScale = map->widthScale();          pen.setWidthF( ( widthScale * pen.widthF() ) );          pen.setCapStyle(Qt::FlatCap); //make sure that the line doesn't extend past its endpoints          painter->setPen ( pen );          painter->setBrush ( sym->brush() );	              if ( vector->vectorType() == QGis::Point ) {            double scale = map->symbolScale();            // Get the picture of appropriate size directly from catalogue            QPixmap pic = QPixmap::fromImage(sym->getPointSymbolAsImage(widthScale,false,sym->color()));            painter->save();            painter->scale(scale,scale);            painter->drawPixmap ( static_cast<int>( (1.*mMargin+mSymbolWidth/2)/scale-pic.width()/2),                                  static_cast<int>( (1.*localHeight+symbolHeight/2)/scale-1.*pic.height()/2),                                  pic );            painter->restore();          } else if ( vector->vectorType() == QGis::Line ) {            painter->drawLine (QPointF(mMargin, localHeight+mSymbolHeight/2),                                QPointF(mMargin+mSymbolWidth, localHeight+mSymbolHeight/2));          } else if ( vector->vectorType() == QGis::Polygon ) {            pen.setCapStyle(Qt::FlatCap);            painter->setPen ( pen );            painter->drawRect (QRectF(mMargin, localHeight, mSymbolWidth, mSymbolHeight));          }          // Label           painter->setPen ( mPen );          painter->setFont ( font );          QString lab;          if ( sectionItemsCount == 1 ) {            lab = sectionTitle;          } else {             lab = itemLabels[icnt];          }	              // drawText (x, y w, h, ...) was cutting last letter (the box was too small)          QRectF br = metrics.boundingRect ( lab );          x = 2*mMargin + mSymbolWidth;          y = localHeight + symbolHeight/2 + ( metrics.height()/2 - metrics.descent());          painter->save(); //Save the painter state so we can undo the scaling later          painter->scale(1./FONT_WORKAROUND_SCALE, 1./FONT_WORKAROUND_SCALE);//scale the painter to work around the font bug          painter->drawText(QPointF(x * FONT_WORKAROUND_SCALE, y * FONT_WORKAROUND_SCALE), lab );          painter->restore();          double w = 3*mMargin + mSymbolWidth + metrics.width(lab);          if ( w > width ) width = w;          localHeight += symbolHeight;          icnt++;	    }//End of iterating through the symbols in the renderer      }      // add height of section items to the total height      height = groupStartHeight;      for ( int j = 0; j < (int)itemHeights.size(); j++ ) {	    height += mSymbolSpace + itemHeights[j];      }      if ( sectionItemsCount > 1 ) { // add more space to separate section from next item        height += mSymbolSpace;      }     }//End of iterating through the layers  }//END if(map)  height += mMargin;  if(mFrame)  {    QPen pen(QColor(0,0,0), 0.5);    painter->setPen( pen );    painter->setBrush( QBrush( QColor(255,255,255), Qt::NoBrush));    painter->setRenderHint(QPainter::Antialiasing, true);//turn on antialiasing    painter->drawRect(QRectF(0, 0, width, height));  }    //  QGraphicsRectItem::setRect(0, 0, width, height); //BUG! - calling this causes a re-draw, which means we are continuously re-drawing.      if ( !p ) {    delete painter;    delete pixmap;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -