Проект iMpos. Часть 007. Отображение информации о подключении и текущем пользователе. Создание Меню. Диалог настроек приложения.

trigger, QStatusBar, SQLite, QMenu, QAction

Хранение информации о текущем пользователе

После открытия главного окна приложения хотелось бы чтобы в строке состояния отображалось имя текущего пользователя и информация о подключении к центральной базе данных.
Также хотелось ограничить права пользователя на некоторые действия. Т.е. пользователю с 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 iMposCh007.zip
Текущее состояние проекта https://github.com/rust3128/iMpos

We recommend hosting TIMEWEB
We recommend hosting TIMEWEB
Stable hosting, on which the social network EVILEG is located. For projects on Django we recommend VDS hosting.

Comments

Only authorized users can post comments.
Please, Log in or Sign up
Donate

Hello, Dear Users of EVILEG!!!

If the site helped you, then support the development of the site financially, please.

You can do it by following ways:

Thank you, Evgenii Legotckoi

n
Dec. 9, 2019, 12:46 p.m.
nastya4554

C++ - Тест 003. Условия и циклы

  • Result:78points,
  • Rating points2
N
Dec. 9, 2019, 4:49 a.m.
Nnnnanananna

C ++ - Test 004. Pointers, Arrays and Loops

  • Result:20points,
  • Rating points-10
NB
Dec. 9, 2019, 3:29 a.m.
Nikolaj Batmanov

C++ - Test 002. Constants

  • Result:58points,
  • Rating points-2
Last comments
Dec. 9, 2019, 3:41 a.m.
Evgenij Legotskoj

Эта ошибка invalid use of incomplete type ‘class Ui::AnotherWindow’ обычно говорит о том, что не найдено определение класса или структуры. Типичная проблема - не подключён заголовочны…
NB
Dec. 9, 2019, 3:36 a.m.
Nikolaj Batmanov

Ну, не настолько со мной всё полхо...))) Вроде бы. Я ж кнопки отрисовываю.
Dec. 9, 2019, 3:14 a.m.
Evgenij Legotskoj

Добрый день. У вас ui файлов по ходу нет. UI файлы используются для вёрстки в графическом дизайнере.
NB
Dec. 9, 2019, 3:05 a.m.
Nikolaj Batmanov

Здравствуйте! Полностью скопировал ваш пример к себе, чтобы разобраться. А он не хочет запускаться, дает ошибку: invalid use of incomplete type ‘class Ui::AnotherWindow’ ui(new Ui…
Dec. 8, 2019, 7:23 a.m.
Evgenij Legotskoj

У меня здесь есть одна старая статья с примером векторного редактора. Там есть ответы на ваши вопросы. Поизучайте Qt/C++ - Урок 072. Пример векторного редактора на Qt QGraphicsItem, QG…
Now discuss on the forum
Dec. 9, 2019, 7:16 a.m.
qml_puthon_user

Я сделал простой вывод текста по испусканию сигнала... Чего не хватает программе?) Python: # системные библиотекиimport cv2import numpy as npimport sysimport threading# PyQt б…
SK
Dec. 8, 2019, 4:11 p.m.
Semen Kosandjak

інтерфейс qt, приклад того додаю на малюнку, я натискаю на кнопку і у мене з'являється 2 текст лайну в які я вводжу значення, тобто в 1 цифри,у другому випадку це літери, тобто c++, без графічно…
Dec. 8, 2019, 10:21 a.m.
qml_puthon_user

Тут не подскажу, пишу на питоне.)
Dec. 8, 2019, 5:31 a.m.
BlinCT

Всем привет. Впервые столкнулся со сборкой buildroot и наткнулся на пару странных ошибок. Надеюсь кто то прочитавший сможет что то подсказать, так как мне пока они не понятный. Пе…
Dec. 5, 2019, 4:12 p.m.
Evgenij Legotskoj

Это уже кастомная стилизация. Придётся отключать обрамление и самостоятельно реализовывать ресайз окна, его перемещение, стиль и т.д. Вот статья, как отключить обрамление окна - QML …
EVILEG
About
Services
© EVILEG 2015-2019
Recommend hosting TIMEWEB