Skip to content

Commit 4506b81

Browse files
committed
[FEATURE][composer] Implement an item tree panel for composer windows
(fix #4358). Allows for selection of items, hiding/showing items, toggling lock status of items and double-clicking to edit item id.
1 parent b357a66 commit 4506b81

20 files changed

+1527
-185
lines changed

python/core/composer/qgscomposeritem.sip

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,24 @@ class QgsComposerItem : QgsComposerObject, QGraphicsRectItem
149149

150150
/** return correct graphics item type. Added in v1.7 */
151151
virtual int type() const;
152+
153+
/**Returns whether this item has been removed from the composition. Items removed
154+
* from the composition are not deleted so that they can be restored via an undo
155+
* command.
156+
* @returns true if the item has been removed from the composition
157+
* @note added in QGIS 2.5
158+
* @see setIsRemoved
159+
*/
160+
virtual bool isRemoved() const;
161+
162+
/**Sets whether this item has been removed from the composition. Items removed
163+
* from the composition are not deleted so that they can be restored via an undo
164+
* command.
165+
* @param removed set to true if the item has been removed from the composition
166+
* @note added in QGIS 2.5
167+
* @see isRemoved
168+
*/
169+
void setIsRemoved( const bool removed );
152170

153171
/** \brief Set selected, selected item should be highlighted */
154172
virtual void setSelected( bool s );
Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
/**
2+
* \class QgsComposerModel
3+
* \ingroup MapComposer
4+
*
5+
* A model for items attached to a composition. The model also maintains the z-order for the
6+
* composition, and must be notified whenever item stacking changes.
7+
*
8+
* Internally, QgsComposerModel maintains two lists. One contains a complete list of all items for
9+
* the composition, ordered by their position within the z-order stack. This list also contains
10+
* items which have been removed from the composition, so that undo/redo commands can restore
11+
* them to their correct position in the stacking order.
12+
*
13+
* The second list contains only items which are currently displayed in the composition's scene.
14+
* It is used as a cache of the last known stacking order, so that the model can compare the current
15+
* stacking of items in the composition to the last known state, and emit the corresponding signals
16+
* as required.
17+
*/
18+
19+
class QgsComposerModel : QAbstractItemModel
20+
{
21+
%TypeHeaderCode
22+
#include "qgscomposermodel.h"
23+
%End
24+
public:
25+
26+
/**Constructor
27+
* @param composition parent composition
28+
*/
29+
explicit QgsComposerModel( QgsComposition* composition, QObject* parent = 0 );
30+
31+
~QgsComposerModel();
32+
33+
//reimplemented QAbstractItemModel methods
34+
QModelIndex index( int row, int column, const QModelIndex &parent = QModelIndex() ) const;
35+
QModelIndex parent( const QModelIndex &index ) const;
36+
int rowCount( const QModelIndex &parent = QModelIndex() ) const;
37+
int columnCount( const QModelIndex &parent = QModelIndex() ) const;
38+
QVariant data( const QModelIndex &index, int role ) const;
39+
Qt::ItemFlags flags( const QModelIndex & index ) const;
40+
bool setData( const QModelIndex & index, const QVariant & value, int role );
41+
QVariant headerData( int section, Qt::Orientation orientation, int role = Qt::DisplayRole ) const;
42+
43+
/**Clears all items from z-order list and resets the model
44+
* @note added in QGIS 2.5
45+
*/
46+
void clear();
47+
48+
/**Returns the size of the z-order list, which includes items which may
49+
* have been removed from the composition.
50+
* @returns size of z-order list
51+
* @note added in QGIS 2.5
52+
*/
53+
int zOrderListSize() const;
54+
55+
/**Rebuilds the z-order list, based on the current stacking of items in the composition.
56+
* This method should be called after adding multiple items to the composition.
57+
* @note added in QGIS 2.5
58+
*/
59+
void rebuildZList();
60+
61+
/**Adds an item to the top of the composition z stack.
62+
* @param item item to add. The item must not already exist in the z-order list.
63+
* @note added in QGIS 2.5
64+
* @see reorderItemToTop
65+
*/
66+
void addItemAtTop( QgsComposerItem *item );
67+
68+
/**Removes an item from the z-order list.
69+
* @param item item to remove
70+
* @note added in QGIS 2.5
71+
*/
72+
void removeItem( QgsComposerItem *item );
73+
74+
/**Moves an item up the z-order list.
75+
* @param item item to move
76+
* @returns true if item was moved. Returns false if item was not found
77+
* in z-order list or was already at the top of the z-order list.
78+
* @see reorderItemDown
79+
* @see reorderItemToTop
80+
* @see reorderItemToBottom
81+
* @note added in QGIS 2.5
82+
*/
83+
bool reorderItemUp( QgsComposerItem *item );
84+
85+
/**Moves an item down the z-order list.
86+
* @param item item to move
87+
* @returns true if item was moved. Returns false if item was not found
88+
* in z-order list or was already at the bottom of the z-order list.
89+
* @see reorderItemUp
90+
* @see reorderItemToTop
91+
* @see reorderItemToBottom
92+
* @note added in QGIS 2.5
93+
*/
94+
bool reorderItemDown( QgsComposerItem *item );
95+
96+
/**Moves an item to the top of the z-order list.
97+
* @param item item to move
98+
* @returns true if item was moved. Returns false if item was not found
99+
* in z-order list or was already at the top of the z-order list.
100+
* @see reorderItemUp
101+
* @see reorderItemDown
102+
* @see reorderItemToBottom
103+
* @note added in QGIS 2.5
104+
*/
105+
bool reorderItemToTop( QgsComposerItem *item );
106+
107+
/**Moves an item to the bottom of the z-order list.
108+
* @param item item to move
109+
* @returns true if item was moved. Returns false if item was not found
110+
* in z-order list or was already at the bottom of the z-order list.
111+
* @see reorderItemUp
112+
* @see reorderItemDown
113+
* @see reorderItemToTop
114+
* @note added in QGIS 2.5
115+
*/
116+
bool reorderItemToBottom( QgsComposerItem *item );
117+
118+
/**Finds the next composer item above an item. This method only considers
119+
* items which are currently in the composition, and ignores items which have been
120+
* removed from the composition.
121+
* @param item item to search above
122+
* @returns item above specified item. If no items were found, no item
123+
* will be returned.
124+
* @see getComposerItemBelow
125+
* @note added in QGIS 2.5
126+
*/
127+
QgsComposerItem* getComposerItemAbove( QgsComposerItem *item ) const;
128+
129+
/**Finds the next composer item below an item. This method only considers
130+
* items which are currently in the composition, and ignores items which have been
131+
* removed from the composition.
132+
* @param item item to search above
133+
* @returns item below specified item. If no items were found, no item
134+
* will be returned.
135+
* @see getComposerItemAbove
136+
* @note added in QGIS 2.5
137+
*/
138+
QgsComposerItem* getComposerItemBelow( QgsComposerItem *item ) const;
139+
140+
/**Returns the item z-order list. This list includes both items currently in the
141+
* composition and items which have been removed from the composition.
142+
* @returns item z-order list
143+
* @note added in QGIS 2.5
144+
*/
145+
QList<QgsComposerItem *>* zOrderList();
146+
147+
/**Marks an item as removed from the composition. This must be called whenever an item
148+
* has been removed from the composition.
149+
* @param item to mark as removed from the composition
150+
* @see setItemRestored
151+
* @note added in QGIS 2.5
152+
*/
153+
void setItemRemoved( QgsComposerItem *item );
154+
155+
/**Restores an item to the composition. This must be called whenever an item removed
156+
* from the composition is restored to the composition.
157+
* @param item to mark as restored to the composition
158+
* @see setItemRemoved
159+
* @note added in QGIS 2.5
160+
*/
161+
void setItemRestored( QgsComposerItem *item );
162+
163+
/**Must be called when an item's display name is modified
164+
* @param item item to update
165+
* @see updateItemLockStatus
166+
* @see updateItemVisibility
167+
* @note added in QGIS 2.5
168+
*/
169+
void updateItemDisplayName( QgsComposerItem *item );
170+
171+
/**Must be called when an item's lock status changes
172+
* @param item item to update
173+
* @see updateItemDisplayName
174+
* @see updateItemVisibility
175+
* @note added in QGIS 2.5
176+
*/
177+
void updateItemLockStatus( QgsComposerItem *item );
178+
179+
/**Must be called when an item's visibility changes
180+
* @param item item to update
181+
* @see updateItemDisplayName
182+
* @see updateItemLockStatus
183+
* @note added in QGIS 2.5
184+
*/
185+
void updateItemVisibility( QgsComposerItem *item );
186+
187+
public slots:
188+
189+
/**Sets an item as the current selection from a QModelIndex
190+
* @param index QModelIndex of item to set as selected
191+
* @note added in QGIS 2.5
192+
*/
193+
void setSelected( const QModelIndex &index );
194+
};

python/core/composer/qgscomposition.sip

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -301,15 +301,17 @@ class QgsComposition : QGraphicsScene
301301
/**Removes item from z list. Usually called from destructor of QgsComposerItem*/
302302
void removeItemFromZList( QgsComposerItem* item );
303303

304-
//functions to move selected items in hierarchy
305-
void raiseSelectedItems();
306-
void raiseItem( QgsComposerItem* item );
304+
//returns true if successful
305+
bool raiseItem( QgsComposerItem* item );
307306
void lowerSelectedItems();
308-
void lowerItem( QgsComposerItem* item );
307+
//returns true if successful
308+
bool lowerItem( QgsComposerItem* item );
309309
void moveSelectedItemsToTop();
310-
void moveItemToTop( QgsComposerItem* item );
310+
//returns true if successful
311+
bool moveItemToTop( QgsComposerItem* item );
311312
void moveSelectedItemsToBottom();
312-
void moveItemToBottom( QgsComposerItem* item );
313+
//returns true if successful
314+
bool moveItemToBottom( QgsComposerItem* item );
313315

314316
//functions to find items by their position in the z list
315317
void selectNextByZOrder( ZValueDirection direction );
@@ -331,10 +333,14 @@ class QgsComposition : QGraphicsScene
331333
void unlockAllItems();
332334

333335
/**Sorts the zList. The only time where this function needs to be called is from QgsComposer
334-
after reading all the items from xml file*/
335-
void sortZList();
336+
* after reading all the items from xml file
337+
* @note deprecated, see @refreshZList instead
338+
*/
339+
void sortZList() /Deprecated/;
336340

337-
/**Rebuilds the z order list based on current order of items in scene*/
341+
/**Rebuilds the z order list by adding any item which are present in the composition
342+
* but missing from the z order list.
343+
*/
338344
void refreshZList();
339345

340346
/**Snaps a scene coordinate point to grid*/
@@ -396,7 +402,7 @@ class QgsComposition : QGraphicsScene
396402
void addComposerHtmlFrame( QgsComposerHtml* html /Transfer/, QgsComposerFrame* frame /Transfer/);
397403

398404
/**Remove item from the graphics scene. Additionally to QGraphicsScene::removeItem, this function considers undo/redo command*/
399-
void removeComposerItem( QgsComposerItem* item, const bool createCommand = true );
405+
void removeComposerItem( QgsComposerItem* item, const bool createCommand = true, const bool removeGroupItems = true );
400406

401407
/**Convenience function to create a QgsAddRemoveItemCommand, connect its signals and push it to the undo stack*/
402408
void pushAddRemoveCommand( QgsComposerItem* item, const QString& text, const QgsAddRemoveItemCommand::State state = QgsAddRemoveItemCommand::Added );
@@ -487,6 +493,12 @@ class QgsComposition : QGraphicsScene
487493
*/
488494
void setDataDefinedProperty( const QgsComposerObject::DataDefinedProperty property, bool active, bool useExpression, const QString &expression, const QString &field );
489495

496+
/**Returns the items model attached to the composition
497+
* @returns QgsComposerModel for composition
498+
* @note this method was added in version 2.5
499+
*/
500+
QgsComposerModel * itemsModel();
501+
490502
public slots:
491503
/**Casts object to the proper subclass type and calls corresponding itemAdded signal*/
492504
void sendItemAddedSignal( QgsComposerItem* item );

python/core/core.sip

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@
135135
%Include composer/qgscomposertablecolumn.sip
136136
%Include composer/qgscomposerutils.sip
137137
%Include composer/qgscomposition.sip
138+
%Include composer/qgscomposermodel.sip
138139
%Include composer/qgsatlascomposition.sip
139140
%Include composer/qgsdoubleboxscalebarstyle.sip
140141
%Include composer/qgslegendmodel.sip

src/app/composer/qgscomposer.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "qgscomposerview.h"
2626
#include "qgscomposition.h"
2727
#include "qgscompositionwidget.h"
28+
#include "qgscomposermodel.h"
2829
#include "qgsatlascompositionwidget.h"
2930
#include "qgscomposerarrow.h"
3031
#include "qgscomposerarrowwidget.h"
@@ -88,6 +89,8 @@
8889
#include <QProgressDialog>
8990
#include <QShortcut>
9091

92+
//For model testing
93+
//#include "modeltest.h"
9194

9295
// sort function for QList<QAction*>, e.g. menu listings
9396
static bool cmpByText_( QAction* a, QAction* b )
@@ -521,22 +524,42 @@ QgsComposer::QgsComposer( QgisApp *qgis, const QString& title )
521524
mAtlasDock = new QDockWidget( tr( "Atlas generation" ), this );
522525
mAtlasDock->setObjectName( "AtlasDock" );
523526
mPanelMenu->addAction( mAtlasDock->toggleViewAction() );
527+
mItemsDock = new QDockWidget( tr( "Items" ), this );
528+
mItemsDock->setObjectName( "ItemsDock" );
529+
mPanelMenu->addAction( mItemsDock->toggleViewAction() );
524530

525531
mGeneralDock->setFeatures( QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetClosable );
526532
mItemDock->setFeatures( QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetClosable );
527533
mUndoDock->setFeatures( QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetClosable );
528534
mAtlasDock->setFeatures( QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetClosable );
535+
mItemsDock->setFeatures( QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetClosable );
529536

530537
createCompositionWidget();
531538

532539
//undo widget
533540
mUndoView = new QUndoView( mComposition->undoStack(), this );
534541
mUndoDock->setWidget( mUndoView );
535542

543+
//items tree widget
544+
mItemsTreeView = new QTreeView( mItemsDock );
545+
mItemsTreeView->setModel( mComposition->itemsModel() );
546+
//for testing:
547+
//new ModelTest( mComposition->itemsModel(), this );
548+
549+
mItemsTreeView->setColumnWidth( 0, 30 );
550+
mItemsTreeView->setColumnWidth( 1, 30 );
551+
mItemsTreeView->header()->setResizeMode( 0, QHeaderView::Fixed );
552+
mItemsTreeView->header()->setResizeMode( 1, QHeaderView::Fixed );
553+
mItemsTreeView->header()->setMovable( false );
554+
mItemsTreeView->setIndentation( 0 );
555+
mItemsDock->setWidget( mItemsTreeView );
556+
connect( mItemsTreeView->selectionModel(), SIGNAL( currentChanged( QModelIndex, QModelIndex ) ), mComposition->itemsModel(), SLOT( setSelected( QModelIndex ) ) );
557+
536558
addDockWidget( Qt::RightDockWidgetArea, mItemDock );
537559
addDockWidget( Qt::RightDockWidgetArea, mGeneralDock );
538560
addDockWidget( Qt::RightDockWidgetArea, mUndoDock );
539561
addDockWidget( Qt::RightDockWidgetArea, mAtlasDock );
562+
addDockWidget( Qt::RightDockWidgetArea, mItemsDock );
540563

541564
QgsAtlasCompositionWidget* atlasWidget = new QgsAtlasCompositionWidget( mGeneralDock, mComposition );
542565
mAtlasDock->setWidget( atlasWidget );
@@ -545,11 +568,13 @@ QgsComposer::QgsComposer( QgisApp *qgis, const QString& title )
545568
mGeneralDock->show();
546569
mUndoDock->show();
547570
mAtlasDock->show();
571+
mItemsDock->show();
548572

549573
tabifyDockWidget( mGeneralDock, mUndoDock );
550574
tabifyDockWidget( mItemDock, mUndoDock );
551575
tabifyDockWidget( mGeneralDock, mItemDock );
552576
tabifyDockWidget( mItemDock, mAtlasDock );
577+
tabifyDockWidget( mItemDock, mItemsDock );
553578

554579
mGeneralDock->raise();
555580

@@ -3047,6 +3072,12 @@ void QgsComposer::readXML( const QDomElement& composerElem, const QDomDocument&
30473072
//default printer page setup
30483073
setPrinterPageDefaults();
30493074

3075+
//setup items tree view
3076+
mItemsTreeView->setModel( mComposition->itemsModel() );
3077+
mItemsTreeView->setColumnWidth( 0, 30 );
3078+
mItemsTreeView->setColumnWidth( 1, 30 );
3079+
connect( mItemsTreeView->selectionModel(), SIGNAL( currentChanged( QModelIndex, QModelIndex ) ), mComposition->itemsModel(), SLOT( setSelected( QModelIndex ) ) );
3080+
30503081
setSelectionTool();
30513082
}
30523083

0 commit comments

Comments
 (0)