ich bin neu in Qt und dabei mich einzuarbeiten.
Ich will ein Programm schreiben, mit dem ich Adressen verwalten kann. Die Daten werden in Xml gespeichert:
Code: Alles auswählen
<?xml version="1.0" encoding="utf-8"?>
<addressbook>
<contacts>
<contact id="Jimmy_Page">
<name>Jimmy Page</name>
<city>Heston</city>
<country>United Kingdom</country>
<email id="webmail">jimmy.page@ledzeppelin.com</email>
</contact>
<contact id="Serj_Tankian">
<name>Serj Tankian</name>
<city>Beirut</city>
<country>Libanon</country>
<email id="webmail">serj.tankian@soad.com</email>
</contact>
</contacts>
</addressbook>
- Xml
- QTreeView
- eigenes Model (QAbstractItemModel)
- undo/redo Framework
Basis meiner Implementierung ist das Qt-Beispiel simpledommodel.
XmlModel : QAbstractItemModel
XmlItem
XmlTreeEditCommand : QCommand
XmlTreeNewCommand : QCommand
XmlTreeRemoveCommand : QCommand
XmlTreeView : QTreeView (für ContextMenu)
Ich habe so weit alles implementiert, das Editieren und Hinzufügen von Einträgen funktioniert. Lediglich das Löschen von Einträgen funktioniert nicht so wie erhofft. Wenn ich ein Element zum Entfernen auswähle, wird immer der letzte <contact> Node innerhalb <contacts> entfernt. Wenn ich dann aber mein Model speichere und die Xml-Datei öffne, wurde das richtige Element entfernt.
Hier mal die - meiner Ansicht nach - wichtigsten Funktionen:
Code: Alles auswählen
bool XmlModel::removeRows(int position, int /*rows*/, const QModelIndex &index)
{
XmlTreeRemoveCommand *command = new XmlTreeRemoveCommand(index, position, this);
mUndoStack->push(command);
return true;
}
void XmlModel::emitDataChanged(const QModelIndex &index)
{
emit dataChanged(index, index);
}
XmlItem *XmlModel::getItem(const QModelIndex &index) const
{
if (index.isValid())
{
XmlItem *item = static_cast<XmlItem*>(index.internalPointer());
if (item)
{
return item;
}
}
return mRootItem;
}
Code: Alles auswählen
class XmlTreeRemoveCommand : public QUndoCommand
{
public:
XmlTreeRemoveCommand(const QModelIndex &index, int position, XmlModel *model);
void undo();
void redo();
private:
QModelIndex mIndex;
int mPosition;
XmlModel *mXmlModel;
QDomNode mOldNode;
};
void XmlTreeRemoveCommand::undo()
{
QDomNode parent = mXmlModel->getItem(mIndex)->node();
QModelIndex preNodeIndex = mXmlModel->index(mPosition - 1, 0, mIndex);
QDomNode preNode = mXmlModel->getItem(preNodeIndex)->node();
mXmlModel->beginInsertRows(mIndex, mPosition, mPosition);
QString s = "insert " + mOldNode.toElement().attribute("id") +
" after " + preNode.toElement().attribute("id");
qDebug(s.toAscii());
parent.insertAfter(mOldNode, preNode);
mXmlModel->endInsertRows();
mXmlModel->emitDataChanged(mIndex);
}
void XmlTreeRemoveCommand::redo()
{
QDomNode parent = mXmlModel->getItem(mIndex)->node();
QDomNode child = parent.childNodes().at(mPosition);
mXmlModel->beginRemoveRows(mIndex, mPosition, mPosition);
QDomNode removed = parent.removeChild(child);
if (removed.isNull())
{
qDebug("could not remove node");
}
else
{
s = "removed node: " + removed.toElement().attribute("id");
qDebug(s.toAscii());
mOldNode = removed;
mXmlModel->endRemoveRows();
mXmlModel->emitDataChanged(mIndex);
}
}
Vielen Dank schon mal
ach ja... im Anhang ist der gesamte Sourcecode