Skip to content

Commit

Permalink
checkbox for legend groups
Browse files Browse the repository at this point in the history
git-svn-id: http://svn.osgeo.org/qgis/trunk@4927 c8812cc2-4d05-0410-92ff-de0c093fc19c
  • Loading branch information
mhugent committed Feb 28, 2006
1 parent 078c75a commit fc7ca7b
Show file tree
Hide file tree
Showing 10 changed files with 287 additions and 55 deletions.
4 changes: 2 additions & 2 deletions qgis.dtd
Expand Up @@ -120,9 +120,9 @@ outlinecolor,outlinestyle,outlinewidth,fillcolor,fillpattern) >
<!ELEMENT legend (legendgroup* | legendlayer*) >
<!ATTLIST legend open (1|0|true|false) "false"> #open or closed
<!ELEMENT legendgroup (legendlayer*) >
<!ATTLIST legendgroup open (1|0|true|false) "false" name CDATA> #open or closed
<!ATTLIST legendgroup open (1|0|true|false) "false" name CDATA checked (Qt::Checked|Qt::Unchecked|Qt::PartiallyChecked) "Qt::Checked">
<!ELEMENT legendlayer (legendsymbologyitem+, legendlayerfilegroup>
<!ATTLIST legendlayer open (1|0|true|false) "false" checked (Qt::Checked|Qt::Unchecked|Qt::PartiallyChecked) "Qt::Checked"> #open or closed
<!ATTLIST legendlayer open (1|0|true|false) "false" checked (Qt::Checked|Qt::Unchecked|Qt::PartiallyChecked) "Qt::Checked">
<!ELEMENT legendlayerfilegroup (legendlayerfile*) >
<!ATTLIST legendlayerfilegroup open (1|0|true|false) "false" > #open or closed
<!ATTLIST legendlayerfilegroup hidden(1|0|true|false) "false"> #hidden or shown
Expand Down
192 changes: 186 additions & 6 deletions src/legend/qgslegend.cpp
Expand Up @@ -84,6 +84,7 @@ QgsLegend::~QgsLegend()
void QgsLegend::addGroup()
{
QgsLegendGroup* group = new QgsLegendGroup(this, tr("group"));
mStateOfCheckBoxes.insert(std::make_pair(group, Qt::Checked)); //insert the check state into the map to query for changes later
setExpanded(indexFromItem(group), true);
}

Expand Down Expand Up @@ -224,8 +225,7 @@ void QgsLegend::mouseMoveEvent(QMouseEvent * e)
setCursor( QCursor(Qt::PointingHandCursor) );
if(origin->parent() != dest)
{
removeItem(origin);
dest->insert(origin, false);
insertItem(origin, dest);
setCurrentItem(origin);
}
}
Expand Down Expand Up @@ -438,7 +438,7 @@ int QgsLegend::getItemPos(QTreeWidgetItem* item)

