diff --git a/CMakeLists.txt b/CMakeLists.txt index 427864b2..e78de330 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -53,6 +53,7 @@ set(ADTOOL_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/main_window.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/entry_widget.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/actions.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/status_bar.cpp ) add_definitions(${QT5_DEFINITIONS}) diff --git a/src/ad_interface.cpp b/src/ad_interface.cpp index b0b6b82f..a7a421c7 100644 --- a/src/ad_interface.cpp +++ b/src/ad_interface.cpp @@ -247,6 +247,10 @@ bool ad_interface_login() { } } +QString get_error_str() { + return QString(ad_get_error()); +} + // TODO: confirm that this encoding is ok const char *qstring_to_cstr(const QString &qstr) { return qstr.toLatin1().constData(); @@ -360,6 +364,8 @@ QString get_attribute(const QString &dn, const QString &attribute) { bool set_attribute(const QString &dn, const QString &attribute, const QString &value) { int result = AD_INVALID_DN; + + const QString old_value = get_attribute(dn, attribute); if (FAKE_AD) { fake_attributes_map[dn][attribute] = {value}; @@ -376,14 +382,16 @@ bool set_attribute(const QString &dn, const QString &attribute, const QString &v } if (result == AD_SUCCESS) { - emit ad_interface.entry_changed(dn); + emit ad_interface.set_attribute_complete(dn, attribute, old_value, value); - // TODO: there's a duplicate load_attributes in ad_model's on_entry_changed() + // TODO: there's a duplicate load_attributes in ad_model's on_set_attribute_complete() // Make it so that there's only one call, preferrably here load_attributes(dn); return true; } else { + emit ad_interface.set_attribute_failed(dn, attribute, old_value, value, get_error_str()); + return false; } } @@ -442,10 +450,12 @@ bool create_entry(const QString &name, const QString &dn, NewEntryType type) { } if (result == AD_SUCCESS) { - emit ad_interface.entry_created(dn); + emit ad_interface.create_entry_complete(dn, type); return true; } else { + emit ad_interface.create_entry_failed(dn, type, get_error_str()); + return false; } } @@ -469,9 +479,11 @@ void delete_entry(const QString &dn) { } if (result == AD_SUCCESS) { - emit ad_interface.entry_deleted(dn); + emit ad_interface.delete_entry_complete(dn); attributes_map.remove(dn); + } else { + emit ad_interface.delete_entry_failed(dn, get_error_str()); } } @@ -494,6 +506,8 @@ void move_user(const QString &user_dn, const QString &container_dn) { } if (result == AD_SUCCESS) { - emit ad_interface.user_moved(user_dn, new_dn, container_dn); + emit ad_interface.move_user_complete(user_dn, container_dn, new_dn); + } else { + emit ad_interface.move_user_failed(user_dn, container_dn, new_dn, get_error_str()); } } diff --git a/src/ad_interface.h b/src/ad_interface.h index 863a5287..4defaf51 100644 --- a/src/ad_interface.h +++ b/src/ad_interface.h @@ -34,10 +34,15 @@ public: public slots: signals: - void entry_deleted(const QString &dn); - void entry_changed(const QString &dn); - void entry_created(const QString &dn); - void user_moved(const QString &old_dn, const QString &new_dn , const QString &new_parent_dn); + void delete_entry_complete(const QString &dn); + void set_attribute_complete(const QString &dn, const QString &attribute, const QString &old_value, const QString &value); + void create_entry_complete(const QString &dn, NewEntryType type); + void move_user_complete(const QString &user_dn, const QString &container_dn, const QString &new_dn); + + void delete_entry_failed(const QString &dn, const QString &error_str); + void set_attribute_failed(const QString &dn, const QString &attribute, const QString &old_value, const QString &value, const QString &error_str); + void create_entry_failed(const QString &dn, NewEntryType type, const QString &error_str); + void move_user_failed(const QString &user_dn, const QString &container_dn, const QString &new_dn, const QString &error_str); private: diff --git a/src/ad_model.cpp b/src/ad_model.cpp index 724187d1..309b6632 100644 --- a/src/ad_model.cpp +++ b/src/ad_model.cpp @@ -1,6 +1,5 @@ #include "ad_model.h" -#include "ad_interface.h" #include "constants.h" #include @@ -189,17 +188,17 @@ AdModel::AdModel(QObject *parent) load_and_add_row(invis_root, head_dn); QObject::connect( - &ad_interface, &AdInterface::entry_deleted, - this, &AdModel::on_entry_deleted); + &ad_interface, &AdInterface::delete_entry_complete, + this, &AdModel::on_delete_entry_complete); QObject::connect( - &ad_interface, &AdInterface::entry_changed, - this, &AdModel::on_entry_changed); + &ad_interface, &AdInterface::set_attribute_complete, + this, &AdModel::on_set_attribute_complete); QObject::connect( - &ad_interface, &AdInterface::user_moved, - this, &AdModel::on_user_moved); + &ad_interface, &AdInterface::move_user_complete, + this, &AdModel::on_move_user_complete); QObject::connect( - &ad_interface, &AdInterface::entry_created, - this, &AdModel::on_entry_created); + &ad_interface, &AdInterface::create_entry_complete, + this, &AdModel::on_create_entry_complete); } bool AdModel::canFetchMore(const QModelIndex &parent) const { @@ -242,7 +241,7 @@ bool AdModel::hasChildren(const QModelIndex &parent = QModelIndex()) const { } } -void AdModel::on_entry_changed(const QString &dn) { +void AdModel::on_set_attribute_complete(const QString &dn, const QString &attribute, const QString &value) { // TODO: confirm what kind of search is this, linear? QList items = findItems(dn, Qt::MatchExactly | Qt::MatchRecursive, AdModel::Column::DN); @@ -271,7 +270,7 @@ void AdModel::on_entry_changed(const QString &dn) { } } -void AdModel::on_entry_deleted(const QString &dn) { +void AdModel::on_delete_entry_complete(const QString &dn) { QList items = findItems(dn, Qt::MatchExactly | Qt::MatchRecursive, AdModel::Column::DN); if (items.size() > 0) { @@ -282,9 +281,9 @@ void AdModel::on_entry_deleted(const QString &dn) { } } -void AdModel::on_user_moved(const QString &old_dn, const QString &new_dn, const QString &new_parent_dn) { +void AdModel::on_move_user_complete(const QString &user_dn, const QString &container_dn, const QString &new_dn) { // Remove old entry from model - QList old_items = findItems(old_dn, Qt::MatchExactly | Qt::MatchRecursive, AdModel::Column::DN); + QList old_items = findItems(user_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(); @@ -292,13 +291,13 @@ void AdModel::on_user_moved(const QString &old_dn, const QString &new_dn, const removeRow(dn_index.row(), dn_index.parent()); } - printf("on_user_moved: %s %s\n", qPrintable(new_dn), qPrintable(new_parent_dn)); + printf("on_move_user_complete: %s %s\n", qPrintable(new_dn), qPrintable(container_dn)); // Need to load entry at new parent if the parent has already // been expanded/fetched // NOTE: loading if parent has already been fetched will // create a duplicate - QList parent_items = findItems(new_parent_dn, Qt::MatchExactly | Qt::MatchRecursive, AdModel::Column::DN); + QList parent_items = findItems(container_dn, 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(); @@ -312,7 +311,7 @@ void AdModel::on_user_moved(const QString &old_dn, const QString &new_dn, const } } -void AdModel::on_entry_created(const QString &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); diff --git a/src/ad_model.h b/src/ad_model.h index aca6786c..d70bfd1b 100644 --- a/src/ad_model.h +++ b/src/ad_model.h @@ -2,6 +2,8 @@ #ifndef AD_MODEL_H #define AD_MODEL_H +#include "ad_interface.h" + #include QString get_dn_of_index(const QModelIndex &index); @@ -35,10 +37,10 @@ public: bool canDropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) const override; private slots: - void on_entry_changed(const QString &dn); - void on_entry_deleted(const QString &dn); - void on_user_moved(const QString &old_dn, const QString &new_dn, const QString &new_parent_dn); - void on_entry_created(const QString &dn); + void on_delete_entry_complete(const QString &dn); + void on_set_attribute_complete(const QString &dn, const QString &attribute, const QString &value); + void on_create_entry_complete(const QString &dn, NewEntryType type); + void on_move_user_complete(const QString &user_dn, const QString &container_dn, const QString &new_dn); private: diff --git a/src/attributes_model.cpp b/src/attributes_model.cpp index a0d4887c..90b5dd23 100644 --- a/src/attributes_model.cpp +++ b/src/attributes_model.cpp @@ -9,8 +9,8 @@ AttributesModel::AttributesModel(QObject *parent) change_target(QString("")); QObject::connect( - &ad_interface, &AdInterface::entry_deleted, - this, &AttributesModel::on_entry_deleted); + &ad_interface, &AdInterface::delete_entry_complete, + this, &AttributesModel::on_delete_entry_complete); } // This will be called when an attribute value is edited @@ -20,7 +20,6 @@ bool AttributesModel::setData(const QModelIndex &index, const QVariant &value, i const QString attribute = name_index.data().toString(); const QString value_str = value.toString(); - // printf("setData: %s, %s, %s\n", qPrintable(target_dn), qPrintable(attribute), qPrintable(value_str)); bool success = set_attribute(target_dn, attribute, value_str); @@ -59,7 +58,7 @@ void AttributesModel::change_target(const QString &new_target_dn) { } } -void AttributesModel::on_entry_deleted(const QString &dn) { +void AttributesModel::on_delete_entry_complete(const QString &dn) { // Clear data if current target was deleted if (target_dn == dn) { change_target(QString("")); diff --git a/src/attributes_model.h b/src/attributes_model.h index ddc732b0..4739c05f 100644 --- a/src/attributes_model.h +++ b/src/attributes_model.h @@ -19,11 +19,8 @@ public: bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole); void change_target(const QString &new_target_dn); -signals: - void entry_changed(const QString &dn); - private slots: - void on_entry_deleted(const QString &dn); + void on_delete_entry_complete(const QString &dn); private: QString target_dn; diff --git a/src/attributes_widget.cpp b/src/attributes_widget.cpp index 0bbdc0bd..7b4491e5 100644 --- a/src/attributes_widget.cpp +++ b/src/attributes_widget.cpp @@ -29,6 +29,5 @@ AttributesWidget::AttributesWidget() }; void AttributesWidget::change_model_target(const QString &new_target_dn) { - // Set model to new target model->change_target(new_target_dn); } diff --git a/src/main_window.cpp b/src/main_window.cpp index 3c187e49..38933c66 100644 --- a/src/main_window.cpp +++ b/src/main_window.cpp @@ -7,6 +7,7 @@ #include "attributes_model.h" #include "create_entry_dialog.h" #include "actions.h" +#include "status_bar.h" #include #include @@ -30,7 +31,7 @@ MainWindow::MainWindow() const auto central_widget = new QWidget(this); setCentralWidget(central_widget); - const auto status_bar = new QStatusBar(this); + const auto status_bar = new StatusBar(); setStatusBar(status_bar); const auto menubar = new QMenuBar(this); diff --git a/src/status_bar.cpp b/src/status_bar.cpp new file mode 100644 index 00000000..cce44310 --- /dev/null +++ b/src/status_bar.cpp @@ -0,0 +1,82 @@ + +#include "status_bar.h" +#include "ad_interface.h" + +StatusBar::StatusBar() +: QStatusBar() +{ + showMessage(tr("Ready"), 10 * 1000); + + // Connect signals + connect( + &ad_interface, &AdInterface::create_entry_complete, + this, &StatusBar::on_create_entry_complete); + connect( + &ad_interface, &AdInterface::set_attribute_complete, + this, &StatusBar::on_set_attribute_complete); + connect( + &ad_interface, &AdInterface::create_entry_complete, + this, &StatusBar::on_create_entry_complete); + connect( + &ad_interface, &AdInterface::move_user_complete, + this, &StatusBar::on_move_user_complete); + + connect( + &ad_interface, &AdInterface::delete_entry_failed, + this, &StatusBar::on_delete_entry_failed); + connect( + &ad_interface, &AdInterface::set_attribute_failed, + this, &StatusBar::on_set_attribute_failed); + connect( + &ad_interface, &AdInterface::create_entry_failed, + this, &StatusBar::on_create_entry_failed); + connect( + &ad_interface, &AdInterface::move_user_failed, + this, &StatusBar::on_move_user_failed); +} + +void StatusBar::on_delete_entry_complete(const QString &dn) { + QString msg = QString("Deleted entry \"%1\"").arg(dn); + + showMessage(msg); +} +void StatusBar::on_set_attribute_complete(const QString &dn, const QString &attribute, const QString &old_value, const QString &value) { + QString msg = QString("Changed attribute \"%1\" of \"%2\" from \"%3\" to \"%4\"").arg(attribute, dn, old_value, value); + + showMessage(msg); +} +void StatusBar::on_create_entry_complete(const QString &dn, NewEntryType type) { + QString type_str = new_entry_type_to_string[type]; + QString msg = QString("Created entry \"%1\" of type \"%2\"").arg(dn, type_str); + + showMessage(msg); +} +void StatusBar::on_move_user_complete(const QString &user_dn, const QString &container_dn, const QString &new_dn) { + QString msg = QString("Moved entry \"%1\" to \"%2\"").arg(user_dn).arg(new_dn); + + showMessage(msg); +} + +// TODO: how to do translation of error messages coming from english-only lib??? +// Probably will end up not using raw error strings anyway, just process error codes to generate localized string +void StatusBar::on_delete_entry_failed(const QString &dn, const QString &error_str) { + QString msg = QString("Failed to delete entry \"%1\". Error: \"%2\"").arg(dn, error_str); + + showMessage(msg); +} +void StatusBar::on_set_attribute_failed(const QString &dn, const QString &attribute, const QString &old_value, const QString &value, const QString &error_str) { + QString msg = QString("Failed to change attribute \"%1\" of entry \"%2\" from \"%3\" to \"%4\". Error: \"%5\"").arg(attribute, dn, old_value, value, error_str); + + showMessage(msg); +} +void StatusBar::on_create_entry_failed(const QString &dn, NewEntryType type, const QString &error_str) { + QString type_str = new_entry_type_to_string[type]; + QString msg = QString("Failed to create entry \"%1\" of type \"%2\". Error: \"%3\"").arg(dn, type_str, error_str); + + showMessage(msg); +} +void StatusBar::on_move_user_failed(const QString &user_dn, const QString &container_dn, const QString &new_dn, const QString &error_str) { + QString msg = QString("Failed to move user \"%1\". Error: \"%2\"").arg(user_dn, error_str); + + showMessage(msg); +} diff --git a/src/status_bar.h b/src/status_bar.h new file mode 100644 index 00000000..9ab06979 --- /dev/null +++ b/src/status_bar.h @@ -0,0 +1,32 @@ + +#ifndef STATUS_BAR_H +#define STATUS_BAR_H + +#include "ad_interface.h" + +#include + +void status_bar_init(QStatusBar *status_bar); + + +// Shows names and values of attributes of the entry selected in contents view +class StatusBar final : public QStatusBar { +Q_OBJECT + +public: + explicit StatusBar(); + +private slots: + void on_delete_entry_complete(const QString &dn); + void on_set_attribute_complete(const QString &dn, const QString &attribute, const QString &old_value, const QString &value); + void on_create_entry_complete(const QString &dn, NewEntryType type); + void on_move_user_complete(const QString &user_dn, const QString &container_dn, const QString &new_dn); + + void on_delete_entry_failed(const QString &dn, const QString &error_str); + void on_set_attribute_failed(const QString &dn, const QString &attribute, const QString &old_value, const QString &value, const QString &error_str); + void on_create_entry_failed(const QString &dn, NewEntryType type, const QString &error_str); + void on_move_user_failed(const QString &user_dn, const QString &container_dn, const QString &new_dn, const QString &error_str); + +}; + +#endif /* STATUS_BAR_H */