25 #include <QStringList>
27 #include <boost/property_tree/ptree.hpp>
28 #include <boost/property_tree/xml_parser.hpp>
34 using boost::property_tree::ptree;
42 only_edit_data =
false;
45 PTreeModel & PTreeModel::operator=(PTreeModel
const& other)
49 root =
new Item(*other.root);
59 int PTreeModel::columnCount(QModelIndex
const& )
const
64 QVariant PTreeModel::data(QModelIndex
const& index,
int role)
const
69 Item* item =
static_cast<Item*
>(index.internalPointer());
71 if (role == Qt::DisplayRole || role==Qt::EditRole) {
72 switch (index.column()) {
80 }
else if (role == Qt::BackgroundRole) {
81 return item->background;
87 bool PTreeModel::dropMimeData(
const QMimeData* data, Qt::DropAction action,
int row,
int column,
88 const QModelIndex & parent)
93 if (action == Qt::IgnoreAction) {
96 if (action == Qt::LinkAction) {
99 if (!data->hasFormat(
"text/plain")) {
110 row = rowCount(parent);
113 QString text = data->text();
116 if (parent.isValid()) {
117 parent_item =
static_cast<Item*
>(parent.internalPointer());
122 std::stringstream sstream(text.toStdString());
125 boost::property_tree::xml_parser::read_xml(sstream, pt, boost::property_tree::xml_parser::trim_whitespace);
127 catch (boost::property_tree::xml_parser::xml_parser_error& e) {
130 undo_stack->push(
new InsertRowsCommand(
this, parent_item, parent, row, pt));
134 Qt::ItemFlags PTreeModel::flags(QModelIndex
const& index)
const
136 if (!index.isValid()) {
137 return Qt::ItemIsDropEnabled;
141 if (index.column() == 0) {
142 if (only_edit_data) {
143 return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled;
145 return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable
146 | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled;
149 if (static_cast<Item*>(index.internalPointer())->GetChildrenCount() == 0) {
150 return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsDragEnabled;
152 return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled;
157 QVariant PTreeModel::headerData(
int section, Qt::Orientation orientation,
int role)
const
159 if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
161 return QVariant(QString(
"Key"));
162 }
else if (section == 1) {
163 return QVariant(QString(
"Data"));
169 QModelIndex PTreeModel::index(
int row,
int column, QModelIndex
const& parent)
const
171 if (!hasIndex(row, column, parent)) {
172 return QModelIndex();
176 if (!parent.isValid()) {
179 parent_tree =
static_cast<Item*
>(parent.internalPointer());
182 Item* child = parent_tree->GetChild(row);
185 return createIndex(row, column, child);
187 return QModelIndex();
191 bool PTreeModel::insertRow(
int row, QModelIndex
const& parent)
193 return insertRows(row, 1, parent);
196 bool PTreeModel::insertRows(
int row,
int count, QModelIndex
const& parent)
198 if (only_edit_data) {
203 if (parent.isValid()) {
204 parent_item =
static_cast<Item*
>(parent.internalPointer());
213 if (row > parent_item->GetChildrenCount()) {
217 undo_stack->push(
new InsertRowsCommand(
this, parent_item, parent, row, count));
223 return only_edit_data;
226 QMimeData* PTreeModel::mimeData(
const QModelIndexList& indexes)
const
228 QMimeData* mime =
new QMimeData();
231 for (
auto const& index : indexes) {
232 if (index.column() == 0) {
233 Item* item =
static_cast<Item*
>(index.internalPointer());
234 std::stringstream sstream;
236 pt.add_child(item->key.toString().toStdString(), item->Store());
237 boost::property_tree::xml_parser::write_xml(sstream, pt);
238 text = sstream.str().c_str();
245 bool PTreeModel::MoveRow(
int old_row,
const QModelIndex & old_parent,
int new_row,
const QModelIndex & new_parent)
247 return MoveRows(old_row, old_parent, new_row, new_parent, 1);
250 bool PTreeModel::MoveRows(
int old_row, QModelIndex
const& old_parent,
int new_row, QModelIndex
const& new_parent,
253 if (only_edit_data) {
257 Item* old_parent_item;
258 if (old_parent.isValid()) {
259 old_parent_item =
static_cast<Item*
>(old_parent.internalPointer());
261 old_parent_item = root;
264 Item* new_parent_item;
265 if (new_parent.isValid()) {
266 new_parent_item =
static_cast<Item*
>(new_parent.internalPointer());
268 new_parent_item = root;
274 if (old_row + count > old_parent_item->GetChildrenCount()) {
280 if (new_row + count > new_parent_item->GetChildrenCount()) {
283 undo_stack->push(
new MoveRowsCommand(
this, old_parent_item, old_parent, old_row,
284 new_parent_item, new_parent, new_row, count));
288 QStringList PTreeModel::mimeTypes()
const
291 types <<
"text/plain";
295 QModelIndex PTreeModel::parent(QModelIndex
const& index)
const
297 if (!index.isValid()) {
298 return QModelIndex();
301 Item* child =
static_cast<Item*
>(index.internalPointer());
302 Item* parent = child->GetParent();
303 if (parent == root) {
304 return QModelIndex();
307 return createIndex(parent->row, 0, parent);
310 bool PTreeModel::removeRow(
int row, QModelIndex
const& parent)
312 return removeRows(row, 1, parent);
315 bool PTreeModel::removeRows(
int row,
int count, QModelIndex
const& parent)
317 if (only_edit_data) {
322 if (parent.isValid()) {
323 parent_item =
static_cast<Item*
>(parent.internalPointer());
332 if (row + count > parent_item->GetChildrenCount()) {
336 undo_stack->push(
new RemoveRowsCommand(
this, parent_item, parent, row, count));
340 int PTreeModel::rowCount(QModelIndex
const& parent)
const
343 if (parent.column() > 0) {
347 if (!parent.isValid()) {
350 item =
static_cast<Item*
>(parent.internalPointer());
352 return item->GetChildrenCount();
355 bool PTreeModel::setData(QModelIndex
const& index,
const QVariant& value,
int role)
357 if (!index.isValid()) {
361 Item* item =
static_cast<Item*
>(index.internalPointer());
362 if (role == Qt::EditRole) {
363 if (index.column() == 0) {
364 if (only_edit_data) {
368 if (value.toString().isEmpty()) {
371 undo_stack->push(
new EditKeyCommand(
this, item, index, item->key, value));
372 }
else if (index.column() == 1) {
373 undo_stack->push(
new EditDataCommand(
this, item, index, item->data, value));
377 }
else if (role == Qt::BackgroundRole) {
378 item->background = value;
380 QModelIndex key_index = index.sibling(index.row(), 0);
381 QModelIndex data_index = index.sibling(index.row(), 1);
382 emit dataChanged(key_index, data_index);
401 return root->Store();
404 Qt::DropActions PTreeModel::supportedDragActions()
const
406 if (only_edit_data) {
407 return Qt::CopyAction;
409 return Qt::CopyAction | Qt::MoveAction;
413 Qt::DropActions PTreeModel::supportedDropActions()
const
415 if (only_edit_data) {
416 return Qt::CopyAction;
419 return Qt::CopyAction | Qt::MoveAction;
425 PTreeModel::Item::Item(Item* p, QVariant
const& k,
int r) : key(k), row(r), parent(p) {}
427 PTreeModel::Item::Item(Item
const& other)
428 : key(other.key), data(other.data), background(other.background),
429 row(other.row), parent(other.parent)
431 for (
auto const& child : other.children) {
432 children.push_back(
new Item(*child));
436 PTreeModel::Item& PTreeModel::Item::operator=(Item
const& other)
438 if (
this != &other) {
440 for (
auto const& child : children) {
444 parent = other.parent;
447 background = other.background;
450 for (
auto const& child : other.children) {
451 children.push_back(
new Item(*child));
457 PTreeModel::Item::~Item()
459 for (
auto const& child : children) {
464 PTreeModel::Item* PTreeModel::Item::GetChild(
unsigned int i)
466 if (i < children.size()) {
473 PTreeModel::Item
const* PTreeModel::Item::GetChild(
unsigned int i)
const
475 if (i < children.size()) {
482 int PTreeModel::Item::GetChildrenCount()
const
484 return children.size();
487 PTreeModel::Item* PTreeModel::Item::GetParent()
492 PTreeModel::Item
const* PTreeModel::Item::GetParent()
const
497 void PTreeModel::Item::InsertChild(
unsigned int row, Item* item)
499 children.insert(children.begin() + row, item);
502 for (
auto it = children.begin() + row; it != children.end(); it++) {
503 (*it)->row = it - children.begin();
507 void PTreeModel::Item::Load(ptree
const& tree)
509 for (
auto const& child : children) {
515 data = QVariant(QString(tree.data().c_str()));
516 children.reserve(tree.size());
517 for (ptree::value_type
const & v : tree) {
518 Item* item =
new Item(
this, QVariant(QString(v.first.c_str())), children.size());
519 item->Load(v.second);
520 children.push_back(item);
524 void PTreeModel::Item::RemoveChild(
unsigned int row)
526 children.erase(children.begin() + row);
529 for (
auto it = children.begin() + row; it != children.end(); it++) {
530 (*it)->row = it - children.begin();
534 ptree PTreeModel::Item::Store()
const
538 if (data.type() == QVariant::String) {
539 t.data() = ptree::data_type(data.toString().toStdString());
541 for (Item* v : children) {
542 ptree child_tree = v->Store();
543 t.push_back(ptree::value_type(ptree::key_type(v->key.toString().toStdString()), child_tree));
Interface for PTree undo commands.
bool MoveRows(int old_row, QModelIndex const &old_parent, int new_row, QModelIndex const &new_parent, int count)
Moves a block of contagious rows from one place to another.
see the online Qt documentation
boost::property_tree::ptree Store() const
Creates a new property tree from the current model state.
PTreeModel(boost::property_tree::ptree const &tree, QObject *parent=0)
Constructs an empty PTreeModel.
bool MoveRow(int old_row, QModelIndex const &old_parent, int new_row, QModelIndex const &new_parent)
Moves a single row from one place to another.
Undo command that represents a single move operation of rows inside a PTreeModel. ...
virtual ~PTreeModel()
Virtual destructor.
bool IsOnlyEditData() const
Test whether the "only edit data" option set.
void SetOnlyEditData(bool)
Set the "only edit values" option.
Interface for PTreeModel.
see the online Qt documentation
Namespace for generic graphical shell for simulators.
void SetUndoStack(QUndoStack *)
Set this model to use a given undo stack.