mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-16 00:03:12 -04:00
[composer] Port composer manager to layout manager
Also switch to using a proper model to show/edit compositions in the dialog.
This commit is contained in:
parent
3aef32a191
commit
53160c7b21
@ -22,9 +22,13 @@ class QgsLayoutManager : QObject
|
|||||||
QString generateUniqueTitle() const;
|
QString generateUniqueTitle() const;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void compositionAdded( const QString& name );
|
|
||||||
void compositionRemoved( const QString& name );
|
void compositionAboutToBeAdded( const QString &name );
|
||||||
void compositionAboutToBeRemoved( const QString& name );
|
void compositionAdded( const QString &name );
|
||||||
|
void compositionRemoved( const QString &name );
|
||||||
|
void compositionAboutToBeRemoved( const QString &name );
|
||||||
|
void compositionRenamed( QgsComposition *composition, const QString &newName );
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -23,6 +23,8 @@
|
|||||||
#include "qgslogger.h"
|
#include "qgslogger.h"
|
||||||
#include "qgssettings.h"
|
#include "qgssettings.h"
|
||||||
#include "qgscomposerview.h"
|
#include "qgscomposerview.h"
|
||||||
|
#include "qgslayoutmanager.h"
|
||||||
|
#include "qgsproject.h"
|
||||||
|
|
||||||
#include <QDesktopServices>
|
#include <QDesktopServices>
|
||||||
#include <QDialog>
|
#include <QDialog>
|
||||||
@ -40,25 +42,25 @@ QgsComposerManager::QgsComposerManager( QWidget *parent, Qt::WindowFlags f ): QD
|
|||||||
QgsSettings settings;
|
QgsSettings settings;
|
||||||
restoreGeometry( settings.value( QStringLiteral( "Windows/ComposerManager/geometry" ) ).toByteArray() );
|
restoreGeometry( settings.value( QStringLiteral( "Windows/ComposerManager/geometry" ) ).toByteArray() );
|
||||||
|
|
||||||
mComposerListWidget->setItemDelegate( new QgsComposerNameDelegate( mComposerListWidget ) );
|
mModel = new QgsLayoutManagerModel( QgsProject::instance()->layoutManager(),
|
||||||
|
this );
|
||||||
|
mComposerListView->setModel( mModel );
|
||||||
|
|
||||||
connect( mButtonBox, SIGNAL( rejected() ), this, SLOT( close() ) );
|
connect( mButtonBox, &QDialogButtonBox::rejected, this, &QWidget::close );
|
||||||
//connect( QgisApp::instance(), &QgisApp::composerAdded, this, &QgsComposerManager::refreshComposers );
|
connect( mComposerListView->selectionModel(), &QItemSelectionModel::selectionChanged,
|
||||||
//connect( QgisApp::instance(), &QgisApp::composerRemoved, this, &QgsComposerManager::refreshComposers );
|
this, &QgsComposerManager::toggleButtons );
|
||||||
|
|
||||||
connect( mComposerListWidget, SIGNAL( itemSelectionChanged() ), this, SLOT( toggleButtons() ) );
|
|
||||||
|
|
||||||
mShowButton = mButtonBox->addButton( tr( "&Show" ), QDialogButtonBox::ActionRole );
|
mShowButton = mButtonBox->addButton( tr( "&Show" ), QDialogButtonBox::ActionRole );
|
||||||
connect( mShowButton, SIGNAL( clicked() ), this, SLOT( show_clicked() ) );
|
connect( mShowButton, &QAbstractButton::clicked, this, &QgsComposerManager::showClicked );
|
||||||
|
|
||||||
mDuplicateButton = mButtonBox->addButton( tr( "&Duplicate" ), QDialogButtonBox::ActionRole );
|
mDuplicateButton = mButtonBox->addButton( tr( "&Duplicate" ), QDialogButtonBox::ActionRole );
|
||||||
connect( mDuplicateButton, SIGNAL( clicked() ), this, SLOT( duplicate_clicked() ) );
|
connect( mDuplicateButton, &QAbstractButton::clicked, this, &QgsComposerManager::duplicateClicked );
|
||||||
|
|
||||||
mRemoveButton = mButtonBox->addButton( tr( "&Remove" ), QDialogButtonBox::ActionRole );
|
mRemoveButton = mButtonBox->addButton( tr( "&Remove" ), QDialogButtonBox::ActionRole );
|
||||||
connect( mRemoveButton, SIGNAL( clicked() ), this, SLOT( remove_clicked() ) );
|
connect( mRemoveButton, &QAbstractButton::clicked, this, &QgsComposerManager::removeClicked );
|
||||||
|
|
||||||
mRenameButton = mButtonBox->addButton( tr( "Re&name" ), QDialogButtonBox::ActionRole );
|
mRenameButton = mButtonBox->addButton( tr( "Re&name" ), QDialogButtonBox::ActionRole );
|
||||||
connect( mRenameButton, SIGNAL( clicked() ), this, SLOT( rename_clicked() ) );
|
connect( mRenameButton, &QAbstractButton::clicked, this, &QgsComposerManager::renameClicked );
|
||||||
|
|
||||||
#ifdef Q_OS_MAC
|
#ifdef Q_OS_MAC
|
||||||
// Create action to select this window
|
// Create action to select this window
|
||||||
@ -79,8 +81,6 @@ QgsComposerManager::QgsComposerManager( QWidget *parent, Qt::WindowFlags f ): QD
|
|||||||
this->addTemplates( this->otherTemplates() );
|
this->addTemplates( this->otherTemplates() );
|
||||||
|
|
||||||
mTemplatePathLineEdit->setText( settings.value( QStringLiteral( "UI/ComposerManager/templatePath" ), QString() ).toString() );
|
mTemplatePathLineEdit->setText( settings.value( QStringLiteral( "UI/ComposerManager/templatePath" ), QString() ).toString() );
|
||||||
|
|
||||||
refreshComposers();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QgsComposerManager::~QgsComposerManager()
|
QgsComposerManager::~QgsComposerManager()
|
||||||
@ -89,65 +89,10 @@ QgsComposerManager::~QgsComposerManager()
|
|||||||
settings.setValue( QStringLiteral( "Windows/ComposerManager/geometry" ), saveGeometry() );
|
settings.setValue( QStringLiteral( "Windows/ComposerManager/geometry" ), saveGeometry() );
|
||||||
}
|
}
|
||||||
|
|
||||||
void QgsComposerManager::refreshComposers()
|
|
||||||
{
|
|
||||||
// Backup selection
|
|
||||||
QSet<QgsComposer *> selectedComposers;
|
|
||||||
Q_FOREACH ( QListWidgetItem *item, mComposerListWidget->selectedItems() )
|
|
||||||
{
|
|
||||||
QMap<QListWidgetItem *, QgsComposer *>::const_iterator it = mItemComposerMap.constFind( item );
|
|
||||||
if ( it != mItemComposerMap.constEnd() )
|
|
||||||
{
|
|
||||||
selectedComposers << it.value();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mItemComposerMap.clear();
|
|
||||||
mComposerListWidget->clear();
|
|
||||||
|
|
||||||
QSet<QgsComposer *> composers = QgisApp::instance()->printComposers();
|
|
||||||
QSet<QgsComposer *>::const_iterator it = composers.constBegin();
|
|
||||||
for ( ; it != composers.constEnd(); ++it )
|
|
||||||
{
|
|
||||||
QListWidgetItem *item = new QListWidgetItem( ( *it )->composition()->name(), mComposerListWidget );
|
|
||||||
item->setFlags( Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable );
|
|
||||||
mItemComposerMap.insert( item, *it );
|
|
||||||
}
|
|
||||||
mComposerListWidget->sortItems();
|
|
||||||
|
|
||||||
// Restore selection
|
|
||||||
bool selectionRestored = false;
|
|
||||||
if ( !selectedComposers.isEmpty() )
|
|
||||||
{
|
|
||||||
QMap<QListWidgetItem *, QgsComposer *>::const_iterator i = mItemComposerMap.constBegin();
|
|
||||||
while ( i != mItemComposerMap.constEnd() )
|
|
||||||
{
|
|
||||||
// This composer was selected: reselect it !
|
|
||||||
if ( selectedComposers.contains( i.value() ) )
|
|
||||||
{
|
|
||||||
selectionRestored = true;
|
|
||||||
int index = mComposerListWidget->row( i.key() );
|
|
||||||
QModelIndex selectLine = mComposerListWidget->model()->index( index, 0, QModelIndex() );
|
|
||||||
mComposerListWidget->selectionModel()->select( selectLine, QItemSelectionModel::Select );
|
|
||||||
}
|
|
||||||
++i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Select the first item by default
|
|
||||||
if ( !selectionRestored && mComposerListWidget->count() > 0 )
|
|
||||||
{
|
|
||||||
QModelIndex firstLine = mComposerListWidget->model()->index( 0, 0, QModelIndex() );
|
|
||||||
mComposerListWidget->selectionModel()->select( firstLine, QItemSelectionModel::Select );
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update buttons
|
|
||||||
toggleButtons();
|
|
||||||
}
|
|
||||||
|
|
||||||
void QgsComposerManager::toggleButtons()
|
void QgsComposerManager::toggleButtons()
|
||||||
{
|
{
|
||||||
// Nothing selected: no button.
|
// Nothing selected: no button.
|
||||||
if ( mComposerListWidget->selectedItems().isEmpty() )
|
if ( mComposerListView->selectionModel()->selectedRows().isEmpty() )
|
||||||
{
|
{
|
||||||
mShowButton->setEnabled( false );
|
mShowButton->setEnabled( false );
|
||||||
mRemoveButton->setEnabled( false );
|
mRemoveButton->setEnabled( false );
|
||||||
@ -155,7 +100,7 @@ void QgsComposerManager::toggleButtons()
|
|||||||
mDuplicateButton->setEnabled( false );
|
mDuplicateButton->setEnabled( false );
|
||||||
}
|
}
|
||||||
// toggle everything if one composer is selected
|
// toggle everything if one composer is selected
|
||||||
else if ( mComposerListWidget->selectedItems().count() == 1 )
|
else if ( mComposerListView->selectionModel()->selectedRows().count() == 1 )
|
||||||
{
|
{
|
||||||
mShowButton->setEnabled( true );
|
mShowButton->setEnabled( true );
|
||||||
mRemoveButton->setEnabled( true );
|
mRemoveButton->setEnabled( true );
|
||||||
@ -297,7 +242,6 @@ void QgsComposerManager::on_mAddButton_clicked()
|
|||||||
|
|
||||||
if ( !loadedOK )
|
if ( !loadedOK )
|
||||||
{
|
{
|
||||||
newComposer->close();
|
|
||||||
QgisApp::instance()->deleteComposer( newComposer );
|
QgisApp::instance()->deleteComposer( newComposer );
|
||||||
newComposer = nullptr;
|
newComposer = nullptr;
|
||||||
QMessageBox::warning( this, tr( "Template error" ), tr( "Error, could not load template file" ) );
|
QMessageBox::warning( this, tr( "Template error" ), tr( "Error, could not load template file" ) );
|
||||||
@ -376,10 +320,9 @@ void QgsComposerManager::changeEvent( QEvent *event )
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void QgsComposerManager::remove_clicked()
|
void QgsComposerManager::removeClicked()
|
||||||
{
|
{
|
||||||
QList<QgsComposer *> composerList;
|
QModelIndexList composerItems = mComposerListView->selectionModel()->selectedRows();
|
||||||
QList<QListWidgetItem *> composerItems = mComposerListWidget->selectedItems();
|
|
||||||
QString title = tr( "Remove composers" );
|
QString title = tr( "Remove composers" );
|
||||||
QString message = tr( "Do you really want to remove all selected map composers?" );
|
QString message = tr( "Do you really want to remove all selected map composers?" );
|
||||||
|
|
||||||
@ -392,8 +335,8 @@ void QgsComposerManager::remove_clicked()
|
|||||||
if ( composerItems.count() == 1 )
|
if ( composerItems.count() == 1 )
|
||||||
{
|
{
|
||||||
title = tr( "Remove composer" );
|
title = tr( "Remove composer" );
|
||||||
QListWidgetItem *uniqItem = composerItems.at( 0 );
|
message = tr( "Do you really want to remove the map composer '%1'?" ).arg(
|
||||||
message = tr( "Do you really want to remove the map composer '%1'?" ).arg( uniqItem->text() );
|
mComposerListView->model()->data( composerItems.at( 0 ), Qt::DisplayRole ).toString() );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( QMessageBox::warning( this, title, message, QMessageBox::Ok | QMessageBox::Cancel ) != QMessageBox::Ok )
|
if ( QMessageBox::warning( this, title, message, QMessageBox::Ok | QMessageBox::Cancel ) != QMessageBox::Ok )
|
||||||
@ -401,73 +344,47 @@ void QgsComposerManager::remove_clicked()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QList<QgsComposition *> composerList;
|
||||||
// Find the QgsComposers that need to be deleted
|
// Find the QgsComposers that need to be deleted
|
||||||
Q_FOREACH ( QListWidgetItem *item, composerItems )
|
Q_FOREACH ( const QModelIndex &index, composerItems )
|
||||||
{
|
{
|
||||||
QMap<QListWidgetItem *, QgsComposer *>::const_iterator it = mItemComposerMap.constFind( item );
|
QgsComposition *c = mModel->compositionFromIndex( index );
|
||||||
if ( it != mItemComposerMap.constEnd() )
|
if ( c )
|
||||||
{
|
{
|
||||||
composerList << it.value();
|
composerList << c;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Once we have the composer list, we can delete all of them !
|
// Once we have the composer list, we can delete all of them !
|
||||||
Q_FOREACH ( QgsComposer *c, composerList )
|
Q_FOREACH ( QgsComposition *c, composerList )
|
||||||
{
|
{
|
||||||
QgisApp::instance()->deleteComposer( c );
|
QgsProject::instance()->layoutManager()->removeComposition( c );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QgsComposerManager::show_clicked()
|
void QgsComposerManager::showClicked()
|
||||||
{
|
{
|
||||||
Q_FOREACH ( QListWidgetItem *item, mComposerListWidget->selectedItems() )
|
Q_FOREACH ( const QModelIndex &index, mComposerListView->selectionModel()->selectedRows() )
|
||||||
{
|
{
|
||||||
QMap<QListWidgetItem *, QgsComposer *>::const_iterator it = mItemComposerMap.constFind( item );
|
QgsComposition *c = mModel->compositionFromIndex( index );
|
||||||
if ( it != mItemComposerMap.constEnd() )
|
|
||||||
{
|
|
||||||
QgsComposer *c = nullptr;
|
|
||||||
if ( it.value() ) //a normal composer
|
|
||||||
{
|
|
||||||
c = it.value();
|
|
||||||
if ( c )
|
if ( c )
|
||||||
{
|
{
|
||||||
// extra activation steps for Windows
|
QgisApp::instance()->openComposer( c );
|
||||||
bool shown = c->isVisible();
|
|
||||||
|
|
||||||
c->activate();
|
|
||||||
|
|
||||||
// extra activation steps for Windows
|
|
||||||
if ( !shown )
|
|
||||||
{
|
|
||||||
c->on_mActionZoomAll_triggered();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QgsComposerManager::duplicate_clicked()
|
void QgsComposerManager::duplicateClicked()
|
||||||
{
|
{
|
||||||
if ( mComposerListWidget->selectedItems().isEmpty() )
|
if ( mComposerListView->selectionModel()->selectedRows().isEmpty() )
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QgsComposer *currentComposer = nullptr;
|
QgsComposition *currentComposer = mModel->compositionFromIndex( mComposerListView->selectionModel()->selectedRows().at( 0 ) );
|
||||||
QString currentTitle;
|
if ( !currentComposer )
|
||||||
|
|
||||||
QListWidgetItem *item = mComposerListWidget->selectedItems().at( 0 );
|
|
||||||
QMap<QListWidgetItem *, QgsComposer *>::const_iterator it = mItemComposerMap.constFind( item );
|
|
||||||
if ( it != mItemComposerMap.constEnd() )
|
|
||||||
{
|
|
||||||
currentComposer = it.value();
|
|
||||||
currentTitle = it.value()->composition()->name();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
QString currentTitle = currentComposer->name();
|
||||||
|
|
||||||
QString newTitle;
|
QString newTitle;
|
||||||
if ( !QgisApp::instance()->uniqueComposerTitle( this, newTitle, false, currentTitle + tr( " copy" ) ) )
|
if ( !QgisApp::instance()->uniqueComposerTitle( this, newTitle, false, currentTitle + tr( " copy" ) ) )
|
||||||
@ -480,121 +397,170 @@ void QgsComposerManager::duplicate_clicked()
|
|||||||
dlg->setStyleSheet( QgisApp::instance()->styleSheet() );
|
dlg->setStyleSheet( QgisApp::instance()->styleSheet() );
|
||||||
dlg->show();
|
dlg->show();
|
||||||
|
|
||||||
QgsComposer *newComposer = QgisApp::instance()->duplicateComposer( currentComposer, newTitle );
|
QgsComposition *newComposition = QgsProject::instance()->layoutManager()->duplicateComposition( currentComposer->name(),
|
||||||
|
newTitle );
|
||||||
|
QgsComposer *newComposer = QgisApp::instance()->openComposer( newComposition );
|
||||||
dlg->close();
|
dlg->close();
|
||||||
delete dlg;
|
delete dlg;
|
||||||
dlg = nullptr;
|
dlg = nullptr;
|
||||||
|
if ( !newComposer )
|
||||||
if ( newComposer )
|
|
||||||
{
|
|
||||||
// extra activation steps for Windows
|
|
||||||
newComposer->activate();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
QMessageBox::warning( this, tr( "Duplicate Composer" ),
|
QMessageBox::warning( this, tr( "Duplicate Composer" ),
|
||||||
tr( "Composer duplication failed." ) );
|
tr( "Composer duplication failed." ) );
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void QgsComposerManager::rename_clicked()
|
|
||||||
{
|
|
||||||
if ( mComposerListWidget->selectedItems().isEmpty() )
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString currentTitle;
|
|
||||||
QgsComposer *currentComposer = nullptr;
|
|
||||||
|
|
||||||
QListWidgetItem *item = mComposerListWidget->selectedItems().at( 0 );
|
|
||||||
QMap<QListWidgetItem *, QgsComposer *>::const_iterator it = mItemComposerMap.constFind( item );
|
|
||||||
if ( it != mItemComposerMap.constEnd() )
|
|
||||||
{
|
|
||||||
currentComposer = it.value();
|
|
||||||
currentTitle = it.value()->composition()->name();
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
newComposer->activate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsComposerManager::renameClicked()
|
||||||
|
{
|
||||||
|
if ( mComposerListView->selectionModel()->selectedRows().isEmpty() )
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QgsComposition *currentComposer = mModel->compositionFromIndex( mComposerListView->selectionModel()->selectedRows().at( 0 ) );
|
||||||
|
if ( !currentComposer )
|
||||||
|
return;
|
||||||
|
|
||||||
|
QString currentTitle = currentComposer->name();
|
||||||
QString newTitle;
|
QString newTitle;
|
||||||
if ( !QgisApp::instance()->uniqueComposerTitle( this, newTitle, false, currentTitle ) )
|
if ( !QgisApp::instance()->uniqueComposerTitle( this, newTitle, false, currentTitle ) )
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
currentComposer->composition()->setName( newTitle );
|
currentComposer->setName( newTitle );
|
||||||
item->setText( newTitle );
|
|
||||||
|
|
||||||
mComposerListWidget->sortItems();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void QgsComposerManager::on_mComposerListWidget_itemChanged( QListWidgetItem *item )
|
//
|
||||||
|
// QgsLayoutManagerModel
|
||||||
|
//
|
||||||
|
|
||||||
|
QgsLayoutManagerModel::QgsLayoutManagerModel( QgsLayoutManager *manager, QObject *parent )
|
||||||
|
: QAbstractListModel( parent )
|
||||||
|
, mLayoutManager( manager )
|
||||||
{
|
{
|
||||||
QMap<QListWidgetItem *, QgsComposer *>::const_iterator it = mItemComposerMap.constFind( item );
|
connect( mLayoutManager, &QgsLayoutManager::compositionAboutToBeAdded, this, &QgsLayoutManagerModel::compositionAboutToBeAdded );
|
||||||
if ( it != mItemComposerMap.constEnd() )
|
connect( mLayoutManager, &QgsLayoutManager::compositionAdded, this, &QgsLayoutManagerModel::compositionAdded );
|
||||||
|
connect( mLayoutManager, &QgsLayoutManager::compositionAboutToBeRemoved, this, &QgsLayoutManagerModel::compositionAboutToBeRemoved );
|
||||||
|
connect( mLayoutManager, &QgsLayoutManager::compositionRemoved, this, &QgsLayoutManagerModel::compositionRemoved );
|
||||||
|
connect( mLayoutManager, &QgsLayoutManager::compositionRenamed, this, &QgsLayoutManagerModel::compositionRenamed );
|
||||||
|
}
|
||||||
|
|
||||||
|
int QgsLayoutManagerModel::rowCount( const QModelIndex &parent ) const
|
||||||
|
{
|
||||||
|
Q_UNUSED( parent );
|
||||||
|
return mLayoutManager->compositions().count();
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant QgsLayoutManagerModel::data( const QModelIndex &index, int role ) const
|
||||||
|
{
|
||||||
|
if ( index.row() < 0 || index.row() >= rowCount( QModelIndex() ) )
|
||||||
|
return QVariant();
|
||||||
|
|
||||||
|
switch ( role )
|
||||||
{
|
{
|
||||||
it.value()->composition()->setName( item->text() );
|
case Qt::DisplayRole:
|
||||||
|
case Qt::ToolTipRole:
|
||||||
|
case Qt::EditRole:
|
||||||
|
return mLayoutManager->compositions().at( index.row() )->name();
|
||||||
|
|
||||||
|
case CompositionRole:
|
||||||
|
return QVariant::fromValue( mLayoutManager->compositions().at( index.row() ) );
|
||||||
|
|
||||||
|
default:
|
||||||
|
return QVariant();
|
||||||
}
|
}
|
||||||
mComposerListWidget->sortItems();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool QgsLayoutManagerModel::setData( const QModelIndex &index, const QVariant &value, int role )
|
||||||
//
|
|
||||||
// QgsComposerNameDelegate
|
|
||||||
//
|
|
||||||
|
|
||||||
QgsComposerNameDelegate::QgsComposerNameDelegate( QObject *parent )
|
|
||||||
: QItemDelegate( parent )
|
|
||||||
{
|
{
|
||||||
|
if ( !index.isValid() || role != Qt::EditRole )
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( index.row() >= mLayoutManager->compositions().count() )
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
if ( value.toString().isEmpty() )
|
||||||
|
return false;
|
||||||
|
|
||||||
QWidget *QgsComposerNameDelegate::createEditor( QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index ) const
|
QgsComposition *c = compositionFromIndex( index );
|
||||||
{
|
if ( !c )
|
||||||
Q_UNUSED( option );
|
return false;
|
||||||
Q_UNUSED( index );
|
|
||||||
|
|
||||||
//create a line edit
|
|
||||||
QLineEdit *lineEdit = new QLineEdit( parent );
|
|
||||||
return lineEdit;
|
|
||||||
}
|
|
||||||
|
|
||||||
void QgsComposerNameDelegate::setEditorData( QWidget *editor, const QModelIndex &index ) const
|
|
||||||
{
|
|
||||||
QString text = index.model()->data( index, Qt::EditRole ).toString();
|
|
||||||
QLineEdit *lineEdit = static_cast<QLineEdit *>( editor );
|
|
||||||
lineEdit->setText( text );
|
|
||||||
}
|
|
||||||
|
|
||||||
void QgsComposerNameDelegate::setModelData( QWidget *editor, QAbstractItemModel *model, const QModelIndex &index ) const
|
|
||||||
{
|
|
||||||
QLineEdit *lineEdit = static_cast<QLineEdit *>( editor );
|
|
||||||
QString value = lineEdit->text();
|
|
||||||
|
|
||||||
//has name changed?
|
//has name changed?
|
||||||
bool changed = model->data( index, Qt::EditRole ).toString() != value;
|
bool changed = c->name() != value.toString();
|
||||||
|
if ( !changed )
|
||||||
|
return true;
|
||||||
|
|
||||||
//check if name already exists
|
//check if name already exists
|
||||||
QStringList cNames;
|
QStringList cNames;
|
||||||
Q_FOREACH ( QgsComposer *c, QgisApp::instance()->printComposers() )
|
Q_FOREACH ( QgsComposition *comp, QgsProject::instance()->layoutManager()->compositions() )
|
||||||
{
|
{
|
||||||
cNames << c->composition()->name();
|
cNames << comp->name();
|
||||||
}
|
}
|
||||||
if ( changed && cNames.contains( value ) )
|
if ( cNames.contains( value.toString() ) )
|
||||||
{
|
{
|
||||||
//name exists!
|
//name exists!
|
||||||
QMessageBox::warning( nullptr, tr( "Rename composer" ), tr( "There is already a composer named \"%1\"" ).arg( value ) );
|
QMessageBox::warning( nullptr, tr( "Rename composer" ), tr( "There is already a composer named \"%1\"" ).arg( value.toString() ) );
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
model->setData( index, QVariant( value ), Qt::EditRole );
|
c->setName( value.toString() );
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QgsComposerNameDelegate::updateEditorGeometry( QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index ) const
|
Qt::ItemFlags QgsLayoutManagerModel::flags( const QModelIndex &index ) const
|
||||||
{
|
{
|
||||||
Q_UNUSED( index );
|
Qt::ItemFlags flags = QAbstractListModel::flags( index );
|
||||||
editor->setGeometry( option.rect );
|
|
||||||
|
if ( index.isValid() )
|
||||||
|
{
|
||||||
|
return flags | Qt::ItemIsEditable;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return flags;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QgsComposition *QgsLayoutManagerModel::compositionFromIndex( const QModelIndex &index ) const
|
||||||
|
{
|
||||||
|
return qobject_cast< QgsComposition * >( qvariant_cast<QObject *>( data( index, CompositionRole ) ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsLayoutManagerModel::compositionAboutToBeAdded( const QString & )
|
||||||
|
{
|
||||||
|
int row = mLayoutManager->compositions().count();
|
||||||
|
beginInsertRows( QModelIndex(), row, row );
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsLayoutManagerModel::compositionAboutToBeRemoved( const QString &name )
|
||||||
|
{
|
||||||
|
QgsComposition *c = mLayoutManager->compositionByName( name );
|
||||||
|
int row = mLayoutManager->compositions().indexOf( c );
|
||||||
|
if ( row >= 0 )
|
||||||
|
beginRemoveRows( QModelIndex(), row, row );
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsLayoutManagerModel::compositionAdded( const QString & )
|
||||||
|
{
|
||||||
|
endInsertRows();
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsLayoutManagerModel::compositionRemoved( const QString & )
|
||||||
|
{
|
||||||
|
endRemoveRows();
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsLayoutManagerModel::compositionRenamed( QgsComposition *composition, const QString & )
|
||||||
|
{
|
||||||
|
int row = mLayoutManager->compositions().indexOf( composition );
|
||||||
|
QModelIndex index = createIndex( row, 0 );
|
||||||
|
emit dataChanged( index, index, QVector<int>() << Qt::DisplayRole );
|
||||||
}
|
}
|
||||||
|
@ -23,24 +23,36 @@
|
|||||||
|
|
||||||
class QListWidgetItem;
|
class QListWidgetItem;
|
||||||
class QgsComposer;
|
class QgsComposer;
|
||||||
|
class QgsComposition;
|
||||||
|
class QgsLayoutManager;
|
||||||
|
|
||||||
//! Delegate for a line edit for renaming a composer. Prevents entry of duplicate composer names.
|
class QgsLayoutManagerModel : public QAbstractListModel
|
||||||
class QgsComposerNameDelegate : public QItemDelegate
|
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit QgsComposerNameDelegate( QObject *parent = nullptr );
|
|
||||||
|
|
||||||
QWidget *createEditor( QWidget *parent, const QStyleOptionViewItem &option,
|
enum Role
|
||||||
const QModelIndex &index ) const override;
|
{
|
||||||
|
CompositionRole = Qt::UserRole + 1,
|
||||||
|
};
|
||||||
|
|
||||||
void setEditorData( QWidget *editor, const QModelIndex &index ) const override;
|
explicit QgsLayoutManagerModel( QgsLayoutManager *manager, QObject *parent = nullptr );
|
||||||
void setModelData( QWidget *editor, QAbstractItemModel *model,
|
|
||||||
const QModelIndex &index ) const override;
|
|
||||||
|
|
||||||
void updateEditorGeometry( QWidget *editor,
|
int rowCount( const QModelIndex &parent ) const override;
|
||||||
const QStyleOptionViewItem &option, const QModelIndex &index ) const override;
|
QVariant data( const QModelIndex &index, int role ) const override;
|
||||||
|
bool setData( const QModelIndex &index, const QVariant &value, int role = Qt::EditRole ) override;
|
||||||
|
Qt::ItemFlags flags( const QModelIndex &index ) const override;
|
||||||
|
QgsComposition *compositionFromIndex( const QModelIndex &index ) const;
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void compositionAboutToBeAdded( const QString &name );
|
||||||
|
void compositionAboutToBeRemoved( const QString &name );
|
||||||
|
void compositionAdded( const QString &name );
|
||||||
|
void compositionRemoved( const QString &name );
|
||||||
|
void compositionRenamed( QgsComposition *composition, const QString &newName );
|
||||||
|
private:
|
||||||
|
QgsLayoutManager *mLayoutManager;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** A dialog that shows the existing composer instances. Lets the user add new
|
/** A dialog that shows the existing composer instances. Lets the user add new
|
||||||
@ -60,10 +72,6 @@ class QgsComposerManager: public QDialog, private Ui::QgsComposerManagerBase
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
/** Stores the relation between items and composer pointers. A 0 pointer for the composer means that
|
|
||||||
this composer needs to be created from a default template*/
|
|
||||||
QMap<QListWidgetItem *, QgsComposer *> mItemComposerMap;
|
|
||||||
|
|
||||||
/** Returns the default templates (key: template name, value: absolute path to template file)
|
/** Returns the default templates (key: template name, value: absolute path to template file)
|
||||||
* @param fromUser whether to return user templates from ~/.qgis/composer_templates
|
* @param fromUser whether to return user templates from ~/.qgis/composer_templates
|
||||||
*/
|
*/
|
||||||
@ -82,6 +90,7 @@ class QgsComposerManager: public QDialog, private Ui::QgsComposerManagerBase
|
|||||||
QPushButton *mRemoveButton = nullptr;
|
QPushButton *mRemoveButton = nullptr;
|
||||||
QPushButton *mRenameButton = nullptr;
|
QPushButton *mRenameButton = nullptr;
|
||||||
QPushButton *mDuplicateButton = nullptr;
|
QPushButton *mDuplicateButton = nullptr;
|
||||||
|
QgsLayoutManagerModel *mModel = nullptr;
|
||||||
|
|
||||||
#ifdef Q_OS_MAC
|
#ifdef Q_OS_MAC
|
||||||
void showEvent( QShowEvent *event );
|
void showEvent( QShowEvent *event );
|
||||||
@ -103,15 +112,11 @@ class QgsComposerManager: public QDialog, private Ui::QgsComposerManagerBase
|
|||||||
//! Slot to open user templates dir with user's system
|
//! Slot to open user templates dir with user's system
|
||||||
void on_mTemplatesUserDirBtn_pressed();
|
void on_mTemplatesUserDirBtn_pressed();
|
||||||
|
|
||||||
//! Refreshes the list of composers
|
void removeClicked();
|
||||||
void refreshComposers();
|
void showClicked();
|
||||||
|
|
||||||
void remove_clicked();
|
|
||||||
void show_clicked();
|
|
||||||
//! Duplicate composer
|
//! Duplicate composer
|
||||||
void duplicate_clicked();
|
void duplicateClicked();
|
||||||
void rename_clicked();
|
void renameClicked();
|
||||||
void on_mComposerListWidget_itemChanged( QListWidgetItem *item );
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // QGSCOMPOSERMANAGER_H
|
#endif // QGSCOMPOSERMANAGER_H
|
||||||
|
@ -41,6 +41,11 @@ bool QgsLayoutManager::addComposition( QgsComposition *composition )
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
connect( composition, &QgsComposition::nameChanged, this, [this, composition]( const QString & newName )
|
||||||
|
{
|
||||||
|
emit compositionRenamed( composition, newName );
|
||||||
|
} );
|
||||||
|
emit compositionAboutToBeAdded( composition->name() );
|
||||||
mCompositions << composition;
|
mCompositions << composition;
|
||||||
emit compositionAdded( composition->name() );
|
emit compositionAdded( composition->name() );
|
||||||
mProject->setDirty( true );
|
mProject->setDirty( true );
|
||||||
|
@ -121,6 +121,9 @@ class CORE_EXPORT QgsLayoutManager : public QObject
|
|||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
|
||||||
|
//! Emitted when a composition is about to be added to the manager
|
||||||
|
void compositionAboutToBeAdded( const QString &name );
|
||||||
|
|
||||||
//! Emitted when a composition has been added to the manager
|
//! Emitted when a composition has been added to the manager
|
||||||
void compositionAdded( const QString &name );
|
void compositionAdded( const QString &name );
|
||||||
|
|
||||||
@ -130,6 +133,9 @@ class CORE_EXPORT QgsLayoutManager : public QObject
|
|||||||
//! Emitted when a composition is about to be removed from the manager
|
//! Emitted when a composition is about to be removed from the manager
|
||||||
void compositionAboutToBeRemoved( const QString &name );
|
void compositionAboutToBeRemoved( const QString &name );
|
||||||
|
|
||||||
|
//! Emitted when a composition is renamed
|
||||||
|
void compositionRenamed( QgsComposition *composition, const QString &newName );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
QgsProject *mProject = nullptr;
|
QgsProject *mProject = nullptr;
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QListWidget" name="mComposerListWidget">
|
<widget class="QListView" name="mComposerListView">
|
||||||
<property name="selectionMode">
|
<property name="selectionMode">
|
||||||
<enum>QAbstractItemView::ExtendedSelection</enum>
|
<enum>QAbstractItemView::ExtendedSelection</enum>
|
||||||
</property>
|
</property>
|
||||||
@ -154,7 +154,7 @@
|
|||||||
</customwidget>
|
</customwidget>
|
||||||
</customwidgets>
|
</customwidgets>
|
||||||
<tabstops>
|
<tabstops>
|
||||||
<tabstop>mComposerListWidget</tabstop>
|
<tabstop>mComposerListView</tabstop>
|
||||||
<tabstop>mTemplateGrpBox</tabstop>
|
<tabstop>mTemplateGrpBox</tabstop>
|
||||||
<tabstop>mTemplate</tabstop>
|
<tabstop>mTemplate</tabstop>
|
||||||
<tabstop>mAddButton</tabstop>
|
<tabstop>mAddButton</tabstop>
|
||||||
|
@ -48,8 +48,11 @@ class TestQgsLayoutManager(unittest.TestCase):
|
|||||||
|
|
||||||
manager = QgsLayoutManager(project)
|
manager = QgsLayoutManager(project)
|
||||||
|
|
||||||
|
composition_about_to_be_added_spy = QSignalSpy(manager.compositionAboutToBeAdded)
|
||||||
composition_added_spy = QSignalSpy(manager.compositionAdded)
|
composition_added_spy = QSignalSpy(manager.compositionAdded)
|
||||||
self.assertTrue(manager.addComposition(composition))
|
self.assertTrue(manager.addComposition(composition))
|
||||||
|
self.assertEqual(len(composition_about_to_be_added_spy), 1)
|
||||||
|
self.assertEqual(composition_about_to_be_added_spy[0][0], 'test composition')
|
||||||
self.assertEqual(len(composition_added_spy), 1)
|
self.assertEqual(len(composition_added_spy), 1)
|
||||||
self.assertEqual(composition_added_spy[0][0], 'test composition')
|
self.assertEqual(composition_added_spy[0][0], 'test composition')
|
||||||
|
|
||||||
@ -61,6 +64,8 @@ class TestQgsLayoutManager(unittest.TestCase):
|
|||||||
composition2.setName('test composition2')
|
composition2.setName('test composition2')
|
||||||
self.assertTrue(manager.addComposition(composition2))
|
self.assertTrue(manager.addComposition(composition2))
|
||||||
self.assertEqual(len(composition_added_spy), 2)
|
self.assertEqual(len(composition_added_spy), 2)
|
||||||
|
self.assertEqual(composition_about_to_be_added_spy[1][0], 'test composition2')
|
||||||
|
self.assertEqual(len(composition_about_to_be_added_spy), 2)
|
||||||
self.assertEqual(composition_added_spy[1][0], 'test composition2')
|
self.assertEqual(composition_added_spy[1][0], 'test composition2')
|
||||||
|
|
||||||
# adding a composition with duplicate name should fail
|
# adding a composition with duplicate name should fail
|
||||||
@ -251,6 +256,26 @@ class TestQgsLayoutManager(unittest.TestCase):
|
|||||||
manager.clear()
|
manager.clear()
|
||||||
self.assertEqual(manager.generateUniqueTitle(), 'Composer 1')
|
self.assertEqual(manager.generateUniqueTitle(), 'Composer 1')
|
||||||
|
|
||||||
|
def testRenameSignal(self):
|
||||||
|
project = QgsProject()
|
||||||
|
manager = QgsLayoutManager(project)
|
||||||
|
composition = QgsComposition(project)
|
||||||
|
composition.setName('c1')
|
||||||
|
manager.addComposition(composition)
|
||||||
|
composition2 = QgsComposition(project)
|
||||||
|
composition2.setName('c2')
|
||||||
|
manager.addComposition(composition2)
|
||||||
|
|
||||||
|
composition_renamed_spy = QSignalSpy(manager.compositionRenamed)
|
||||||
|
composition.setName('d1')
|
||||||
|
self.assertEqual(len(composition_renamed_spy), 1)
|
||||||
|
self.assertEqual(composition_renamed_spy[0][0], composition)
|
||||||
|
self.assertEqual(composition_renamed_spy[0][1], 'd1')
|
||||||
|
composition2.setName('d2')
|
||||||
|
self.assertEqual(len(composition_renamed_spy), 2)
|
||||||
|
self.assertEqual(composition_renamed_spy[1][0], composition2)
|
||||||
|
self.assertEqual(composition_renamed_spy[1][1], 'd2')
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user