diff --git a/model/xqcommand.cpp b/model/xqcommand.cpp index f9dbae4..9245322 100644 --- a/model/xqcommand.cpp +++ b/model/xqcommand.cpp @@ -27,12 +27,11 @@ void XQNodeStore::dumpList( const QString& title ) const XQCommand::XQCommand(CmdType cmdType, XQModel* modelView ) - : _cmdType{ cmdType }, _modelView(modelView) + : _cmdType{ cmdType }, _model(modelView) { } - XQCommand::~XQCommand() { qDebug() << " --- command destructor: " << toString(); @@ -49,22 +48,34 @@ void XQCommand::setCommandType( XQCommand::CmdType cmdType ) _cmdType = cmdType; } + +//! ruft 'onCommandRedo' 'meines' models auf. + void XQCommand::redo() { - _modelView->onCommandRedo( *this ); + _model->onCommandRedo( *this ); } + +//! ruft 'onCommandUndo' 'meines' models auf. + void XQCommand::undo() { - _modelView->onCommandUndo( *this ); + _model->onCommandUndo( *this ); } +//! gibt den urpsrungs-index dieses commands zurück. + const QModelIndex& XQCommand::originIndex() const { return _originIndex; } + +//! merkt sich den ersten QModelIndex der von diesem command +//! betroffenen items. zusätzlich wird der command-text erzeugt. + void XQCommand::setOriginIndex( const QModelIndex& origin ) { QString cmdText("%1: %2 (%3)"); @@ -78,17 +89,24 @@ void XQCommand::setOriginIndex( const QModelIndex& origin ) } +//! erzeugt aus den 'selected indices' eine liste mit der jewiligen knotenposition, +//! der item-zeile und dem content-knoten. + void XQCommand::saveNodes( const QModelIndexList& list ) { clear(); + // über jede zeil for( auto entry : list ) { - XQNodePtr contentNode = XQItem::xqItemFromIndex( entry ).contentNode(); - // im command speichern wir den original knoten, nicht eine kopie, wie im clipboard. + // knoten holen + const XQNodePtr& contentNode = XQItem::xqItemFromIndex( entry ).contentNode(); + // hier speichern wir den original knoten, nicht einen clone, wie im clipboard. push_back( {entry.row(), contentNode->own_pos(), contentNode } ); } } +//! erzeugt einen string aus dem command-type, fürs debuggen. + QString XQCommand::toString() { diff --git a/model/xqcommand.h b/model/xqcommand.h index 1929e2d..b1c0c7a 100644 --- a/model/xqcommand.h +++ b/model/xqcommand.h @@ -85,7 +85,7 @@ public: protected: CmdType _cmdType{cmdInvalid}; - XQModel* _modelView{}; // needed for redo() / undo() + XQModel* _model{}; // needed for redo() / undo() QModelIndex _originIndex; /* diff --git a/model/xqmodel.cpp b/model/xqmodel.cpp index 52645d5..e309788 100644 --- a/model/xqmodel.cpp +++ b/model/xqmodel.cpp @@ -255,52 +255,47 @@ void XQModel::onCommandUndo( XQCommand& command ) // undo-/redo-able stuff -/** - * @brief XQModel::cmdCutRows Cut the rows whose positions have been store in the command. - * @param command - */ - +//! markierte knoten entfernen, 'command' enthält die liste void XQModel::cmdCut( XQCommand& command ) { // wir gehen rückwärts über alle gemerkten knoten ... for (auto it = command.rbegin(); it != command.rend(); ++it) { // ... holen das erste item, das auch den content node enthält - const XQNodeBackup& entry = *it; - XQItem& firstItem = xqFirstItem( (*it).itemPos ); - qDebug() << " --- Cut: " << firstItem.text() << " " << firstItem.row() << " id#" << entry.contentNode->_id; + //const XQNodeBackup& entry = *it; + //XQItem& firstItem = xqFirstItem( (*it).itemPos ); + //qDebug() << " --- Cut: " << firstItem.text() << " " << firstItem.row() << " id#" << entry.contentNode->_id; // jetzt löschen, dabei wird die parent-verbindung entfernt + const XQNodeBackup& entry = *it; entry.contentNode->unlink_self(); removeRow(entry.itemPos ); } } - -// clone to clipboard, remove items +//! entfernte knoten aus wieder einfügen , 'command' enthält die liste void XQModel::cmdCutUndo( XQCommand& command ) { - command.dumpList("UNDO Cut"); - _sections.dump(); - - int xx = command.first().itemPos; - const XQModelSection& section = _sections.sectionFromRow( xx ); - + // die anfangsposition + int itmPos = command.first().itemPos; + // die 'zuständige' section rausfinden + const XQModelSection& section = _sections.sectionFromRow( itmPos ); + // über alle einträge ... for (auto& entry : command ) { - XQNodePtr savedNode = entry.contentNode; - // __fix! should not bee _contentRoot! - savedNode->add_me_at( entry.nodePos, _contentRoot ); - + const XQNodePtr& savedNode = entry.contentNode; + // __fix! should not be _contentRoot! + savedNode->add_me_at( entry.nodePos, _contentRoot ); XQItemList list = _itemFactory.makeContentRow( savedNode, section.sheetRootNode ); + XQItem& firstItem = *((XQItem*)list[0]); - qDebug() << " --- Cut Undo: " << firstItem.text() << " " << firstItem.row() << " id#" << entry.contentNode->_id; + qDebug() << " --- Cut Undo: " << firstItem.text() << " " << firstItem.row() << " id#" << entry.contentNode->_id << " count: " << entry.contentNode.use_count(); insertRow( entry.itemPos, list ); } } - +//! clipboard inhalte einfügen void XQModel::cmdPaste( XQCommand& command ) { // selection holen ... @@ -320,11 +315,19 @@ void XQModel::cmdPaste( XQCommand& command ) // wir pasten das clipboard for (auto& entry : _clipBoard ) { + // + // siehe! und es war schrott! + // + + // das ist ein clon XQNodePtr savedNode = entry.contentNode; + // der wir hier rein gelinkt XQItemList list = _itemFactory.makeContentRow( savedNode, section.sheetRootNode ); + // wir klonen den knoten aus dem clipbord savedNode->clone(section.contentRootNode )->add_me_at( nodePos ); insertRow( insRow, list ); + const QModelIndex& selIdx = list[0]->index(); _treeView->selectionModel()->select(selIdx, QItemSelectionModel::Select | QItemSelectionModel::Rows); // zur nächsten zeile diff --git a/model/xqmodel.h b/model/xqmodel.h index 718b3c5..28ee926 100644 --- a/model/xqmodel.h +++ b/model/xqmodel.h @@ -85,7 +85,7 @@ public: virtual void cmdNew( XQCommand& command ); virtual void cmdNewUndo( XQCommand& command ); - // wtf!? + /* bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole) override { qDebug() << " --- setData: " << value.toString(); @@ -96,6 +96,7 @@ public: { return QStandardItemModel::data( index, role ); } + */ public slots: diff --git a/nodes/znode.h b/nodes/znode.h index c2e9b2f..88f930c 100644 --- a/nodes/znode.h +++ b/nodes/znode.h @@ -34,7 +34,13 @@ namespace znode { - /// ----------------- snip 8< ----------------------------------------------------------------------------------------------------------------------------- + /* + + - die payload attributes wird 'drangeerbt'. sollte die nicht besser ge-templatet sein? + - die finder sollten besser ausgelagert sein + + */ + // forward declaration of base class zbasic_node ... //template @@ -45,7 +51,7 @@ namespace znode //using zshared_node = std::shared_ptr>; - // main class + //! einfache tree-klasse, besonderheit: der nutzlast-string-type ist templated. template class zbasic_node : public zid, public zpayload, public std::enable_shared_from_this> { @@ -88,29 +94,30 @@ namespace znode public: + //! shortcut auf std::make_shared... static zshared_node make_node( str_cref arg1, str_cref arg2 = "" , zshared_cref parent = nullptr ) { return std::make_shared( arg1, arg2, parent ); } + //! leerer konstruktor zbasic_node() = default; - // ... + //! konstruktor mit tag_name und optionalem elternknoten zbasic_node( str_cref tag_name, zshared_cref parent = nullptr ) : zpayload{tag_name}, _parent{parent} { } - - // ... + //! konstruktor mit tag_name, value und optionalem elternknoten zbasic_node( str_cref tag_name, str_cref value, zshared_cref parent = nullptr ) : zpayload{tag_name,value}, _parent{parent} { } - + //! konstruktor mit tag_name, attributlist und optionalem elternknoten zbasic_node( str_cref tag_name, const str_list& attributes, zshared_cref parent = nullptr ) : zbasic_node{tag_name, parent} { @@ -122,16 +129,18 @@ namespace znode } } + //! default destruktor virtual ~zbasic_node() = default; - // Kopieren ist hier nicht sinnvoll (Child-Pointer müssen konsistent bleiben) + //! kopieren ist hier nicht sinnvoll zbasic_node(const zbasic_node&) = delete; zbasic_node& operator=(const zbasic_node&) = delete; - // Bewegen geht (shared_from_this bleibt gültig) + // 'move' geht (shared_from_this bleibt gültig) zbasic_node(zbasic_node&&) noexcept = default; zbasic_node& operator=(zbasic_node&&) noexcept = default; + //! erzeugt eine deep-copy von 'mir' _mit_ allen kindknoten virtual zshared_node clone(const zshared_node& parent = nullptr ) const { // copy als shared ptr erzeugen @@ -148,12 +157,13 @@ namespace znode } - // STL-ish traverse iterators + //! stl-ish traverse iterators auto begin() { return ziterator(this); } + //! stl-ish traverse iterators auto end() { return ziterator(nullptr); @@ -162,7 +172,7 @@ namespace znode // ... set_int // ... as_int - //zweak_node parent() + //! erzeugt einen shared_ptr zshared_node parent() const { return _parent.lock(); @@ -221,21 +231,29 @@ namespace znode return int(children().size() - 1); } + //! fügt einen knoten in meine kinderliste ein und macht mich + //! zu dessen elternknoten. int add_child_at( int idx, const zshared_node& node ) { + // _fixme! was ist, wenn da schon ein elternknoten ist? + _children.insert(children().begin() + idx, node ); node->_parent = this->shared_from_this(); return int(children().size() - 1); } + //! fügt einen shard_ptr von 'mir' in die kinderliste meines elternknotens ein. void add_me_at( int offset ) { if( parent() ) parent()->add_child_at( offset, this->shared_from_this() ); else - qDebug() << " -- fick2"; // shold throw? + throw std::runtime_error("add_me_at(offset): no parent node"); + } + //! fügt einen shard_ptr von 'mir' in die kinderliste des übergebenen knotens ein + //! und macht diesen zu meinem elternknoten. void add_me_at( int offset, const zshared_node& parent_node ) { if( parent_node ) @@ -244,7 +262,10 @@ namespace znode parent_node->add_child_at( offset, this->shared_from_this() ); } else - qDebug() << " -- fick4"; // shold throw? + { + throw std::runtime_error("add_me_at(offset,parent): no parent node"); + } + } int own_pos() @@ -278,14 +299,17 @@ namespace znode return removed; } + //! entfernt 'mich' aus der kinderliste des elternknotens. void unlink_self() { if(parent()) parent()->unlink_child( this->shared_from_this() ); else - qDebug() << " -- fuck: "; + throw std::runtime_error("unlink_self(): no parent node"); } + //! findet den ersten kind-knoten mit dem attribut 'attrkey' welches den + //! wert 'attrvalue' hat. zshared_node find_child_by_attribute(str_cref attrkey, str_cref attrvalue ) { for( auto child : _children ) @@ -297,7 +321,7 @@ namespace znode return zshared_node(); } - + // zshared_node find_child_by_tag_name(str_cref tagname ) { for( auto child : _children )