1
0
mirror of https://github.com/altlinux/admc.git synced 2024-10-26 17:25:38 +03:00

change members tab to apply non-instantly

repurpose move dialog to select dialog, renamed in next commit
move object moving and adding to group outside of move dialog
\ to object context menu
This commit is contained in:
Dmitry Degtyarev 2020-08-31 15:07:00 +04:00
parent 44c0ba6bc6
commit 89a21240c6
10 changed files with 305 additions and 308 deletions

View File

@ -75,6 +75,7 @@ set(ADMC_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/src/rename_dialog.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/create_dialog.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/attribute_display_strings.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/edits/attribute_edit.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/edits/string_edit.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/edits/country_edit.cpp

View File

@ -1354,3 +1354,17 @@ int bit_set(int bitmask, int bit, bool set) {
bool bit_is_set(int bitmask, int bit) {
return ((bitmask & bit) != 0);
}
QString object_class_display_string(const QString &object_class) {
static const QHash<QString, QString> strings = {
{CLASS_CONTAINER, QObject::tr("Container")},
{CLASS_OU, QObject::tr("OU")},
{CLASS_GROUP, QObject::tr("Group")},
{CLASS_USER, QObject::tr("User")}
};
const QString default_value = object_class;
const QString display_string = strings.value(object_class, default_value);
return display_string;
}

View File

@ -244,5 +244,6 @@ QString datetime_raw_to_display_string(const QString &attribute, const QString &
QDateTime datetime_raw_to_datetime(const QString &attribute, const QString &raw_value);
QString group_scope_to_string(GroupScope scope);
QString group_type_to_string(GroupType type);
QString object_class_display_string(const QString &c);
#endif /* AD_INTERFACE_H */

View File

@ -39,9 +39,6 @@ public:
virtual bool verify() = 0;
virtual void apply() = 0;
signals:
void edited();
public slots:
void on_edit_changed();

View File

@ -21,9 +21,18 @@
#include "object_context_menu.h"
#include "utils.h"
#include "dn_column_proxy.h"
#include "move_dialog.h"
#include <QTreeView>
#include <QVBoxLayout>
#include <QStandardItemModel>
#include <QMenu>
#include <QPushButton>
// Store members in a set
// Generate model from current members list
// Add new members via select dialog
// Remove through context menu or select+remove button
enum MembersColumn {
MembersColumn_Name,
@ -36,40 +45,73 @@ MembersTab::MembersTab(ObjectContextMenu *object_context_menu, DetailsWidget *de
{
view = new QTreeView(this);
view->setEditTriggers(QAbstractItemView::NoEditTriggers);
view->setAcceptDrops(true);
view->setContextMenuPolicy(Qt::CustomContextMenu);
view->setDragDropMode(QAbstractItemView::DragDrop);
view->setAllColumnsShowFocus(true);
view->setSortingEnabled(true);
object_context_menu->connect_view(view, MembersColumn_DN);
model = new MembersModel(this);
model = new QStandardItemModel(0, MembersColumn_COUNT, this);
model->setHorizontalHeaderItem(MembersColumn_Name, new QStandardItem(tr("Name")));
model->setHorizontalHeaderItem(MembersColumn_DN, new QStandardItem(tr("DN")));
const auto dn_column_proxy = new DnColumnProxy(MembersColumn_DN, this);
setup_model_chain(view, model, {dn_column_proxy});
const auto layout = new QVBoxLayout(this);
auto add_button = new QPushButton(tr("Add"));
auto remove_button = new QPushButton(tr("Remove"));
auto button_layout = new QHBoxLayout();
button_layout->addWidget(add_button);
button_layout->addWidget(remove_button);
const auto layout = new QVBoxLayout();
setLayout(layout);
layout->setContentsMargins(0, 0, 0, 0);
layout->setSpacing(0);
layout->addWidget(view);
layout->addLayout(button_layout);
connect(
remove_button, &QAbstractButton::clicked,
this, &MembersTab::on_remove_button);
connect(
add_button, &QAbstractButton::clicked,
this, &MembersTab::on_add_button);
QObject::connect(
view, &QWidget::customContextMenuRequested,
this, &MembersTab::on_context_menu);
}
bool MembersTab::changed() const {
return false;
return (current_members != original_members);
}
bool MembersTab::verify() {
return true;
}
// TODO: could do this with less requests by deleting all values of ATTRIBUTE_MEMBER and then setting to the list of values, but need to implement this in adldap
void MembersTab::apply() {
for (auto member : original_members) {
const bool removed = !current_members.contains(member);
if (removed) {
AdInterface::instance()->attribute_delete(target(), ATTRIBUTE_MEMBER, member);
}
}
for (auto member : current_members) {
const bool added = !original_members.contains(member);
if (added) {
AdInterface::instance()->attribute_add(target(), ATTRIBUTE_MEMBER, member);
}
}
}
void MembersTab::reload() {
model->change_target(target());
const QList<QString> members = AdInterface::instance()->attribute_get_multi(target(), ATTRIBUTE_MEMBER);
original_members = members.toSet();
current_members = original_members;
set_root_to_head(view);
load_current_members_into_model();
}
bool MembersTab::accepts_target() const {
@ -78,37 +120,84 @@ bool MembersTab::accepts_target() const {
return is_group;
}
MembersModel::MembersModel(QObject *parent)
: ObjectModel(MembersColumn_COUNT, MembersColumn_DN, parent)
{
setHorizontalHeaderItem(MembersColumn_Name, new QStandardItem(tr("Name")));
setHorizontalHeaderItem(MembersColumn_DN, new QStandardItem(tr("DN")));
// TODO: similar to code in ObjectContextMenu
void MembersTab::on_context_menu(const QPoint pos) {
const QModelIndex base_index = view->indexAt(pos);
if (!base_index.isValid()) {
return;
}
const QModelIndex index = convert_to_source(base_index);
const QString dn = get_dn_from_index(index, MembersColumn_DN);
const QPoint global_pos = view->mapToGlobal(pos);
auto menu = new QMenu(this);
QAction *remove_action = menu->addAction(tr("Remove from group"));
connect(
remove_action, &QAction::triggered,
[this, dn]() {
const QList<QString> removed_members = {dn};
remove_members(removed_members);
});
menu->popup(global_pos);
}
void MembersModel::change_target(const QString &dn) {
removeRows(0, rowCount());
void MembersTab::on_add_button() {
const QList<QString> classes = {CLASS_USER};
const QList<QString> selected_objects = MoveDialog::open(classes, MoveDialogMultiSelection_Yes);
auto create_row = [this](const QString &row_dn) {
if (selected_objects.size() > 0) {
add_members(selected_objects);
}
}
void MembersTab::on_remove_button() {
const QItemSelectionModel *selection_model = view->selectionModel();
const QList<QModelIndex> selected = selection_model->selectedIndexes();
QList<QString> removed_members;
for (auto index : selected) {
const QModelIndex converted = convert_to_source(index);
const QString dn = get_dn_from_index(converted, MembersColumn_DN);
removed_members.append(dn);
}
remove_members(removed_members);
}
void MembersTab::load_current_members_into_model() {
model->removeRows(0, model->rowCount());
for (auto dn : current_members) {
QList<QStandardItem *> row;
for (int i = 0; i < MembersColumn_COUNT; i++) {
row.append(new QStandardItem());
}
const QString name = AdInterface::instance()->attribute_get(row_dn, ATTRIBUTE_NAME);
const QString name = extract_name_from_dn(dn);
row[MembersColumn_Name]->setText(name);
row[MembersColumn_DN]->setText(row_dn);
row[MembersColumn_DN]->setText(dn);
return row;
};
// Create root item to represent group itself
QList<QStandardItem *> group_row = create_row(dn);
appendRow(group_row);
QStandardItem *group_item = group_row[0];
// Populate model with members of new root
const QList<QString> members = AdInterface::instance()->attribute_get_multi(dn, ATTRIBUTE_MEMBER);
for (auto member_dn : members) {
QList<QStandardItem *> member_row = create_row(member_dn);
group_item->appendRow(member_row);
model->appendRow(row);
}
}
void MembersTab::add_members(QList<QString> members) {
for (auto member : members) {
current_members.insert(member);
}
load_current_members_into_model();
on_edit_changed();
}
void MembersTab::remove_members(QList<QString> members) {
for (auto member : members) {
current_members.remove(member);
}
load_current_members_into_model();
on_edit_changed();
}

View File

@ -23,11 +23,17 @@
#include "details_tab.h"
#include "object_model.h"
#include <QPoint>
#include <QSet>
#include <QString>
class QTreeView;
class QString;
class ObjectContextMenu;
class MembersModel;
class QStandardItemModel;
// Shows member objects of targeted group
class MembersTab final : public DetailsTab {
Q_OBJECT
@ -36,18 +42,21 @@ public:
MembersTab(ObjectContextMenu *object_context_menu, DetailsWidget *details_arg);
DECL_DETAILS_TAB_VIRTUALS();
private slots:
void on_context_menu(const QPoint pos);
void on_add_button();
void on_remove_button();
private:
MembersModel *model = nullptr;
// MembersModel *model = nullptr;
QStandardItemModel *model = nullptr;
QTreeView *view = nullptr;
};
QSet<QString> original_members;
QSet<QString> current_members;
class MembersModel final : public ObjectModel {
Q_OBJECT
public:
MembersModel(QObject *parent);
void change_target(const QString &dn);
void load_current_members_into_model();
void add_members(QList<QString> members);
void remove_members(QList<QString> members);
};
#endif /* MEMBERS_TAB_H */

View File

@ -20,7 +20,6 @@
#include "move_dialog.h"
#include "ad_interface.h"
#include "settings.h"
#include "confirmation_dialog.h"
#include "dn_column_proxy.h"
#include "utils.h"
@ -30,10 +29,9 @@
#include <QTreeView>
#include <QSortFilterProxyModel>
#include <QComboBox>
#include <QAction>
#include <QPushButton>
#include <QItemSelectionModel>
#include <QList>
#include <QStandardItemModel>
enum MoveDialogColumn {
MoveDialogColumn_Name,
@ -42,15 +40,15 @@ enum MoveDialogColumn {
MoveDialogColumn_COUNT
};
const QMap<ClassFilter, QString> class_filter_string = {
{ClassFilter_All, ""},
{ClassFilter_Containers, CLASS_CONTAINER},
{ClassFilter_OUs, CLASS_OU},
{ClassFilter_Groups, CLASS_GROUP},
};
QList<QString> MoveDialog::open(QList<QString> classes, MoveDialogMultiSelection multi_selection) {
MoveDialog dialog(classes, multi_selection);
dialog.exec();
MoveDialog::MoveDialog(QWidget *parent)
: QDialog(parent)
return dialog.selected_objects;
}
MoveDialog::MoveDialog(QList<QString> classes, MoveDialogMultiSelection multi_selection)
: QDialog()
{
resize(600, 600);
@ -58,13 +56,17 @@ MoveDialog::MoveDialog(QWidget *parent)
view->setEditTriggers(QAbstractItemView::NoEditTriggers);
view->setSortingEnabled(true);
target_label = new QLabel(tr("TARGET"), this);
if (multi_selection == MoveDialogMultiSelection_Yes) {
view->setSelectionMode(QAbstractItemView::MultiSelection);
}
filter_class_label = new QLabel(tr("Class: "), this);
filter_class_combo_box = new QComboBox(this);
auto target_label = new QLabel(tr("Select object"), this);
auto filter_class_label = new QLabel(tr("Class: "), this);
auto filter_class_combo = new QComboBox(this);
const auto filter_name_label = new QLabel(tr("Name: "), this);
filter_name_line_edit = new QLineEdit(this);
auto filter_name_edit = new QLineEdit(this);
const auto select_button = new QPushButton(tr("Select"), this);
const auto cancel_button = new QPushButton(tr("Cancel"), this);
@ -72,199 +74,28 @@ MoveDialog::MoveDialog(QWidget *parent)
const auto layout = new QGridLayout(this);
layout->addWidget(target_label, 0, 0);
layout->addWidget(filter_class_label, 1, 0, Qt::AlignRight);
layout->addWidget(filter_class_combo_box, 1, 1, 1, 2);
layout->addWidget(filter_class_combo, 1, 1, 1, 2);
layout->addWidget(filter_name_label, 2, 0, Qt::AlignRight);
layout->addWidget(filter_name_line_edit, 2, 1, 1, 2);
layout->addWidget(filter_name_edit, 2, 1, 1, 2);
layout->addWidget(view, 3, 0, 1, 3);
layout->addWidget(cancel_button, 4, 0, Qt::AlignLeft);
layout->addWidget(select_button, 4, 2, Qt::AlignRight);
model = new MoveDialogModel(this);
proxy_name = new QSortFilterProxyModel(this);
auto proxy_name = new QSortFilterProxyModel(this);
proxy_name->setFilterKeyColumn(MoveDialogColumn_Name);
proxy_class = new QSortFilterProxyModel(this);
auto proxy_class = new QSortFilterProxyModel(this);
proxy_class->setFilterKeyColumn(MoveDialogColumn_Class);
const auto dn_column_proxy = new DnColumnProxy(MoveDialogColumn_DN, this);
setup_model_chain(view, model, {proxy_name, proxy_class, dn_column_proxy});
connect(
view, &QAbstractItemView::doubleClicked,
this, &MoveDialog::on_double_clicked);
connect(
filter_name_line_edit, &QLineEdit::textChanged,
this, &MoveDialog::on_filter_name_changed);
connect(filter_class_combo_box, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &MoveDialog::on_filter_class_changed);
connect(
select_button, &QAbstractButton::clicked,
this, &MoveDialog::on_select_button);
connect(
cancel_button, &QAbstractButton::clicked,
this, &MoveDialog::on_cancel_button);
connect(
this, &QDialog::finished,
model, &MoveDialogModel::on_dialog_finished);
}
void MoveDialog::open_for_object(const QString &dn, MoveDialogType type_arg) {
target_dn = dn;
type = type_arg;
filter_name_line_edit->setText("");
on_filter_name_changed("");
QString target_label_text;
switch (type) {
case MoveDialogType_Move: {
target_label_text = QString(tr("Moving \"%1\"")).arg(target_dn);
break;
}
case MoveDialogType_AddToGroup: {
target_label_text = QString(tr("Adding \"%1\" to group")).arg(target_dn);
break;
}
}
target_label->setText(target_label_text);
// Select classes that this object can be moved to
// TODO: cover all cases
QList<ClassFilter> classes;
switch (type) {
case MoveDialogType_Move: {
const bool is_container = AdInterface::instance()->is_container(dn);
if (is_container) {
classes = {ClassFilter_Containers};
} else {
classes = {ClassFilter_Containers, ClassFilter_OUs};
}
break;
}
case MoveDialogType_AddToGroup: {
classes = {ClassFilter_Groups};
break;
}
}
// Fill class combo box with possible classes and "All" option
filter_class_combo_box->clear();
QList<ClassFilter> combo_classes = {ClassFilter_All};
combo_classes += classes;
for (auto c : combo_classes) {
auto filter_display_string =
[] (ClassFilter filter) {
switch (filter) {
case ClassFilter_All: return MoveDialog::tr("All");
case ClassFilter_Containers: return MoveDialog::tr("Containers");
case ClassFilter_OUs: return MoveDialog::tr("OU's");
case ClassFilter_Groups: return MoveDialog::tr("Groups");
case ClassFilter_COUNT: return QString("COUNT");
}
return QString("");
};
const QString display_string = filter_display_string(c);
filter_class_combo_box->addItem(display_string, c);
}
// Show or hide class-related elements depending on type
switch (type) {
case MoveDialogType_Move: {
filter_class_combo_box->show();
filter_class_label->show();
view->setColumnHidden(MoveDialogColumn_Class, false);
break;
}
case MoveDialogType_AddToGroup: {
filter_class_combo_box->hide();
filter_class_label->hide();
view->setColumnHidden(MoveDialogColumn_Class, true);
break;
}
}
model->load(dn, classes);
for (int col = 0; col < view->model()->columnCount(); col++) {
view->resizeColumnToContents(col);
}
open();
}
void MoveDialog::on_filter_name_changed(const QString &text) {
proxy_name->setFilterRegExp(QRegExp(text, Qt::CaseInsensitive, QRegExp::FixedString));
}
void MoveDialog::on_filter_class_changed(int index) {
const QVariant item_data = filter_class_combo_box->itemData(index);
const ClassFilter class_filter = item_data.value<ClassFilter>();
const QString regexp = class_filter_string[class_filter];
proxy_class->setFilterRegExp(QRegExp(regexp, Qt::CaseInsensitive, QRegExp::FixedString));
}
void MoveDialog::complete(const QString &move_dn) {
const QString confirm_text = QString(tr("Move \"%1\" to \"%2\"?")).arg(target_dn, move_dn);
const bool confirmed = confirmation_dialog(confirm_text, this);
if (confirmed) {
switch (type) {
case MoveDialogType_Move: {
AdInterface::instance()->object_move(target_dn, move_dn);
break;
}
case MoveDialogType_AddToGroup: {
AdInterface::instance()->group_add_user(move_dn, target_dn);
break;
}
}
done(QDialog::Accepted);
}
}
void MoveDialog::on_select_button(bool) {
const QItemSelectionModel *selection_model = view->selectionModel();
if (!selection_model->hasSelection()) {
return;
}
const QModelIndex selected_index = selection_model->currentIndex();
const QString move_dn = get_dn_from_index(selected_index, MoveDialogColumn_DN);
complete(move_dn);
}
void MoveDialog::on_double_clicked(const QModelIndex &index) {
const QString move_dn = get_dn_from_index(index, MoveDialogColumn_DN);
complete(move_dn);
}
void MoveDialog::on_cancel_button(bool) {
done(QDialog::Rejected);
}
MoveDialogModel::MoveDialogModel(QObject *parent)
: QStandardItemModel(0, MoveDialogColumn_COUNT, parent)
{
setHorizontalHeaderItem(MoveDialogColumn_Name, new QStandardItem(tr("Name")));
setHorizontalHeaderItem(MoveDialogColumn_Class, new QStandardItem(tr("Class")));
setHorizontalHeaderItem(MoveDialogColumn_DN, new QStandardItem(tr("DN")));
}
void MoveDialogModel::load(const QString &dn, QList<ClassFilter> classes) {
for (auto c : classes) {
const QString class_string = class_filter_string[c];
QString filter = filter_EQUALS(ATTRIBUTE_OBJECT_CLASS, class_string);
// Load model
auto model = new QStandardItemModel(0, MoveDialogColumn_COUNT, this);
model->setHorizontalHeaderItem(MoveDialogColumn_Name, new QStandardItem(tr("Name")));
model->setHorizontalHeaderItem(MoveDialogColumn_Class, new QStandardItem(tr("Class")));
model->setHorizontalHeaderItem(MoveDialogColumn_DN, new QStandardItem(tr("DN")));
for (auto object_class : classes) {
QString filter = filter_EQUALS(ATTRIBUTE_OBJECT_CLASS, object_class);
// Filter out advanced objects if needed
const bool advanced_view = Settings::instance()->get_bool(BoolSetting_AdvancedView);
@ -287,14 +118,78 @@ void MoveDialogModel::load(const QString &dn, QList<ClassFilter> classes) {
const QString name = extract_name_from_dn(e_dn);
row[MoveDialogColumn_Name]->setText(name);
row[MoveDialogColumn_Class]->setText(class_string);
row[MoveDialogColumn_Class]->setText(object_class);
row[MoveDialogColumn_DN]->setText(e_dn);
appendRow(row);
model->appendRow(row);
}
}
setup_model_chain(view, model, {proxy_name, proxy_class, dn_column_proxy});
// Fill class combo box with possible classes
filter_class_combo->clear();
for (auto object_class : classes) {
auto display_string = object_class_display_string(object_class);
filter_class_combo->addItem(display_string, object_class);
}
// Disable/hide class-related elements if selecting only from one class
if (classes.size() == 1) {
filter_class_combo->setEnabled(false);
view->setColumnHidden(MoveDialogColumn_Class, true);
}
for (int col = 0; col < view->model()->columnCount(); col++) {
view->resizeColumnToContents(col);
}
// Disable select button when there's no selection and enable when there is
const QItemSelectionModel *selection_model = view->selectionModel();
connect(selection_model, &QItemSelectionModel::selectionChanged,
[selection_model, select_button]() {
const bool enable_select_button = selection_model->hasSelection();
select_button->setEnabled(enable_select_button);
});
// Update proxy name when filter name changes
connect(
filter_name_edit, &QLineEdit::textChanged,
[proxy_name](const QString &text) {
proxy_name->setFilterRegExp(QRegExp(text, Qt::CaseInsensitive, QRegExp::FixedString));
});
filter_name_edit->setText("");
// Update proxy class when filter class changes
connect(filter_class_combo, QOverload<int>::of(&QComboBox::currentIndexChanged),
[filter_class_combo, proxy_class](const int index) {
const QVariant item_data = filter_class_combo->itemData(index);
const QString object_class = item_data.toString();
proxy_class->setFilterRegExp(QRegExp(object_class, Qt::CaseInsensitive, QRegExp::FixedString));
});
connect(
select_button, &QAbstractButton::clicked,
this, &QDialog::accept);
connect(
cancel_button, &QAbstractButton::clicked,
this, &QDialog::reject);
}
void MoveDialogModel::on_dialog_finished(int) {
removeRows(0, rowCount());
void MoveDialog::accept() {
const QItemSelectionModel *selection_model = view->selectionModel();
const QList<QModelIndex> selected_indexes = selection_model->selectedIndexes();
selected_objects.clear();
for (auto index : selected_indexes) {
const QString dn = get_dn_from_index(index, MoveDialogColumn_DN);
if (!selected_objects.contains(dn)) {
selected_objects.append(dn);
}
}
QDialog::accept();
}

View File

@ -22,72 +22,29 @@
#include <QDialog>
#include <QString>
#include <QStandardItemModel>
#include <QList>
class QWidget;
class QLineEdit;
class QSortFilterProxyModel;
class QComboBox;
class MoveDialogModel;
class QTreeView;
class QLabel;
class QAction;
enum MoveDialogType {
MoveDialogType_Move,
MoveDialogType_AddToGroup
enum MoveDialogMultiSelection {
MoveDialogMultiSelection_Yes,
MoveDialogMultiSelection_No
};
enum ClassFilter {
ClassFilter_All,
ClassFilter_Containers,
ClassFilter_OUs,
ClassFilter_Groups,
ClassFilter_COUNT
};
Q_DECLARE_METATYPE(ClassFilter)
class MoveDialog final : public QDialog {
Q_OBJECT
public:
MoveDialog(QWidget *parent);
void open_for_object(const QString &dn, MoveDialogType type);
static QList<QString> open(QList<QString> classes, MoveDialogMultiSelection multi_selection = MoveDialogMultiSelection_No);
private slots:
void on_filter_name_changed(const QString &text);
void on_filter_class_changed(int index);
void on_select_button(bool checked);
void on_cancel_button(bool checked);
void on_double_clicked(const QModelIndex &index);
void accept();
private:
QTreeView *view = nullptr;
QLabel *target_label = nullptr;
QLabel *filter_class_label = nullptr;
QComboBox *filter_class_combo_box = nullptr;
QLineEdit *filter_name_line_edit = nullptr;
MoveDialogModel *model = nullptr;
QSortFilterProxyModel *proxy_name = nullptr;
QSortFilterProxyModel *proxy_class = nullptr;
QString target_dn = "";
MoveDialogType type;
QTreeView *view;
QList<QString> selected_objects;
void complete(const QString &move_dn);
};
class MoveDialogModel final : public QStandardItemModel {
Q_OBJECT
public:
MoveDialogModel(QObject *parent);
void load(const QString &dn, QList<ClassFilter> classes);
public slots:
void on_dialog_finished(int);
MoveDialog(QList<QString> classes, MoveDialogMultiSelection multi_selection);
};
#endif /* MOVE_DIALOG_H */

View File

@ -41,8 +41,6 @@ void force_reload_attributes_and_diff(const QString &dn);
ObjectContextMenu::ObjectContextMenu(QWidget *parent)
: QMenu(parent)
{
// NOTE: use parent, not context menu itself so dialog is centered
move_dialog = new MoveDialog(parent);
}
// Open this context menu when view requests one
@ -98,13 +96,16 @@ void ObjectContextMenu::open(const QPoint &global_pos, const QString &dn, const
});
}
addAction(tr("Move"), [this, dn]() {
move_dialog->open_for_object(dn, MoveDialogType_Move);
});
QAction *move_action = addAction(tr("Move"));
connect(
move_action, &QAction::triggered,
[this, dn]() {
move(dn);
});
const bool is_policy = AdInterface::instance()->is_policy(dn);
const bool is_user = AdInterface::instance()->is_user(dn);
if (is_policy) {
submenu_new->addAction(tr("Edit Policy"), [this, dn]() {
edit_policy(dn);
@ -112,9 +113,12 @@ void ObjectContextMenu::open(const QPoint &global_pos, const QString &dn, const
}
if (is_user) {
addAction(tr("Add to group"), [this, dn]() {
move_dialog->open_for_object(dn, MoveDialogType_AddToGroup);
});
QAction *add_to_group_action = addAction(tr("Add to group"));
connect(
add_to_group_action, &QAction::triggered,
[this, dn]() {
add_to_group(dn);
});
addAction(tr("Reset password"), [this, dn]() {
const auto password_dialog = new PasswordDialog(dn, this);
@ -187,6 +191,36 @@ void ObjectContextMenu::edit_policy(const QString &dn) {
process->start();
}
void ObjectContextMenu::move(const QString &dn) {
// TODO: somehow formalize "class X can only be moved to X,Y,Z..." better
const bool is_container = AdInterface::instance()->is_container(dn);
QList<QString> classes;
if (is_container) {
classes = {CLASS_CONTAINER};
} else {
classes = {CLASS_CONTAINER, CLASS_OU};
}
const QList<QString> selected_objects = MoveDialog::open(classes);
if (selected_objects.size() == 1) {
const QString container = selected_objects[0];
AdInterface::instance()->object_move(dn, container);
}
}
void ObjectContextMenu::add_to_group(const QString &dn) {
const QList<QString> classes = {CLASS_GROUP};
const QList<QString> selected_objects = MoveDialog::open(classes, MoveDialogMultiSelection_Yes);
if (selected_objects.size() > 0) {
for (auto group : selected_objects) {
AdInterface::instance()->group_add_user(group, dn);
}
}
}
void force_reload_attributes_and_diff(const QString &dn) {
QMap<QString, QList<QString>> old_attributes = AdInterface::instance()->get_all_attributes(dn);

View File

@ -39,13 +39,13 @@ public:
signals:
void details(const QString &dn);
private:
MoveDialog *move_dialog = nullptr;
void open(const QPoint &global_pos, const QString &dn, const QString &parent_dn);
void delete_object(const QString &dn);
void edit_policy(const QString &dn);
void move(const QString &dn);
void add_to_group(const QString &dn);
};