Skip to content

Commit

Permalink
Merge branch 'embed_layers'
Browse files Browse the repository at this point in the history
  • Loading branch information
Marco Hugentobler committed Jun 6, 2011
2 parents 107df1f + ba39378 commit c2b418b
Show file tree
Hide file tree
Showing 23 changed files with 973 additions and 126 deletions.
2 changes: 2 additions & 0 deletions src/app/CMakeLists.txt
Expand Up @@ -20,6 +20,7 @@ SET(QGIS_APP_SRCS
qgscustomprojectiondialog.cpp
qgsdbfilterproxymodel.cpp
qgsdbtablemodel.cpp
qgsembedlayerdialog.cpp
qgsformannotationdialog.cpp
qgsdelattrdialog.cpp
qgsdisplayangle.cpp
Expand Down Expand Up @@ -152,6 +153,7 @@ SET (QGIS_APP_MOC_HDRS
qgsdbtablemodel.h
qgsdelattrdialog.h
qgsdisplayangle.h
qgsembedlayerdialog.h
qgsfeatureaction.h
qgsfieldcalculator.h
qgsformannotationdialog.h
Expand Down
243 changes: 208 additions & 35 deletions src/app/legend/qgslegend.cpp
Expand Up @@ -295,6 +295,12 @@ void QgsLegend::mouseMoveEvent( QMouseEvent * e )
// record which items were selected and hide them
foreach( QTreeWidgetItem * item, selectedItems() )
{
//prevent to drag out content under groups that are embedded from other
//project files.
if( parentGroupEmbedded( item ) )
{
continue;
}
item->setHidden( true );
mItemsBeingMoved << item;
}
Expand Down Expand Up @@ -324,6 +330,7 @@ void QgsLegend::mouseMoveEvent( QMouseEvent * e )
if ( mItemsBeingMoved.isEmpty() )
{
QgsDebugMsg( "nothing to move" );
setCursor( QCursor( Qt::ArrowCursor ) );
return;
}

Expand Down Expand Up @@ -364,36 +371,47 @@ void QgsLegend::mouseMoveEvent( QMouseEvent * e )

mDropTarget = layer;

if ( e->y() < ( y0 + y1 ) / 2 )
//prevent inserting content into embedded groups
if( !parentGroupEmbedded( litem ) )
{
QgsDebugMsg( "insert before layer" );
mDropAction = BEFORE;
line_y = y0;
}
else
{
QgsDebugMsg( "insert after layer" );
mDropAction = AFTER;
line_y = y1;
if ( e->y() < ( y0 + y1 ) / 2 )
{
QgsDebugMsg( "insert before layer" );
mDropAction = BEFORE;
line_y = y0;
}
else
{
QgsDebugMsg( "insert after layer" );
mDropAction = AFTER;
line_y = y1;
}
}
}
else if ( group )
{
else if ( group )
{
if ( yCoordAboveCenter( litem, e->y() ) ) //over center of item
{
QgsDebugMsg( "insert before group" );

line_y = visualItemRect( item ).top() + 1;
mDropTarget = item;
mDropAction = BEFORE;
//prevent inserting content into embedded groups
if( !parentGroupEmbedded( item ) )
{
line_y = visualItemRect( item ).top() + 1;
mDropTarget = item;
mDropAction = BEFORE;
}
}
else // below center of item
{
QgsDebugMsg( "insert into group" );
if( !groupEmbedded( item ) )
{
QgsDebugMsg( "insert into group" );

line_y = visualItemRect( item ).bottom() - 2;
mDropTarget = item;
mDropAction = INSERT;
line_y = visualItemRect( item ).bottom() - 2;
mDropTarget = item;
mDropAction = INSERT;
}
}
}
else
Expand Down Expand Up @@ -566,7 +584,7 @@ void QgsLegend::handleRightClickEvent( QTreeWidgetItem* item, const QPoint& posi
{
qobject_cast<QgsLegendLayer*>( li )->addToPopupMenu( theMenu );

if ( li->parent() )
if ( li->parent() && !parentGroupEmbedded( li ) )
{
theMenu.addAction( tr( "&Make to toplevel item" ), this, SLOT( makeToTopLevelItem() ) );
}
Expand All @@ -583,7 +601,7 @@ void QgsLegend::handleRightClickEvent( QTreeWidgetItem* item, const QPoint& posi
tr( "&Set group CRS" ), this, SLOT( legendGroupSetCRS() ) );
}

if ( li->type() == QgsLegendItem::LEGEND_LAYER || li->type() == QgsLegendItem::LEGEND_GROUP )
if ( ( li->type() == QgsLegendItem::LEGEND_LAYER || li->type() == QgsLegendItem::LEGEND_GROUP ) && !groupEmbedded( li ) && !parentGroupEmbedded( li ) )
{
theMenu.addAction( tr( "Re&name" ), this, SLOT( openEditor() ) );
}
Expand Down Expand Up @@ -611,6 +629,87 @@ Qt::CheckState QgsLegend::layerCheckState( QgsMapLayer * layer )
return ll ? ll->checkState( 0 ) : Qt::Unchecked;
}

QgsLegendGroup* QgsLegend::addEmbeddedGroup( const QString& groupName, const QString& projectFilePath, QgsLegendItem* parent )
{
mEmbeddedGroups.insert( groupName, projectFilePath );

//open project file, get layer ids in group, add the layers
QFile projectFile( projectFilePath );
if( !projectFile.open( QIODevice::ReadOnly ) )
{
return 0;
}

QDomDocument projectDocument;
if( !projectDocument.setContent( &projectFile ) )
{
return 0;
}

QDomElement legendElem = projectDocument.documentElement().firstChildElement("legend");
if( legendElem.isNull() )
{
return 0;
}

QList<QDomNode> brokenNodes;
QList< QPair< QgsVectorLayer*, QDomElement > > vectorLayerList;
QSettings settings;

QDomNodeList legendGroupList = legendElem.elementsByTagName("legendgroup");
for( int i = 0; i < legendGroupList.size(); ++i )
{
QDomElement legendElem = legendGroupList.at(i).toElement();
if( legendElem.attribute("name") == groupName )
{
//embedded groups cannot be embedded again
if( legendElem.attribute("embedded") == "1" )
{
mEmbeddedGroups.remove( groupName );
return 0;
}

QgsLegendGroup* group = 0;
if( parent )
{
group = new QgsLegendGroup( parent, groupName );
}
else
{
group = new QgsLegendGroup( this, groupName );
}

QFont groupFont;
groupFont.setItalic( true );
group->setFont( 0, groupFont );
setCurrentItem( group );

QDomNodeList groupChildren = legendElem.childNodes();
for( int j = 0; j < groupChildren.size(); ++j )
{
QDomElement childElem = groupChildren.at( j ).toElement();
QString tagName = childElem.tagName();
if( tagName == "legendlayer" )
{
QString layerId = childElem.firstChildElement("filegroup").firstChildElement("legendlayerfile").attribute("layerid");
QgsProject::instance()->createEmbeddedLayer( layerId, projectFilePath, brokenNodes, vectorLayerList, false );
if( currentItem() && currentItem() != group )
{
insertItem( currentItem(), group );
}
}
else if( tagName == "legendgroup" )
{
addEmbeddedGroup( childElem.attribute("name"), projectFilePath, group );
}
}
checkLayerOrderUpdate();
return group;
}
}
return 0;
}

int QgsLegend::getItemPos( QTreeWidgetItem* item )
{
int counter = 1;
Expand All @@ -636,6 +735,12 @@ void QgsLegend::addLayer( QgsMapLayer * layer )
}

QgsLegendLayer* llayer = new QgsLegendLayer( layer );
if( !QgsProject::instance()->layerIsEmbedded( layer->id() ).isEmpty() )
{
QFont itemFont;
itemFont.setItalic( true );
llayer->setFont( 0, itemFont );
}

//set the correct check states
blockSignals( true );
Expand Down Expand Up @@ -926,14 +1031,22 @@ bool QgsLegend::writeXML( QList<QTreeWidgetItem *> items, QDomNode &node, QDomDo
legendgroupnode.setAttribute( "checked", "Qt::PartiallyChecked" );
}

QList<QTreeWidgetItem *> children;
for ( int i = 0; i < currentItem->childCount(); i++ )
QHash< QString, QString >::const_iterator embedIt = mEmbeddedGroups.find( item->text( 0 ) );
if( embedIt != mEmbeddedGroups.constEnd() )
{
children << currentItem->child( i );
legendgroupnode.setAttribute("embedded", 1);
legendgroupnode.setAttribute("project", embedIt.value() );
}
else
{
QList<QTreeWidgetItem *> children;
for ( int i = 0; i < currentItem->childCount(); i++ )
{
children << currentItem->child( i );
}

writeXML( children, legendgroupnode, document );

writeXML( children, legendgroupnode, document );
}
node.appendChild( legendgroupnode );
}
else if ( item->type() == QgsLegendItem::LEGEND_LAYER )
Expand Down Expand Up @@ -1005,6 +1118,12 @@ bool QgsLegend::writeXML( QList<QTreeWidgetItem *> items, QDomNode &node, QDomDo
legendlayerfilenode.setAttribute( "layerid", layer->id() );
layerfilegroupnode.appendChild( legendlayerfilenode );

//embedded layer?
if( !QgsProject::instance()->layerIsEmbedded( layer->id() ).isEmpty() )
{
legendlayerfilenode.setAttribute( "embedded", "1" );
}

// visible flag
legendlayerfilenode.setAttribute( "visible", ll->isVisible() );

Expand Down Expand Up @@ -1032,11 +1151,23 @@ bool QgsLegend::readXML( QgsLegendGroup *parent, const QDomNode &node )
//test every possibility of element...
if ( childelem.tagName() == "legendgroup" )
{
QgsLegendGroup *theGroup;
if ( parent )
theGroup = new QgsLegendGroup( parent, name );
QgsLegendGroup* theGroup = 0;
if( childelem.attribute("embedded") == "1" )
{
theGroup = addEmbeddedGroup( name, childelem.attribute( "project" ) );
}
else
theGroup = new QgsLegendGroup( this, name );
{
if ( parent )
theGroup = new QgsLegendGroup( parent, name );
else
theGroup = new QgsLegendGroup( this, name );
}

if( !theGroup )
{
continue;
}

//set the checkbox of the legend group to the right state
blockSignals( true );
Expand Down Expand Up @@ -1720,7 +1851,10 @@ void QgsLegend::openEditor()
QTreeWidgetItem* theItem = currentItem();
if ( theItem )
{
editItem( theItem, 0 );
if( !groupEmbedded( theItem ) && !parentGroupEmbedded( theItem ) )
{
editItem( theItem, 0 );
}
}
}

Expand All @@ -1729,10 +1863,13 @@ void QgsLegend::makeToTopLevelItem()
QgsLegendItem* theItem = dynamic_cast<QgsLegendItem *>( currentItem() );
if ( theItem )
{
theItem->storeAppearanceSettings();
removeItem( theItem );
addTopLevelItem( theItem );
theItem->restoreAppearanceSettings();
if( !parentGroupEmbedded( theItem ) )
{
theItem->storeAppearanceSettings();
removeItem( theItem );
addTopLevelItem( theItem );
theItem->restoreAppearanceSettings();
}
}
}

Expand Down Expand Up @@ -2036,3 +2173,39 @@ void QgsLegend::setCRSForSelectedLayers( const QgsCoordinateReferenceSystem &crs
if ( renderFlagState )
mMapCanvas->setRenderFlag( true );
}

bool QgsLegend::parentGroupEmbedded( QTreeWidgetItem* item ) const
{
if( !item )
{
return false;
}

QgsLegendItem* lItem = dynamic_cast<QgsLegendItem*>(item);
if( lItem && lItem->parent() )
{
QgsLegendGroup* parentGroup = dynamic_cast<QgsLegendGroup*>( lItem->parent() );
if( parentGroup && parentGroup->type() == QgsLegendItem::LEGEND_GROUP
&& mEmbeddedGroups.contains( parentGroup->text( 0 ) ) )
{
return true;
}
}
return false;
}

bool QgsLegend::groupEmbedded( QTreeWidgetItem* item ) const
{
if( !item )
{
return false;
}

QgsLegendGroup* gItem = dynamic_cast<QgsLegendGroup*>(item);
if( !gItem )
{
return false;
}

return mEmbeddedGroups.contains( gItem->text( 0 ) );
}
13 changes: 13 additions & 0 deletions src/app/legend/qgslegend.h
Expand Up @@ -193,6 +193,9 @@ class QgsLegend : public QTreeWidget
/**Returns a layers check state*/
Qt::CheckState layerCheckState( QgsMapLayer * layer );

/**Add group from other project file. Returns a pointer to the new group in case of success or 0 in case of error*/
QgsLegendGroup* addEmbeddedGroup( const QString& groupName, const QString& projectFilePath, QgsLegendItem* parent = 0 );

public slots:

/*!Adds a new layer group with the maplayer to the canvas*/
Expand Down Expand Up @@ -367,6 +370,10 @@ class QgsLegend : public QTreeWidget
// The action when the mouse is released
enum { BEFORE, INSERT, AFTER } mDropAction;

/** Groups defined in other project files.
Key: group name, value: absolute path to project file*/
QHash< QString, QString > mEmbeddedGroups;

/** Hide the line that indicates insertion position */
void hideLine();

Expand Down Expand Up @@ -430,6 +437,12 @@ class QgsLegend : public QTreeWidget
*/
int getItemPos( QTreeWidgetItem* item );

/**Returns true if the item is a group embedde from another project*/
bool groupEmbedded( QTreeWidgetItem* item ) const;

/**Returns true if the parent group is embedded from another project*/
bool parentGroupEmbedded( QTreeWidgetItem* item ) const;

/**Pointer to the main canvas. Used for requiring repaints in case of legend changes*/
QgsMapCanvas* mMapCanvas;

Expand Down

0 comments on commit c2b418b

Please sign in to comment.