Хранение информации о текущем пользователе
После открытия главного окна приложения хотелось бы чтобы в строке состояния отображалось имя текущего пользователя и информация о подключении к центральной базе данных.
Также хотелось ограничить права пользователя на некоторые действия. Т.е. пользователю с usder_id отличным от 1 было доступен урезанный функционал приложения.
Для хранения id текущего пользователя добавить опцию 1020. Для этого в метод
DataBases::connectOptions()
добавим еще один запрос жля создания опции.
listSQL << "INSERT INTO `options`(`option_id`,`value`,`comment`) VALUES (1020, '1', 'Текущий пользователь системы')";
Если изменить параметр 1000 (Использовать аутентификацию) то необходимо и установить id текущего пользователя равным 1. Т.е. если пароль не спрашиваем то система работает с правами администратора. Если база данных может это сделать то пусть занимается, поэтому следить за значением устанавливаемого параметра поручим SQLite.
Для этого добавим в базу данных триггер который и будет следить за значением опции 1000:
listSQL << "CREATE TRIGGER use_login AFTER UPDATE " "ON options WHEN (SELECT value FROM options WHERE option_id =1000) = 'false' OR (SELECT value FROM options WHERE option_id =1000) = 0 " "BEGIN " "UPDATE options SET value = 1 WHERE option_id= 1020; " "END";
Если значение устанавливается как ’false’ или 0 то происходит сброс id пользователя на значение 1.
Добавим запись в таблицу options id пользователя успешно вошедшего в систему.
void LoginDialog::on_buttonBox_accepted() { if(ui->comboBoxUser->currentIndex()>=0) { if(userPass==ui->lineEditPass->text().trimmed()) { qInfo(logInfo()) << QString("Пользователь: %1. Успешный вход в систему.").arg(ui->comboBoxUser->currentText()); //Запись в таблицу options ID пользователя Options opt; opt.setOption(1020,QString::number(userID)); this->accept(); } else { ui->labelInfo->setText("Не верный пароль!"); qWarning(logInfo()) << QString("Пользователь: %1. Не верный пароль!.").arg(ui->comboBoxUser->currentText()); ui->lineEditPass->clear(); } } }
Отображение информации о подключении и текущем пользователе
Информацию о текущем пользователе и подключении к базе данных будем отображать в строке состояния главного окна.
Метод void createUI() будет осуществлять первоначальную настройку внешнего вида главного окна, вызываем его в конструкторе MainWindow.
void MainWindow::createUI() { //Создаем два QLabels которые поместим в StatusBar QLabel *labelUsers = new QLabel(); QLabel *labelConnections = new QLabel(); //Получаем данные о текущем пользователе QSqlDatabase db = QSqlDatabase::database("options"); QSqlQuery q = QSqlQuery(db); q.exec("SELECT u.fio FROM users u " "INNER JOIN options o ON u.user_id = o.value " "WHERE o.option_id = 1020"); q.next(); labelUsers->setText("Пользователь: "+q.value(0).toString()); //Получаем данные о текущем подключении QSqlDatabase dbcentr = QSqlDatabase::database(); labelConnections->setText("База данных:"+dbcentr.hostName()+":"+dbcentr.databaseName()); //Добавляем виджеты в строку состояния //Нормальное сообщение ui->statusBar->addWidget(labelUsers); //Постоянное сообщение ui->statusBar->addPermanentWidget(labelConnections); }
Создание меню
Открываем форму mainwindow.ui.
В место
Пишите здесь
пишем наименование меню верхнего уровня: Инструменты
Ниже указываем название пункта меню: Параметры...
В список обхектов добавится объекты menu и action, а в нижней части отобразится редактор действий.
Дадим объектам осмысленнные имена. После этого двойной щелчек в редакторе действий и отроется окно настройки действий.
В нем задаем предварительно добавленный в ресурсы значек для меню и горячую клавишу.
После этого перетаскиваем действие на панель инструментов главного окна.
Правой кнопкой на действии, выбераем перейти к слоту. Нас интересует слот triggered(). Получаем слот который уже связан с выбором пункта меню или нажатием кнопки на панели инструментов.
void MainWindow::on_actionSettings_triggered() { }
Диалоговое окно настроек
Создаем новый класс формы Qt Designer SettingsDialog. В редакторе ресурсов добавляем необходимые элементы управления присваиваем им осмысленные имена и выполняем компоновку.
В MainWindow::on_actionSettings_triggered() будем осуществлять вызов диалога, предварительно подключив заголовочный файл класса диалога.
void MainWindow::on_actionSettings_triggered() { //Создаем объект диалога SettingsDialog *settingsDlg = new SettingsDialog(); //позиционируем диалог по центру главного окна settingsDlg->move(this->geometry().center().x() - settingsDlg->geometry().center().x(), this->geometry().center().y() - settingsDlg->geometry().center().y()); //Отображаем диалог settingsDlg->exec(); }
Проверяем.
Реализация работы диалога настроек:
settingsdialog.h
#ifndef SETTINGSDIALOG_H #define SETTINGSDIALOG_H #include "DataBases/options.h" #include <QDialog> namespace Ui { class SettingsDialog; } class SettingsDialog : public QDialog { Q_OBJECT public: explicit SettingsDialog(QWidget *parent = nullptr); ~SettingsDialog(); private slots: void on_buttonBox_accepted(); private: Ui::SettingsDialog *ui; Options opt; //чтение запись таблицы options private: void createUI(); //Настройка первоначального интерфейса }; #endif // SETTINGSDIALOG_H
settingsdialog.cpp
#include "settingsdialog.h" #include "ui_settingsdialog.h" SettingsDialog::SettingsDialog(QWidget *parent) : QDialog(parent), ui(new Ui::SettingsDialog) { ui->setupUi(this); createUI(); } SettingsDialog::~SettingsDialog() { delete ui; } void SettingsDialog::createUI() { //Устанавливаем сотояния в зависимости от значений в таблице ui->checkBoxLogin->setChecked(opt.getOption(1000).toBool()); ui->checkBoxRegions->setChecked(opt.getOption(1010).toBool()); } void SettingsDialog::on_buttonBox_accepted() { //Записываем в таблицу состояние opt.setOption(1000,QVariant(ui->checkBoxLogin->isChecked()).toString()); opt.setOption(1010,QVariant(ui->checkBoxRegions->isChecked()).toString()); }
Файл проекта:
iMposCh007.zip
Текущее состояние проекта
https://github.com/rust3128/iMpos