pgLab/pglab/NamespaceItemModel.cpp

308 lines
6.9 KiB
C++
Raw Normal View History

#include "NamespaceItemModel.h"
#include "catalog/PgNamespace.h"
#include "catalog/PgNamespaceContainer.h"
#include "ScopeGuard.h"
namespace NamespaceItemModel_impl {
class Node {
public:
2018-12-16 15:38:32 +01:00
virtual ~Node() = default;
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;
2019-11-20 19:09:22 +01:00
virtual int columnCount() 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)
{}
2018-12-16 15:38:32 +01:00
int getRowCount() const override
{
return 0;
}
2018-12-16 15:38:32 +01:00
Qt::CheckState getCheckState() const override
{
return checked ? Qt::Checked : Qt::Unchecked;
}
2018-12-16 15:38:32 +01:00
void setChecked(NamespaceItemModel *model, const QModelIndex &index, bool chk) override
{
checked = chk;
emit model->dataChanged(index, index);
emit model->dataChanged(index.parent(), index.parent());
}
2019-11-20 19:09:22 +01:00
QVariant data(const QModelIndex &index, int role) const override
{
QVariant v;
if (role == Qt::DisplayRole) {
2019-11-20 19:09:22 +01:00
switch (index.column()) {
case NamespaceItemModel::ColNamespaceName:
return ns.objectName();
case NamespaceItemModel::ColOwner:
return ns.ownerName();
case NamespaceItemModel::ColAcl:
return ns.aclString();
}
}
else if (role == Qt::CheckStateRole) {
2019-11-20 19:09:22 +01:00
if (index.column() == 0)
return getCheckState();
}
2019-11-20 19:09:22 +01:00
return {};
}
int columnCount() const override
{
return NamespaceItemModel::ColCount;
}
bool operator < (const LeafNode &rhs) const
{
return ns.objectName() < rhs.ns.objectName();
}
};
class GroupNode: public Node {
public:
2019-11-20 19:09:22 +01:00
using LeafVec = QVector<std::shared_ptr<LeafNode>>;
QString name;
LeafVec leaves;
GroupNode(QString n)
: name(n)
{}
2018-12-16 15:38:32 +01:00
int getRowCount() const override
{
return leaves.size();
}
void sortLeaves()
{
std::sort(leaves.begin(), leaves.end(),
[] (auto l, auto r) -> bool { return *l < *r; });
}
2018-12-16 15:38:32 +01:00
Qt::CheckState getCheckState() const override
{
bool some_checked = false;
bool some_unchecked = false;
2018-12-16 15:38:32 +01:00
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;
}
2018-12-16 15:38:32 +01:00
void setChecked(NamespaceItemModel *model, const QModelIndex &index, bool chk) override
{
if (chk)
2018-12-16 15:38:32 +01:00
for (auto&& l : leaves)
l->checked = true;
if (!chk)
2018-12-16 15:38:32 +01:00
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));
}
2019-11-20 19:09:22 +01:00
QVariant data(const QModelIndex &index, int role) const override
{
QVariant v;
if (role == Qt::DisplayRole) {
2019-11-20 19:09:22 +01:00
switch (index.column()) {
case NamespaceItemModel::ColNamespaceName:
return name;
}
}
else if(role == Qt::CheckStateRole) {
2019-11-20 19:09:22 +01:00
if (index.column() == 0)
return getCheckState();
}
2019-11-20 19:09:22 +01:00
return {};
}
int columnCount() const override
{
return 1;
}
};
} // 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 };
2018-12-16 15:38:32 +01:00
for (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();
2018-12-16 15:38:32 +01:00
for (auto&& e : user->leaves)
e->checked = true;
}
2019-11-20 19:09:22 +01:00
void NamespaceItemModel::setEnableCheckboxes(bool enable)
{
if (m_enableCheckboxes != enable) {
beginResetModel();
SCOPE_EXIT { endResetModel(); };
m_enableCheckboxes = enable;
}
}
bool NamespaceItemModel::isEnableCheckboxes() const
{
return m_enableCheckboxes;
}
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()) {
2018-12-16 15:38:32 +01:00
auto n = static_cast<Node*>(index.internalPointer());
auto ln = dynamic_cast<LeafNode*>(n);
if (ln) { // leafnode
auto grp = ln->parent.lock(); // Get the parent group
2019-11-20 19:09:22 +01:00
// auto fr = std::find(groups.begin(), groups.end(), grp); // find it in the list
// int row = fr - groups.begin(); // calculate index ie row
int row = groups.indexOf(grp);
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
{
2019-11-20 19:09:22 +01:00
// if (index.isValid()) {
// auto *n = static_cast<Node*>(index.internalPointer());
// return n->columnCount();
// }
return ColCount;
}
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());
2019-11-20 19:09:22 +01:00
if (index.column() == 0)
n->setChecked(this, index, value == Qt::Checked);
return true;
}
Qt::ItemFlags NamespaceItemModel::flags(const QModelIndex &index) const
{
Qt::ItemFlags flags = QAbstractItemModel::flags(index);
2019-11-20 19:09:22 +01:00
if (index.column() == 0 && m_enableCheckboxes)
flags.setFlag(Qt::ItemIsUserCheckable);
return flags;
}
2019-11-20 19:09:22 +01:00
QVariant NamespaceItemModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if (orientation == Qt::Horizontal) {
if (role == Qt::DisplayRole) {
switch (section) {
case ColNamespaceName: return tr("Name");
case ColOwner: return tr("Owner");
case ColAcl: return tr("ACL");
}
}
}
return {};
}