mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-13 00:03:09 -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;
|
||||
|
||||
signals:
|
||||
void compositionAdded( const QString& name );
|
||||
void compositionRemoved( const QString& name );
|
||||
void compositionAboutToBeRemoved( const QString& name );
|
||||
|
||||
void compositionAboutToBeAdded( 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 "qgssettings.h"
|
||||
#include "qgscomposerview.h"
|
||||
#include "qgslayoutmanager.h"
|
||||
#include "qgsproject.h"
|
||||
|
||||
#include <QDesktopServices>
|
||||
#include <QDialog>
|
||||
@ -40,25 +42,25 @@ QgsComposerManager::QgsComposerManager( QWidget *parent, Qt::WindowFlags f ): QD
|
||||
QgsSettings settings;
|
||||
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( QgisApp::instance(), &QgisApp::composerAdded, this, &QgsComposerManager::refreshComposers );
|
||||
//connect( QgisApp::instance(), &QgisApp::composerRemoved, this, &QgsComposerManager::refreshComposers );
|
||||
|
||||
connect( mComposerListWidget, SIGNAL( itemSelectionChanged() ), this, SLOT( toggleButtons() ) );
|
||||
connect( mButtonBox, &QDialogButtonBox::rejected, this, &QWidget::close );
|
||||
connect( mComposerListView->selectionModel(), &QItemSelectionModel::selectionChanged,
|
||||
this, &QgsComposerManager::toggleButtons );
|
||||
|
||||
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 );
|
||||
connect( mDuplicateButton, SIGNAL( clicked() ), this, SLOT( duplicate_clicked() ) );
|
||||
connect( mDuplicateButton, &QAbstractButton::clicked, this, &QgsComposerManager::duplicateClicked );
|
||||
|
||||
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 );
|
||||
connect( mRenameButton, SIGNAL( clicked() ), this, SLOT( rename_clicked() ) );
|
||||
connect( mRenameButton, &QAbstractButton::clicked, this, &QgsComposerManager::renameClicked );
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
// Create action to select this window
|
||||
@ -79,8 +81,6 @@ QgsComposerManager::QgsComposerManager( QWidget *parent, Qt::WindowFlags f ): QD
|
||||
this->addTemplates( this->otherTemplates() );
|
||||
|
||||
mTemplatePathLineEdit->setText( settings.value( QStringLiteral( "UI/ComposerManager/templatePath" ), QString() ).toString() );
|
||||
|
||||
refreshComposers();
|
||||
}
|
||||
|
||||
QgsComposerManager::~QgsComposerManager()
|
||||
@ -89,65 +89,10 @@ QgsComposerManager::~QgsComposerManager()
|
||||
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()
|
||||
{
|
||||
// Nothing selected: no button.
|
||||
if ( mComposerListWidget->selectedItems().isEmpty() )
|
||||
if ( mComposerListView->selectionModel()->selectedRows().isEmpty() )
|
||||
{
|
||||
mShowButton->setEnabled( false );
|
||||
mRemoveButton->setEnabled( false );
|
||||
@ -155,7 +100,7 @@ void QgsComposerManager::toggleButtons()
|
||||
mDuplicateButton->setEnabled( false );
|
||||
}
|
||||
// toggle everything if one composer is selected
|
||||
else if ( mComposerListWidget->selectedItems().count() == 1 )
|
||||
else if ( mComposerListView->selectionModel()->selectedRows().count() == 1 )
|
||||
{
|
||||
mShowButton->setEnabled( true );
|
||||
mRemoveButton->setEnabled( true );
|
||||
@ -297,7 +242,6 @@ void QgsComposerManager::on_mAddButton_clicked()
|
||||
|
||||
if ( !loadedOK )
|
||||
{
|
||||
newComposer->close();
|
||||
QgisApp::instance()->deleteComposer( newComposer );
|
||||
newComposer = nullptr;
|
||||
QMessageBox::warning( this, tr( "Template error" ), tr( "Error, could not load template file" ) );
|
||||
@ -376,10 +320,9 @@ void QgsComposerManager::changeEvent( QEvent *event )
|
||||
}
|
||||
#endif
|
||||
|
||||
void QgsComposerManager::remove_clicked()
|
||||
void QgsComposerManager::removeClicked()
|
||||
{
|
||||
QList<QgsComposer *> composerList;
|
||||
QList<QListWidgetItem *> composerItems = mComposerListWidget->selectedItems();
|
||||
QModelIndexList composerItems = mComposerListView->selectionModel()->selectedRows();
|
||||
QString title = tr( "Remove 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 )
|
||||
{
|
||||
title = tr( "Remove composer" );
|
||||
QListWidgetItem *uniqItem = composerItems.at( 0 );
|
||||
message = tr( "Do you really want to remove the map composer '%1'?" ).arg( uniqItem->text() );
|
||||
message = tr( "Do you really want to remove the map composer '%1'?" ).arg(
|
||||
mComposerListView->model()->data( composerItems.at( 0 ), Qt::DisplayRole ).toString() );
|
||||
}
|
||||
|
||||
if ( QMessageBox::warning( this, title, message, QMessageBox::Ok | QMessageBox::Cancel ) != QMessageBox::Ok )
|
||||
@ -401,73 +344,47 @@ void QgsComposerManager::remove_clicked()
|
||||
return;
|
||||
}
|
||||
|
||||
QList<QgsComposition *> composerList;
|
||||
// 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 );
|
||||
if ( it != mItemComposerMap.constEnd() )
|
||||
QgsComposition *c = mModel->compositionFromIndex( index );
|
||||
if ( c )
|
||||
{
|
||||
composerList << it.value();
|
||||
composerList << c;
|
||||
}
|
||||
}
|
||||
|
||||
// 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 );
|
||||
if ( it != mItemComposerMap.constEnd() )
|
||||
QgsComposition *c = mModel->compositionFromIndex( index );
|
||||
if ( c )
|
||||
{
|
||||
QgsComposer *c = nullptr;
|
||||
if ( it.value() ) //a normal composer
|
||||
{
|
||||
c = it.value();
|
||||
if ( c )
|
||||
{
|
||||
// extra activation steps for Windows
|
||||
bool shown = c->isVisible();
|
||||
|
||||
c->activate();
|
||||
|
||||
// extra activation steps for Windows
|
||||
if ( !shown )
|
||||
{
|
||||
c->on_mActionZoomAll_triggered();
|
||||
}
|
||||
}
|
||||
}
|
||||
QgisApp::instance()->openComposer( c );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QgsComposerManager::duplicate_clicked()
|
||||
void QgsComposerManager::duplicateClicked()
|
||||
{
|
||||
if ( mComposerListWidget->selectedItems().isEmpty() )
|
||||
if ( mComposerListView->selectionModel()->selectedRows().isEmpty() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
QgsComposer *currentComposer = nullptr;
|
||||
QString currentTitle;
|
||||
|
||||
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
|
||||
{
|
||||
QgsComposition *currentComposer = mModel->compositionFromIndex( mComposerListView->selectionModel()->selectedRows().at( 0 ) );
|
||||
if ( !currentComposer )
|
||||
return;
|
||||
}
|
||||
QString currentTitle = currentComposer->name();
|
||||
|
||||
QString newTitle;
|
||||
if ( !QgisApp::instance()->uniqueComposerTitle( this, newTitle, false, currentTitle + tr( " copy" ) ) )
|
||||
@ -480,121 +397,170 @@ void QgsComposerManager::duplicate_clicked()
|
||||
dlg->setStyleSheet( QgisApp::instance()->styleSheet() );
|
||||
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();
|
||||
delete dlg;
|
||||
dlg = nullptr;
|
||||
|
||||
if ( newComposer )
|
||||
{
|
||||
// extra activation steps for Windows
|
||||
newComposer->activate();
|
||||
}
|
||||
else
|
||||
if ( !newComposer )
|
||||
{
|
||||
QMessageBox::warning( this, tr( "Duplicate Composer" ),
|
||||
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
|
||||
{
|
||||
newComposer->activate();
|
||||
}
|
||||
}
|
||||
|
||||
void QgsComposerManager::renameClicked()
|
||||
{
|
||||
if ( mComposerListView->selectionModel()->selectedRows().isEmpty() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
QgsComposition *currentComposer = mModel->compositionFromIndex( mComposerListView->selectionModel()->selectedRows().at( 0 ) );
|
||||
if ( !currentComposer )
|
||||
return;
|
||||
|
||||
QString currentTitle = currentComposer->name();
|
||||
QString newTitle;
|
||||
if ( !QgisApp::instance()->uniqueComposerTitle( this, newTitle, false, currentTitle ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
currentComposer->composition()->setName( newTitle );
|
||||
item->setText( newTitle );
|
||||
|
||||
mComposerListWidget->sortItems();
|
||||
currentComposer->setName( newTitle );
|
||||
}
|
||||
|
||||
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 );
|
||||
if ( it != mItemComposerMap.constEnd() )
|
||||
connect( mLayoutManager, &QgsLayoutManager::compositionAboutToBeAdded, this, &QgsLayoutManagerModel::compositionAboutToBeAdded );
|
||||
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();
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// QgsComposerNameDelegate
|
||||
//
|
||||
|
||||
QgsComposerNameDelegate::QgsComposerNameDelegate( QObject *parent )
|
||||
: QItemDelegate( parent )
|
||||
bool QgsLayoutManagerModel::setData( const QModelIndex &index, const QVariant &value, int role )
|
||||
{
|
||||
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
|
||||
{
|
||||
Q_UNUSED( option );
|
||||
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();
|
||||
QgsComposition *c = compositionFromIndex( index );
|
||||
if ( !c )
|
||||
return false;
|
||||
|
||||
//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
|
||||
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!
|
||||
QMessageBox::warning( nullptr, tr( "Rename composer" ), tr( "There is already a composer named \"%1\"" ).arg( value ) );
|
||||
return;
|
||||
QMessageBox::warning( nullptr, tr( "Rename composer" ), tr( "There is already a composer named \"%1\"" ).arg( value.toString() ) );
|
||||
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 );
|
||||
editor->setGeometry( option.rect );
|
||||
Qt::ItemFlags flags = QAbstractListModel::flags( index );
|
||||
|
||||
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 QgsComposer;
|
||||
class QgsComposition;
|
||||
class QgsLayoutManager;
|
||||
|
||||
//! Delegate for a line edit for renaming a composer. Prevents entry of duplicate composer names.
|
||||
class QgsComposerNameDelegate : public QItemDelegate
|
||||
class QgsLayoutManagerModel : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit QgsComposerNameDelegate( QObject *parent = nullptr );
|
||||
|
||||
QWidget *createEditor( QWidget *parent, const QStyleOptionViewItem &option,
|
||||
const QModelIndex &index ) const override;
|
||||
enum Role
|
||||
{
|
||||
CompositionRole = Qt::UserRole + 1,
|
||||
};
|
||||
|
||||
void setEditorData( QWidget *editor, const QModelIndex &index ) const override;
|
||||
void setModelData( QWidget *editor, QAbstractItemModel *model,
|
||||
const QModelIndex &index ) const override;
|
||||
explicit QgsLayoutManagerModel( QgsLayoutManager *manager, QObject *parent = nullptr );
|
||||
|
||||
void updateEditorGeometry( QWidget *editor,
|
||||
const QStyleOptionViewItem &option, const QModelIndex &index ) const override;
|
||||
int rowCount( const QModelIndex &parent ) 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
|
||||
@ -60,10 +72,6 @@ class QgsComposerManager: public QDialog, private Ui::QgsComposerManagerBase
|
||||
|
||||
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)
|
||||
* @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 *mRenameButton = nullptr;
|
||||
QPushButton *mDuplicateButton = nullptr;
|
||||
QgsLayoutManagerModel *mModel = nullptr;
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
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
|
||||
void on_mTemplatesUserDirBtn_pressed();
|
||||
|
||||
//! Refreshes the list of composers
|
||||
void refreshComposers();
|
||||
|
||||
void remove_clicked();
|
||||
void show_clicked();
|
||||
void removeClicked();
|
||||
void showClicked();
|
||||
//! Duplicate composer
|
||||
void duplicate_clicked();
|
||||
void rename_clicked();
|
||||
void on_mComposerListWidget_itemChanged( QListWidgetItem *item );
|
||||
void duplicateClicked();
|
||||
void renameClicked();
|
||||
};
|
||||
|
||||
#endif // QGSCOMPOSERMANAGER_H
|
||||
|
@ -41,6 +41,11 @@ bool QgsLayoutManager::addComposition( QgsComposition *composition )
|
||||
return false;
|
||||
}
|
||||
|
||||
connect( composition, &QgsComposition::nameChanged, this, [this, composition]( const QString & newName )
|
||||
{
|
||||
emit compositionRenamed( composition, newName );
|
||||
} );
|
||||
emit compositionAboutToBeAdded( composition->name() );
|
||||
mCompositions << composition;
|
||||
emit compositionAdded( composition->name() );
|
||||
mProject->setDirty( true );
|
||||
|
@ -121,6 +121,9 @@ class CORE_EXPORT QgsLayoutManager : public QObject
|
||||
|
||||
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
|
||||
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
|
||||
void compositionAboutToBeRemoved( const QString &name );
|
||||
|
||||
//! Emitted when a composition is renamed
|
||||
void compositionRenamed( QgsComposition *composition, const QString &newName );
|
||||
|
||||
private:
|
||||
|
||||
QgsProject *mProject = nullptr;
|
||||
|
@ -21,7 +21,7 @@
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QListWidget" name="mComposerListWidget">
|
||||
<widget class="QListView" name="mComposerListView">
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::ExtendedSelection</enum>
|
||||
</property>
|
||||
@ -154,7 +154,7 @@
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<tabstops>
|
||||
<tabstop>mComposerListWidget</tabstop>
|
||||
<tabstop>mComposerListView</tabstop>
|
||||
<tabstop>mTemplateGrpBox</tabstop>
|
||||
<tabstop>mTemplate</tabstop>
|
||||
<tabstop>mAddButton</tabstop>
|
||||
|
@ -48,8 +48,11 @@ class TestQgsLayoutManager(unittest.TestCase):
|
||||
|
||||
manager = QgsLayoutManager(project)
|
||||
|
||||
composition_about_to_be_added_spy = QSignalSpy(manager.compositionAboutToBeAdded)
|
||||
composition_added_spy = QSignalSpy(manager.compositionAdded)
|
||||
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(composition_added_spy[0][0], 'test composition')
|
||||
|
||||
@ -61,6 +64,8 @@ class TestQgsLayoutManager(unittest.TestCase):
|
||||
composition2.setName('test composition2')
|
||||
self.assertTrue(manager.addComposition(composition2))
|
||||
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')
|
||||
|
||||
# adding a composition with duplicate name should fail
|
||||
@ -251,6 +256,26 @@ class TestQgsLayoutManager(unittest.TestCase):
|
||||
manager.clear()
|
||||
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__':
|
||||
unittest.main()
|
||||
|
Loading…
x
Reference in New Issue
Block a user