Skip to content
Permalink
Browse files

[FEATURE] add commandline options for dxf export

* Initialize dxf export dialog with current visible layers w/o preset
* Also save dxf export settings into project file (including preset selection)

TODO: dxf export (but also snapshot) cause plugins to crash on exit
(--noplugins helps)
  • Loading branch information
jef-n committed Aug 29, 2015
1 parent f7e07c2 commit be2ff5c4c7ae3480697a255a35b27f2226ce90c5
Showing with 222 additions and 35 deletions.
  1. +184 −23 src/app/main.cpp
  2. +31 −5 src/app/qgsdxfexportdialog.cpp
  3. +2 −0 src/gui/qgsfieldexpressionwidget.cpp
  4. +5 −7 src/gui/qgsfieldmodel.cpp
@@ -36,12 +36,6 @@
#include <QImageReader>
#include <QMessageBox>

#include "qgscustomization.h"
#include "qgsfontutils.h"
#include "qgspluginregistry.h"
#include "qgsmessagelog.h"
#include "qgspythonrunner.h"

#include <cstdio>
#include <stdio.h>
#include <stdlib.h>
@@ -76,17 +70,6 @@ typedef SInt32 SRefCon;
#include <limits.h>
#endif

#include "qgisapp.h"
#include "qgsmapcanvas.h"
#include "qgsapplication.h"
#include <qgsconfig.h>
#include <qgscustomization.h>
#include <qgsversion.h>
#include "qgsexception.h"
#include "qgsproject.h"
#include "qgsrectangle.h"
#include "qgslogger.h"

#if ((defined(linux) || defined(__linux__)) && !defined(ANDROID)) || defined(__FreeBSD__)
#include <unistd.h>
#include <execinfo.h>
@@ -95,6 +78,26 @@ typedef SInt32 SRefCon;
#include <errno.h>
#endif

#include "qgscustomization.h"
#include "qgsfontutils.h"
#include "qgspluginregistry.h"
#include "qgsmessagelog.h"
#include "qgspythonrunner.h"
#include "qgslocalec.h"
#include "qgisapp.h"
#include "qgsmapcanvas.h"
#include "qgsapplication.h"
#include "qgsconfig.h"
#include "qgsversion.h"
#include "qgsexception.h"
#include "qgsproject.h"
#include "qgsrectangle.h"
#include "qgslogger.h"
#include "qgsdxfexport.h"
#include "qgsvisibilitypresets.h"
#include "qgsmaplayerregistry.h"
#include "qgsvectorlayer.h"

/** Print usage text
*/
void usage( std::string const & appName )
@@ -118,6 +121,12 @@ void usage( std::string const & appName )
<< "\t[--configpath path]\tuse the given path for all user configuration\n"
<< "\t[--code path]\trun the given python file on load\n"
<< "\t[--defaultui]\tstart by resetting user ui settings to default\n"
<< "\t[--dxf-export filename.dxf]\temit dxf output of loaded datasets to given file\n"
<< "\t[--dxf-extent xmin,ymin,xmax,ymax]\tset extent to export to dxf\n"
<< "\t[--dxf-symbology-mode none|symbollayer|feature]\tsymbology mode for dxf output\n"
<< "\t[--dxf-scale-denom scale]\tscale for dxf output\n"
<< "\t[--dxf-encoding encoding]\tencoding to use for dxf output\n"
<< "\t[--dxf-preset visiblity-preset]\tlayer visibility preset to use for dxf output\n"
<< "\t[--help]\t\tthis text\n\n"
<< " FILE:\n"
<< " Files specified on the command line can include rasters,\n"
@@ -469,6 +478,13 @@ APP_EXPORT int main( int argc, char *argv[] )
bool myRestorePlugins = true;
bool myCustomization = true;

QString dxfOutputFile;
QgsDxfExport::SymbologyExport dxfSymbologyMode = QgsDxfExport::SymbolLayerSymbology;
double dxfScaleDenom = 50000.0;
QString dxfEncoding = "CP1252";
QString dxfPreset;
QgsRectangle dxfExtent;

