diff --git a/src/admc/CMakeLists.txt b/src/admc/CMakeLists.txt index 3c31b399..fd96e715 100644 --- a/src/admc/CMakeLists.txt +++ b/src/admc/CMakeLists.txt @@ -40,6 +40,7 @@ set(ADMC_SOURCES widget_state.cpp main_window.cpp + main_window_connection_error.cpp find_widget.cpp tab_widget.cpp help_browser.cpp diff --git a/src/admc/globals.cpp b/src/admc/globals.cpp index 58c8973c..d25de420 100644 --- a/src/admc/globals.cpp +++ b/src/admc/globals.cpp @@ -22,6 +22,9 @@ #include "adldap.h" #include "status.h" +#include "settings.h" + +#include AdConfig *g_adconfig = new AdConfig(); @@ -32,3 +35,9 @@ Status *g_status() { return &instance; } + +void load_g_adconfig(AdInterface &ad) { + const QLocale locale = settings_get_variant(SETTING_locale).toLocale(); + g_adconfig->load(ad, locale); + AdInterface::set_config(g_adconfig); +} diff --git a/src/admc/globals.h b/src/admc/globals.h index ca3e00f1..09aedc5e 100644 --- a/src/admc/globals.h +++ b/src/admc/globals.h @@ -22,9 +22,12 @@ #define GLOBALS_H class AdConfig; +class AdInterface; class Status; extern AdConfig *g_adconfig; Status *g_status(); +void load_g_adconfig(AdInterface &ad); + #endif /* GLOBALS_H */ diff --git a/src/admc/main.cpp b/src/admc/main.cpp index 53983eba..0fce57d8 100644 --- a/src/admc/main.cpp +++ b/src/admc/main.cpp @@ -22,7 +22,9 @@ #include "config.h" #include "globals.h" #include "main_window.h" +#include "main_window_connection_error.h" #include "settings.h" +#include "utils.h" #include #include @@ -72,10 +74,37 @@ int main(int argc, char **argv) { qDebug() << "Failed to load qt translation"; } - MainWindow main_window; - main_window.show(); + load_connection_options(); + + // In case of failure to connect to AD and load + // adconfig, we open a special alternative main window. + // We do this to acomplish 2 objectives: + // * First, we check that connection is possible at + // startup and give the user an opportunity to + // troubleshoot by adjusting connection options + // (available in the alternative main window). + // * Secondly, we guarantee that the real MainWindow is + // created only after adconfig has been loaded. This + // is needed because many child widgets used by + // MainWindow require adconfig to load their UI + // elements. + QMainWindow *first_main_window = [&]() -> QMainWindow * { + AdInterface ad; + + if (ad_connected(ad)) { + load_g_adconfig(ad); + + return new MainWindow(ad); + } else { + return new MainWindowConnectionError(); + } + }(); + + first_main_window->show(); const int retval = app.exec(); + delete first_main_window; + return retval; } diff --git a/src/admc/main_window.cpp b/src/admc/main_window.cpp index 0a2a3061..390c6cbd 100644 --- a/src/admc/main_window.cpp +++ b/src/admc/main_window.cpp @@ -22,6 +22,7 @@ #include "main_window_p.h" #include "ui_main_window.h" +#include "main_window_connection_error.h" #include "about_dialog.h" #include "adldap.h" #include "changelog_dialog.h" @@ -46,8 +47,8 @@ #include #include -MainWindow::MainWindow() -: QMainWindow() { +MainWindow::MainWindow(AdInterface &ad, QWidget *parent) +: QMainWindow(parent) { ui = new Ui::MainWindow(); ui->setupUi(this); @@ -180,9 +181,6 @@ MainWindow::MainWindow() // // Connect actions // - connect( - ui->action_connect, &QAction::triggered, - this, &MainWindow::connect_to_server); connect( ui->action_connection_options, &QAction::triggered, connection_options_dialog, &QDialog::open); @@ -238,8 +236,7 @@ MainWindow::MainWindow() connect( connection_options_dialog, &QDialog::accepted, - this, &MainWindow::load_connection_options); - load_connection_options(); + load_connection_options); connect( ui->action_filter_objects, &QAction::triggered, @@ -268,7 +265,7 @@ MainWindow::MainWindow() const QVariant console_widget_state = settings_get_variant(SETTING_console_widget_state); ui->console->restore_state(console_widget_state); - connect_to_server(); + connect_to_server(ad); const bool first_time_opening_this_version = []() { const QString last_version = settings_get_variant(SETTING_last_opened_version).toString(); @@ -345,7 +342,10 @@ void MainWindow::on_show_client_user() { d->client_user_label->setVisible(visible); } -void MainWindow::load_connection_options() { +void load_connection_options() { + const QString saved_dc = settings_get_variant(SETTING_dc).toString(); + AdInterface::set_dc(saved_dc); + const QVariant sasl_nocanon = settings_get_variant(SETTING_sasl_nocanon); if (sasl_nocanon.isValid()) { AdInterface::set_sasl_nocanon(sasl_nocanon.toBool()); @@ -397,23 +397,9 @@ void MainWindow::on_language_action(bool checked) { message_box_information(this, tr("Info"), tr("Restart the app to switch to the selected language.")); } -void MainWindow::connect_to_server() { - const QString saved_dc = settings_get_variant(SETTING_dc).toString(); - AdInterface::set_dc(saved_dc); - - AdInterface ad; - if (ad_failed(ad)) { - return; - } - +void MainWindow::connect_to_server(AdInterface &ad) { d->client_user_label->setText(ad.client_user()); - const QLocale locale = settings_get_variant(SETTING_locale).toLocale(); - g_adconfig->load(ad, locale); - AdInterface::set_config(g_adconfig); - - qDebug() << "domain =" << g_adconfig->domain(); - // Load console tree's console_object_tree_init(ui->console, ad); console_policy_tree_init(ui->console); @@ -435,10 +421,6 @@ void MainWindow::connect_to_server() { d->query_item_impl->init(ad.adconfig()); d->query_folder_impl->init(ad.adconfig()); - // Disable connect action once connected because - // it's not needed at that point - ui->action_connect->setEnabled(false); - ui->action_filter_objects->setEnabled(true); // NOTE: need to restore console state again after diff --git a/src/admc/main_window.h b/src/admc/main_window.h index 93b6ebab..78b8a1a1 100644 --- a/src/admc/main_window.h +++ b/src/admc/main_window.h @@ -24,6 +24,7 @@ #include class MainWindowPrivate; +class AdInterface; namespace Ui { class MainWindow; @@ -35,7 +36,7 @@ class MainWindow final : public QMainWindow { public: Ui::MainWindow *ui; - MainWindow(); + MainWindow(AdInterface &ad, QWidget *parent = nullptr); ~MainWindow(); protected: @@ -44,7 +45,7 @@ protected: private: MainWindowPrivate *d; - void connect_to_server(); + void connect_to_server(AdInterface &ad); void refresh_object_tree(); void on_show_non_containers(bool checked); void on_dev_mode(bool checked); @@ -52,8 +53,9 @@ private: void on_filter_dialog_accepted(); void on_log_searches_changed(); void on_show_client_user(); - void load_connection_options(); void on_language_action(bool checked); }; +void load_connection_options(); + #endif /* MAIN_WINDOW_H */ diff --git a/src/admc/main_window.ui b/src/admc/main_window.ui index 2d4dfb49..fbc46cf7 100644 --- a/src/admc/main_window.ui +++ b/src/admc/main_window.ui @@ -27,7 +27,6 @@ File - diff --git a/src/admc/main_window_connection_error.cpp b/src/admc/main_window_connection_error.cpp new file mode 100644 index 00000000..34f4015e --- /dev/null +++ b/src/admc/main_window_connection_error.cpp @@ -0,0 +1,67 @@ +/* + * ADMC - AD Management Center + * + * Copyright (C) 2020-2021 BaseALT Ltd. + * Copyright (C) 2020-2021 Dmitry Degtyarev + * + * 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 . + */ + +#include "main_window_connection_error.h" +#include "ui_main_window_connection_error.h" + +#include "adldap.h" +#include "main_window.h" +#include "settings.h" +#include "utils.h" +#include "globals.h" +#include "connection_options_dialog.h" + +MainWindowConnectionError::MainWindowConnectionError() +: QMainWindow() { + ui = new Ui::MainWindowConnectionError(); + ui->setupUi(this); + + auto connection_options_dialog = new ConnectionOptionsDialog(this); + + connect( + ui->retry_button, &QAbstractButton::clicked, + this, &MainWindowConnectionError::on_retry_button); + connect( + ui->quit_button, &QAbstractButton::clicked, + this, &MainWindow::close); + connect( + ui->options_button, &QAbstractButton::clicked, + connection_options_dialog, &QDialog::open); + connect( + connection_options_dialog, &QDialog::accepted, + load_connection_options); +} + +MainWindowConnectionError::~MainWindowConnectionError() { + delete ui; +} + +void MainWindowConnectionError::on_retry_button() { + AdInterface ad; + + if (ad_connected(ad)) { + load_g_adconfig(ad); + + MainWindow *real_main_window = new MainWindow(ad, this); + real_main_window->show(); + + QMainWindow::hide(); + } +} diff --git a/src/admc/main_window_connection_error.h b/src/admc/main_window_connection_error.h new file mode 100644 index 00000000..7464472d --- /dev/null +++ b/src/admc/main_window_connection_error.h @@ -0,0 +1,43 @@ +/* + * ADMC - AD Management Center + * + * Copyright (C) 2020-2021 BaseALT Ltd. + * Copyright (C) 2020-2021 Dmitry Degtyarev + * + * 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 . + */ + +#ifndef MAIN_WINDOW_PRE_H +#define MAIN_WINDOW_PRE_H + +#include + +namespace Ui { +class MainWindowConnectionError; +} + +class MainWindowConnectionError final : public QMainWindow { + Q_OBJECT + +public: + Ui::MainWindowConnectionError *ui; + + MainWindowConnectionError(); + ~MainWindowConnectionError(); + +private: + void on_retry_button(); +}; + +#endif /* MAIN_WINDOW_PRE_H */ diff --git a/src/admc/main_window_connection_error.ui b/src/admc/main_window_connection_error.ui new file mode 100644 index 00000000..86c76057 --- /dev/null +++ b/src/admc/main_window_connection_error.ui @@ -0,0 +1,94 @@ + + + MainWindowConnectionError + + + + 0 + 0 + 400 + 120 + + + + MainWindow + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Failed to connect to domain. + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Retry + + + + + + + Connection Options + + + + + + + Quit + + + + + + + + + + +