Branch data Line data Source code
1 : : /*************************************************************************** 2 : : qgslayoutitempolygon.cpp 3 : : begin : March 2016 4 : : copyright : (C) 2016 Paul Blottiere, Oslandia 5 : : email : paul dot blottiere at oslandia dot com 6 : : ***************************************************************************/ 7 : : 8 : : /*************************************************************************** 9 : : * * 10 : : * This program is free software; you can redistribute it and/or modify * 11 : : * it under the terms of the GNU General Public License as published by * 12 : : * the Free Software Foundation; either version 2 of the License, or * 13 : : * (at your option) any later version. * 14 : : * * 15 : : ***************************************************************************/ 16 : : 17 : : #include "qgslayoutitempolygon.h" 18 : : #include "qgslayoutitemregistry.h" 19 : : #include "qgslayoututils.h" 20 : : #include "qgslayout.h" 21 : : #include "qgspathresolver.h" 22 : : #include "qgsreadwritecontext.h" 23 : : #include "qgssymbollayerutils.h" 24 : : #include "qgssymbol.h" 25 : : #include "qgsmapsettings.h" 26 : : #include "qgsstyleentityvisitor.h" 27 : : 28 : : #include <limits> 29 : : 30 : 0 : QgsLayoutItemPolygon::QgsLayoutItemPolygon( QgsLayout *layout ) 31 : 0 : : QgsLayoutNodesItem( layout ) 32 : 0 : { 33 : 0 : createDefaultPolygonStyleSymbol(); 34 : 0 : } 35 : : 36 : 0 : QgsLayoutItemPolygon::QgsLayoutItemPolygon( const QPolygonF &polygon, QgsLayout *layout ) 37 : 0 : : QgsLayoutNodesItem( polygon, layout ) 38 : 0 : { 39 : 0 : createDefaultPolygonStyleSymbol(); 40 : 0 : } 41 : : 42 : 0 : QgsLayoutItemPolygon *QgsLayoutItemPolygon::create( QgsLayout *layout ) 43 : : { 44 : 0 : return new QgsLayoutItemPolygon( layout ); 45 : 0 : } 46 : : 47 : 0 : int QgsLayoutItemPolygon::type() const 48 : : { 49 : 0 : return QgsLayoutItemRegistry::LayoutPolygon; 50 : : } 51 : : 52 : 0 : QIcon QgsLayoutItemPolygon::icon() const 53 : : { 54 : 0 : return QgsApplication::getThemeIcon( QStringLiteral( "/mLayoutItemPolygon.svg" ) ); 55 : 0 : } 56 : : 57 : 0 : bool QgsLayoutItemPolygon::_addNode( const int indexPoint, 58 : : QPointF newPoint, 59 : : const double radius ) 60 : : { 61 : : Q_UNUSED( radius ) 62 : 0 : mPolygon.insert( indexPoint + 1, newPoint ); 63 : 0 : return true; 64 : : } 65 : : 66 : 0 : void QgsLayoutItemPolygon::createDefaultPolygonStyleSymbol() 67 : : { 68 : 0 : QVariantMap properties; 69 : 0 : properties.insert( QStringLiteral( "color" ), QStringLiteral( "white" ) ); 70 : 0 : properties.insert( QStringLiteral( "style" ), QStringLiteral( "solid" ) ); 71 : 0 : properties.insert( QStringLiteral( "style_border" ), QStringLiteral( "solid" ) ); 72 : 0 : properties.insert( QStringLiteral( "color_border" ), QStringLiteral( "black" ) ); 73 : 0 : properties.insert( QStringLiteral( "width_border" ), QStringLiteral( "0.3" ) ); 74 : 0 : properties.insert( QStringLiteral( "joinstyle" ), QStringLiteral( "miter" ) ); 75 : : 76 : 0 : mPolygonStyleSymbol.reset( QgsFillSymbol::createSimple( properties ) ); 77 : : 78 : 0 : refreshSymbol(); 79 : 0 : } 80 : : 81 : 0 : void QgsLayoutItemPolygon::refreshSymbol() 82 : : { 83 : 0 : if ( auto *lLayout = layout() ) 84 : : { 85 : 0 : QgsRenderContext rc = QgsLayoutUtils::createRenderContextForLayout( lLayout, nullptr, lLayout->renderContext().dpi() ); 86 : 0 : mMaxSymbolBleed = ( 25.4 / lLayout->renderContext().dpi() ) * QgsSymbolLayerUtils::estimateMaxSymbolBleed( mPolygonStyleSymbol.get(), rc ); 87 : 0 : } 88 : : 89 : 0 : updateSceneRect(); 90 : : 91 : 0 : emit frameChanged(); 92 : 0 : } 93 : : 94 : 0 : QString QgsLayoutItemPolygon::displayName() const 95 : : { 96 : 0 : if ( !id().isEmpty() ) 97 : 0 : return id(); 98 : : 99 : 0 : return tr( "<Polygon>" ); 100 : 0 : } 101 : : 102 : 0 : bool QgsLayoutItemPolygon::accept( QgsStyleEntityVisitorInterface *visitor ) const 103 : : { 104 : 0 : if ( mPolygonStyleSymbol ) 105 : : { 106 : 0 : QgsStyleSymbolEntity entity( mPolygonStyleSymbol.get() ); 107 : 0 : if ( !visitor->visit( QgsStyleEntityVisitorInterface::StyleLeaf( &entity, uuid(), displayName() ) ) ) 108 : 0 : return false; 109 : 0 : } 110 : : 111 : 0 : return true; 112 : 0 : } 113 : : 114 : 0 : QgsLayoutItem::Flags QgsLayoutItemPolygon::itemFlags() const 115 : : { 116 : 0 : QgsLayoutItem::Flags flags = QgsLayoutNodesItem::itemFlags(); 117 : 0 : flags |= QgsLayoutItem::FlagProvidesClipPath; 118 : 0 : return flags; 119 : : } 120 : : 121 : 0 : QgsGeometry QgsLayoutItemPolygon::clipPath() const 122 : : { 123 : 0 : QPolygonF path = mapToScene( mPolygon ); 124 : : // ensure polygon is closed 125 : 0 : if ( path.at( 0 ) != path.constLast() ) 126 : 0 : path << path.at( 0 ); 127 : 0 : return QgsGeometry::fromQPolygonF( path ); 128 : 0 : } 129 : : 130 : 0 : void QgsLayoutItemPolygon::_draw( QgsLayoutItemRenderContext &context, const QStyleOptionGraphicsItem * ) 131 : : { 132 : : //setup painter scaling to dots so that raster symbology is drawn to scale 133 : 0 : double scale = context.renderContext().convertToPainterUnits( 1, QgsUnitTypes::RenderMillimeters ); 134 : 0 : QTransform t = QTransform::fromScale( scale, scale ); 135 : : 136 : 0 : QVector<QPolygonF> rings; //empty 137 : 0 : QPainterPath polygonPath; 138 : 0 : polygonPath.addPolygon( mPolygon ); 139 : : 140 : 0 : mPolygonStyleSymbol->startRender( context.renderContext() ); 141 : 0 : mPolygonStyleSymbol->renderPolygon( polygonPath.toFillPolygon( t ), &rings, 142 : 0 : nullptr, context.renderContext() ); 143 : 0 : mPolygonStyleSymbol->stopRender( context.renderContext() ); 144 : 0 : } 145 : : 146 : 0 : void QgsLayoutItemPolygon::_readXmlStyle( const QDomElement &elmt, const QgsReadWriteContext &context ) 147 : : { 148 : 0 : mPolygonStyleSymbol.reset( QgsSymbolLayerUtils::loadSymbol<QgsFillSymbol>( elmt, context ) ); 149 : 0 : } 150 : : 151 : 0 : void QgsLayoutItemPolygon::setSymbol( QgsFillSymbol *symbol ) 152 : : { 153 : 0 : mPolygonStyleSymbol.reset( static_cast<QgsFillSymbol *>( symbol->clone() ) ); 154 : 0 : refreshSymbol(); 155 : 0 : } 156 : : 157 : 0 : void QgsLayoutItemPolygon::_writeXmlStyle( QDomDocument &doc, QDomElement &elmt, const QgsReadWriteContext &context ) const 158 : : { 159 : 0 : const QDomElement pe = QgsSymbolLayerUtils::saveSymbol( QString(), 160 : 0 : mPolygonStyleSymbol.get(), 161 : 0 : doc, 162 : 0 : context ); 163 : 0 : elmt.appendChild( pe ); 164 : 0 : } 165 : : 166 : 0 : bool QgsLayoutItemPolygon::_removeNode( const int index ) 167 : : { 168 : 0 : if ( index < 0 || index >= mPolygon.size() ) 169 : 0 : return false; 170 : : 171 : 0 : mPolygon.remove( index ); 172 : : 173 : 0 : if ( mPolygon.size() < 3 ) 174 : 0 : mPolygon.clear(); 175 : : else 176 : : { 177 : 0 : int newSelectNode = index; 178 : 0 : if ( index == mPolygon.size() ) 179 : 0 : newSelectNode = 0; 180 : 0 : setSelectedNode( newSelectNode ); 181 : : } 182 : : 183 : 0 : return true; 184 : 0 : }