void QgsLegend::addLayer( QgsMapLayer * layer )
{
QgsLegendLayer * llayer = new QgsLegendLayer(QString(layer->name()));
QgsLegendLayer * llayer = new QgsLegendLayer(layer->name());
mStateOfCheckBoxes.insert(std::make_pair(llayer, Qt::Checked)); //insert the check state into the map to query for changes later
QgsLegendLayerFileGroup * llfgroup = new QgsLegendLayerFileGroup(llayer,QString("Files"));
QgsLegendLayerFile * llfile = new QgsLegendLayerFile(llfgroup, QgsLegendLayerFile::nameFromLayer(layer), layer);
Expand Down Expand Up @@ -681,7 +681,7 @@ bool QgsLegend::writeXML( QDomNode & layer_node, QDomDocument & document )
QDomElement legendpropertynode;
QDomElement legendlayerfilenode;
QgsLegendLayerFile* llf;
Qt::CheckState cstate; //check state for legend layers
Qt::CheckState cstate; //check state for legend layers and legend groups

QTreeWidgetItem* currentItem = firstItem();
while(currentItem)
Expand All @@ -707,6 +707,19 @@ bool QgsLegend::writeXML( QDomNode & layer_node, QDomDocument & document )
legendgroupnode.setAttribute("open","false");
}
legendgroupnode.setAttribute("name",item->text(0));
cstate = item->checkState(0);
if(cstate == Qt::Checked)
{
legendgroupnode.setAttribute("checked","Qt::Checked");
}
else if(cstate == Qt::Unchecked)
{
legendgroupnode.setAttribute("checked","Qt::Unchecked");
}
else if(cstate == Qt::PartiallyChecked)
{
legendgroupnode.setAttribute("checked","Qt::PartiallyChecked");
}
legendnode.appendChild(legendgroupnode);
tmplegendnode = legendnode;
legendnode = legendgroupnode;
Expand Down Expand Up @@ -837,6 +850,25 @@ bool QgsLegend::readXML(QDomNode& legendnode)
{
QgsLegendGroup* theGroup = new QgsLegendGroup(this, name);
childelem.attribute("open") == "true" ? expandItem(theGroup) : collapseItem(theGroup);
//set the checkbox of the legend group to the right state
blockSignals(true);
QString checked = childelem.attribute("checked");
if(checked == "Qt::Checked")
{
theGroup->setCheckState(0, Qt::Checked);
mStateOfCheckBoxes.insert(std::make_pair(theGroup, Qt::Checked));
}
else if(checked == "Qt::Unchecked")
{
theGroup->setCheckState(0, Qt::Unchecked);
mStateOfCheckBoxes.insert(std::make_pair(theGroup, Qt::Unchecked));
}
else if(checked == "Qt::PartiallyChecked")
{
theGroup->setCheckState(0, Qt::PartiallyChecked);
mStateOfCheckBoxes.insert(std::make_pair(theGroup, Qt::PartiallyChecked));
}
blockSignals(false);
lastGroup = theGroup;
}
else if(childelem.tagName()=="legendlayer")
Expand Down Expand Up @@ -1121,6 +1153,20 @@ QDomNode QgsLegend::nextDomNode(const QDomNode& theNode)
}
}

void QgsLegend::insertItem(QTreeWidgetItem* move, QTreeWidgetItem* into)
{
QgsLegendItem* movedItem = dynamic_cast<QgsLegendItem*>(move);
QgsLegendItem* intoItem = dynamic_cast<QgsLegendItem*>(into);

if(movedItem && intoItem)
{
movedItem->storeAppearanceSettings();//store settings in the moved item and its children
removeItem(movedItem);
intoItem->insert(movedItem);
movedItem->restoreAppearanceSettings();//apply the settings again
}
}

