Skip to content

Commit

Permalink
[FEATURE] Add UI for configuring layer-by-layer export attributes and…
Browse files Browse the repository at this point in the history
… layer groups to GeoPDF export

Allows users to set on a layer-by-layer basis whether layers should be identifiable
and include vector features in a GeoPDF export, and optionally whether to group multiple
layers together into a single logical, switchable entry in the GeoPDF layer tree.
  • Loading branch information
nyalldawson committed Aug 21, 2019
1 parent 2ca3029 commit 7c22da0
Show file tree
Hide file tree
Showing 5 changed files with 241 additions and 17 deletions.
2 changes: 2 additions & 0 deletions src/app/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ SET(QGIS_APP_SRCS

browser/qgsinbuiltdataitemproviders.cpp

layout/qgsgeopdflayertreemodel.cpp
layout/qgslayoutaddpagesdialog.cpp
layout/qgslayoutapputils.cpp
layout/qgslayoutatlaswidget.cpp
Expand Down Expand Up @@ -425,6 +426,7 @@ SET (QGIS_APP_MOC_HDRS

browser/qgsinbuiltdataitemproviders.h

layout/qgsgeopdflayertreemodel.h
layout/qgslayoutaddpagesdialog.h
layout/qgslayoutappmenuprovider.h
layout/qgslayoutatlaswidget.h
Expand Down
170 changes: 170 additions & 0 deletions src/app/layout/qgsgeopdflayertreemodel.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
/***************************************************************************
qgsgeopdflayertreemodel.cpp
---------------------
begin : August 2019
copyright : (C) 2019 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 <QComboBox>
#include <QDoubleSpinBox>

#include "qgsgeopdflayertreemodel.h"
#include "qgslayertree.h"
#include "qgsproject.h"
#include "qgsvectorlayer.h"
#include "qgsapplication.h"

QgsGeoPdfLayerTreeModel::QgsGeoPdfLayerTreeModel( QgsLayerTree *rootNode, QObject *parent )
: QgsLayerTreeModel( rootNode, parent )
{
setFlags( nullptr ); // ideally we'd just show embedded legend nodes - but the api doesn't exist for this
}

int QgsGeoPdfLayerTreeModel::columnCount( const QModelIndex &parent ) const
{
Q_UNUSED( parent )
return 2;
}

Qt::ItemFlags QgsGeoPdfLayerTreeModel::flags( const QModelIndex &idx ) const
{
if ( idx.column() == LayerColumn )
{
return QgsLayerTreeModel::flags( idx ) | Qt::ItemIsUserCheckable;
}

QgsVectorLayer *vl = vectorLayer( idx );
if ( !vl )
{
return Qt::NoItemFlags;
}
else
{
const QModelIndex layerIndex = sibling( idx.row(), LayerColumn, idx );
if ( data( layerIndex, Qt::CheckStateRole ) == Qt::Checked )
{
return Qt::ItemIsEnabled | Qt::ItemIsEditable;
}
}
return Qt::NoItemFlags;
}

QgsVectorLayer *QgsGeoPdfLayerTreeModel::vectorLayer( const QModelIndex &idx ) const
{
QgsLayerTreeNode *node = index2node( index( idx.row(), LayerColumn, idx.parent() ) );
if ( !node || !QgsLayerTree::isLayer( node ) )
return nullptr;

return qobject_cast<QgsVectorLayer *>( QgsLayerTree::toLayer( node )->layer() );
}

QVariant QgsGeoPdfLayerTreeModel::headerData( int section, Qt::Orientation orientation, int role ) const
{
if ( orientation == Qt::Horizontal )
{
if ( role == Qt::DisplayRole )
{
switch ( section )
{
case 0:
return tr( "Layer" );
case 1:
return tr( "PDF Group" );
default:
return QVariant();
}
}
}
return QgsLayerTreeModel::headerData( section, orientation, role );
}

QVariant QgsGeoPdfLayerTreeModel::data( const QModelIndex &idx, int role ) const
{
switch ( idx.column() )
{
case LayerColumn:
{
if ( role == Qt::CheckStateRole )
{
QgsLayerTreeNode *node = index2node( index( idx.row(), LayerColumn, idx.parent() ) );
QgsVectorLayer *vl = vectorLayer( idx );
if ( vl )
{
const QVariant v = vl->customProperty( QStringLiteral( "geopdf/includeFeatures" ) );
if ( v.isValid() )
{
return v.toBool() ? Qt::Checked : Qt::Unchecked;
}
else
{
// otherwise, we default to the layer's visibility
return node->itemVisibilityChecked() ? Qt::Checked : Qt::Unchecked;
}
}
return QVariant();
}
return QgsLayerTreeModel::data( idx, role );
}
case GroupColumn:
{
switch ( role )
{
case Qt::DisplayRole:
{
if ( QgsVectorLayer *vl = vectorLayer( idx ) )
{
return vl->customProperty( QStringLiteral( "geopdf/groupName" ) ).toString();
}
break;
}
}

return QVariant();
}
}

return QVariant();
}

bool QgsGeoPdfLayerTreeModel::setData( const QModelIndex &index, const QVariant &value, int role )
{
switch ( index.column() )
{
case LayerColumn:
{
if ( role == Qt::CheckStateRole )
{
if ( QgsVectorLayer *vl = vectorLayer( index ) )
{
vl->setCustomProperty( QStringLiteral( "geopdf/includeFeatures" ), value.toInt() == Qt::Checked );
emit dataChanged( index, index );
return true;
}
}
break;
}

case GroupColumn:
{
if ( role == Qt::EditRole )
{
if ( QgsVectorLayer *vl = vectorLayer( index ) )
{
vl->setCustomProperty( QStringLiteral( "geopdf/groupName" ), value.toString() );
emit dataChanged( index, index );
return true;
}
}
break;
}
}
return false;
}
51 changes: 51 additions & 0 deletions src/app/layout/qgsgeopdflayertreemodel.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/***************************************************************************
qgsgeopdflayertreemodel.h
---------------------
begin : August 2019
copyright : (C) 2019 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. *
* *
***************************************************************************/
#ifndef QGSGEOPDFLAYERTREEMODEL_H
#define QGSGEOPDFLAYERTREEMODEL_H

#include <QSortFilterProxyModel>
#include <QItemDelegate>

#include "qgslayertreemodel.h"
#include "qgis_app.h"

class QgsMapCanvas;
class QgsProject;


class APP_EXPORT QgsGeoPdfLayerTreeModel : public QgsLayerTreeModel
{
Q_OBJECT

public:
QgsGeoPdfLayerTreeModel( QgsLayerTree *rootNode, QObject *parent = nullptr );

int columnCount( const QModelIndex &parent ) const override;
QVariant headerData( int section, Qt::Orientation orientation, int role ) const override;
Qt::ItemFlags flags( const QModelIndex &idx ) const override;
QVariant data( const QModelIndex &index, int role ) const override;
bool setData( const QModelIndex &index, const QVariant &value, int role ) override;

private:
enum Columns
{
LayerColumn = 0,
GroupColumn
};

QgsVectorLayer *vectorLayer( const QModelIndex &idx ) const;
};

#endif // QGSGEOPDFLAYERTREEMODEL_H
11 changes: 9 additions & 2 deletions src/app/layout/qgslayoutpdfexportoptionsdialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "qgsabstractgeopdfexporter.h"
#include "qgsproject.h"
#include "qgsmapthemecollection.h"
#include "qgsgeopdflayertreemodel.h"

#include <QCheckBox>
#include <QPushButton>
Expand All @@ -35,9 +36,9 @@ QgsLayoutPdfExportOptionsDialog::QgsLayoutPdfExportOptionsDialog( QWidget *paren
mTextRenderFormatComboBox->addItem( tr( "Always Export Text as Text Objects" ), QgsRenderContext::TextFormatAlwaysText );

mGeopdfAvailable = QgsAbstractGeoPdfExporter::geoPDFCreationAvailable();
mGeoPDFGroupBox->setEnabled( mGeopdfAvailable );
mGeoPDFGroupBox->setEnabled( true || mGeopdfAvailable );
mGeoPDFGroupBox->setChecked( false );
if ( !mGeopdfAvailable )
if ( false && !mGeopdfAvailable )
{
mGeoPDFOptionsStackedWidget->setCurrentIndex( 0 );
mGeoPdfUnavailableReason->setText( QgsAbstractGeoPdfExporter::geoPDFAvailabilityExplanation() );
Expand All @@ -63,6 +64,12 @@ QgsLayoutPdfExportOptionsDialog::QgsLayoutPdfExportOptionsDialog( QWidget *paren
mThemesList->addItem( item );
}

QgsGeoPdfLayerTreeModel *model = new QgsGeoPdfLayerTreeModel( QgsProject::instance()->layerTreeRoot(), this );
mGeoPdfStructureTree->setModel( model );
mGeoPdfStructureTree->resizeColumnToContents( 0 );
mGeoPdfStructureTree->header()->show();
mGeoPdfStructureTree->setSelectionMode( QAbstractItemView::NoSelection );

connect( buttonBox, &QDialogButtonBox::helpRequested, this, &QgsLayoutPdfExportOptionsDialog::showHelp );
QgsGui::enableAutoGeometryRestore( this );
}
Expand Down
24 changes: 9 additions & 15 deletions src/ui/layout/qgspdfexportoptions.ui
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>489</width>
<height>563</height>
<height>484</height>
</rect>
</property>
<property name="windowTitle">
Expand Down Expand Up @@ -159,6 +159,13 @@
</widget>
</widget>
</item>
<item>
<widget class="QTreeView" name="mGeoPdfStructureTree">
<property name="headerHidden">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
Expand Down Expand Up @@ -194,19 +201,6 @@
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
Expand All @@ -223,7 +217,7 @@
<customwidget>
<class>QgsCollapsibleGroupBoxBasic</class>
<extends>QGroupBox</extends>
<header location="global">qgscollapsiblegroupbox.h</header>
<header>qgscollapsiblegroupbox.h</header>
<container>1</container>
</customwidget>
</customwidgets>
Expand Down

0 comments on commit 7c22da0

Please sign in to comment.