// This behaviour will set initial extent of map canvas, but only if
// there are no command line arguments. This gives a usable map
// extent when qgis starts with no layers loaded. When layers are
@@ -508,7 +524,7 @@ APP_EXPORT int main( int argc, char *argv[] )

for ( int i = 1; i < args.size(); ++i )
{
QString arg = args[i];
const QString &arg = args[i];

if ( arg == "--help" || arg == "-?" )
{
@@ -571,6 +587,91 @@ APP_EXPORT int main( int argc, char *argv[] )
{
myRestoreDefaultWindowState = true;
}
else if ( arg == "--dxf-export" )
{
dxfOutputFile = args[++i];
}
else if ( arg == "--dxf-extent" )
{
QgsLocaleNumC l;
QString ext( args[++i] );
QStringList coords( ext.split( "," ) );

if ( coords.size() != 4 )
{
std::cerr << "invalid dxf extent " << ext.toStdString() << std::endl;
return 2;
}

for ( int i = 0; i < 4; i++ )
{
bool ok;
double d;

d = coords[i].toDouble( &ok );
if ( !ok )
{
std::cerr << "invalid dxf coordinate " << coords[i].toStdString() << " in extent " << ext.toStdString() << std::endl;
return 2;
}

switch ( i )
{
case 0:
dxfExtent.setXMinimum( d );
break;
case 1:
dxfExtent.setYMinimum( d );
break;
case 2:
dxfExtent.setXMaximum( d );
break;
case 3:
dxfExtent.setYMaximum( d );
break;
}
}
}
else if ( arg == "--dxf-symbology-mode" )
{
QString mode( args[++i] );
if ( mode == "none" )
{
dxfSymbologyMode = QgsDxfExport::NoSymbology;
}
else if ( mode == "symbollayer" )
{
dxfSymbologyMode = QgsDxfExport::SymbolLayerSymbology;
}
else if ( mode == "feature" )
{
dxfSymbologyMode = QgsDxfExport::FeatureSymbology;
}
else
{
std::cerr << "invalid dxf symbology mode " << mode.toStdString() << std::endl;
return 2;
}
}
else if ( arg == "--dxf-scale-denom" )
{
bool ok;
QString scale( args[++i] );
dxfScaleDenom = scale.toDouble( &ok );
if ( !ok )
{
std::cerr << "invalid dxf scale " << scale.toStdString() << std::endl;
return 2;
}
}
else if ( arg == "--dxf-encoding" )
{
dxfEncoding = args[++i];
}
else if ( arg == "--dxf-preset" )
{
dxfPreset = args[++i];
}
else
{
myFileList.append( QDir::toNativeSeparators( QFileInfo( args[i] ).absoluteFilePath() ) );
@@ -947,12 +1048,11 @@ APP_EXPORT int main( int argc, char *argv[] )
/////////////////////////////////////////////////////////////////////
if ( ! myInitialExtent.isEmpty() )
{
QgsLocaleNumC l;
double coords[4];
int pos, posOld = 0;
bool ok = true;

// XXX is it necessary to switch to "C" locale?

// parse values from string
// extent is defined by string "xmin,ymin,xmax,ymax"
for ( int i = 0; i < 3; i++ )
@@ -1006,7 +1106,6 @@ APP_EXPORT int main( int argc, char *argv[] )
/////////////////////////////////////////////////////////////////////
if ( mySnapshotFileName != "" )
{

/*You must have at least one paintEvent() delivered for the window to be
rendered properly.
@@ -1024,11 +1123,73 @@ APP_EXPORT int main( int argc, char *argv[] )
myApp.processEvents();
qgis->hide();

QgsPluginRegistry::instance()->unloadAll();

return 1;
}

if ( !dxfOutputFile.isEmpty() )
{
qgis->hide();

QgsDxfExport dxfExport;
dxfExport.setSymbologyScaleDenominator( dxfScaleDenom );
dxfExport.setSymbologyExport( dxfSymbologyMode );
dxfExport.setExtent( dxfExtent );

QStringList layerIds;
QList< QPair<QgsVectorLayer *, int > > layers;
if ( !dxfPreset.isEmpty() )
{
foreach ( QString layer, QgsProject::instance()->visibilityPresetCollection()->presetVisibleLayers( dxfPreset ) )
{
QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( QgsMapLayerRegistry::instance()->mapLayer( layer ) );
if ( !vl )
continue;
layers << qMakePair<QgsVectorLayer *, int>( vl, -1 );
layerIds << vl->id();
}
}
else
{
foreach ( QgsMapLayer *ml, QgsMapLayerRegistry::instance()->mapLayers().values() )
{
QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( ml );
if ( !vl )
continue;
layers << qMakePair<QgsVectorLayer *, int>( vl, -1 );
layerIds << vl->id();
}
}

if ( !layers.isEmpty() )
{
dxfExport.addLayers( layers );
}

QFile dxfFile;
if ( dxfOutputFile == "-" )
{
if ( !dxfFile.open( STDOUT_FILENO, QIODevice::WriteOnly ) )
{
std::cerr << "could not open stdout" << std::endl;
return 2;
}
}
else
{
if ( !dxfOutputFile.endsWith( ".dxf", Qt::CaseInsensitive ) )
dxfOutputFile += ".dxf";
dxfFile.setFileName( dxfOutputFile );
}

int res = dxfExport.writeToFile( &dxfFile, dxfEncoding );
if ( res )
std::cerr << "dxf output failed with error code " << res << std::endl;

delete qgis;

return res;
}

/////////////////////////////////////////////////////////////////////
// Continue on to interactive gui...
/////////////////////////////////////////////////////////////////////
@@ -27,6 +27,7 @@
#include "qgisapp.h"
#include "qgslayertreemapcanvasbridge.h"
#include "qgsvisibilitypresetcollection.h"
#include "qgsmapcanvas.h"

#include <QFileDialog>
#include <QPushButton>
@@ -329,7 +330,23 @@ QList< QPair<QgsVectorLayer *, int> > QgsVectorLayerAndAttributeModel::layers()

void QgsVectorLayerAndAttributeModel::applyVisibilityPreset( const QString &name )
{
QSet<QString> visibleLayers = QgsProject::instance()->visibilityPresetCollection()->presetVisibleLayers( name ).toSet();
QSet<QString> visibleLayers;

if ( name.isEmpty() )
{
foreach ( const QgsMapLayer *ml, QgisApp::instance()->mapCanvas()->layers() )
{
const QgsVectorLayer *vl = qobject_cast<const QgsVectorLayer *>( ml );
if ( !vl )
continue;
visibleLayers.insert( vl->id() );
}
}
else
{
visibleLayers = QgsProject::instance()->visibilityPresetCollection()->presetVisibleLayers( name ).toSet();
}

if ( visibleLayers.isEmpty() )
return;

@@ -423,20 +440,22 @@ QgsDxfExportDialog::QgsDxfExportDialog( QWidget *parent, Qt::WindowFlags f )

//last dxf symbology mode
QSettings s;
mSymbologyModeComboBox->setCurrentIndex( s.value( "qgis/lastDxfSymbologyMode", "2" ).toInt() );
mSymbologyModeComboBox->setCurrentIndex( QgsProject::instance()->readEntry( "dxf", "/lastDxfSymbologyMode", s.value( "qgis/lastDxfSymbologyMode", "2" ).toString() ).toInt() );

//last symbol scale
mScaleWidget->setMapCanvas( QgisApp::instance()->mapCanvas() );
mScaleWidget->setScale( s.value( "qgis/lastSymbologyExportScale", "1/50000" ).toDouble() );
mMapExtentCheckBox->setChecked( s.value( "qgis/lastDxfMapRectangle", "false" ).toBool() );
mScaleWidget->setScale( QgsProject::instance()->readEntry( "dxf", "/lastSymbologyExportScale", s.value( "qgis/lastSymbologyExportScale", "1/50000" ).toString() ).toDouble() );
mMapExtentCheckBox->setChecked( QgsProject::instance()->readEntry( "dxf", "/lastDxfMapRectangle", s.value( "qgis/lastDxfMapRectangle", "false" ).toString() ) != "false" );

QStringList ids = QgsProject::instance()->visibilityPresetCollection()->presets();
ids.prepend( "" );
mVisibilityPresets->addItems( ids );
mVisibilityPresets->setCurrentIndex( mVisibilityPresets->findText( QgsProject::instance()->readEntry( "dxf", "/lastVisibilityPreset", "" ) ) );

buttonBox->button( QDialogButtonBox::Ok )->setEnabled( false );
restoreGeometry( s.value( "/Windows/DxfExport/geometry" ).toByteArray() );
mEncoding->addItems( QgsDxfExport::encodings() );
mEncoding->setCurrentIndex( mEncoding->findText( s.value( "qgis/lastDxfEncoding", "CP1252" ).toString() ) );
mEncoding->setCurrentIndex( mEncoding->findText( QgsProject::instance()->readEntry( "dxf", "/lastDxfEncoding", s.value( "qgis/lastDxfEncoding", "CP1252" ).toString() ) ) );
}


@@ -571,8 +590,15 @@ void QgsDxfExportDialog::saveSettings()
s.setValue( "qgis/lastSymbologyExportScale", mScaleWidget->scale() );
s.setValue( "qgis/lastDxfMapRectangle", mMapExtentCheckBox->isChecked() );
s.setValue( "qgis/lastDxfEncoding", mEncoding->currentText() );

QgsProject::instance()->writeEntry( "dxf", "/lastDxfSymbologyMode", mSymbologyModeComboBox->currentIndex() );
QgsProject::instance()->writeEntry( "dxf", "/lastSymbologyExportScale", mScaleWidget->scale() );
QgsProject::instance()->writeEntry( "dxf", "/lastDxfMapRectangle", mMapExtentCheckBox->isChecked() );
QgsProject::instance()->writeEntry( "dxf", "/lastDxfEncoding", mEncoding->currentText() );
QgsProject::instance()->writeEntry( "dxf", "/lastVisibilityPreset", mVisibilityPresets->currentText() );
}


QString QgsDxfExportDialog::encoding() const
{
return mEncoding->currentText();
@@ -31,11 +31,13 @@ QgsFieldExpressionWidget::QgsFieldExpressionWidget( QWidget *parent )
{
QHBoxLayout* layout = new QHBoxLayout( this );
layout->setContentsMargins( 0, 0, 0, 0 );

mCombo = new QComboBox( this );
mCombo->setEditable( true );
mCombo->setSizePolicy( QSizePolicy::MinimumExpanding, QSizePolicy::Minimum );
int width = mCombo->minimumSizeHint().width();
mCombo->setMinimumWidth( width );

mFieldProxyModel = new QgsFieldProxyModel( mCombo );
mFieldProxyModel->sourceFieldModel()->setAllowExpression( true );
mCombo->setModel( mFieldProxyModel );
@@ -75,16 +75,14 @@ void QgsFieldModel::setLayer( QgsVectorLayer *layer )
disconnect( mLayer, SIGNAL( layerDeleted() ), this, SLOT( layerDeleted() ) );
}

if ( !layer )
mLayer = layer;

if ( mLayer )
{
mLayer = 0;
updateModel();
return;
connect( mLayer, SIGNAL( updatedFields() ), this, SLOT( updateModel() ) );
connect( mLayer, SIGNAL( layerDeleted() ), this, SLOT( layerDeleted() ) );
}

mLayer = layer;
connect( mLayer, SIGNAL( updatedFields() ), this, SLOT( updateModel() ) );
connect( mLayer, SIGNAL( layerDeleted() ), this, SLOT( layerDeleted() ) );
updateModel();
}

1 comment on commit be2ff5c

@3nids

This comment has been minimized.

Copy link
Member

@3nids 3nids commented on be2ff5c Aug 30, 2015

that was fast, thanks a lot!

Please sign in to comment.
You can’t perform that action at this time.