void QgsLegend::moveItem(QTreeWidgetItem* move, QTreeWidgetItem* after)
{
static_cast<QgsLegendItem*>(move)->storeAppearanceSettings();//store settings in the moved item and its childern
Expand Down Expand Up @@ -1227,7 +1273,138 @@ void QgsLegend::changeSymbologySettings(const QString& key, const std::list< std

void QgsLegend::handleItemChange(QTreeWidgetItem* item, int row)
{
if(!item)
{
return;
}

closePersistentEditor(item, row);

std::map<QTreeWidgetItem*, Qt::CheckState>::iterator it = mStateOfCheckBoxes.find(item);
if(it != mStateOfCheckBoxes.end())
{
if(it->second != item->checkState(0)) //the checkState has changed
{

QgsLegendLayerFile* llf = dynamic_cast<QgsLegendLayerFile*>(item); //item is a layer file
if(llf)
{
if(llf->layer())
{
llf->layer()->setVisible(item->checkState(0) == Qt::Checked);
}
//update check state of the legend layer
QgsLegendLayer* ll = dynamic_cast<QgsLegendLayer*>(item->parent()->parent());
if(ll)
{
ll->updateCheckState();
mStateOfCheckBoxes[ll] = ll->checkState(0);
}
//update check state of the legend group (if any)
if(item->parent()->parent()->parent())
{
QgsLegendGroup* lg = dynamic_cast<QgsLegendGroup*>(item->parent()->parent()->parent());
if(lg)
{
lg->updateCheckState();
mStateOfCheckBoxes[lg] = lg->checkState(0);
}
}
mStateOfCheckBoxes[item] = item->checkState(0);
return;
}

std::list<QgsLegendLayerFile*> subfiles;
QgsLegendGroup* lg = dynamic_cast<QgsLegendGroup*>(item); //item is a legend group
if(lg)
{
//set all the child layer files to the new check state
subfiles = lg->legendLayerFiles();
mMapCanvas->setRenderFlag(false);
for(std::list<QgsLegendLayerFile*>::iterator iter = subfiles.begin(); iter != subfiles.end(); ++iter)
{
#ifdef QGISDEBUG
if(item->checkState(0) == Qt::Checked)
{
qWarning("item checked");
}
else if(item->checkState(0) == Qt::Unchecked)
{
qWarning("item unchecked");
}
else if(item->checkState(0) == Qt::PartiallyChecked)
{
qWarning("item partially checked");
}
#endif
blockSignals(true);
(*iter)->setCheckState(0, item->checkState(0));
blockSignals(false);
mStateOfCheckBoxes[(*iter)] = item->checkState(0);
if((*iter)->layer())
{
(*iter)->layer()->setVisible(item->checkState(0) == Qt::Checked);
}
}

//update the check states of all child legend layers
for(int i = 0; i < lg->childCount(); ++i)
{
static_cast<QgsLegendLayer*>(lg->child(i))->updateCheckState();
mStateOfCheckBoxes[lg->child(i)] = lg->child(i)->checkState(0);
}
mMapCanvas->setRenderFlag(true);
mStateOfCheckBoxes[item] = item->checkState(0);
return;
}

QgsLegendLayer* ll = dynamic_cast<QgsLegendLayer*>(item); //item is a legend layer
if(ll)
{
//set all the child layer files to the new check state
subfiles = ll->legendLayerFiles();
mMapCanvas->setRenderFlag(false);
for(std::list<QgsLegendLayerFile*>::iterator iter = subfiles.begin(); iter != subfiles.end(); ++iter)
{
blockSignals(true);
(*iter)->setCheckState(0, item->checkState(0));
blockSignals(false);
mStateOfCheckBoxes[(*iter)] = item->checkState(0);
if((*iter)->layer())
{
(*iter)->layer()->setVisible(item->checkState(0) == Qt::Checked);
}
}
if(ll->parent())
{
static_cast<QgsLegendGroup*>(ll->parent())->updateCheckState();
mStateOfCheckBoxes[ll->parent()] = ll->parent()->checkState(0);
}
mMapCanvas->setRenderFlag(true);
//update check state of the legend group
}
mStateOfCheckBoxes[item] = item->checkState(0);
}
}
#if 0
QgsLegendGroup* lg = dynamic_cast<QgsLegendGroup*>(item);
if(lg)
{
#ifdef QGISDEBUG
qWarning("detected legend group in QgsLegend::handleItemChange");
#endif
std::map<QTreeWidgetItem*, Qt::CheckState>::iterator it = mStateOfCheckBoxes.find(item);
if(it != mStateOfCheckBoxes.end())
{
if(it->second != item->checkState(0)) //the checkState has changed
{
bool checked = (item->checkState(0) == Qt::Checked);

}
}
return;
}

QgsLegendLayerFile* llf = dynamic_cast<QgsLegendLayerFile*>(item);
if(llf)
{
Expand All @@ -1244,7 +1421,7 @@ void QgsLegend::handleItemChange(QTreeWidgetItem* item, int row)
{
bool checked = (item->checkState(0) == Qt::Checked);
theLayer->setVisible(checked);
//todo: check, how the checkbox of the legendlayer needs to be updated
//check, how the checkbox of the legendlayer needs to be updated
QgsLegendLayer* ll = dynamic_cast<QgsLegendLayer*>(item->parent()->parent());
std::list<QgsLegendLayerFile*> llfiles = ll->legendLayerFiles();
std::list<QgsLegendLayerFile*>::iterator iter = llfiles.begin();
Expand Down Expand Up @@ -1304,6 +1481,7 @@ void QgsLegend::handleItemChange(QTreeWidgetItem* item, int row)
}
}
}
#endif //0
}

void QgsLegend::openEditor()
Expand All @@ -1317,11 +1495,13 @@ void QgsLegend::openEditor()

void QgsLegend::makeToTopLevelItem()
{
QTreeWidgetItem* theItem = currentItem();
QgsLegendItem* theItem = dynamic_cast<QgsLegendItem*>(currentItem());
if(theItem)
{
theItem->storeAppearanceSettings();
removeItem(theItem);
addTopLevelItem(theItem);
theItem->restoreAppearanceSettings();
}
}

Expand Down
7 changes: 6 additions & 1 deletion src/legend/qgslegend.h
Expand Up @@ -124,7 +124,12 @@ class QgsLegend : public QTreeWidget
/**Finds the next dom node. This function is used by QgsLegend, but probably its not a good place here*/
static QDomNode nextDomNode(const QDomNode& theNode);

/**Moves an item after another one*/
/**Inserts an item into another one. Stores the item specific settings of the moved item (and its subitems)
and applies it afterwards again*/
void insertItem(QTreeWidgetItem* move, QTreeWidgetItem* into);

/**Moves an item after another one. Stores the item specific settings of the moved item (and its subitems)
and applies it afterwards again*/
void moveItem(QTreeWidgetItem* move, QTreeWidgetItem* after);

/**Removes an item from the legend. This is e.g. necessary before shifting it to another place*/
Expand Down
55 changes: 51 additions & 4 deletions src/legend/qgslegendgroup.cpp
Expand Up @@ -19,30 +19,35 @@
***************************************************************************/
#include "qgsapplication.h"
#include "qgslegendgroup.h"
#include "qgslegendlayer.h"
#include "qgslegendlayerfile.h"
#include <QCoreApplication>
#include <QIcon>

QgsLegendGroup::QgsLegendGroup(QTreeWidgetItem * theItem ,QString theName)
: QgsLegendItem(theItem,theName)
{
mType=LEGEND_GROUP;
setFlags(Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsSelectable);
setFlags(Qt::ItemIsEditable | Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable);
setCheckState (0, Qt::Checked);
QIcon myIcon(QgsApplication::themePath()+"/mActionFolder.png");
setIcon(0, myIcon);
}
QgsLegendGroup::QgsLegendGroup(QTreeWidget* theListView, QString theString)
: QgsLegendItem(theListView,theString)
{
mType=LEGEND_GROUP;
setFlags(Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsSelectable);
setFlags(Qt::ItemIsEditable | Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable);
setCheckState (0, Qt::Checked);
QIcon myIcon(QgsApplication::themePath()+"/mActionFolder.png");
setIcon(0, myIcon);
}

QgsLegendGroup::QgsLegendGroup(QString name): QgsLegendItem()
{
mType=LEGEND_GROUP;
setFlags(Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsSelectable);
setFlags(Qt::ItemIsEditable | Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable);
setCheckState (0, Qt::Checked);
QIcon myIcon(QgsApplication::themePath()+"/mActionFolder.png");
setText(0, name);
setIcon(0, myIcon);
Expand Down Expand Up @@ -90,10 +95,52 @@ QgsLegendItem::DRAG_ACTION QgsLegendGroup::accept(const QgsLegendItem* li) const
return NO_ACTION;
}

bool QgsLegendGroup::insert(QgsLegendItem* theItem, bool changesettings)
bool QgsLegendGroup::insert(QgsLegendItem* theItem)
{
if(theItem->type() == LEGEND_LAYER)
{
addChild(theItem);
}
}

std::list<QgsLegendLayerFile*> QgsLegendGroup::legendLayerFiles()
{
std::list<QgsLegendLayerFile*> result;
for(int i = 0; i < childCount(); ++i)
{
QgsLegendLayer* childItem = dynamic_cast<QgsLegendLayer*>(child(i));
if(childItem)
{
std::list<QgsLegendLayerFile*> childList = childItem->legendLayerFiles();
result.splice(result.end(), childList);
}
}
return result;
}

void QgsLegendGroup::updateCheckState()
{
std::list<QgsLegendLayerFile*> llfiles = legendLayerFiles();
if(llfiles.size() < 1)
{
return;
}

std::list<QgsLegendLayerFile*>::iterator iter = llfiles.begin();
Qt::CheckState theState = (*iter)->checkState(0);
for(; iter != llfiles.end(); ++iter)
{
if(theState != (*iter)->checkState(0))
{
theState = Qt::PartiallyChecked;
break;
}
}

if(theState != checkState(0))
{
treeWidget()->blockSignals(true);
setCheckState(0, theState);
treeWidget()->blockSignals(false);
}
}

0 comments on commit fc7ca7b

Please sign in to comment.