#include "NamespaceItemModel.h" #include "PgNamespace.h" #include "PgNamespaceContainer.h" #include "ScopeGuard.h" namespace NamespaceItemModel_impl { class Node { public: virtual ~Node() {} virtual int getRowCount() const = 0; virtual Qt::CheckState getCheckState() const = 0; virtual void setChecked(NamespaceItemModel *model, const QModelIndex &index, bool checked) = 0; virtual QVariant data(const QModelIndex &index, int role) const = 0; }; class GroupNode; class LeafNode: public Node { public: std::weak_ptr parent; bool checked = false; PgNamespace ns; LeafNode(std::weak_ptr p, const PgNamespace &nspace) : parent(p) , ns(nspace) {} virtual int getRowCount() const override { return 0; } virtual Qt::CheckState getCheckState() const override { return checked ? Qt::Checked : Qt::Unchecked; } virtual void setChecked(NamespaceItemModel *model, const QModelIndex &index, bool chk) override { checked = chk; emit model->dataChanged(index, index); emit model->dataChanged(index.parent(), index.parent()); } virtual QVariant data(const QModelIndex &/*index*/, int role) const override { QVariant v; if (role == Qt::DisplayRole) { v = ns.name; } else if (role == Qt::CheckStateRole) { v = getCheckState(); } return v; } bool operator < (const LeafNode &rhs) const { return ns.name < rhs.ns.name; } }; class GroupNode: public Node { public: using LeafVec = std::vector>; QString name; LeafVec leaves; GroupNode(QString n) : name(n) {} virtual int getRowCount() const override { return leaves.size(); } void sortLeaves() { std::sort(leaves.begin(), leaves.end(), [] (auto l, auto r) -> bool { return *l < *r; }); } virtual Qt::CheckState getCheckState() const override { bool some_checked = false; bool some_unchecked = false; for (auto l : leaves) { if (l->checked) some_checked = true; else some_unchecked = true; } Qt::CheckState result; if (some_checked && some_unchecked) result = Qt::PartiallyChecked; else if (some_checked) result = Qt::Checked; else result = Qt::Unchecked; return result; } virtual void setChecked(NamespaceItemModel *model, const QModelIndex &index, bool chk) override { if (chk) for (auto l : leaves) l->checked = true; if (!chk) for (auto l : leaves) l->checked = false; emit model->dataChanged(index, index); emit model->dataChanged(model->index(0, 0, index), model->index(leaves.size(), 0, index)); } virtual QVariant data(const QModelIndex &/*index*/, int role) const override { QVariant v; if (role == Qt::DisplayRole) { v = name; } else if(role == Qt::CheckStateRole) { v = getCheckState(); } return v; } }; } // end of NamespaceItemModel_impl using namespace NamespaceItemModel_impl; NamespaceItemModel::NamespaceItemModel(QObject *parent) : QAbstractItemModel(parent) { } void NamespaceItemModel::init(std::shared_ptr ns) { beginResetModel(); SCOPE_EXIT { endResetModel(); }; auto system = std::make_shared("System"); auto user = std::make_shared("User"); groups = { system, user }; for (const auto e : *ns) if (e.isSystemCatalog()) system->leaves.push_back(std::make_shared(system, e)); else user->leaves.push_back(std::make_shared(user, e)); system->sortLeaves(); user->sortLeaves(); for (auto e : user->leaves) e->checked = true; } QModelIndex NamespaceItemModel::index(int row, int column, const QModelIndex &parent) const { QModelIndex result; if (hasIndex(row, column, parent)) { // We only have two levels, the groups and the namespaces if (parent.isValid()) { // namespace level auto grp = static_cast(parent.internalPointer()); result = createIndex(row, column, grp->leaves[row].get()); } else { // toplevel (groups) const auto grp = groups[row]; result = createIndex(row, column, grp.get()); } } return result; } QModelIndex NamespaceItemModel::parent(const QModelIndex &index) const { QModelIndex result; if (index.isValid()) { auto *n = static_cast(index.internalPointer()); LeafNode *ln = dynamic_cast(n); if (ln) { // leafnode auto grp = ln->parent.lock(); // Get the parent group auto fr = std::find(groups.begin(), groups.end(), grp); // find it in the list int row = fr - groups.begin(); // calculate index ie row result = createIndex(row, 0, grp.get()); // return index } } return result; } int NamespaceItemModel::rowCount(const QModelIndex &parent) const { int count = 0; if (parent.isValid() && parent.column() <= 0) { auto node = static_cast(parent.internalPointer()); count = node->getRowCount(); } else { count = groups.size(); } return count; } int NamespaceItemModel::columnCount(const QModelIndex &/*index*/) const { return 1; } QVariant NamespaceItemModel::data(const QModelIndex &index, int role) const { QVariant v; auto *n = static_cast(index.internalPointer()); v = n->data(index, role); return v; } bool NamespaceItemModel::setData(const QModelIndex &index, const QVariant &value, int role) { if(!index.isValid() || role != Qt::CheckStateRole) return false; auto *n = static_cast(index.internalPointer()); n->setChecked(this, index, value == Qt::Checked); return true; } Qt::ItemFlags NamespaceItemModel::flags(const QModelIndex &index) const { Qt::ItemFlags flags = QAbstractItemModel::flags(index); flags.setFlag(Qt::ItemIsUserCheckable); return flags; }