Merge pull request #5702 from nyalldawson/dxf_improve

[dxf] Add option to export labels as text elements, instead of mtext
This commit is contained in:
Nyall Dawson 2017-11-24 15:58:46 +11:00 committed by GitHub
commit 03ec2d8a98
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 728 additions and 283 deletions

View File

@ -27,6 +27,13 @@ class QgsDxfExport
SymbolLayerSymbology
};
enum Flag
{
FlagNoMText,
};
typedef QFlags<QgsDxfExport::Flag> 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<QgsVectorLayer *, int > > &layers );
%Docstring
Add layers to export
@ -342,6 +364,9 @@ return list of available DXF encodings
};
QFlags<QgsDxfExport::Flag> operator|(QgsDxfExport::Flag f1, QFlags<QgsDxfExport::Flag> f2);
/************************************************************************
* This file has been generated automatically from *
* *

View File

@ -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

View File

@ -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.

View File

@ -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( "" ) );
@ -611,6 +612,11 @@ bool QgsDxfExportDialog::force2d() const
return mForce2d->isChecked();
}
bool QgsDxfExportDialog::useMText() const
{
return mMTextCheckBox->isChecked();
}
void QgsDxfExportDialog::saveSettings()
{
QgsSettings s;
@ -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() );
}

View File

@ -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;

View File

@ -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<QgsMapLayer *> layerList;
@ -491,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;
}
@ -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() );
}

View File

@ -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<QString, int> mLayerNameAttribute;
double mFactor = 1.0;
bool mForce2d = false;
QgsDxfExport::Flags mFlags = 0;
};
Q_DECLARE_OPERATORS_FOR_FLAGS( QgsDxfExport::Flags )
#endif // QGSDXFEXPORT_H

View File

@ -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})

View File

@ -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 <QDialog>
#include <QFormLayout>
#include <QPlainTextEdit>
#include <QPushButton>
#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 <QDialog>
#include <QFormLayout>
#include <QPlainTextEdit>
#include <QPushButton>
#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

View File

@ -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 <QObject>
#include <QVector>
/**
* 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 <QObject>
#include <QVector>
/**
* 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

166
src/ui/qgsdxfexportdialogbase.ui Normal file → Executable file
View File

@ -14,17 +14,10 @@
<string>DXF Export</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="2" column="0">
<widget class="QLabel" name="mSymbologyScaleLabel">
<item row="1" column="0">
<widget class="QLabel" name="mSymbologyModeLabel">
<property name="text">
<string>Symbology scale</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QToolButton" name="mFileSelectionButton">
<property name="text">
<string>…</string>
<string>Symbology mode</string>
</property>
</widget>
</item>
@ -35,6 +28,13 @@
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QToolButton" name="mFileSelectionButton">
<property name="text">
<string>…</string>
</property>
</widget>
</item>
<item row="1" column="1" colspan="2">
<widget class="QComboBox" name="mSymbologyModeComboBox">
<item>
@ -54,13 +54,16 @@
</item>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="mSymbologyModeLabel">
<item row="2" column="0">
<widget class="QLabel" name="mSymbologyScaleLabel">
<property name="text">
<string>Symbology mode</string>
<string>Symbology scale</string>
</property>
</widget>
</item>
<item row="3" column="1" colspan="2">
<widget class="QComboBox" name="mEncoding"/>
</item>
<item row="7" column="0" colspan="3">
<widget class="QgsLayerTreeView" name="mTreeView">
<property name="selectionMode">
@ -81,8 +84,35 @@
</property>
</widget>
</item>
<item row="3" column="1" colspan="2">
<widget class="QComboBox" name="mEncoding"/>
<item row="5" column="1" colspan="2">
<widget class="QgsProjectionSelectionWidget" name="mCrsSelector" native="true">
<property name="focusPolicy">
<enum>Qt::StrongFocus</enum>
</property>
</widget>
</item>
<item row="4" column="1" colspan="2">
<widget class="QComboBox" name="mVisibilityPresets"/>
</item>
<item row="15" column="0" colspan="3">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Help|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="mFileLineEdit"/>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>CRS</string>
</property>
</widget>
</item>
<item row="9" column="0" colspan="3">
<layout class="QGridLayout" name="gridLayout_3">
@ -115,29 +145,13 @@
</item>
</layout>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="mFileLineEdit"/>
</item>
<item row="11" column="0" colspan="3">
<widget class="QCheckBox" name="mMapExtentCheckBox">
<item row="3" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Export features intersecting the current map extent</string>
<string>Encoding</string>
</property>
</widget>
</item>
<item row="13" column="0" colspan="3">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Help|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
<item row="4" column="1" colspan="2">
<widget class="QComboBox" name="mVisibilityPresets"/>
</item>
<item row="4" column="0">
<widget class="QLabel" name="mSymbologyScaleLabel_2">
<property name="text">
@ -145,40 +159,53 @@
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Encoding</string>
</property>
</widget>
</item>
<item row="10" column="0" colspan="3">
<widget class="QCheckBox" name="mLayerTitleAsName">
<property name="text">
<string>Use layer title as name if set</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>CRS</string>
</property>
</widget>
</item>
<item row="5" column="1" colspan="2">
<widget class="QgsProjectionSelectionWidget" name="mCrsSelector" native="true">
<property name="focusPolicy">
<enum>Qt::StrongFocus</enum>
</property>
</widget>
</item>
<item row="12" column="0" colspan="3">
<widget class="QCheckBox" name="mForce2d">
<property name="text">
<string>Force 2d output (eg. to support polyline width)</string>
</property>
</widget>
<item row="11" column="0" colspan="3">
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="0">
<widget class="QCheckBox" name="mMapExtentCheckBox">
<property name="text">
<string>Export features intersecting the current map extent</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QCheckBox" name="mLayerTitleAsName">
<property name="text">
<string>Use layer title as name if set</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QCheckBox" name="mForce2d">
<property name="text">
<string>Force 2d output (eg. to support polyline width)</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QCheckBox" name="mMTextCheckBox">
<property name="text">
<string>Export labels as MTEXT elements</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="2">
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</widget>
@ -211,9 +238,6 @@
<tabstop>mTreeView</tabstop>
<tabstop>mSelectAllButton</tabstop>
<tabstop>mDeselectAllButton</tabstop>
<tabstop>mLayerTitleAsName</tabstop>
<tabstop>mMapExtentCheckBox</tabstop>
<tabstop>mForce2d</tabstop>
<tabstop>buttonBox</tabstop>
</tabstops>
<resources/>

View File

@ -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

View File

@ -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 <QTemporaryFile>
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<QgsMapLayer *>() << 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<QgsMapLayer *>() << 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<QgsMapLayer *>() << 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<QgsMapLayer *>() << 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<QgsMapLayer *>() << 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"