From 1535ff84ffb2a16678e96cbf1cfc98e7a00477ff Mon Sep 17 00:00:00 2001 From: Nyall Dawson Date: Thu, 16 Nov 2017 14:44:17 +1000 Subject: [PATCH 1/3] [dxf][feature] Add option to export labels as text elements, instead of mtext Sponsored by SMEC --- python/core/dxf/qgsdxfexport.sip | 25 +++++ src/app/qgisapp.cpp | 6 ++ src/app/qgsdxfexportdialog.cpp | 10 +- src/app/qgsdxfexportdialog.h | 1 + src/core/dxf/qgsdxfexport.cpp | 57 +++++++---- src/core/dxf/qgsdxfexport.h | 32 +++++- src/ui/qgsdxfexportdialogbase.ui | 166 ++++++++++++++++++------------- 7 files changed, 202 insertions(+), 95 deletions(-) mode change 100644 => 100755 src/app/qgsdxfexportdialog.h mode change 100644 => 100755 src/core/dxf/qgsdxfexport.cpp mode change 100644 => 100755 src/ui/qgsdxfexportdialogbase.ui diff --git a/python/core/dxf/qgsdxfexport.sip b/python/core/dxf/qgsdxfexport.sip index 1aaf32aa792..e0a120c7560 100644 --- a/python/core/dxf/qgsdxfexport.sip +++ b/python/core/dxf/qgsdxfexport.sip @@ -27,6 +27,13 @@ class QgsDxfExport SymbolLayerSymbology }; + enum Flag + { + FlagNoMText, + }; + typedef QFlags Flags; + + QgsDxfExport(); %Docstring Constructor for QgsDxfExport. @@ -38,6 +45,21 @@ class QgsDxfExport \param settings map settings to apply %End + void setFlags( QgsDxfExport::Flags flags ); +%Docstring + Sets the export flags. +.. versionadded:: 3.0 +.. seealso:: flags() +%End + + QgsDxfExport::Flags flags() const; +%Docstring + Returns the export flags. +.. versionadded:: 3.0 +.. seealso:: setFlags() + :rtype: QgsDxfExport.Flags +%End + void addLayers( const QList< QPair > &layers ); %Docstring Add layers to export @@ -342,6 +364,9 @@ return list of available DXF encodings }; +QFlags operator|(QgsDxfExport::Flag f1, QFlags f2); + + /************************************************************************ * This file has been generated automatically from * * * diff --git a/src/app/qgisapp.cpp b/src/app/qgisapp.cpp index f0d08cdd3a2..ca94804c47c 100644 --- a/src/app/qgisapp.cpp +++ b/src/app/qgisapp.cpp @@ -5700,6 +5700,12 @@ void QgisApp::dxfExport() dxfExport.setLayerTitleAsName( d.layerTitleAsName() ); dxfExport.setDestinationCrs( d.crs() ); dxfExport.setForce2d( d.force2d() ); + + QgsDxfExport::Flags flags = 0; + if ( !d.useMText() ) + flags = flags | QgsDxfExport::FlagNoMText; + dxfExport.setFlags( flags ); + if ( mapCanvas() ) { //extent diff --git a/src/app/qgsdxfexportdialog.cpp b/src/app/qgsdxfexportdialog.cpp index c815bb90de4..83bb294bd90 100644 --- a/src/app/qgsdxfexportdialog.cpp +++ b/src/app/qgsdxfexportdialog.cpp @@ -458,6 +458,7 @@ QgsDxfExportDialog::QgsDxfExportDialog( QWidget *parent, Qt::WindowFlags f ) mScaleWidget->setScale( 1.0 / oldScale ); mLayerTitleAsName->setChecked( QgsProject::instance()->readEntry( QStringLiteral( "dxf" ), QStringLiteral( "/lastDxfLayerTitleAsName" ), s.value( QStringLiteral( "qgis/lastDxfLayerTitleAsName" ), "false" ).toString() ) != QLatin1String( "false" ) ); mMapExtentCheckBox->setChecked( QgsProject::instance()->readEntry( QStringLiteral( "dxf" ), QStringLiteral( "/lastDxfMapRectangle" ), s.value( QStringLiteral( "qgis/lastDxfMapRectangle" ), "false" ).toString() ) != QLatin1String( "false" ) ); + mMTextCheckBox->setChecked( QgsProject::instance()->readEntry( QStringLiteral( "dxf" ), QStringLiteral( "/lastDxfUseMText" ), s.value( QStringLiteral( "qgis/lastDxfUseMText" ), "true" ).toString() ) != QLatin1String( "false" ) ); QStringList ids = QgsProject::instance()->mapThemeCollection()->mapThemes(); ids.prepend( QLatin1String( "" ) ); @@ -608,7 +609,12 @@ bool QgsDxfExportDialog::layerTitleAsName() const bool QgsDxfExportDialog::force2d() const { - return mForce2d->isChecked(); + return mForce2d->isChecked(); +} + +bool QgsDxfExportDialog::useMText() const +{ + return mMTextCheckBox->isChecked(); } void QgsDxfExportDialog::saveSettings() @@ -622,6 +628,7 @@ void QgsDxfExportDialog::saveSettings() s.setValue( QStringLiteral( "qgis/lastDxfLayerTitleAsName" ), mLayerTitleAsName->isChecked() ); s.setValue( QStringLiteral( "qgis/lastDxfEncoding" ), mEncoding->currentText() ); s.setValue( QStringLiteral( "qgis/lastDxfCrs" ), QString::number( mCRS.srsid() ) ); + s.setValue( QStringLiteral( "qgis/lastDxfUseMText" ), mMTextCheckBox->isChecked() ); QgsProject::instance()->writeEntry( QStringLiteral( "dxf" ), QStringLiteral( "/lastDxfSymbologyMode" ), mSymbologyModeComboBox->currentIndex() ); QgsProject::instance()->writeEntry( QStringLiteral( "dxf" ), QStringLiteral( "/lastSymbologyExportScale" ), mScaleWidget->scale() != 0 ? 1.0 / mScaleWidget->scale() : 0 ); @@ -630,6 +637,7 @@ void QgsDxfExportDialog::saveSettings() QgsProject::instance()->writeEntry( QStringLiteral( "dxf" ), QStringLiteral( "/lastDxfEncoding" ), mEncoding->currentText() ); QgsProject::instance()->writeEntry( QStringLiteral( "dxf" ), QStringLiteral( "/lastVisibilityPreset" ), mVisibilityPresets->currentText() ); QgsProject::instance()->writeEntry( QStringLiteral( "dxf" ), QStringLiteral( "/lastDxfCrs" ), QString::number( mCRS.srsid() ) ); + QgsProject::instance()->writeEntry( QStringLiteral( "dxf" ), QStringLiteral( "/lastDxfUseMText" ), mMTextCheckBox->isChecked() ); } diff --git a/src/app/qgsdxfexportdialog.h b/src/app/qgsdxfexportdialog.h old mode 100644 new mode 100755 index 2841f5c6e5a..0b03fa9b051 --- a/src/app/qgsdxfexportdialog.h +++ b/src/app/qgsdxfexportdialog.h @@ -88,6 +88,7 @@ class QgsDxfExportDialog : public QDialog, private Ui::QgsDxfExportDialogBase bool exportMapExtent() const; bool layerTitleAsName() const; bool force2d() const; + bool useMText() const; QString mapTheme() const; QString encoding() const; QgsCoordinateReferenceSystem crs() const; diff --git a/src/core/dxf/qgsdxfexport.cpp b/src/core/dxf/qgsdxfexport.cpp old mode 100644 new mode 100755 index 6237283ea09..1a4425b8ec3 --- a/src/core/dxf/qgsdxfexport.cpp +++ b/src/core/dxf/qgsdxfexport.cpp @@ -389,6 +389,16 @@ void QgsDxfExport::setMapSettings( const QgsMapSettings &settings ) mMapSettings = settings; } +void QgsDxfExport::setFlags( QgsDxfExport::Flags flags ) +{ + mFlags = flags; +} + +QgsDxfExport::Flags QgsDxfExport::flags() const +{ + return mFlags; +} + void QgsDxfExport::addLayers( const QList< QPair< QgsVectorLayer *, int > > &layers ) { QList layerList; @@ -3633,6 +3643,7 @@ void QgsDxfExport::writeText( const QString &layer, const QString &text, const Q writeGroup( 1, text ); writeGroup( 50, angle ); writeGroup( 7, QStringLiteral( "STANDARD" ) ); // so far only support for standard font + writeGroup( 100, QStringLiteral( "AcDbText" ) ); } void QgsDxfExport::writeMText( const QString &layer, const QString &text, const QgsPoint &pt, double width, double angle, const QColor &color ) @@ -4400,30 +4411,36 @@ void QgsDxfExport::drawLabel( const QString &layerId, QgsRenderContext &context, } } - txt = txt.replace( wrapchr, QLatin1String( "\\P" ) ); - - if ( tmpLyr.format().font().underline() ) + if ( mFlags & FlagNoMText ) { - txt.prepend( "\\L" ).append( "\\l" ); + writeText( dxfLayer, txt, QgsPoint( label->getX(), label->getY() ), label->getHeight(), label->getAlpha() * 180.0 / M_PI, tmpLyr.format().color() ); } - - if ( tmpLyr.format().font().overline() ) + else { - txt.prepend( "\\O" ).append( "\\o" ); + txt = txt.replace( wrapchr, QLatin1String( "\\P" ) ); + + if ( tmpLyr.format().font().underline() ) + { + txt.prepend( "\\L" ).append( "\\l" ); + } + + if ( tmpLyr.format().font().overline() ) + { + txt.prepend( "\\O" ).append( "\\o" ); + } + + if ( tmpLyr.format().font().strikeOut() ) + { + txt.prepend( "\\K" ).append( "\\k" ); + } + + txt.prepend( QStringLiteral( "\\f%1|i%2|b%3;\\H%4;" ) + .arg( tmpLyr.format().font().family() ) + .arg( tmpLyr.format().font().italic() ? 1 : 0 ) + .arg( tmpLyr.format().font().bold() ? 1 : 0 ) + .arg( label->getHeight() / ( 1 + txt.count( QStringLiteral( "\\P" ) ) ) * 0.75 ) ); + writeMText( dxfLayer, txt, QgsPoint( label->getX(), label->getY() ), label->getWidth(), label->getAlpha() * 180.0 / M_PI, tmpLyr.format().color() ); } - - if ( tmpLyr.format().font().strikeOut() ) - { - txt.prepend( "\\K" ).append( "\\k" ); - } - - txt.prepend( QStringLiteral( "\\f%1|i%2|b%3;\\H%4;" ) - .arg( tmpLyr.format().font().family() ) - .arg( tmpLyr.format().font().italic() ? 1 : 0 ) - .arg( tmpLyr.format().font().bold() ? 1 : 0 ) - .arg( label->getHeight() / ( 1 + txt.count( QStringLiteral( "\\P" ) ) ) * 0.75 ) ); - - writeMText( dxfLayer, txt, QgsPoint( label->getX(), label->getY() ), label->getWidth(), label->getAlpha() * 180.0 / M_PI, tmpLyr.format().color() ); } diff --git a/src/core/dxf/qgsdxfexport.h b/src/core/dxf/qgsdxfexport.h index ee47ca4ecce..08daafe2f31 100644 --- a/src/core/dxf/qgsdxfexport.h +++ b/src/core/dxf/qgsdxfexport.h @@ -53,11 +53,18 @@ class CORE_EXPORT QgsDxfExport public: enum SymbologyExport { - NoSymbology = 0, //export only data - FeatureSymbology, //Keeps the number of features and export symbology per feature (using the first symbol level) - SymbolLayerSymbology //Exports one feature per symbol layer (considering symbol levels) + NoSymbology = 0, //!< Export only data + FeatureSymbology, //!< Keeps the number of features and export symbology per feature (using the first symbol level) + SymbolLayerSymbology //!< Exports one feature per symbol layer (considering symbol levels) }; + //! Export flags + enum Flag + { + FlagNoMText = 1 << 1, //!< Export text as TEXT elements. If not set, text will be exported as MTEXT elements. + }; + Q_DECLARE_FLAGS( Flags, Flag ) + /** * Constructor for QgsDxfExport. */ @@ -71,6 +78,20 @@ class CORE_EXPORT QgsDxfExport */ void setMapSettings( const QgsMapSettings &settings ); + /** + * Sets the export flags. + * \since QGIS 3.0 + * \see flags() + */ + void setFlags( QgsDxfExport::Flags flags ); + + /** + * Returns the export flags. + * \since QGIS 3.0 + * \see setFlags() + */ + QgsDxfExport::Flags flags() const; + /** * Add layers to export * \param layers list of layers and corresponding attribute indexes that determine the layer name (-1 for original layer name or title) @@ -440,6 +461,11 @@ class CORE_EXPORT QgsDxfExport QHash mLayerNameAttribute; double mFactor = 1.0; bool mForce2d = false; + + QgsDxfExport::Flags mFlags = 0; + }; +Q_DECLARE_OPERATORS_FOR_FLAGS( QgsDxfExport::Flags ) + #endif // QGSDXFEXPORT_H diff --git a/src/ui/qgsdxfexportdialogbase.ui b/src/ui/qgsdxfexportdialogbase.ui old mode 100644 new mode 100755 index 4e533d89a78..cf1b4347527 --- a/src/ui/qgsdxfexportdialogbase.ui +++ b/src/ui/qgsdxfexportdialogbase.ui @@ -14,17 +14,10 @@ DXF Export - - + + - Symbology scale - - - - - - - + Symbology mode @@ -35,6 +28,13 @@ + + + + + + + @@ -54,13 +54,16 @@ - - + + - Symbology mode + Symbology scale + + + @@ -81,8 +84,35 @@ - - + + + + Qt::StrongFocus + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Help|QDialogButtonBox::Ok + + + + + + + + + + CRS + + @@ -115,29 +145,13 @@ - - - - - + + - Export features intersecting the current map extent + Encoding - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Help|QDialogButtonBox::Ok - - - - - - @@ -145,40 +159,53 @@ - - - - Encoding - - - - - - - Use layer title as name if set - - - - - - - CRS - - - - - - - Qt::StrongFocus - - - - - - - Force 2d output (eg. to support polyline width) - - + + + + + + Export features intersecting the current map extent + + + + + + + Use layer title as name if set + + + + + + + Force 2d output (eg. to support polyline width) + + + + + + + Export labels as MTEXT elements + + + true + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + @@ -211,9 +238,6 @@ mTreeView mSelectAllButton mDeselectAllButton - mLayerTitleAsName - mMapExtentCheckBox - mForce2d buttonBox From 07e4c57291427504a011ead5e0cf8afa43634ddb Mon Sep 17 00:00:00 2001 From: Nyall Dawson Date: Thu, 16 Nov 2017 15:38:46 +1000 Subject: [PATCH 2/3] Add some unit tests for DXF export --- src/core/dxf/qgsdxfexport.cpp | 4 +- tests/src/core/CMakeLists.txt | 2 + tests/src/core/testqgsdxfexport.cpp | 335 ++++++++++++++++++++++++++++ 3 files changed, 339 insertions(+), 2 deletions(-) mode change 100755 => 100644 src/core/dxf/qgsdxfexport.cpp create mode 100644 tests/src/core/testqgsdxfexport.cpp diff --git a/src/core/dxf/qgsdxfexport.cpp b/src/core/dxf/qgsdxfexport.cpp old mode 100755 new mode 100644 index 1a4425b8ec3..4bf27349322 --- a/src/core/dxf/qgsdxfexport.cpp +++ b/src/core/dxf/qgsdxfexport.cpp @@ -501,7 +501,7 @@ int QgsDxfExport::writeToFile( QIODevice *d, const QString &encoding ) return 1; } - if ( !d->isOpen() && !d->open( QIODevice::WriteOnly ) ) + if ( !d->isOpen() && !d->open( QIODevice::WriteOnly | QIODevice::Truncate ) ) { return 2; } @@ -4413,7 +4413,7 @@ void QgsDxfExport::drawLabel( const QString &layerId, QgsRenderContext &context, if ( mFlags & FlagNoMText ) { - writeText( dxfLayer, txt, QgsPoint( label->getX(), label->getY() ), label->getHeight(), label->getAlpha() * 180.0 / M_PI, tmpLyr.format().color() ); + writeText( dxfLayer, txt, QgsPoint( label->getX(), label->getY() ), label->getHeight(), label->getAlpha() * 180.0 / M_PI, tmpLyr.format().color() ); } else { diff --git a/tests/src/core/CMakeLists.txt b/tests/src/core/CMakeLists.txt index 9efd4b2ad96..f567619e7e7 100755 --- a/tests/src/core/CMakeLists.txt +++ b/tests/src/core/CMakeLists.txt @@ -11,6 +11,7 @@ INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/src/annotations ${CMAKE_SOURCE_DIR}/src/core/auth ${CMAKE_SOURCE_DIR}/src/core/composer + ${CMAKE_SOURCE_DIR}/src/core/dxf ${CMAKE_SOURCE_DIR}/src/core/expression ${CMAKE_SOURCE_DIR}/src/core/geometry ${CMAKE_SOURCE_DIR}/src/core/layout @@ -109,6 +110,7 @@ SET(TESTS testqgsdatasourceuri.cpp testqgsdiagram.cpp testqgsdistancearea.cpp + testqgsdxfexport.cpp testqgsellipsemarker.cpp testqgsexpressioncontext.cpp testqgsexpression.cpp diff --git a/tests/src/core/testqgsdxfexport.cpp b/tests/src/core/testqgsdxfexport.cpp new file mode 100644 index 00000000000..f3de184ddde --- /dev/null +++ b/tests/src/core/testqgsdxfexport.cpp @@ -0,0 +1,335 @@ +/*************************************************************************** + testqgsdxfexport.cpp + -------------------- + Date : November 2017 + Copyright : (C) 2017 by Nyall Dawson + Email : nyall dot dawson at gmail dot com + *************************************************************************** + * * + * 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 "qgstest.h" + +#include "qgsapplication.h" +#include "qgsdxfexport.h" +#include "qgsproject.h" +#include "qgsvectorlayer.h" +#include "qgsfontutils.h" +#include "qgstextrenderer.h" +#include "qgspallabeling.h" +#include "qgslabelingengine.h" +#include "qgsvectorlayerlabeling.h" +#include + +class TestQgsDxfExport : public QObject +{ + Q_OBJECT + public: + TestQgsDxfExport() = default; + + private slots: + void initTestCase(); + void cleanupTestCase(); + void init();// will be called before each testfunction is executed. + void cleanup();// will be called after every testfunction. + void testPoints(); + void testLines(); + void testPolygons(); + void testMtext(); + void testText(); + + private: + QgsVectorLayer *mPointLayer = nullptr; + QgsVectorLayer *mLineLayer = nullptr; + QgsVectorLayer *mPolygonLayer = nullptr; + + QString mReport; + + void setDefaultLabelParams( QgsPalLayerSettings &settings ); + QString getTempFileName( const QString &file ) const; + + bool fileContainsText( const QString &path, const QString &text ) const; +}; + +void TestQgsDxfExport::initTestCase() +{ + QgsApplication::init(); + QgsApplication::initQgis(); + QgsApplication::showSettings(); + QgsFontUtils::loadStandardTestFonts( QStringList() << QStringLiteral( "Bold" ) ); +} + +void TestQgsDxfExport::cleanupTestCase() +{ + QgsApplication::exitQgis(); +} + +void TestQgsDxfExport::init() +{ + QString filename = QStringLiteral( TEST_DATA_DIR ) + "/points.shp"; + mPointLayer = new QgsVectorLayer( filename, QStringLiteral( "points" ), QStringLiteral( "ogr" ) ); + Q_ASSERT( mPointLayer->isValid() ); + QgsProject::instance()->addMapLayer( mPointLayer ); + filename = QStringLiteral( TEST_DATA_DIR ) + "/lines.shp"; + mLineLayer = new QgsVectorLayer( filename, QStringLiteral( "lines" ), QStringLiteral( "ogr" ) ); + Q_ASSERT( mLineLayer->isValid() ); + QgsProject::instance()->addMapLayer( mLineLayer ); + filename = QStringLiteral( TEST_DATA_DIR ) + "/polys.shp"; + mPolygonLayer = new QgsVectorLayer( filename, QStringLiteral( "polygons" ), QStringLiteral( "ogr" ) ); + Q_ASSERT( mPolygonLayer->isValid() ); + QgsProject::instance()->addMapLayer( mPolygonLayer ); +} + +void TestQgsDxfExport::cleanup() +{ + QgsProject::instance()->removeMapLayer( mPointLayer->id() ); + mPointLayer = nullptr; +} + +void TestQgsDxfExport::testPoints() +{ + QgsDxfExport d; + d.addLayers( QList< QPair< QgsVectorLayer *, int > >() << qMakePair( mPointLayer, -1 ) ); + + QgsMapSettings mapSettings; + QSize size( 640, 480 ); + mapSettings.setOutputSize( size ); + mapSettings.setExtent( mPointLayer->extent() ); + mapSettings.setLayers( QList() << mPointLayer ); + mapSettings.setOutputDpi( 96 ); + mapSettings.setDestinationCrs( mPointLayer->crs() ); + + d.setMapSettings( mapSettings ); + d.setSymbologyScale( 1000 ); + + QString file = getTempFileName( "point_dxf" ); + QFile dxfFile( file ); + QCOMPARE( d.writeToFile( &dxfFile, QStringLiteral( "CP1252" ) ), 0 ); + dxfFile.close(); + + // reload and compare + std::unique_ptr< QgsVectorLayer > result = qgis::make_unique< QgsVectorLayer >( file, "dxf" ); + QVERIFY( result->isValid() ); + QCOMPARE( result->featureCount(), mPointLayer->featureCount() ); + QCOMPARE( result->wkbType(), QgsWkbTypes::Point ); +} + +void TestQgsDxfExport::testLines() +{ + QgsDxfExport d; + d.addLayers( QList< QPair< QgsVectorLayer *, int > >() << qMakePair( mLineLayer, -1 ) ); + + QgsMapSettings mapSettings; + QSize size( 640, 480 ); + mapSettings.setOutputSize( size ); + mapSettings.setExtent( mLineLayer->extent() ); + mapSettings.setLayers( QList() << mLineLayer ); + mapSettings.setOutputDpi( 96 ); + mapSettings.setDestinationCrs( mLineLayer->crs() ); + + d.setMapSettings( mapSettings ); + d.setSymbologyScale( 1000 ); + + QString file = getTempFileName( "line_dxf" ); + QFile dxfFile( file ); + QCOMPARE( d.writeToFile( &dxfFile, QStringLiteral( "CP1252" ) ), 0 ); + dxfFile.close(); + + // reload and compare + std::unique_ptr< QgsVectorLayer > result = qgis::make_unique< QgsVectorLayer >( file, "dxf" ); + QVERIFY( result->isValid() ); + QCOMPARE( result->featureCount(), mLineLayer->featureCount() ); + QCOMPARE( result->wkbType(), QgsWkbTypes::LineString ); +} + +void TestQgsDxfExport::testPolygons() +{ + QgsDxfExport d; + d.addLayers( QList< QPair< QgsVectorLayer *, int > >() << qMakePair( mPolygonLayer, -1 ) ); + + QgsMapSettings mapSettings; + QSize size( 640, 480 ); + mapSettings.setOutputSize( size ); + mapSettings.setExtent( mPolygonLayer->extent() ); + mapSettings.setLayers( QList() << mPolygonLayer ); + mapSettings.setOutputDpi( 96 ); + mapSettings.setDestinationCrs( mPolygonLayer->crs() ); + + d.setMapSettings( mapSettings ); + d.setSymbologyScale( 1000 ); + + QString file = getTempFileName( "polygon_dxf" ); + QFile dxfFile( file ); + QCOMPARE( d.writeToFile( &dxfFile, QStringLiteral( "CP1252" ) ), 0 ); + dxfFile.close(); + + // reload and compare + std::unique_ptr< QgsVectorLayer > result = qgis::make_unique< QgsVectorLayer >( file, "dxf" ); + QVERIFY( result->isValid() ); + QCOMPARE( result->featureCount(), 12L ); + QCOMPARE( result->wkbType(), QgsWkbTypes::LineString ); +} + +void TestQgsDxfExport::testMtext() +{ + QgsPalLayerSettings settings; + settings.fieldName = QStringLiteral( "Class" ); + QgsTextFormat format; + format.setFont( QgsFontUtils::getStandardTestFont( QStringLiteral( "Bold" ) ).family() ); + format.setSize( 12 ); + format.setNamedStyle( QStringLiteral( "Bold" ) ); + format.setColor( QColor( 200, 0, 200 ) ); + settings.setFormat( format ); + mPointLayer->setLabeling( new QgsVectorLayerSimpleLabeling( settings ) ); + + QgsDxfExport d; + d.addLayers( QList< QPair< QgsVectorLayer *, int > >() << qMakePair( mPointLayer, -1 ) ); + + QgsMapSettings mapSettings; + QSize size( 640, 480 ); + mapSettings.setOutputSize( size ); + mapSettings.setExtent( mPointLayer->extent() ); + mapSettings.setLayers( QList() << mPointLayer ); + mapSettings.setOutputDpi( 96 ); + mapSettings.setDestinationCrs( mPointLayer->crs() ); + + d.setMapSettings( mapSettings ); + d.setSymbologyScale( 1000 ); + d.setSymbologyExport( QgsDxfExport::FeatureSymbology ); + + QString file = getTempFileName( "mtext_dxf" ); + QFile dxfFile( file ); + QCOMPARE( d.writeToFile( &dxfFile, QStringLiteral( "CP1252" ) ), 0 ); + dxfFile.close(); + + + QVERIFY( fileContainsText( file, "MTEXT\n" + " 5\n" + "dd\n" + "100\n" + "AcDbEntity\n" + "100\n" + "AcDbMText\n" + " 8\n" + "points\n" + "420\n" + "**no check**\n" + " 10\n" + "**no check**\n" + " 20\n" + "**no check**\n" + " 1\n" + "\\fQGIS Vera Sans|i0|b1;\\H3.81136;Biplane\n" + " 50\n" + "0.0\n" + " 41\n" + "**no check**\n" + " 71\n" + " 7\n" + " 7\n" + "STANDARD\n" + " 0" ) ); +} + +void TestQgsDxfExport::testText() +{ + QgsPalLayerSettings settings; + settings.fieldName = QStringLiteral( "Class" ); + QgsTextFormat format; + format.setFont( QgsFontUtils::getStandardTestFont( QStringLiteral( "Bold" ) ).family() ); + format.setSize( 12 ); + format.setNamedStyle( QStringLiteral( "Bold" ) ); + format.setColor( QColor( 200, 0, 200 ) ); + settings.setFormat( format ); + mPointLayer->setLabeling( new QgsVectorLayerSimpleLabeling( settings ) ); + + QgsDxfExport d; + d.addLayers( QList< QPair< QgsVectorLayer *, int > >() << qMakePair( mPointLayer, -1 ) ); + + QgsMapSettings mapSettings; + QSize size( 640, 480 ); + mapSettings.setOutputSize( size ); + mapSettings.setExtent( mPointLayer->extent() ); + mapSettings.setLayers( QList() << mPointLayer ); + mapSettings.setOutputDpi( 96 ); + mapSettings.setDestinationCrs( mPointLayer->crs() ); + + d.setMapSettings( mapSettings ); + d.setSymbologyScale( 1000 ); + d.setSymbologyExport( QgsDxfExport::FeatureSymbology ); + d.setFlags( QgsDxfExport::FlagNoMText ); + + QString file = getTempFileName( "text_dxf" ); + QFile dxfFile( file ); + QCOMPARE( d.writeToFile( &dxfFile, QStringLiteral( "CP1252" ) ), 0 ); + dxfFile.close(); + + + QVERIFY( fileContainsText( file, "TEXT\n" + " 5\n" + "dd\n" + "100\n" + "AcDbEntity\n" + "100\n" + "AcDbText\n" + " 8\n" + "points\n" + "420\n" + "**no check**\n" + " 10\n" + "**no check**\n" + " 20\n" + "**no check**\n" + " 40\n" + "**no check**\n" + " 1\n" + "Biplane\n" + " 50\n" + "0.0\n" + " 7\n" + "STANDARD\n" + "100\n" + "AcDbText" ) ); +} + +bool TestQgsDxfExport::fileContainsText( const QString &path, const QString &text ) const +{ + QStringList searchLines = text.split( '\n' ); + QFile file( path ); + file.open( QIODevice::ReadOnly ); + QTextStream in( &file ); + QString line; + do + { + bool found = true; + for ( const QString &searchLine : searchLines ) + { + line = in.readLine(); + if ( searchLine != QLatin1String( "**no check**" ) && line != searchLine ) + { + found = false; + break; + } + int i = 1; + i++; + } + if ( found ) + return true; + } + while ( !line.isNull() ); + return false; +} + +QString TestQgsDxfExport::getTempFileName( const QString &file ) const +{ + return QDir::tempPath() + '/' + file + ".dxf"; +} + + +QGSTEST_MAIN( TestQgsDxfExport ) +#include "testqgsdxfexport.moc" From f8d839519f95f179f37e0848c9c78e0137d6e25a Mon Sep 17 00:00:00 2001 From: Nyall Dawson Date: Thu, 23 Nov 2017 15:43:17 +1000 Subject: [PATCH 3/3] Fix indentation --- src/app/qgscrashhandler.h | 1 + src/app/qgsdxfexportdialog.cpp | 4 +- src/app/qgsdxfexportdialog.h | 0 src/crashhandler/CMakeLists.txt | 64 +++++----- src/crashhandler/qgscrashdialog.h | 110 ++++++++-------- src/crashhandler/qgscrashreport.h | 202 +++++++++++++++--------------- 6 files changed, 191 insertions(+), 190 deletions(-) mode change 100755 => 100644 src/app/qgsdxfexportdialog.h diff --git a/src/app/qgscrashhandler.h b/src/app/qgscrashhandler.h index f3c16fef525..c9ebfc4fc44 100644 --- a/src/app/qgscrashhandler.h +++ b/src/app/qgscrashhandler.h @@ -31,6 +31,7 @@ class APP_EXPORT QgsCrashHandler { public: + /** * This class doesn't need to be created by anyone as is only used to handle * crashes in the application. diff --git a/src/app/qgsdxfexportdialog.cpp b/src/app/qgsdxfexportdialog.cpp index 83bb294bd90..c3197ca9cd8 100644 --- a/src/app/qgsdxfexportdialog.cpp +++ b/src/app/qgsdxfexportdialog.cpp @@ -609,12 +609,12 @@ bool QgsDxfExportDialog::layerTitleAsName() const bool QgsDxfExportDialog::force2d() const { - return mForce2d->isChecked(); + return mForce2d->isChecked(); } bool QgsDxfExportDialog::useMText() const { - return mMTextCheckBox->isChecked(); + return mMTextCheckBox->isChecked(); } void QgsDxfExportDialog::saveSettings() diff --git a/src/app/qgsdxfexportdialog.h b/src/app/qgsdxfexportdialog.h old mode 100755 new mode 100644 diff --git a/src/crashhandler/CMakeLists.txt b/src/crashhandler/CMakeLists.txt index 22891b7f837..a0578e0af17 100644 --- a/src/crashhandler/CMakeLists.txt +++ b/src/crashhandler/CMakeLists.txt @@ -1,32 +1,32 @@ -INCLUDE_DIRECTORIES(SYSTEM - ${CMAKE_CURRENT_BINARY_DIR} -) - -QT5_WRAP_UI(CRASH_UIS_H qgscrashdialog.ui) -QT5_WRAP_CPP(CRASH_HDR_MOC qgscrashdialog.h) - -SET(IMAGE_RCCS ../../images/images.qrc) -QT5_ADD_RESOURCES(IMAGE_RCC_SRCS ${IMAGE_RCCS}) - -# -wd4091 Avoid 'typedef' ignored on left of '' when no variable is declared warning in DbgHelp.h -SET_SOURCE_FILES_PROPERTIES(qgsstacktrace.cpp PROPERTIES COMPILE_FLAGS -wd4091) - -ADD_EXECUTABLE(qgiscrashhandler WIN32 - main.cpp - ${CRASH_UIS_H} - ${CRASH_HDR_MOC} - ${IMAGE_RCC_SRCS} - qgscrashdialog.cpp - qgsstacktrace.cpp - qgscrashreport.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/../app/qgis_win32.rc - ) - -TARGET_LINK_LIBRARIES(qgiscrashhandler - ${QT_QTCORE_LIBRARY} - ${QT_QTGUI_LIBRARY} - DbgHelp -) - -INSTALL(CODE "MESSAGE(\"Installing crashhandler ...\")") -INSTALL(TARGETS qgiscrashhandler RUNTIME DESTINATION ${QGIS_LIBEXEC_DIR}) +INCLUDE_DIRECTORIES(SYSTEM + ${CMAKE_CURRENT_BINARY_DIR} +) + +QT5_WRAP_UI(CRASH_UIS_H qgscrashdialog.ui) +QT5_WRAP_CPP(CRASH_HDR_MOC qgscrashdialog.h) + +SET(IMAGE_RCCS ../../images/images.qrc) +QT5_ADD_RESOURCES(IMAGE_RCC_SRCS ${IMAGE_RCCS}) + +# -wd4091 Avoid 'typedef' ignored on left of '' when no variable is declared warning in DbgHelp.h +SET_SOURCE_FILES_PROPERTIES(qgsstacktrace.cpp PROPERTIES COMPILE_FLAGS -wd4091) + +ADD_EXECUTABLE(qgiscrashhandler WIN32 + main.cpp + ${CRASH_UIS_H} + ${CRASH_HDR_MOC} + ${IMAGE_RCC_SRCS} + qgscrashdialog.cpp + qgsstacktrace.cpp + qgscrashreport.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/../app/qgis_win32.rc + ) + +TARGET_LINK_LIBRARIES(qgiscrashhandler + ${QT_QTCORE_LIBRARY} + ${QT_QTGUI_LIBRARY} + DbgHelp +) + +INSTALL(CODE "MESSAGE(\"Installing crashhandler ...\")") +INSTALL(TARGETS qgiscrashhandler RUNTIME DESTINATION ${QGIS_LIBEXEC_DIR}) diff --git a/src/crashhandler/qgscrashdialog.h b/src/crashhandler/qgscrashdialog.h index 447523a2aed..ee0d2daa0d0 100644 --- a/src/crashhandler/qgscrashdialog.h +++ b/src/crashhandler/qgscrashdialog.h @@ -1,55 +1,55 @@ -/*************************************************************************** - qgscrashdialog.h - QgsCrashDialog - - --------------------- - begin : 11.4.2017 - copyright : (C) 2017 by Nathan Woodrow - email : woodrow.nathan@gmail.com - *************************************************************************** - * * - * 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. * - * * - ***************************************************************************/ - -#ifndef QGSCRASHDIALOG_H -#define QGSCRASHDIALOG_H - -#include -#include -#include -#include - -#include "ui_qgscrashdialog.h" - -/** - * A dialog to show a nicer crash dialog to the user. - */ -class QgsCrashDialog : public QDialog, private Ui::QgsCrashDialog -{ - Q_OBJECT - public: - - /** - * A dialog to show a nicer crash dialog to the user. - */ - QgsCrashDialog( QWidget *parent = nullptr ); - - void setBugReport( const QString &reportData ); - void setReloadArgs( const QString &reloadArgs ); - - static QString htmlToMarkdown( const QString &html ); - - private slots: - void showReportWidget(); - void createBugReport(); - void reloadQGIS(); - - private: - QString mReportData; - QString mReloadArgs; -}; - -#endif // QGSCRASHDIALOG_H +/*************************************************************************** + qgscrashdialog.h - QgsCrashDialog + + --------------------- + begin : 11.4.2017 + copyright : (C) 2017 by Nathan Woodrow + email : woodrow.nathan@gmail.com + *************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#ifndef QGSCRASHDIALOG_H +#define QGSCRASHDIALOG_H + +#include +#include +#include +#include + +#include "ui_qgscrashdialog.h" + +/** + * A dialog to show a nicer crash dialog to the user. + */ +class QgsCrashDialog : public QDialog, private Ui::QgsCrashDialog +{ + Q_OBJECT + public: + + /** + * A dialog to show a nicer crash dialog to the user. + */ + QgsCrashDialog( QWidget *parent = nullptr ); + + void setBugReport( const QString &reportData ); + void setReloadArgs( const QString &reloadArgs ); + + static QString htmlToMarkdown( const QString &html ); + + private slots: + void showReportWidget(); + void createBugReport(); + void reloadQGIS(); + + private: + QString mReportData; + QString mReloadArgs; +}; + +#endif // QGSCRASHDIALOG_H diff --git a/src/crashhandler/qgscrashreport.h b/src/crashhandler/qgscrashreport.h index d89855dd13c..78568495fa2 100644 --- a/src/crashhandler/qgscrashreport.h +++ b/src/crashhandler/qgscrashreport.h @@ -1,101 +1,101 @@ -/*************************************************************************** - qgscrashreport.h - QgsCrashReport - - --------------------- - begin : 16.4.2017 - copyright : (C) 2017 by Nathan Woodrow - email : woodrow.nathan@gmail.com - *************************************************************************** - * * - * 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. * - * * - ***************************************************************************/ -#ifndef QGSCRASHREPORT_H -#define QGSCRASHREPORT_H - -#include "qgsstacktrace.h" - -#include -#include - - -/** - * Include information to generate user friendly crash report for QGIS. - */ -class QgsCrashReport -{ - public: - - /** - * Include information to generate user friendly crash report for QGIS. - */ - QgsCrashReport(); - - public: - enum Flag - { - Stack = 1 << 0, - Plugins = 1 << 1, - ProjectDetails = 1 << 2, - SystemInfo = 1 << 3, - QgisInfo = 1 << 4, - All = Stack | Plugins | ProjectDetails | SystemInfo | QgisInfo - }; - Q_DECLARE_FLAGS( Flags, Flag ) - - /** - * Sets the stack trace for the crash report. - * \param value A string list for each line in the stack trace. - */ - void setStackTrace( QgsStackTrace *value ) { mStackTrace = value; } - - /** - * Returns the stack trace for this report. - * \return A string list for each line in the stack trace. - */ - QgsStackTrace *StackTrace() const { return mStackTrace; } - - /** - * Set the flags to mark which features are included in this crash report. - * \param flags The flag for each feature. - */ - void setFlags( QgsCrashReport::Flags flags ); - - /** - * Returns the include flags that have been set for this report. - * \return The flags marking what details are included in this report. - */ - Flags flags() const { return mFlags; } - - const QString toMarkdown(); - - /** - * Generate a string version of the report. - * \return A formatted string including all the information from the report. - */ - const QString toHtml() const; - - /** - * Generates a crash ID for the crash report. - * \return - */ - const QString crashID() const; - - void exportToCrashFolder(); - - QString crashReportFolder(); - - void setVersionInfo( const QStringList &versionInfo ) { mVersionInfo = versionInfo; } - - private: - Flags mFlags; - QgsStackTrace *mStackTrace; - QStringList mVersionInfo; -}; - -Q_DECLARE_OPERATORS_FOR_FLAGS( QgsCrashReport::Flags ) - -#endif // QGSCRASHREPORT_H +/*************************************************************************** + qgscrashreport.h - QgsCrashReport + + --------------------- + begin : 16.4.2017 + copyright : (C) 2017 by Nathan Woodrow + email : woodrow.nathan@gmail.com + *************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ +#ifndef QGSCRASHREPORT_H +#define QGSCRASHREPORT_H + +#include "qgsstacktrace.h" + +#include +#include + + +/** + * Include information to generate user friendly crash report for QGIS. + */ +class QgsCrashReport +{ + public: + + /** + * Include information to generate user friendly crash report for QGIS. + */ + QgsCrashReport(); + + public: + enum Flag + { + Stack = 1 << 0, + Plugins = 1 << 1, + ProjectDetails = 1 << 2, + SystemInfo = 1 << 3, + QgisInfo = 1 << 4, + All = Stack | Plugins | ProjectDetails | SystemInfo | QgisInfo + }; + Q_DECLARE_FLAGS( Flags, Flag ) + + /** + * Sets the stack trace for the crash report. + * \param value A string list for each line in the stack trace. + */ + void setStackTrace( QgsStackTrace *value ) { mStackTrace = value; } + + /** + * Returns the stack trace for this report. + * \return A string list for each line in the stack trace. + */ + QgsStackTrace *StackTrace() const { return mStackTrace; } + + /** + * Set the flags to mark which features are included in this crash report. + * \param flags The flag for each feature. + */ + void setFlags( QgsCrashReport::Flags flags ); + + /** + * Returns the include flags that have been set for this report. + * \return The flags marking what details are included in this report. + */ + Flags flags() const { return mFlags; } + + const QString toMarkdown(); + + /** + * Generate a string version of the report. + * \return A formatted string including all the information from the report. + */ + const QString toHtml() const; + + /** + * Generates a crash ID for the crash report. + * \return + */ + const QString crashID() const; + + void exportToCrashFolder(); + + QString crashReportFolder(); + + void setVersionInfo( const QStringList &versionInfo ) { mVersionInfo = versionInfo; } + + private: + Flags mFlags; + QgsStackTrace *mStackTrace; + QStringList mVersionInfo; +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS( QgsCrashReport::Flags ) + +#endif // QGSCRASHREPORT_H