The enitities and containers of the catalog now go into catalog subfolder Models go into model
248 lines
5.6 KiB
C++
248 lines
5.6 KiB
C++
#include "NamespaceItemModel.h"
|
|
#include "catalog/PgNamespace.h"
|
|
#include "catalog/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<GroupNode> parent;
|
|
bool checked = false;
|
|
|
|
PgNamespace ns;
|
|
LeafNode(std::weak_ptr<GroupNode> 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.objectName();
|
|
}
|
|
else if (role == Qt::CheckStateRole) {
|
|
v = getCheckState();
|
|
}
|
|
return v;
|
|
}
|
|
|
|
bool operator < (const LeafNode &rhs) const
|
|
{
|
|
return ns.objectName() < rhs.ns.objectName();
|
|
}
|
|
|
|
|
|
};
|
|
|
|
class GroupNode: public Node {
|
|
public:
|
|
using LeafVec = std::vector<std::shared_ptr<LeafNode>>;
|
|
|
|
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<const PgNamespaceContainer> ns)
|
|
{
|
|
beginResetModel();
|
|
SCOPE_EXIT { endResetModel(); };
|
|
|
|
auto system = std::make_shared<GroupNode>("System");
|
|
auto user = std::make_shared<GroupNode>("User");
|
|
groups = { system, user };
|
|
|
|
for (const auto e : *ns)
|
|
if (e.isSystemCatalog())
|
|
system->leaves.push_back(std::make_shared<LeafNode>(system, e));
|
|
else
|
|
user->leaves.push_back(std::make_shared<LeafNode>(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<GroupNode*>(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<Node*>(index.internalPointer());
|
|
LeafNode *ln = dynamic_cast<LeafNode*>(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<Node*>(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<Node*>(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<Node*>(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;
|
|
}
|
|
|