📄 qgscomposerscalebar.cpp
字号:
/*************************************************************************** qgscomposerscalebar.cpp ------------------- begin : March 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 "qgscomposerscalebar.h"#include "qgscomposermap.h"#include "qgsproject.h"#include <QFontDialog>#include <QPainter>#include <QGraphicsScene>#include <cmath>#include <iostream>//can we/should we remove the x and y parameters?QgsComposerScalebar::QgsComposerScalebar ( QgsComposition *composition, int id, int x, int y ) : QWidget(composition), QAbstractGraphicsShapeItem(0), mComposition(composition), mMap(0), mBrush(QColor(150,150,150)){ setupUi(this); std::cout << "QgsComposerScalebar::QgsComposerScalebar()" << std::endl; mId = id; mSelected = false; mMapCanvas = mComposition->mapCanvas(); QAbstractGraphicsShapeItem::setPos(x, y); init(); // Set map to the first available if any std::vector < QgsComposerMap * >maps = mComposition->maps(); if (maps.size() > 0) { mMap = maps[0]->id(); } // Set default according to the map QgsComposerMap *map = mComposition->map(mMap); if (map) { mMapUnitsPerUnit = 1.; mUnitLabel = "m"; // make one segment cca 1/10 of map width and it will be 1xxx, 2xxx or 5xxx double mapwidth = 1. * map->QGraphicsRectItem::rect().width() / map->scale(); mSegmentLength = mapwidth / 10; int powerOf10 = int (pow(10.0, int (log(mSegmentLength) / log(10.0)))); // from scalebar plugin int isize = (int) ceil(mSegmentLength / powerOf10); if (isize == 3) isize = 2; else if (isize == 4) isize = 5; else if (isize > 5 && isize < 8) isize = 5; else if (isize > 7) isize = 10; mSegmentLength = isize * powerOf10; // the scale bar will take cca 1/4 of the map width // But always have at least one segment. mNumSegments = std::max(1, (int) (mapwidth / 4 / mSegmentLength)); int segsize = (int) (mSegmentLength * map->scale()); int fontsize = segsize / 3; if(fontsize < 6) { fontsize = 6; } mFont.setPointSize(fontsize); } else { mFont.setPointSize(6); mMapUnitsPerUnit = 1.; mUnitLabel = "m"; mSegmentLength = 1000.; mNumSegments = 5; } // Calc size recalculate(); // Add to scene mComposition->canvas()->addItem(this); QAbstractGraphicsShapeItem::show(); QAbstractGraphicsShapeItem::update(); writeSettings();}QgsComposerScalebar::QgsComposerScalebar ( QgsComposition *composition, int id ) : QAbstractGraphicsShapeItem(0), mComposition(composition), mMap(0), mBrush(QColor(150,150,150)){ std::cout << "QgsComposerScalebar::QgsComposerScalebar()" << std::endl; setupUi(this); mId = id; mSelected = false; mMapCanvas = mComposition->mapCanvas(); init(); readSettings(); // Calc size recalculate(); // Add to scene mComposition->canvas()->addItem(this); QAbstractGraphicsShapeItem::show(); QAbstractGraphicsShapeItem::update();}void QgsComposerScalebar::init(void){ mUnitLabel = "m"; // Rectangle QAbstractGraphicsShapeItem::setZValue(50);// setActive(true); // Default value (map units?) for the scalebar border mPen.setWidthF(.5); // Plot style setPlotStyle(QgsComposition::Preview); connect(mComposition, SIGNAL(mapChanged(int)), this, SLOT(mapChanged(int)));}QgsComposerScalebar::~QgsComposerScalebar(){ std::cerr << "QgsComposerScalebar::~QgsComposerScalebar()" << std::endl; QGraphicsItem::hide();}#define FONT_WORKAROUND_SCALE 10QRectF QgsComposerScalebar::render(QPainter * p){#ifdef QGISDEBUG std::cout << "QgsComposerScalebar::render() "<< std::endl;#endif // Painter can be 0, create dummy to avoid many if below QPainter *painter; QPixmap *pixmap=NULL; if (p) { painter = p; }else { pixmap = new QPixmap(1, 1); painter = new QPainter(pixmap); }#ifdef QGISDEBUG std::cout << "mComposition->scale() = " << mComposition->scale() << std::endl;#endif QgsComposerMap *map = mComposition->map(mMap); //Get the topmost map from the composition double segwidth; if(map) { segwidth = (mSegmentLength * map->scale()); //width of one segment } else //if there is no map, make up a segment width { segwidth = mSegmentLength/100; } double width = (segwidth * mNumSegments); //width of whole scalebar double barLx = -width / 2; //x offset to the left double barHeight = (25.4 * mComposition->scale() * mFont.pointSize() / 72); double tickSize = barHeight * 1.5; //ticks go from the base of the bar to 1/2 the bar's height above it // Draw background rectangle painter->setPen(QPen(QColor(255, 255, 255), 0)); painter->setBrush(QBrush(QColor(255, 255, 255), Qt::SolidPattern)); painter->drawRect(QRectF(barLx, -barHeight, width, barHeight)); // set the painter to have grey background and black border painter->setPen(QPen(QColor(0, 0, 0), mPen.widthF())); painter->setBrush(QBrush(QColor(127, 127, 127)));//default to solid brush // fill every other segment with grey for (int i = 0; i < mNumSegments; i += 2) { painter->drawRect(QRectF(barLx + ((double)i * segwidth), -barHeight, segwidth, barHeight)); } // draw a box around the all of the segments painter->setBrush(Qt::NoBrush); painter->drawRect(QRectF(barLx, -barHeight, width, barHeight)); // set up the pen to draw the tick marks painter->setPen(QPen(QColor(0, 0, 0), mPen.widthF())); // draw the tick marks for (int i = 0; i <= mNumSegments; i++) { painter->drawLine(QLineF(barLx + ((double)i * segwidth), 0, barLx + (i * segwidth), -tickSize)); } // labels // Font size in canvas units float size = 25.4 * mComposition->scale() * mFont.pointSizeFloat() / 72; // Create QFontMetrics so we can correctly place the text QFont font(mFont); font.setPointSizeFloat(size); QFontMetrics metrics(font); font.setPointSizeFloat(size * FONT_WORKAROUND_SCALE); //hack to work around Qt font bug if (plotStyle() == QgsComposition::Postscript) { font.setPointSizeF(metrics.ascent() * 72.0 / mComposition->resolution() * FONT_WORKAROUND_SCALE); } painter->setFont(font); // Not sure about Style Strategy, QFont::PreferMatch? font.setStyleStrategy((QFont::StyleStrategy) (QFont::PreferOutline | QFont::PreferAntialias)); double offset = .5 * tickSize; //vertical offset above the top of the tick marks double textRightOverhang=0;//amount the label text hangs over the right edge of the scalebar - used for the bounding box for (int i = 0; i <= mNumSegments; i++) { int lab = (int) ((double)i * mSegmentLength / mMapUnitsPerUnit); QString txt = QString::number(lab); double shift = (double)metrics.width(txt) / 2; if (i == mNumSegments) //on the last label, append the appropriate unit symbol { txt.append(" " + mUnitLabel); textRightOverhang = (double)metrics.width(txt) - shift; } double x = barLx + (i * segwidth) - shift; //figure out the bottom left corner and draw the text double y = -tickSize - offset - metrics.descent(); painter->save(); painter->scale(1./FONT_WORKAROUND_SCALE, 1./FONT_WORKAROUND_SCALE); painter->drawText(QPointF(x * FONT_WORKAROUND_SCALE, y * FONT_WORKAROUND_SCALE), txt); painter->restore(); }//end of label drawing double totalHeight = tickSize + offset + metrics.height();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -