Skip to content

Commit 3c33177

Browse files
Médéric RIBREUXnyalldawson
authored andcommitted
[feature][composer] Allow multiple selection of compositions in manager
Allows multiple compositions to be opened and deleted. Fix #2917.
1 parent 052fd79 commit 3c33177

File tree

3 files changed

+135
-85
lines changed

3 files changed

+135
-85
lines changed

src/app/composer/qgscomposermanager.cpp

Lines changed: 121 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,6 @@
3434

3535
QgsComposerManager::QgsComposerManager( QWidget * parent, Qt::WindowFlags f ): QDialog( parent, f )
3636
{
37-
QPushButton *pb;
38-
3937
setupUi( this );
4038

4139
QSettings settings;
@@ -47,21 +45,19 @@ QgsComposerManager::QgsComposerManager( QWidget * parent, Qt::WindowFlags f ): Q
4745
connect( QgisApp::instance(), SIGNAL( composerAdded( QgsComposerView* ) ), this, SLOT( refreshComposers() ) );
4846
connect( QgisApp::instance(), SIGNAL( composerRemoved( QgsComposerView* ) ), this, SLOT( refreshComposers() ) );
4947

50-
pb = new QPushButton( tr( "&Show" ) );
51-
mButtonBox->addButton( pb, QDialogButtonBox::ActionRole );
52-
connect( pb, SIGNAL( clicked() ), this, SLOT( show_clicked() ) );
48+
connect( mComposerListWidget, SIGNAL( itemSelectionChanged() ), this, SLOT( toggleButtons() ) );
49+
50+
mShowButton = mButtonBox->addButton( tr( "&Show" ), QDialogButtonBox::ActionRole );
51+
connect( mShowButton, SIGNAL( clicked() ), this, SLOT( show_clicked() ) );
5352

54-
pb = new QPushButton( tr( "&Duplicate" ) );
55-
mButtonBox->addButton( pb, QDialogButtonBox::ActionRole );
56-
connect( pb, SIGNAL( clicked() ), this, SLOT( duplicate_clicked() ) );
53+
mDuplicateButton = mButtonBox->addButton( tr( "&Duplicate" ), QDialogButtonBox::ActionRole );
54+
connect( mDuplicateButton, SIGNAL( clicked() ), this, SLOT( duplicate_clicked() ) );
5755

58-
pb = new QPushButton( tr( "&Remove" ) );
59-
mButtonBox->addButton( pb, QDialogButtonBox::ActionRole );
60-
connect( pb, SIGNAL( clicked() ), this, SLOT( remove_clicked() ) );
56+
mRemoveButton = mButtonBox->addButton( tr( "&Remove" ), QDialogButtonBox::ActionRole );
57+
connect( mRemoveButton, SIGNAL( clicked() ), this, SLOT( remove_clicked() ) );
6158

62-
pb = new QPushButton( tr( "Re&name" ) );
63-
mButtonBox->addButton( pb, QDialogButtonBox::ActionRole );
64-
connect( pb, SIGNAL( clicked() ), this, SLOT( rename_clicked() ) );
59+
mRenameButton = mButtonBox->addButton( tr( "Re&name" ), QDialogButtonBox::ActionRole );
60+
connect( mRenameButton, SIGNAL( clicked() ), this, SLOT( rename_clicked() ) );
6561

6662
#ifdef Q_OS_MAC
6763
// Create action to select this window
@@ -94,7 +90,16 @@ QgsComposerManager::~QgsComposerManager()
9490

9591
void QgsComposerManager::refreshComposers()
9692
{
97-
QString selName = mComposerListWidget->currentItem() ? mComposerListWidget->currentItem()->text() : "";
93+
// Backup selection
94+
QSet<QgsComposer *> selectedComposers;
95+
Q_FOREACH ( QListWidgetItem* item, mComposerListWidget->selectedItems() )
96+
{
97+
QMap<QListWidgetItem*, QgsComposer*>::iterator it = mItemComposerMap.find( item );
98+
if ( it != mItemComposerMap.end() )
99+
{
100+
selectedComposers << it.value();
101+
}
102+
}
98103

99104
mItemComposerMap.clear();
100105
mComposerListWidget->clear();
@@ -110,14 +115,60 @@ void QgsComposerManager::refreshComposers()
110115
mComposerListWidget->sortItems();
111116

112117
// Restore selection
113-
if ( !selName.isEmpty() )
118+
bool selectionRestored = false;
119+
if ( !selectedComposers.isEmpty() )
114120
{
115-
QList<QListWidgetItem*> items = mComposerListWidget->findItems( selName, Qt::MatchExactly );
116-
if ( !items.isEmpty() )
121+
QMap<QListWidgetItem*, QgsComposer*>::const_iterator i = mItemComposerMap.constBegin();
122+
while ( i != mItemComposerMap.constEnd() )
117123
{
118-
mComposerListWidget->setCurrentItem( items.first() );
124+
// This composer was selected: reselect it !
125+
if ( selectedComposers.contains( i.value() ) )
126+
{
127+
selectionRestored = true;
128+
int inDex = mComposerListWidget->row( i.key() );
129+
QModelIndex selectLine = mComposerListWidget->model()->index( inDex, 0, QModelIndex() );
130+
mComposerListWidget->selectionModel()->select( selectLine, QItemSelectionModel::Select );
131+
}
132+
++i;
119133
}
120134
}
135+
// Select the first item by default
136+
if ( !selectionRestored && mComposerListWidget->count() > 0 )
137+
{
138+
QModelIndex firstLine = mComposerListWidget->model()->index( 0, 0, QModelIndex() );
139+
mComposerListWidget->selectionModel()->select( firstLine, QItemSelectionModel::Select );
140+
}
141+
142+
// Update buttons
143+
toggleButtons();
144+
}
145+
146+
void QgsComposerManager::toggleButtons()
147+
{
148+
// Nothing selected: no button.
149+
if ( mComposerListWidget->selectedItems().isEmpty() )
150+
{
151+
mShowButton->setEnabled( false );
152+
mRemoveButton->setEnabled( false );
153+
mRenameButton->setEnabled( false );
154+
mDuplicateButton->setEnabled( false );
155+
}
156+
// toggle everything if one composer is selected
157+
else if ( mComposerListWidget->selectedItems().count() == 1 )
158+
{
159+
mShowButton->setEnabled( true );
160+
mRemoveButton->setEnabled( true );
161+
mRenameButton->setEnabled( true );
162+
mDuplicateButton->setEnabled( true );
163+
}
164+
// toggle only show and remove buttons in other cases
165+
else
166+
{
167+
mShowButton->setEnabled( true );
168+
mRemoveButton->setEnabled( true );
169+
mRenameButton->setEnabled( false );
170+
mDuplicateButton->setEnabled( false );
171+
}
121172
}
122173

123174
void QgsComposerManager::addTemplates( const QMap<QString, QString>& templates )
@@ -164,7 +215,6 @@ QMap<QString, QString> QgsComposerManager::otherTemplates() const
164215
return templateMap;
165216
}
166217

167-
168218
QMap<QString, QString> QgsComposerManager::templatesFromPath( const QString& path ) const
169219
{
170220
QMap<QString, QString> templateMap;
@@ -338,101 +388,86 @@ void QgsComposerManager::changeEvent( QEvent* event )
338388

339389
void QgsComposerManager::remove_clicked()
340390
{
341-
QListWidgetItem* item = mComposerListWidget->currentItem();
342-
if ( !item )
391+
QList<QgsComposer *> composerList;
392+
QList<QListWidgetItem *> composerItems = mComposerListWidget->selectedItems();
393+
QString title = tr( "Remove composers" );
394+
QString message = tr( "Do you really want to remove all selected map composers ?" );
395+
396+
if ( composerItems.isEmpty() )
343397
{
344398
return;
345399
}
346400

347-
//ask for confirmation
348-
if ( QMessageBox::warning( this, tr( "Remove composer" ), tr( "Do you really want to remove the map composer '%1'?" ).arg( item->text() ), QMessageBox::Ok | QMessageBox::Cancel ) != QMessageBox::Ok )
401+
// Ask for confirmation
402+
if ( composerItems.count() == 1 )
403+
{
404+
title = tr( "Remove composer" );
405+
QListWidgetItem* uniqItem = composerItems.at( 0 );
406+
message = tr( "Do you really want to remove the map composer '%1'?" ).arg( uniqItem->text() );
407+
}
408+
409+
if ( QMessageBox::warning( this, title, message, QMessageBox::Ok | QMessageBox::Cancel ) != QMessageBox::Ok )
349410
{
350411
return;
351412
}
352413

353-
//delete composer
354-
QMap<QListWidgetItem*, QgsComposer*>::iterator it = mItemComposerMap.find( item );
355-
if ( it != mItemComposerMap.end() )
414+
// Find the QgsComposers that need to be deleted
415+
Q_FOREACH ( QListWidgetItem* item, composerItems )
356416
{
357-
QgisApp::instance()->deleteComposer( it.value() );
417+
QMap<QListWidgetItem*, QgsComposer*>::iterator it = mItemComposerMap.find( item );
418+
if ( it != mItemComposerMap.end() )
419+
{
420+
composerList << it.value();
421+
}
358422
}
359-
}
360423

361-
void QgsComposerManager::show_clicked()
362-
{
363-
QListWidgetItem* item = mComposerListWidget->currentItem();
364-
if ( !item )
424+
// Once we have the composer list, we can delete all of them !
425+
Q_FOREACH ( QgsComposer* c, composerList )
365426
{
366-
return;
427+
QgisApp::instance()->deleteComposer( c );
367428
}
429+
}
368430

369-
QMap<QListWidgetItem*, QgsComposer*>::iterator it = mItemComposerMap.find( item );
370-
if ( it != mItemComposerMap.end() )
431+
void QgsComposerManager::show_clicked()
432+
{
433+
Q_FOREACH ( QListWidgetItem* item, mComposerListWidget->selectedItems() )
371434
{
372-
QgsComposer* c = 0;
373-
if ( it.value() ) //a normal composer
435+
QMap<QListWidgetItem*, QgsComposer*>::const_iterator it = mItemComposerMap.find( item );
436+
if ( it != mItemComposerMap.constEnd() )
374437
{
375-
c = it.value();
376-
if ( c )
438+
QgsComposer* c = 0;
439+
if ( it.value() ) //a normal composer
377440
{
378-
// extra activation steps for Windows
379-
bool shown = c->isVisible();
441+
c = it.value();
442+
if ( c )
443+
{
444+
// extra activation steps for Windows
445+
bool shown = c->isVisible();
380446

381-
c->activate();
447+
c->activate();
382448

383-
// extra activation steps for Windows
384-
if ( !shown )
385-
{
386-
c->on_mActionZoomAll_triggered();
449+
// extra activation steps for Windows
450+
if ( !shown )
451+
{
452+
c->on_mActionZoomAll_triggered();
453+
}
387454
}
388455
}
389456
}
390457
}
391-
#if 0
392-
else //create composer from default template
393-
{
394-
QMap<QString, QString>::const_iterator templateIt = mDefaultTemplateMap.find( it.key()->text() );
395-
if ( templateIt == mDefaultTemplateMap.constEnd() )
396-
{
397-
return;
398-
}
399-
400-
QDomDocument templateDoc;
401-
QFile templateFile( templateIt.value() );
402-
if ( !templateFile.open( QIODevice::ReadOnly ) )
403-
{
404-
return;
405-
}
406-
407-
if ( !templateDoc.setContent( &templateFile, false ) )
408-
{
409-
return;
410-
}
411-
c = QgisApp::instance()->createNewComposer();
412-
c->setTitle( it.key()->text() );
413-
if ( c )
414-
{
415-
c->readXML( templateDoc );
416-
}
417-
}
418-
419-
if ( c )
420-
{
421-
c->activate();
422-
}
423-
#endif //0
424458
}
425459

426460
void QgsComposerManager::duplicate_clicked()
427461
{
428-
QListWidgetItem* item = mComposerListWidget->currentItem();
429-
if ( !item )
462+
if ( mComposerListWidget->selectedItems().isEmpty() )
430463
{
431464
return;
432465
}
433466

434467
QgsComposer* currentComposer = 0;
435468
QString currentTitle;
469+
470+
QListWidgetItem* item = mComposerListWidget->selectedItems().at( 0 );
436471
QMap<QListWidgetItem*, QgsComposer*>::iterator it = mItemComposerMap.find( item );
437472
if ( it != mItemComposerMap.end() )
438473
{
@@ -475,14 +510,15 @@ void QgsComposerManager::duplicate_clicked()
475510

476511
void QgsComposerManager::rename_clicked()
477512
{
478-
QListWidgetItem* item = mComposerListWidget->currentItem();
479-
if ( !item )
513+
if ( mComposerListWidget->selectedItems().isEmpty() )
480514
{
481515
return;
482516
}
483517

484518
QString currentTitle;
485519
QgsComposer* currentComposer = 0;
520+
521+
QListWidgetItem* item = mComposerListWidget->selectedItems().at( 0 );
486522
QMap<QListWidgetItem*, QgsComposer*>::iterator it = mItemComposerMap.find( item );
487523
if ( it != mItemComposerMap.end() )
488524
{
@@ -493,6 +529,7 @@ void QgsComposerManager::rename_clicked()
493529
{
494530
return;
495531
}
532+
496533
QString newTitle;
497534
if ( !QgisApp::instance()->uniqueComposerTitle( this, newTitle, false, currentTitle ) )
498535
{

src/app/composer/qgscomposermanager.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,10 @@ class QgsComposerManager: public QDialog, private Ui::QgsComposerManagerBase
7777

7878
QString mDefaultTemplatesDir;
7979
QString mUserTemplatesDir;
80+
QPushButton* mShowButton;
81+
QPushButton* mRemoveButton;
82+
QPushButton* mRenameButton;
83+
QPushButton* mDuplicateButton;
8084

8185
#ifdef Q_OS_MAC
8286
void showEvent( QShowEvent *event );
@@ -86,6 +90,8 @@ class QgsComposerManager: public QDialog, private Ui::QgsComposerManagerBase
8690
#endif
8791

8892
private slots:
93+
/** Slot to update buttons state when selecting compositions */
94+
void toggleButtons();
8995
void on_mAddButton_clicked();
9096
/** Slot to track combobox to use specific template path */
9197
void on_mTemplate_currentIndexChanged( int indx );

src/ui/composer/qgscomposermanagerbase.ui

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,14 @@
2121
</property>
2222
<layout class="QVBoxLayout" name="verticalLayout">
2323
<item>
24-
<widget class="QListWidget" name="mComposerListWidget"/>
24+
<widget class="QListWidget" name="mComposerListWidget">
25+
<property name="selectionMode">
26+
<enum>QAbstractItemView::ExtendedSelection</enum>
27+
</property>
28+
<property name="selectionBehavior">
29+
<enum>QAbstractItemView::SelectRows</enum>
30+
</property>
31+
</widget>
2532
</item>
2633
<item>
2734
<widget class="QgsCollapsibleGroupBox" name="mTemplateGrpBox">

0 commit comments

Comments
 (0)