[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:
Nyall Dawson 2017-03-18 12:41:38 +10:00
parent 3aef32a191
commit 53160c7b21
7 changed files with 232 additions and 221 deletions

View File

@ -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 );
};

View File

@ -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 );
}

View File

@ -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

View File

@ -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 );

View File

@ -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;

View File

@ -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>

View File

@ -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()