Skip to content

Commit

Permalink
[FEATURE][composer] Implement an item tree panel for composer windows
Browse files Browse the repository at this point in the history
(fix #4358). Allows for selection of items, hiding/showing items,
toggling lock status of items and double-clicking to edit item id.
  • Loading branch information
nyalldawson committed Jul 30, 2014
1 parent b357a66 commit 4506b81
Show file tree
Hide file tree
Showing 20 changed files with 1,527 additions and 185 deletions.
18 changes: 18 additions & 0 deletions python/core/composer/qgscomposeritem.sip
Expand Up @@ -149,6 +149,24 @@ class QgsComposerItem : QgsComposerObject, QGraphicsRectItem

/** return correct graphics item type. Added in v1.7 */
virtual int type() const;

/**Returns whether this item has been removed from the composition. Items removed
* from the composition are not deleted so that they can be restored via an undo
* command.
* @returns true if the item has been removed from the composition
* @note added in QGIS 2.5
* @see setIsRemoved
*/
virtual bool isRemoved() const;

/**Sets whether this item has been removed from the composition. Items removed
* from the composition are not deleted so that they can be restored via an undo
* command.
* @param removed set to true if the item has been removed from the composition
* @note added in QGIS 2.5
* @see isRemoved
*/
void setIsRemoved( const bool removed );

/** \brief Set selected, selected item should be highlighted */
virtual void setSelected( bool s );
Expand Down
194 changes: 194 additions & 0 deletions python/core/composer/qgscomposermodel.sip
@@ -0,0 +1,194 @@
/**
* \class QgsComposerModel
* \ingroup MapComposer
*
* A model for items attached to a composition. The model also maintains the z-order for the
* composition, and must be notified whenever item stacking changes.
*
* Internally, QgsComposerModel maintains two lists. One contains a complete list of all items for
* the composition, ordered by their position within the z-order stack. This list also contains
* items which have been removed from the composition, so that undo/redo commands can restore
* them to their correct position in the stacking order.
*
* The second list contains only items which are currently displayed in the composition's scene.
* It is used as a cache of the last known stacking order, so that the model can compare the current
* stacking of items in the composition to the last known state, and emit the corresponding signals
* as required.
*/

class QgsComposerModel : QAbstractItemModel
{
%TypeHeaderCode
#include "qgscomposermodel.h"
%End
public:

/**Constructor
* @param composition parent composition
*/
explicit QgsComposerModel( QgsComposition* composition, QObject* parent = 0 );

~QgsComposerModel();

//reimplemented QAbstractItemModel methods
QModelIndex index( int row, int column, const QModelIndex &parent = QModelIndex() ) const;
QModelIndex parent( const QModelIndex &index ) const;
int rowCount( const QModelIndex &parent = QModelIndex() ) const;
int columnCount( const QModelIndex &parent = QModelIndex() ) const;
QVariant data( const QModelIndex &index, int role ) const;
Qt::ItemFlags flags( const QModelIndex & index ) const;
bool setData( const QModelIndex & index, const QVariant & value, int role );
QVariant headerData( int section, Qt::Orientation orientation, int role = Qt::DisplayRole ) const;

/**Clears all items from z-order list and resets the model
* @note added in QGIS 2.5
*/
void clear();

/**Returns the size of the z-order list, which includes items which may
* have been removed from the composition.
* @returns size of z-order list
* @note added in QGIS 2.5
*/
int zOrderListSize() const;

/**Rebuilds the z-order list, based on the current stacking of items in the composition.
* This method should be called after adding multiple items to the composition.
* @note added in QGIS 2.5
*/
void rebuildZList();

/**Adds an item to the top of the composition z stack.
* @param item item to add. The item must not already exist in the z-order list.
* @note added in QGIS 2.5
* @see reorderItemToTop
*/
void addItemAtTop( QgsComposerItem *item );

/**Removes an item from the z-order list.
* @param item item to remove
* @note added in QGIS 2.5
*/
void removeItem( QgsComposerItem *item );

/**Moves an item up the z-order list.
* @param item item to move
* @returns true if item was moved. Returns false if item was not found
* in z-order list or was already at the top of the z-order list.
* @see reorderItemDown
* @see reorderItemToTop
* @see reorderItemToBottom
* @note added in QGIS 2.5
*/
bool reorderItemUp( QgsComposerItem *item );

/**Moves an item down the z-order list.
* @param item item to move
* @returns true if item was moved. Returns false if item was not found
* in z-order list or was already at the bottom of the z-order list.
* @see reorderItemUp
* @see reorderItemToTop
* @see reorderItemToBottom
* @note added in QGIS 2.5
*/
bool reorderItemDown( QgsComposerItem *item );

/**Moves an item to the top of the z-order list.
* @param item item to move
* @returns true if item was moved. Returns false if item was not found
* in z-order list or was already at the top of the z-order list.
* @see reorderItemUp
* @see reorderItemDown
* @see reorderItemToBottom
* @note added in QGIS 2.5
*/
bool reorderItemToTop( QgsComposerItem *item );

/**Moves an item to the bottom of the z-order list.
* @param item item to move
* @returns true if item was moved. Returns false if item was not found
* in z-order list or was already at the bottom of the z-order list.
* @see reorderItemUp
* @see reorderItemDown
* @see reorderItemToTop
* @note added in QGIS 2.5
*/
bool reorderItemToBottom( QgsComposerItem *item );

/**Finds the next composer item above an item. This method only considers
* items which are currently in the composition, and ignores items which have been
* removed from the composition.
* @param item item to search above
* @returns item above specified item. If no items were found, no item
* will be returned.
* @see getComposerItemBelow
* @note added in QGIS 2.5
*/
QgsComposerItem* getComposerItemAbove( QgsComposerItem *item ) const;

/**Finds the next composer item below an item. This method only considers
* items which are currently in the composition, and ignores items which have been
* removed from the composition.
* @param item item to search above
* @returns item below specified item. If no items were found, no item
* will be returned.
* @see getComposerItemAbove
* @note added in QGIS 2.5
*/
QgsComposerItem* getComposerItemBelow( QgsComposerItem *item ) const;

/**Returns the item z-order list. This list includes both items currently in the
* composition and items which have been removed from the composition.
* @returns item z-order list
* @note added in QGIS 2.5
*/
QList<QgsComposerItem *>* zOrderList();

/**Marks an item as removed from the composition. This must be called whenever an item
* has been removed from the composition.
* @param item to mark as removed from the composition
* @see setItemRestored
* @note added in QGIS 2.5
*/
void setItemRemoved( QgsComposerItem *item );

/**Restores an item to the composition. This must be called whenever an item removed
* from the composition is restored to the composition.
* @param item to mark as restored to the composition
* @see setItemRemoved
* @note added in QGIS 2.5
*/
void setItemRestored( QgsComposerItem *item );

/**Must be called when an item's display name is modified
* @param item item to update
* @see updateItemLockStatus
* @see updateItemVisibility
* @note added in QGIS 2.5
*/
void updateItemDisplayName( QgsComposerItem *item );

/**Must be called when an item's lock status changes
* @param item item to update
* @see updateItemDisplayName
* @see updateItemVisibility
* @note added in QGIS 2.5
*/
void updateItemLockStatus( QgsComposerItem *item );

/**Must be called when an item's visibility changes
* @param item item to update
* @see updateItemDisplayName
* @see updateItemLockStatus
* @note added in QGIS 2.5
*/
void updateItemVisibility( QgsComposerItem *item );

public slots:

/**Sets an item as the current selection from a QModelIndex
* @param index QModelIndex of item to set as selected
* @note added in QGIS 2.5
*/
void setSelected( const QModelIndex &index );
};
32 changes: 22 additions & 10 deletions python/core/composer/qgscomposition.sip
Expand Up @@ -301,15 +301,17 @@ class QgsComposition : QGraphicsScene
/**Removes item from z list. Usually called from destructor of QgsComposerItem*/
void removeItemFromZList( QgsComposerItem* item );

//functions to move selected items in hierarchy
void raiseSelectedItems();
void raiseItem( QgsComposerItem* item );
//returns true if successful
bool raiseItem( QgsComposerItem* item );
void lowerSelectedItems();
void lowerItem( QgsComposerItem* item );
//returns true if successful
bool lowerItem( QgsComposerItem* item );
void moveSelectedItemsToTop();
void moveItemToTop( QgsComposerItem* item );
//returns true if successful
bool moveItemToTop( QgsComposerItem* item );
void moveSelectedItemsToBottom();
void moveItemToBottom( QgsComposerItem* item );
//returns true if successful
bool moveItemToBottom( QgsComposerItem* item );

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

/**Sorts the zList. The only time where this function needs to be called is from QgsComposer
after reading all the items from xml file*/
void sortZList();
* after reading all the items from xml file
* @note deprecated, see @refreshZList instead
*/
void sortZList() /Deprecated/;

/**Rebuilds the z order list based on current order of items in scene*/
/**Rebuilds the z order list by adding any item which are present in the composition
* but missing from the z order list.
*/
void refreshZList();

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

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

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

/**Returns the items model attached to the composition
* @returns QgsComposerModel for composition
* @note this method was added in version 2.5
*/
QgsComposerModel * itemsModel();

public slots:
/**Casts object to the proper subclass type and calls corresponding itemAdded signal*/
void sendItemAddedSignal( QgsComposerItem* item );
Expand Down
1 change: 1 addition & 0 deletions python/core/core.sip
Expand Up @@ -135,6 +135,7 @@
%Include composer/qgscomposertablecolumn.sip
%Include composer/qgscomposerutils.sip
%Include composer/qgscomposition.sip
%Include composer/qgscomposermodel.sip
%Include composer/qgsatlascomposition.sip
%Include composer/qgsdoubleboxscalebarstyle.sip
%Include composer/qgslegendmodel.sip
Expand Down
31 changes: 31 additions & 0 deletions src/app/composer/qgscomposer.cpp
Expand Up @@ -25,6 +25,7 @@
#include "qgscomposerview.h"
#include "qgscomposition.h"
#include "qgscompositionwidget.h"
#include "qgscomposermodel.h"
#include "qgsatlascompositionwidget.h"
#include "qgscomposerarrow.h"
#include "qgscomposerarrowwidget.h"
Expand Down Expand Up @@ -88,6 +89,8 @@
#include <QProgressDialog>
#include <QShortcut>

//For model testing
//#include "modeltest.h"

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

mGeneralDock->setFeatures( QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetClosable );
mItemDock->setFeatures( QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetClosable );
mUndoDock->setFeatures( QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetClosable );
mAtlasDock->setFeatures( QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetClosable );
mItemsDock->setFeatures( QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetClosable );

createCompositionWidget();

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

//items tree widget
mItemsTreeView = new QTreeView( mItemsDock );
mItemsTreeView->setModel( mComposition->itemsModel() );
//for testing:
//new ModelTest( mComposition->itemsModel(), this );

mItemsTreeView->setColumnWidth( 0, 30 );
mItemsTreeView->setColumnWidth( 1, 30 );
mItemsTreeView->header()->setResizeMode( 0, QHeaderView::Fixed );
mItemsTreeView->header()->setResizeMode( 1, QHeaderView::Fixed );
mItemsTreeView->header()->setMovable( false );
mItemsTreeView->setIndentation( 0 );
mItemsDock->setWidget( mItemsTreeView );
connect( mItemsTreeView->selectionModel(), SIGNAL( currentChanged( QModelIndex, QModelIndex ) ), mComposition->itemsModel(), SLOT( setSelected( QModelIndex ) ) );

addDockWidget( Qt::RightDockWidgetArea, mItemDock );
addDockWidget( Qt::RightDockWidgetArea, mGeneralDock );
addDockWidget( Qt::RightDockWidgetArea, mUndoDock );
addDockWidget( Qt::RightDockWidgetArea, mAtlasDock );
addDockWidget( Qt::RightDockWidgetArea, mItemsDock );

QgsAtlasCompositionWidget* atlasWidget = new QgsAtlasCompositionWidget( mGeneralDock, mComposition );
mAtlasDock->setWidget( atlasWidget );
Expand All @@ -545,11 +568,13 @@ QgsComposer::QgsComposer( QgisApp *qgis, const QString& title )
mGeneralDock->show();
mUndoDock->show();
mAtlasDock->show();
mItemsDock->show();

tabifyDockWidget( mGeneralDock, mUndoDock );
tabifyDockWidget( mItemDock, mUndoDock );
tabifyDockWidget( mGeneralDock, mItemDock );
tabifyDockWidget( mItemDock, mAtlasDock );
tabifyDockWidget( mItemDock, mItemsDock );

mGeneralDock->raise();

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

//setup items tree view
mItemsTreeView->setModel( mComposition->itemsModel() );
mItemsTreeView->setColumnWidth( 0, 30 );
mItemsTreeView->setColumnWidth( 1, 30 );
connect( mItemsTreeView->selectionModel(), SIGNAL( currentChanged( QModelIndex, QModelIndex ) ), mComposition->itemsModel(), SLOT( setSelected( QModelIndex ) ) );

setSelectionTool();
}

Expand Down

0 comments on commit 4506b81

Please sign in to comment.