1
0
mirror of https://github.com/altlinux/admc.git synced 2024-10-27 01:55:37 +03:00

remove AdModel source files

This commit is contained in:
Dmitry Degtyarev 2020-06-22 17:43:48 +04:00
parent c4d5555e09
commit 5730a2cf05
8 changed files with 258 additions and 315 deletions

View File

@ -50,7 +50,6 @@ set(ADTOOL_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/src/admc.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/Runner.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/ad_interface.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/ad_model.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/details_widget.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/attributes_model.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/containers_widget.cpp

View File

@ -1,242 +0,0 @@
/*
* ADMC - AD Management Center
*
* Copyright (C) 2020 BaseALT Ltd.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "ad_model.h"
#include "ad_interface.h"
#include <QMimeData>
#include <QMap>
#include <QIcon>
void make_new_row(QStandardItem *parent, const QString &dn);
void load_row(QList<QStandardItem *> row, const QString &dn);
AdModel::AdModel(QObject *parent)
: EntryModel(Column::COUNT, Column::DN, parent)
{
setHorizontalHeaderItem(Column::Name, new QStandardItem("Name"));
setHorizontalHeaderItem(Column::DN, new QStandardItem("DN"));
connect(
AD(), &AdInterface::ad_interface_login_complete,
this, &AdModel::on_ad_interface_login_complete);
connect(
AD(), &AdInterface::delete_entry_complete,
this, &AdModel::on_delete_entry_complete);
connect(
AD(), &AdInterface::dn_changed,
this, &AdModel::on_dn_changed);
connect(
AD(), &AdInterface::create_entry_complete,
this, &AdModel::on_create_entry_complete);
connect(
AD(), &AdInterface::attributes_changed,
this, &AdModel::on_attributes_changed);
}
bool AdModel::canFetchMore(const QModelIndex &parent) const {
if (!parent.isValid()) {
return false;
}
bool can_fetch = parent.data(AdModel::Roles::CanFetch).toBool();
return can_fetch;
}
void AdModel::fetchMore(const QModelIndex &parent) {
if (!parent.isValid() || !canFetchMore(parent)) {
return;
}
QString dn = get_dn_from_index(parent);
QStandardItem *parent_item = itemFromIndex(parent);
// Add children
QList<QString> children = AD()->load_children(dn);
for (auto child : children) {
make_new_row(parent_item, child);
}
// Unset CanFetch flag
parent_item->setData(false, AdModel::Roles::CanFetch);
}
// Override this so that unexpanded and unfetched items show the expander even though they technically don't have any children loaded
// NOTE: expander is show if hasChildren returns true
bool AdModel::hasChildren(const QModelIndex &parent = QModelIndex()) const {
if (canFetchMore(parent)) {
return true;
} else {
return QStandardItemModel::hasChildren(parent);
}
}
void AdModel::on_ad_interface_login_complete(const QString &search_base, const QString &head_dn) {
removeRows(0, rowCount());
// Load head
QStandardItem *invis_root = invisibleRootItem();
make_new_row(invis_root, head_dn);
}
void AdModel::on_delete_entry_complete(const QString &dn) {
QList<QStandardItem *> items = findItems(dn, Qt::MatchExactly | Qt::MatchRecursive, AdModel::Column::DN);
if (items.size() > 0) {
QStandardItem *dn_item = items[0];
QModelIndex dn_index = dn_item->index();
removeRow(dn_index.row(), dn_index.parent());
}
}
void AdModel::on_dn_changed(const QString &old_dn, const QString &new_dn) {
// Remove old entry from model
QList<QStandardItem *> old_items = findItems(old_dn, Qt::MatchExactly | Qt::MatchRecursive, AdModel::Column::DN);
if (old_items.size() > 0) {
QStandardItem *dn_item = old_items[0];
QModelIndex dn_index = dn_item->index();
removeRow(dn_index.row(), dn_index.parent());
}
// Need to load entry at new parent if the parent has already
// been expanded/fetched
// NOTE: loading if parent hasn't been fetched will
// create a duplicate
const QString new_parent = extract_parent_dn_from_dn(new_dn);
QList<QStandardItem *> parent_items = findItems(new_parent, Qt::MatchExactly | Qt::MatchRecursive, AdModel::Column::DN);
if (parent_items.size() > 0) {
QStandardItem *parent_dn_item = parent_items[0];
QModelIndex parent_dn_index = parent_dn_item->index();
QModelIndex parent_index = parent_dn_index.siblingAtColumn(Column::Name);
QStandardItem *parent_item = itemFromIndex(parent_index);
if (!canFetchMore(parent_index)) {
make_new_row(parent_item, new_dn);
}
}
}
void AdModel::on_create_entry_complete(const QString &dn, NewEntryType type) {
// Load entry to model if it's parent has already been fetched
// If it hasn't been fetched, then this new entry will be loaded with all other children when the parent is fetched
QString parent_dn = extract_parent_dn_from_dn(dn);
QList<QStandardItem *> items = findItems(parent_dn, Qt::MatchExactly | Qt::MatchRecursive, Column::DN);
if (items.size() > 0) {
QStandardItem *dn_item = items[0];
QModelIndex dn_index = dn_item->index();
QModelIndex parent_index = dn_index.siblingAtColumn(0);
QStandardItem *parent = itemFromIndex(parent_index);
bool fetched_already = !canFetchMore(parent_index);
if (fetched_already) {
make_new_row(parent, dn);
}
}
}
void AdModel::on_attributes_changed(const QString &dn) {
// Compose row based on dn
QList<QStandardItem *> items = findItems(dn, Qt::MatchExactly | Qt::MatchRecursive, AdModel::Column::DN);
if (items.size() == 0) {
return;
}
QStandardItem *dn_item = items[0];
QModelIndex dn_index = dn_item->index();
// Compose indexes for all columns
auto indexes = QList<QModelIndex>();
for (int i = 0; i < AdModel::Column::COUNT; i++) {
QModelIndex index = dn_index.siblingAtColumn(i);
indexes.push_back(index);
}
// Compose the row of items from indexes
auto row = QList<QStandardItem *>();
for (int i = 0; i < AdModel::Column::COUNT; i++) {
QModelIndex index = indexes[i];
QStandardItem *item = itemFromIndex(index);
row.push_back(item);
}
load_row(row, dn);
}
// Load data into row of items based on entry attributes
void load_row(QList<QStandardItem *> row, const QString &dn) {
QString name = AD()->get_attribute(dn, "name");
row[AdModel::Column::Name]->setText(name);
row[AdModel::Column::DN]->setText(dn);
QIcon icon = get_entry_icon(dn);
row[0]->setIcon(icon);
}
// Make new row in model at given parent based on entry with given dn
void make_new_row(QStandardItem *parent, const QString &dn) {
auto row = QList<QStandardItem *>();
for (int i = 0; i < AdModel::Column::COUNT; i++) {
row.push_back(new QStandardItem());
}
// Set fetch flag because row is new and can be fetched
row[0]->setData(true, AdModel::Roles::CanFetch);
// Load dn, so the row can be searched for later
QStandardItem *dn_item = row[AdModel::Column::DN];
dn_item->setText(dn);
parent->appendRow(row);
load_row(row, dn);
}
QIcon get_entry_icon(const QString &dn) {
// TODO: change to custom, good icons, add those icons to installation?
// TODO: are there cases where an entry can have multiple icons due to multiple objectClasses and one of them needs to be prioritized?
QMap<QString, QString> class_to_icon = {
{"groupPolicyContainer", "x-office-address-book"},
{"container", "folder"},
{"organizationalUnit", "network-workgroup"},
{"person", "avatar-default"},
{"group", "application-x-smb-workgroup"},
{"builtinDomain", "emblem-system"},
};
QString icon_name = "dialog-question";
for (auto c : class_to_icon.keys()) {
if (AD()->attribute_value_exists(dn, "objectClass", c)) {
icon_name = class_to_icon[c];
break;
}
}
QIcon icon = QIcon::fromTheme(icon_name);
return icon;
}

View File

@ -1,65 +0,0 @@
/*
* ADMC - AD Management Center
*
* Copyright (C) 2020 BaseALT Ltd.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef AD_MODEL_H
#define AD_MODEL_H
#include "ad_interface.h"
#include "entry_model.h"
// Model for containers and contents widgets
// Contains columns for DN(from EntryModel) and some entry attributes
// For now only has name, category and description columns
// Loads entries only when they become visible in views that use
// this model
class AdModel final : public EntryModel {
Q_OBJECT
public:
enum Column {
Name,
DN,
COUNT,
};
enum Roles {
CanFetch = Qt::UserRole + 1,
};
explicit AdModel(QObject *parent);
bool canFetchMore(const QModelIndex &parent) const;
void fetchMore(const QModelIndex &parent);
bool hasChildren(const QModelIndex &parent) const override;
private slots:
void on_ad_interface_login_complete(const QString &search_base, const QString &head_dn);
void on_attributes_changed(const QString &dn);
void on_delete_entry_complete(const QString &dn);
void on_dn_changed(const QString &old_dn, const QString &new_dn);
void on_create_entry_complete(const QString &dn, NewEntryType type);
private:
void set_headers();
};
QIcon get_entry_icon(const QString &dn);
#endif /* AD_MODEL_H */

View File

@ -18,7 +18,6 @@
*/
#include "attributes_model.h"
#include "ad_model.h"
#include "ad_interface.h"
AttributesModel::AttributesModel(QObject *parent)

View File

@ -18,16 +18,25 @@
*/
#include "containers_widget.h"
#include "ad_model.h"
#include "entry_proxy_model.h"
#include <QTreeView>
#include <QLabel>
#include <QLayout>
#include <QMimeData>
#include <QMap>
#include <QIcon>
ContainersWidget::ContainersWidget(AdModel *model, QWidget *parent)
: EntryWidget(model, parent)
void make_new_row(QStandardItem *parent, const QString &dn);
void load_row(QList<QStandardItem *> row, const QString &dn);
ContainersWidget::ContainersWidget(AdModel *model_arg, QWidget *parent)
: EntryWidget(model_arg, parent)
{
model = model_arg;
model->setHorizontalHeaderItem(AdModel::Column::Name, new QStandardItem("Name"));
model->setHorizontalHeaderItem(AdModel::Column::DN, new QStandardItem("DN"));
proxy = new EntryProxyModel(model, this);
proxy->only_show_containers = true;
@ -50,6 +59,22 @@ ContainersWidget::ContainersWidget(AdModel *model, QWidget *parent)
connect(
view->selectionModel(), &QItemSelectionModel::selectionChanged,
this, &ContainersWidget::on_selection_changed);
connect(
AD(), &AdInterface::ad_interface_login_complete,
this, &ContainersWidget::on_ad_interface_login_complete);
connect(
AD(), &AdInterface::delete_entry_complete,
this, &ContainersWidget::on_delete_entry_complete);
connect(
AD(), &AdInterface::dn_changed,
this, &ContainersWidget::on_dn_changed);
connect(
AD(), &AdInterface::create_entry_complete,
this, &ContainersWidget::on_create_entry_complete);
connect(
AD(), &AdInterface::attributes_changed,
this, &ContainersWidget::on_attributes_changed);
};
void ContainersWidget::on_selection_changed(const QItemSelection &selected, const QItemSelection &) {
@ -65,3 +90,200 @@ void ContainersWidget::on_selection_changed(const QItemSelection &selected, cons
emit selected_changed(dn);
}
}
AdModel::AdModel(QObject *parent)
: EntryModel(Column::COUNT, AdModel::Column::DN, parent)
{
}
bool AdModel::canFetchMore(const QModelIndex &parent) const {
if (!parent.isValid()) {
return false;
}
bool can_fetch = parent.data(AdModel::Roles::CanFetch).toBool();
return can_fetch;
}
void AdModel::fetchMore(const QModelIndex &parent) {
if (!parent.isValid() || !canFetchMore(parent)) {
return;
}
QString dn = get_dn_from_index(parent);
QStandardItem *parent_item = itemFromIndex(parent);
// Add children
QList<QString> children = AD()->load_children(dn);
for (auto child : children) {
make_new_row(parent_item, child);
}
// Unset CanFetch flag
parent_item->setData(false, AdModel::Roles::CanFetch);
}
// Override this so that unexpanded and unfetched items show the expander even though they technically don't have any children loaded
// NOTE: expander is show if hasChildren returns true
bool AdModel::hasChildren(const QModelIndex &parent = QModelIndex()) const {
if (canFetchMore(parent)) {
return true;
} else {
return QStandardItemModel::hasChildren(parent);
}
}
void ContainersWidget::on_ad_interface_login_complete(const QString &search_base, const QString &head_dn) {
model->removeRows(0, model->rowCount());
// Load head
QStandardItem *invis_root = model->invisibleRootItem();
make_new_row(invis_root, head_dn);
}
void ContainersWidget::on_delete_entry_complete(const QString &dn) {
QList<QStandardItem *> items = model->findItems(dn, Qt::MatchExactly | Qt::MatchRecursive, AdModel::Column::DN);
if (items.size() > 0) {
QStandardItem *dn_item = items[0];
QModelIndex dn_index = dn_item->index();
model->removeRow(dn_index.row(), dn_index.parent());
}
}
void ContainersWidget::on_dn_changed(const QString &old_dn, const QString &new_dn) {
// Remove old entry from model
QList<QStandardItem *> old_items = model->findItems(old_dn, Qt::MatchExactly | Qt::MatchRecursive, AdModel::Column::DN);
if (old_items.size() > 0) {
QStandardItem *dn_item = old_items[0];
QModelIndex dn_index = dn_item->index();
model->removeRow(dn_index.row(), dn_index.parent());
}
// Need to load entry at new parent if the parent has already
// been expanded/fetched
// NOTE: loading if parent hasn't been fetched will
// create a duplicate
const QString new_parent = extract_parent_dn_from_dn(new_dn);
QList<QStandardItem *> parent_items = model->findItems(new_parent, Qt::MatchExactly | Qt::MatchRecursive, AdModel::Column::DN);
if (parent_items.size() > 0) {
QStandardItem *parent_dn_item = parent_items[0];
QModelIndex parent_dn_index = parent_dn_item->index();
QModelIndex parent_index = parent_dn_index.siblingAtColumn(AdModel::Column::Name);
QStandardItem *parent_item = model->itemFromIndex(parent_index);
if (!model->canFetchMore(parent_index)) {
make_new_row(parent_item, new_dn);
}
}
}
void ContainersWidget::on_create_entry_complete(const QString &dn, NewEntryType type) {
// Load entry to model if it's parent has already been fetched
// If it hasn't been fetched, then this new entry will be loaded with all other children when the parent is fetched
QString parent_dn = extract_parent_dn_from_dn(dn);
QList<QStandardItem *> items = model->findItems(parent_dn, Qt::MatchExactly | Qt::MatchRecursive, AdModel::Column::DN);
if (items.size() > 0) {
QStandardItem *dn_item = items[0];
QModelIndex dn_index = dn_item->index();
QModelIndex parent_index = dn_index.siblingAtColumn(0);
QStandardItem *parent = model->itemFromIndex(parent_index);
bool fetched_already = !model->canFetchMore(parent_index);
if (fetched_already) {
make_new_row(parent, dn);
}
}
}
void ContainersWidget::on_attributes_changed(const QString &dn) {
// Compose row based on dn
QList<QStandardItem *> items = model->findItems(dn, Qt::MatchExactly | Qt::MatchRecursive, AdModel::Column::DN);
if (items.size() == 0) {
return;
}
QStandardItem *dn_item = items[0];
QModelIndex dn_index = dn_item->index();
// Compose indexes for all columns
auto indexes = QList<QModelIndex>();
for (int i = 0; i < AdModel::Column::COUNT; i++) {
QModelIndex index = dn_index.siblingAtColumn(i);
indexes.push_back(index);
}
// Compose the row of items from indexes
auto row = QList<QStandardItem *>();
for (int i = 0; i < AdModel::Column::COUNT; i++) {
QModelIndex index = indexes[i];
QStandardItem *item = model->itemFromIndex(index);
row.push_back(item);
}
load_row(row, dn);
}
// Load data into row of items based on entry attributes
void load_row(QList<QStandardItem *> row, const QString &dn) {
QString name = AD()->get_attribute(dn, "name");
row[AdModel::Column::Name]->setText(name);
row[AdModel::Column::DN]->setText(dn);
QIcon icon = get_entry_icon(dn);
row[0]->setIcon(icon);
}
// Make new row in model at given parent based on entry with given dn
void make_new_row(QStandardItem *parent, const QString &dn) {
auto row = QList<QStandardItem *>();
for (int i = 0; i < AdModel::Column::COUNT; i++) {
row.push_back(new QStandardItem());
}
// Set fetch flag because row is new and can be fetched
row[0]->setData(true, AdModel::Roles::CanFetch);
// Load dn, so the row can be searched for later
QStandardItem *dn_item = row[AdModel::Column::DN];
dn_item->setText(dn);
parent->appendRow(row);
load_row(row, dn);
}
QIcon get_entry_icon(const QString &dn) {
// TODO: change to custom, good icons, add those icons to installation?
// TODO: are there cases where an entry can have multiple icons due to multiple objectClasses and one of them needs to be prioritized?
QMap<QString, QString> class_to_icon = {
{"groupPolicyContainer", "x-office-address-book"},
{"container", "folder"},
{"organizationalUnit", "network-workgroup"},
{"person", "avatar-default"},
{"group", "application-x-smb-workgroup"},
{"builtinDomain", "emblem-system"},
};
QString icon_name = "dialog-question";
for (auto c : class_to_icon.keys()) {
if (AD()->attribute_value_exists(dn, "objectClass", c)) {
icon_name = class_to_icon[c];
break;
}
}
QIcon icon = QIcon::fromTheme(icon_name);
return icon;
}

View File

@ -21,6 +21,8 @@
#define CONTAINERS_WIDGET_H
#include "entry_widget.h"
#include "ad_interface.h"
#include "entry_model.h"
class QItemSelection;
class AdModel;
@ -33,7 +35,7 @@ class ContainersWidget final : public EntryWidget {
Q_OBJECT
public:
ContainersWidget(AdModel *model, QWidget *parent);
ContainersWidget(AdModel *model_arg, QWidget *parent);
signals:
void selected_changed(const QString &dn);
@ -41,9 +43,39 @@ signals:
private slots:
void on_selection_changed(const QItemSelection &selected, const QItemSelection &);
void on_ad_interface_login_complete(const QString &search_base, const QString &head_dn);
void on_attributes_changed(const QString &dn);
void on_delete_entry_complete(const QString &dn);
void on_dn_changed(const QString &old_dn, const QString &new_dn);
void on_create_entry_complete(const QString &dn, NewEntryType type);
private:
AdModel *model = nullptr;
EntryProxyModel *proxy = nullptr;
};
class AdModel final : public EntryModel {
public:
enum Column {
Name,
DN,
COUNT,
};
enum Roles {
CanFetch = Qt::UserRole + 1,
};
explicit AdModel(QObject *parent);
bool canFetchMore(const QModelIndex &parent) const;
void fetchMore(const QModelIndex &parent);
bool hasChildren(const QModelIndex &parent) const override;
};
QIcon get_entry_icon(const QString &dn);
#endif /* CONTAINERS_WIDGET_H */

View File

@ -20,7 +20,6 @@
#include "contents_widget.h"
#include "containers_widget.h"
#include "ad_interface.h"
#include "ad_model.h"
#include "entry_proxy_model.h"
#include "entry_model.h"

View File

@ -25,7 +25,6 @@
#include "members_model.h"
#include "members_widget.h"
#include "details_widget.h"
#include "ad_model.h"
#include "attributes_model.h"
#include "status.h"
#include "entry_widget.h"