From c9ddc9fda05b2fb941bb971d51b8439f6cae9f83 Mon Sep 17 00:00:00 2001 From: Nyall Dawson Date: Sat, 30 Dec 2017 17:54:41 +1000 Subject: [PATCH] Start on ui for configuring reports --- .../core/layout/qgsabstractreportsection.sip | 5 + python/core/layout/qgsreport.sip | 1 + .../layout/qgsreportsectionfieldgroup.sip | 2 + python/core/layout/qgsreportsectionlayout.sip | 1 + src/app/CMakeLists.txt | 4 + src/app/layout/qgslayoutdesignerdialog.cpp | 32 ++- src/app/layout/qgslayoutdesignerdialog.h | 3 + src/app/layout/qgsreportorganizerwidget.cpp | 154 +++++++++++++ src/app/layout/qgsreportorganizerwidget.h | 59 +++++ src/app/layout/qgsreportsectionmodel.cpp | 211 ++++++++++++++++++ src/app/layout/qgsreportsectionmodel.h | 63 ++++++ src/core/layout/qgsabstractreportsection.h | 5 + src/core/layout/qgsreport.h | 1 + .../layout/qgsreportsectionfieldgroup.cpp | 5 + src/core/layout/qgsreportsectionfieldgroup.h | 1 + src/core/layout/qgsreportsectionlayout.h | 1 + src/ui/layout/qgsreportorganizerwidgetbase.ui | 150 +++++++++++++ 17 files changed, 697 insertions(+), 1 deletion(-) create mode 100644 src/app/layout/qgsreportorganizerwidget.cpp create mode 100644 src/app/layout/qgsreportorganizerwidget.h create mode 100644 src/app/layout/qgsreportsectionmodel.cpp create mode 100644 src/app/layout/qgsreportsectionmodel.h create mode 100644 src/ui/layout/qgsreportorganizerwidgetbase.ui diff --git a/python/core/layout/qgsabstractreportsection.sip b/python/core/layout/qgsabstractreportsection.sip index bdf85bd996c..56f330782a3 100644 --- a/python/core/layout/qgsabstractreportsection.sip +++ b/python/core/layout/qgsabstractreportsection.sip @@ -69,6 +69,11 @@ Note that ownership is not transferred to ``parent``. virtual QString type() const = 0; %Docstring Returns the section subclass type. +%End + + virtual QString description() const = 0; +%Docstring +Returns a user-visible, translated description of the section. %End virtual QgsAbstractReportSection *clone() const = 0 /Factory/; diff --git a/python/core/layout/qgsreport.sip b/python/core/layout/qgsreport.sip index 306b9eea3b3..e8ce2be53a2 100644 --- a/python/core/layout/qgsreport.sip +++ b/python/core/layout/qgsreport.sip @@ -39,6 +39,7 @@ Note that ownership is not transferred to ``project``. %End virtual QString type() const; + virtual QString description() const; virtual QIcon icon() const; virtual QgsProject *layoutProject() const; diff --git a/python/core/layout/qgsreportsectionfieldgroup.sip b/python/core/layout/qgsreportsectionfieldgroup.sip index c47241fe943..88adc6dcb61 100644 --- a/python/core/layout/qgsreportsectionfieldgroup.sip +++ b/python/core/layout/qgsreportsectionfieldgroup.sip @@ -35,6 +35,8 @@ Note that ownership is not transferred to ``parent``. %End virtual QString type() const; + virtual QString description() const; + QgsLayout *body(); %Docstring diff --git a/python/core/layout/qgsreportsectionlayout.sip b/python/core/layout/qgsreportsectionlayout.sip index b97688db097..61992e7089c 100644 --- a/python/core/layout/qgsreportsectionlayout.sip +++ b/python/core/layout/qgsreportsectionlayout.sip @@ -34,6 +34,7 @@ Note that ownership is not transferred to ``parent``. %End virtual QString type() const; + virtual QString description() const; QgsLayout *body(); %Docstring diff --git a/src/app/CMakeLists.txt b/src/app/CMakeLists.txt index 744a4208a10..852457603ce 100644 --- a/src/app/CMakeLists.txt +++ b/src/app/CMakeLists.txt @@ -204,6 +204,8 @@ SET(QGIS_APP_SRCS layout/qgslayoutscalebarwidget.cpp layout/qgslayoutshapewidget.cpp layout/qgslayouttablebackgroundcolorsdialog.cpp + layout/qgsreportorganizerwidget.cpp + layout/qgsreportsectionmodel.cpp locator/qgsinbuiltlocatorfilters.cpp locator/qgslocatoroptionswidget.cpp @@ -423,6 +425,8 @@ SET (QGIS_APP_MOC_HDRS layout/qgslayoutscalebarwidget.h layout/qgslayoutshapewidget.h layout/qgslayouttablebackgroundcolorsdialog.h + layout/qgsreportorganizerwidget.h + layout/qgsreportsectionmodel.h locator/qgsinbuiltlocatorfilters.h locator/qgslocatoroptionswidget.h diff --git a/src/app/layout/qgslayoutdesignerdialog.cpp b/src/app/layout/qgslayoutdesignerdialog.cpp index 27ab561ec2c..d2d0a5958ef 100644 --- a/src/app/layout/qgslayoutdesignerdialog.cpp +++ b/src/app/layout/qgslayoutdesignerdialog.cpp @@ -60,6 +60,7 @@ #include "qgslayoutatlaswidget.h" #include "qgslayoutpagecollection.h" #include "qgsreport.h" +#include "qgsreportorganizerwidget.h" #include "ui_qgssvgexportoptions.h" #include #include @@ -646,6 +647,9 @@ QgsLayoutDesignerDialog::QgsLayoutDesignerDialog( QWidget *parent, Qt::WindowFla mAtlasDock = new QgsDockWidget( tr( "Atlas" ), this ); mAtlasDock->setObjectName( QStringLiteral( "AtlasDock" ) ); + mReportDock = new QgsDockWidget( tr( "Report" ), this ); + mReportDock->setObjectName( QStringLiteral( "ReportDock" ) ); + const QList docks = findChildren(); for ( QDockWidget *dock : docks ) { @@ -658,6 +662,7 @@ QgsLayoutDesignerDialog::QgsLayoutDesignerDialog( QWidget *parent, Qt::WindowFla addDockWidget( Qt::RightDockWidgetArea, mUndoDock ); addDockWidget( Qt::RightDockWidgetArea, mItemsDock ); addDockWidget( Qt::RightDockWidgetArea, mAtlasDock ); + addDockWidget( Qt::RightDockWidgetArea, mReportDock ); createLayoutPropertiesWidget(); @@ -665,6 +670,7 @@ QgsLayoutDesignerDialog::QgsLayoutDesignerDialog( QWidget *parent, Qt::WindowFla mItemDock->show(); mGeneralDock->show(); mAtlasDock->show(); + mReportDock->show(); mItemsDock->show(); tabifyDockWidget( mGeneralDock, mUndoDock ); @@ -672,6 +678,7 @@ QgsLayoutDesignerDialog::QgsLayoutDesignerDialog( QWidget *parent, Qt::WindowFla tabifyDockWidget( mGeneralDock, mItemDock ); tabifyDockWidget( mItemDock, mItemsDock ); tabifyDockWidget( mItemDock, mAtlasDock ); + tabifyDockWidget( mItemDock, mReportDock ); toggleActions( false ); @@ -739,6 +746,19 @@ void QgsLayoutDesignerDialog::setMasterLayout( QgsMasterLayoutInterface *layout mMenuAtlas = nullptr; mAtlasToolbar->hide(); } + + if ( dynamic_cast< QgsReport * >( layout ) ) + { + createReportWidget(); + } + else + { + // ideally we'd only create mReportDock in createReportWidget() - + // but if we do that, then it's always brought to the focus + // in tab widgets + mReportDock->hide(); + mPanelsMenu->removeAction( mReportDock->toggleViewAction() ); + } } QgsMasterLayoutInterface *QgsLayoutDesignerDialog::masterLayout() @@ -2680,7 +2700,7 @@ void QgsLayoutDesignerDialog::createLayoutPropertiesWidget() void QgsLayoutDesignerDialog::createAtlasWidget() { - QgsPrintLayout *printLayout = qobject_cast< QgsPrintLayout * >( mLayout ); + QgsPrintLayout *printLayout = dynamic_cast< QgsPrintLayout * >( mMasterLayout ); QgsLayoutAtlas *atlas = printLayout->atlas(); QgsLayoutAtlasWidget *atlasWidget = new QgsLayoutAtlasWidget( mAtlasDock, printLayout ); atlasWidget->setMessageBar( mMessageBar ); @@ -2700,6 +2720,16 @@ void QgsLayoutDesignerDialog::createAtlasWidget() toggleAtlasControls( atlas->enabled() && atlas->coverageLayer() ); } +void QgsLayoutDesignerDialog::createReportWidget() +{ + QgsReport *report = dynamic_cast< QgsReport * >( mMasterLayout ); + QgsReportOrganizerWidget *reportWidget = new QgsReportOrganizerWidget( mReportDock, this, report ); + reportWidget->setMessageBar( mMessageBar ); + mReportDock->setWidget( reportWidget ); + + mPanelsMenu->addAction( mReportDock->toggleViewAction() ); +} + void QgsLayoutDesignerDialog::initializeRegistry() { sInitializedRegistry = true; diff --git a/src/app/layout/qgslayoutdesignerdialog.h b/src/app/layout/qgslayoutdesignerdialog.h index 6f7eff3b4eb..7a651b00cf5 100644 --- a/src/app/layout/qgslayoutdesignerdialog.h +++ b/src/app/layout/qgslayoutdesignerdialog.h @@ -373,6 +373,8 @@ class QgsLayoutDesignerDialog: public QMainWindow, private Ui::QgsLayoutDesigner QgsDockWidget *mItemsDock = nullptr; QgsLayoutItemsListView *mItemsTreeView = nullptr; + QgsDockWidget *mReportDock = nullptr; + QAction *mUndoAction = nullptr; QAction *mRedoAction = nullptr; //! Copy/cut/paste actions @@ -406,6 +408,7 @@ class QgsLayoutDesignerDialog: public QMainWindow, private Ui::QgsLayoutDesigner void createLayoutPropertiesWidget(); void createAtlasWidget(); + void createReportWidget(); void initializeRegistry(); diff --git a/src/app/layout/qgsreportorganizerwidget.cpp b/src/app/layout/qgsreportorganizerwidget.cpp new file mode 100644 index 00000000000..48bc3ff3ddf --- /dev/null +++ b/src/app/layout/qgsreportorganizerwidget.cpp @@ -0,0 +1,154 @@ +/*************************************************************************** + qgsreportorganizerwidget.cpp + ------------------------ + begin : December 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 "qgsreportorganizerwidget.h" +#include "qgsreport.h" +#include "qgsreportsectionmodel.h" +#include "qgsreportsectionlayout.h" +#include "qgsreportsectionfieldgroup.h" +#include "qgslayout.h" +#include "qgslayoutdesignerdialog.h" +#include +#include + +#ifdef ENABLE_MODELTEST +#include "modeltest.h" +#endif + +QgsReportOrganizerWidget::QgsReportOrganizerWidget( QWidget *parent, QgsLayoutDesignerDialog *designer, QgsReport *report ) + : QgsPanelWidget( parent ) + , mReport( report ) + , mDesigner( designer ) +{ + setupUi( this ); + setPanelTitle( tr( "Report" ) ); + + mSectionModel = new QgsReportSectionModel( mReport, mViewSections ); + mViewSections->setModel( mSectionModel ); + +#ifdef ENABLE_MODELTEST + //new ModelTest( mSectionModel, this ); +#endif + + mViewSections->setEditTriggers( QAbstractItemView::AllEditTriggers ); + + QMenu *addMenu = new QMenu( mButtonAddSection ); + QAction *layoutSection = new QAction( tr( "Single section" ), addMenu ); + addMenu->addAction( layoutSection ); + connect( layoutSection, &QAction::triggered, this, &QgsReportOrganizerWidget::addLayoutSection ); + QAction *fieldGroupSection = new QAction( tr( "Field group" ), addMenu ); + addMenu->addAction( fieldGroupSection ); + connect( fieldGroupSection, &QAction::triggered, this, &QgsReportOrganizerWidget::addFieldGroupSection ); + + connect( mCheckShowHeader, &QCheckBox::toggled, this, &QgsReportOrganizerWidget::toggleHeader ); + connect( mCheckShowFooter, &QCheckBox::toggled, this, &QgsReportOrganizerWidget::toggleFooter ); + connect( mButtonEditHeader, &QPushButton::clicked, this, &QgsReportOrganizerWidget::editHeader ); + connect( mButtonEditFooter, &QPushButton::clicked, this, &QgsReportOrganizerWidget::editFooter ); + connect( mViewSections->selectionModel(), &QItemSelectionModel::currentChanged, this, &QgsReportOrganizerWidget::selectionChanged ); + + mButtonAddSection->setMenu( addMenu ); + connect( mButtonRemoveSection, &QPushButton::clicked, this, &QgsReportOrganizerWidget::removeSection ); +} + +void QgsReportOrganizerWidget::setMessageBar( QgsMessageBar *bar ) +{ + mMessageBar = bar; +} + +void QgsReportOrganizerWidget::addLayoutSection() +{ + std::unique_ptr< QgsReportSectionLayout > section = qgis::make_unique< QgsReportSectionLayout >(); + mSectionModel->addSection( mViewSections->currentIndex(), std::move( section ) ); +} + +void QgsReportOrganizerWidget::addFieldGroupSection() +{ + std::unique_ptr< QgsReportSectionFieldGroup > section = qgis::make_unique< QgsReportSectionFieldGroup >(); + mSectionModel->addSection( mViewSections->currentIndex(), std::move( section ) ); +} + +void QgsReportOrganizerWidget::removeSection() +{ + QgsAbstractReportSection *section = mSectionModel->sectionForIndex( mViewSections->currentIndex() ); + if ( dynamic_cast< QgsReport * >( section ) ) + return; //report cannot be removed + + int res = QMessageBox::question( this, tr( "Remove Section" ), + tr( "Are you sure you want to remove the report section?" ), + QMessageBox::Yes | QMessageBox::No, QMessageBox::No ); + if ( res == QMessageBox::No ) + return; + + mSectionModel->removeRow( mViewSections->currentIndex().row(), mViewSections->currentIndex().parent() ); +} + +void QgsReportOrganizerWidget::toggleHeader( bool enabled ) +{ + QgsAbstractReportSection *parent = mSectionModel->sectionForIndex( mViewSections->currentIndex() ); + if ( !parent ) + parent = mReport; + parent->setHeaderEnabled( enabled ); +} + +void QgsReportOrganizerWidget::toggleFooter( bool enabled ) +{ + QgsAbstractReportSection *parent = mSectionModel->sectionForIndex( mViewSections->currentIndex() ); + if ( !parent ) + parent = mReport; + parent->setFooterEnabled( enabled ); +} + +void QgsReportOrganizerWidget::editHeader() +{ + QgsAbstractReportSection *parent = mSectionModel->sectionForIndex( mViewSections->currentIndex() ); + if ( !parent ) + parent = mReport; + + if ( !parent->header() ) + { + std::unique_ptr< QgsLayout > header = qgis::make_unique< QgsLayout >( mReport->layoutProject() ); + header->initializeDefaults(); + parent->setHeader( header.release() ); + } + + mDesigner->setCurrentLayout( parent->header() ); +} + +void QgsReportOrganizerWidget::editFooter() +{ + QgsAbstractReportSection *parent = mSectionModel->sectionForIndex( mViewSections->currentIndex() ); + if ( !parent ) + parent = mReport; + + if ( !parent->footer() ) + { + std::unique_ptr< QgsLayout > footer = qgis::make_unique< QgsLayout >( mReport->layoutProject() ); + footer->initializeDefaults(); + parent->setFooter( footer.release() ); + } + + mDesigner->setCurrentLayout( parent->footer() ); +} + +void QgsReportOrganizerWidget::selectionChanged( const QModelIndex ¤t, const QModelIndex & ) +{ + QgsAbstractReportSection *parent = mSectionModel->sectionForIndex( current ); + if ( !parent ) + parent = mReport; + + whileBlocking( mCheckShowHeader )->setChecked( parent->headerEnabled() ); + whileBlocking( mCheckShowFooter )->setChecked( parent->footerEnabled() ); +} diff --git a/src/app/layout/qgsreportorganizerwidget.h b/src/app/layout/qgsreportorganizerwidget.h new file mode 100644 index 00000000000..28b1ec29a51 --- /dev/null +++ b/src/app/layout/qgsreportorganizerwidget.h @@ -0,0 +1,59 @@ +/*************************************************************************** + qgsreportorganizerwidget.h + ---------------------- + begin : December 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. * + * * + ***************************************************************************/ + +#ifndef QGSREPORTORGANIZERWIDGET_H +#define QGSREPORTORGANIZERWIDGET_H + +#include "ui_qgsreportorganizerwidgetbase.h" +#include "qgspanelwidget.h" +#include + +class QgsReportSectionModel; +class QgsReport; +class QgsMessageBar; +class QgsLayoutDesignerDialog ; + +class QgsReportOrganizerWidget: public QgsPanelWidget, private Ui::QgsReportOrganizerBase +{ + Q_OBJECT + public: + QgsReportOrganizerWidget( QWidget *parent, QgsLayoutDesignerDialog *designer, QgsReport *report ); + + void setMessageBar( QgsMessageBar *bar ); + + private slots: + + void addLayoutSection(); + void addFieldGroupSection(); + void removeSection(); + void toggleHeader( bool enabled ); + void toggleFooter( bool enabled ); + void editHeader(); + void editFooter(); + void selectionChanged( const QModelIndex ¤t, const QModelIndex &previous ); + + private: + + QgsReport *mReport = nullptr; + QgsReportSectionModel *mSectionModel = nullptr; + QgsMessageBar *mMessageBar; + QgsLayoutDesignerDialog *mDesigner = nullptr; + +}; + + + +#endif // QGSREPORTORGANIZERWIDGET_H diff --git a/src/app/layout/qgsreportsectionmodel.cpp b/src/app/layout/qgsreportsectionmodel.cpp new file mode 100644 index 00000000000..e59e89df01e --- /dev/null +++ b/src/app/layout/qgsreportsectionmodel.cpp @@ -0,0 +1,211 @@ +/*************************************************************************** + qgsreportsectionmodel.cpp + --------------------- + begin : December 2017 + copyright : (C) 2017 by Nyall Dawso + 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 "qgsreportsectionmodel.h" + +#ifdef ENABLE_MODELTEST +#include "modeltest.h" +#endif + +QgsReportSectionModel::QgsReportSectionModel( QgsReport *report, QObject *parent ) + : QAbstractItemModel( parent ) + , mReport( report ) +{ +} + +Qt::ItemFlags QgsReportSectionModel::flags( const QModelIndex &index ) const +{ + if ( !index.isValid() ) + return 0; + + return QAbstractItemModel::flags( index ); +} + +QVariant QgsReportSectionModel::data( const QModelIndex &index, int role ) const +{ + if ( !index.isValid() ) + return QVariant(); + + QgsAbstractReportSection *section = sectionForIndex( index ); + if ( !section ) + return QVariant(); + + switch ( role ) + { + case Qt::DisplayRole: + case Qt::ToolTipRole: + { + switch ( index.column() ) + { + case 0: + return section->description(); + default: + return QVariant(); + } + break; + } + + case Qt::TextAlignmentRole: + { + return ( index.column() == 2 || index.column() == 3 ) ? Qt::AlignRight : Qt::AlignLeft; + } + + case Qt::EditRole: + { + switch ( index.column() ) + { + case 0: + return section->type(); + + default: + return QVariant(); + } + break; + } + + default: + return QVariant(); + } + + return QVariant(); +} + +QVariant QgsReportSectionModel::headerData( int section, Qt::Orientation orientation, int role ) const +{ + if ( orientation == Qt::Horizontal && role == Qt::DisplayRole && section >= 0 && section <= 0 ) + { + QStringList lst; + lst << tr( "Section" ); + return lst[section]; + } + + return QVariant(); +} + +int QgsReportSectionModel::rowCount( const QModelIndex &parent ) const +{ + QgsAbstractReportSection *parentSection = nullptr; + if ( parent.column() > 0 ) + return 0; + + if ( !parent.isValid() ) + parentSection = mReport; + else + parentSection = sectionForIndex( parent ); + + return parentSection->childCount(); +} + +int QgsReportSectionModel::columnCount( const QModelIndex & ) const +{ + return 1; +} + +QModelIndex QgsReportSectionModel::index( int row, int column, const QModelIndex &parent ) const +{ + if ( !hasIndex( row, column, parent ) ) + return QModelIndex(); + + QgsAbstractReportSection *parentSection = nullptr; + + if ( !parent.isValid() ) + parentSection = mReport; + else + parentSection = sectionForIndex( parent ); + + QgsAbstractReportSection *childSection = parentSection->childSection( row ); + if ( childSection ) + return createIndex( row, column, childSection ); + else + return QModelIndex(); +} + +QModelIndex QgsReportSectionModel::parent( const QModelIndex &index ) const +{ + if ( !index.isValid() ) + return QModelIndex(); + + QgsAbstractReportSection *childSection = sectionForIndex( index ); + QgsAbstractReportSection *parentSection = childSection->parentSection(); + + if ( parentSection == mReport ) + return QModelIndex(); + + return createIndex( parentSection->row(), 0, parentSection ); +} + +bool QgsReportSectionModel::setData( const QModelIndex &index, const QVariant &value, int role ) +{ + if ( !index.isValid() ) + return false; + + QgsAbstractReportSection *section = sectionForIndex( index ); + ( void )section; + ( void )value; + + if ( role != Qt::EditRole ) + return false; + + switch ( index.column() ) + { + case 0: + return false; + + default: + return false; + } + + emit dataChanged( index, index ); + return true; +} + +QgsAbstractReportSection *QgsReportSectionModel::sectionForIndex( const QModelIndex &index ) const +{ + return static_cast( index.internalPointer() ); +} + +bool QgsReportSectionModel::removeRows( int row, int count, const QModelIndex &parent ) +{ + QgsAbstractReportSection *parentSection = sectionForIndex( parent ); + + if ( row < 0 || row >= parentSection->childCount() ) + return false; + + beginRemoveRows( parent, row, row + count - 1 ); + + for ( int i = 0; i < count; i++ ) + { + if ( row < parentSection->childCount() ) + { + parentSection->removeChildAt( row ); + } + } + + endRemoveRows(); + + return true; +} + +void QgsReportSectionModel::addSection( const QModelIndex &parent, std::unique_ptr section ) +{ + QgsAbstractReportSection *parentSection = sectionForIndex( parent ); + if ( !parentSection ) + return; + + beginInsertRows( parent, parentSection->childCount(), parentSection->childCount() ); + parentSection->appendChild( section.release() ); + endInsertRows(); +} + diff --git a/src/app/layout/qgsreportsectionmodel.h b/src/app/layout/qgsreportsectionmodel.h new file mode 100644 index 00000000000..09dfcc3d815 --- /dev/null +++ b/src/app/layout/qgsreportsectionmodel.h @@ -0,0 +1,63 @@ +/*************************************************************************** + qgsreportsectionmodel.h + --------------------- + begin : December 2017 + copyright : (C) 2017 by Nyall Dawso + 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 QGSREPORTSECTIONMODEL_H +#define QGSREPORTSECTIONMODEL_H + +#include "qgis.h" +#include "qgsreport.h" +#include + +/** + * \ingroup app + * \class QgsReportSectionModel + * \brief A model for managing the sections in a QgsReport. + * \since QGIS 3.0 + */ +class QgsReportSectionModel : public QAbstractItemModel +{ + Q_OBJECT + + public: + + /** + * Constructor for QgsReportSectionModel, for the specified \a report. + */ + QgsReportSectionModel( QgsReport *report, QObject *parent ); + + Qt::ItemFlags flags( const QModelIndex &index ) const override; + QVariant data( const QModelIndex &index, int role = Qt::DisplayRole ) const override; + QVariant headerData( int section, Qt::Orientation orientation, + int role = Qt::DisplayRole ) const override; + int rowCount( const QModelIndex &parent = QModelIndex() ) const override; + int columnCount( const QModelIndex & = QModelIndex() ) const override; + + QModelIndex index( int row, int column, const QModelIndex &parent = QModelIndex() ) const override; + QModelIndex parent( const QModelIndex &index ) const override; + bool setData( const QModelIndex &index, const QVariant &value, int role = Qt::EditRole ) override; + bool removeRows( int row, int count, const QModelIndex &parent = QModelIndex() ) override; + + void addSection( const QModelIndex &parent, std::unique_ptr< QgsAbstractReportSection > section ); + + /** + * Returns the report section for the given \a index. + */ + QgsAbstractReportSection *sectionForIndex( const QModelIndex &index ) const; + + private: + QgsReport *mReport = nullptr; +}; + +#endif // QGSREPORTSECTIONMODEL_H diff --git a/src/core/layout/qgsabstractreportsection.h b/src/core/layout/qgsabstractreportsection.h index b350cf2bbc0..6b1d21f5906 100644 --- a/src/core/layout/qgsabstractreportsection.h +++ b/src/core/layout/qgsabstractreportsection.h @@ -85,6 +85,11 @@ class CORE_EXPORT QgsAbstractReportSection : public QgsAbstractLayoutIterator */ virtual QString type() const = 0; + /** + * Returns a user-visible, translated description of the section. + */ + virtual QString description() const = 0; + /** * Clones the report section. Ownership of the returned section is * transferred to the caller. diff --git a/src/core/layout/qgsreport.h b/src/core/layout/qgsreport.h index 8ead5c779ad..2fbb7e335ec 100644 --- a/src/core/layout/qgsreport.h +++ b/src/core/layout/qgsreport.h @@ -53,6 +53,7 @@ class CORE_EXPORT QgsReport : public QObject, public QgsAbstractReportSection, p QgsReport( QgsProject *project ); QString type() const override { return QStringLiteral( "SectionReport" ); } + QString description() const override { return QObject::tr( "Report" ); } QIcon icon() const override; QgsProject *layoutProject() const override { return mProject; } QgsReport *clone() const override SIP_FACTORY; diff --git a/src/core/layout/qgsreportsectionfieldgroup.cpp b/src/core/layout/qgsreportsectionfieldgroup.cpp index 24cdb38360f..14eb9729de6 100644 --- a/src/core/layout/qgsreportsectionfieldgroup.cpp +++ b/src/core/layout/qgsreportsectionfieldgroup.cpp @@ -25,6 +25,11 @@ QgsReportSectionFieldGroup::QgsReportSectionFieldGroup( QgsAbstractReportSection } +QString QgsReportSectionFieldGroup::description() const +{ + return QObject::tr( "Group: %1" ).arg( mField ); +} + QgsReportSectionFieldGroup *QgsReportSectionFieldGroup::clone() const { std::unique_ptr< QgsReportSectionFieldGroup > copy = qgis::make_unique< QgsReportSectionFieldGroup >( nullptr ); diff --git a/src/core/layout/qgsreportsectionfieldgroup.h b/src/core/layout/qgsreportsectionfieldgroup.h index 8cb9f65d08b..bb2e248fa86 100644 --- a/src/core/layout/qgsreportsectionfieldgroup.h +++ b/src/core/layout/qgsreportsectionfieldgroup.h @@ -45,6 +45,7 @@ class CORE_EXPORT QgsReportSectionFieldGroup : public QgsAbstractReportSection QgsReportSectionFieldGroup( QgsAbstractReportSection *parentSection = nullptr ); QString type() const override { return QStringLiteral( "SectionFieldGroup" ); } + QString description() const override; /** * Returns the body layout for the section. diff --git a/src/core/layout/qgsreportsectionlayout.h b/src/core/layout/qgsreportsectionlayout.h index c683c8deecf..e60dbbc5acb 100644 --- a/src/core/layout/qgsreportsectionlayout.h +++ b/src/core/layout/qgsreportsectionlayout.h @@ -42,6 +42,7 @@ class CORE_EXPORT QgsReportSectionLayout : public QgsAbstractReportSection QgsReportSectionLayout( QgsAbstractReportSection *parentSection = nullptr ); QString type() const override { return QStringLiteral( "SectionLayout" ); } + QString description() const override { return QObject::tr( "Section" ); } /** * Returns the body layout for the section. diff --git a/src/ui/layout/qgsreportorganizerwidgetbase.ui b/src/ui/layout/qgsreportorganizerwidgetbase.ui new file mode 100644 index 00000000000..481f8cc5c41 --- /dev/null +++ b/src/ui/layout/qgsreportorganizerwidgetbase.ui @@ -0,0 +1,150 @@ + + + QgsReportOrganizerBase + + + + 0 + 0 + 723 + 520 + + + + + 425 + 300 + + + + Layout Manager + + + + + + Qt::CustomContextMenu + + + true + + + QAbstractItemView::EditKeyPressed|QAbstractItemView::SelectedClicked + + + true + + + QAbstractItemView::InternalMove + + + QAbstractItemView::ExtendedSelection + + + true + + + 100 + + + true + + + + + + + + + Add rule + + + + + + + :/images/themes/default/symbologyAdd.svg:/images/themes/default/symbologyAdd.svg + + + + + + + Remove selected rules + + + + + + + :/images/themes/default/symbologyRemove.svg:/images/themes/default/symbologyRemove.svg + + + + + + + Qt::Horizontal + + + + 0 + 20 + + + + + + + + + + + + Edit + + + + + + + Show header + + + + + + + Edit + + + + + + + Show footer + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + +