Ruslan Polupan
Ruslan PolupanAug. 7, 2019, 10:41 a.m.

IMpos project. Part 010. Obtaining names of fuel

We received a list of gas stations with which we will perform further actions.
We create a slot called when clicking on the CheckBox on the GroupBox Actions.

void FuelNameDialog::on_groupBoxActions_clicked(bool checked)
{
    if(checked){
        //Очищаем список терминалов передаваемых для дальнейшей обработки
        listTerminals.clear();
        //Добавляем отмеченные терминалы в список
        int rowCount = ui->tableWidgetTerm->rowCount();
        for(int i=0; i<rowCount; ++i){
            QWidget *item = ui->tableWidgetTerm->cellWidget(i,0);
            QCheckBox *checkBox = qobject_cast<QCheckBox*>(item->layout()->itemAt(0)->widget());
            if(checkBox->isChecked()){
               listTerminals.append(ui->tableWidgetTerm->item(i,1)->data(Qt::DisplayRole).toInt());
            }
        }
        //Проверяем что список не пустой
        if(listTerminals.size()==0){
            QMessageBox::warning(this, "Ошибка ввода","Нет выбранных терминалов");
            ui->groupBoxActions->setChecked(false);
            return;
        }
    }
    ui->groupBoxFuel->setEnabled(!checked);
}

By default, the View Report option is selected on the View tab.
We assign slots to process signals from buttonBoxView:

void FuelNameDialog::on_buttonBoxView_rejected()
{
    ui->groupBoxFuel->setEnabled(true);
    ui->groupBoxActions->setChecked(false);
}

void FuelNameDialog::on_buttonBoxView_accepted()
{
    //Диалог для отображения результатов и прогресса получения данных с АЗС
    ViewFuelNameDialog *viewFnDlg = new ViewFuelNameDialog(&listTerminals,this);
    viewFnDlg->exec();
}

The general algorithm for obtaining data on the names of fuel types is as follows:
- get connection parameters to the gas station database;
- using streams, we get connection information from displaying the current progress for each gas station;
- provide the user with the result in the form of a table.

To store information about the name, let's create the FuelName data type, which will allow you to store and receive information and contains the following fields:
- tank number;
- fuel type code;
- short name of the fuel;
- the full name of the fuel that is displayed in the fiscal receipt.

We create the FuelName class. Add the following properties to the header file:

    int m_tankID;             //    номер резервуара;
    int m_fuelID;             //    код вида топлива;
    QString m_shortName;      //    краткое наименование топлива;
    QString m_name;           //    полное наименование топлива которое отображается в фискальном чеке.

Qt Creator allows you to quickly create a property getter setter method. To do this, we call the context menu on the property name, select Refactoring Create methods for getting and setting values. We repeat the steps for all the properties of our class.

As a result, we get the following:

fuelname.h

#ifndef FUELNAME_H
#define FUELNAME_H
#include <QString>

class FuelName
{
public:
    FuelName();
    int tankID() const;
    void setTankID(int tankID);

    int fuelID() const;
    void setFuelID(int fuelID);

    QString shortName() const;
    void setShortName(const QString &shortName);

    QString name() const;
    void setName(const QString &name);

private:
    int m_tankID;             //    номер резервуара;
    int m_fuelID;             //    код вида топлива;
    QString m_shortName;      //    краткое наименование топлива;
    QString m_name;           //    полное наименование топлива которое отображается в фискальном чеке.   
};

#endif // FUELNAME_H

fuelname.cpp

#include "fuelname.h"

FuelName::FuelName()
{

}

int FuelName::tankID() const
{
    return m_tankID;
}

void FuelName::setTankID(int tankID)
{
    m_tankID = tankID;
}

int FuelName::fuelID() const
{
    return m_fuelID;
}

void FuelName::setFuelID(int fuelID)
{
    m_fuelID = fuelID;
}

QString FuelName::shortName() const
{
    return m_shortName;
}

void FuelName::setShortName(const QString &shortName)
{
    m_shortName = shortName;
}

QString FuelName::name() const
{
    return m_name;
}

void FuelName::setName(const QString &name)
{
    m_name = name;
}

To store information about all types of fuel at gas stations, let's create another AzsFuelName class:
azsfuelname.h

#ifndef AZSFUELNAME_H
#define AZSFUELNAME_H
#include "fuelname.h"
#include <QList>
#include <QString>

class AzsFuelName
{
public:
    AzsFuelName();
    QList<FuelName> listFuels() const;
    void insertFuelName(int tankID, int fuelID,  QString shortName, QString name); //Добавления наименования топлива
    int terminalID() const;
    void setTerminalID(int terminalID);
private:
    int m_terminalID;           //Номер терминала 
    QList<FuelName> m_listFuels;//Список наименований топлива
};

#endif // AZSFUELNAME_H

azsfuelname.cpp

#include "azsfuelname.h"

AzsFuelName::AzsFuelName()
{

}

QList<FuelName> AzsFuelName::listFuels() const
{
    return m_listFuels;
}

void AzsFuelName::insertFuelName(int tankID, int fuelID, QString shortName, QString name)
{
    FuelName fn;
    fn.setTankID(tankID);
    fn.setFuelID(fuelID);
    fn.setShortName(shortName);
    fn.setName(name);
    m_listFuels.append(fn);
}

int AzsFuelName::terminalID() const
{
    return m_terminalID;
}

void AzsFuelName::setTerminalID(int terminalID)
{
    m_terminalID = terminalID;
}

Let's create a header file in which we define a structure for storing the current request execution status in the stream and enumerate the current request execution statuses.
statusthread.h

#ifndef STATUSTHREAD_H
#define STATUSTHREAD_H
#include <QObject>

struct statusThread             //Структура для хранения текущего статуса 
{
    int terminalId;             //Номер терминала
    int currentStatus;          //Текущий статус операции получения наименования
};

enum statusList {               //Список статусов
    CONNECT_TO_DATABASE,        //Соединение с базой данных
    SELECT_FUEL_NAME,           //Выполнение запроса
    ERROR_OPEN_DATABASE,        //Ошибка отрытия базы данных
    ERROR_GET_FUEL_NAME,        //Ошибка выполнения запроса
    FINISHED                    //Удачное завершение запроса
};

//Разрешаем использовать данный тип данных во взаимодействии сигнал-слот
Q_DECLARE_METATYPE(statusThread);

#endif // STATUSTHREAD_H

To implement the receipt of information in the flow, we will create a class in which the list of fuel names GetFuelNameClass will be obtained.

getfuelnameclass.h

#ifndef GETFUELNAMECLASS_H
#define GETFUELNAMECLASS_H
#include "statusthread.h"
#include "azsfuelname.h"
#include <QObject>
#include <QSqlQuery>
#include <QSqlError>


class GetFuelNameClass : public QObject
{
    Q_OBJECT
public:
    explicit GetFuelNameClass(QStringList connList, QObject *parent = nullptr);

signals:
    void finisList();                           //Получение наименований завершено
    void signalSendStatus(statusThread);        //Текущий статус получеия наименований
    void signalSendAzsFuelName(AzsFuelName);    //Отправка наименований видов топлива в основной поток
public slots:
    void getFuelList();                         //Получение наименований топлива
private:
    QStringList m_connList;                     //Параменты подключения к базе данный АЗС
    statusThread currentStatus;                 //Текущий статус выполнения
};

#endif // GETFUELNAMECLASS_H

getfuelnameclass.cpp

#include "getfuelnameclass.h"
#include "LoggingCategories/loggingcategories.h"

GetFuelNameClass::GetFuelNameClass(QStringList connList, QObject *parent) : 
    QObject(parent),
    m_connList(connList)
{
    typedef statusThread st;
    qRegisterMetaType<st>("st");
}

void GetFuelNameClass::getFuelList()
{
    //Устанавливаем текущий статус выполнения
    currentStatus.terminalId=m_connList[0].toInt();
    currentStatus.currentStatus=CONNECT_TO_DATABASE;
    emit signalSendStatus(currentStatus);

    //Cоздаем подключение к базе данных АЗС
    QSqlDatabase db = QSqlDatabase::addDatabase("QIBASE", m_connList[0]);

    db.setHostName(m_connList[1]);
    db.setDatabaseName(m_connList[2]);
    db.setUserName("SYSDBA");
    db.setPassword(m_connList[3]);

    //Подключаемся к базе данных АЗС
    if(!db.open()){
        //Не удалось подключится
        qCritical(logCritical()) << Q_FUNC_INFO << "Невозможно подключится к базе данных АСЗ" << m_connList[0] << db.lastError().text();
        //Меняем статус выполнения
        currentStatus.currentStatus=ERROR_OPEN_DATABASE;
        //Отправляем статус главному потоку
        emit signalSendStatus(currentStatus);
        //Завершаем выполнение по данной АЗС
        emit finisGetList();
        return;
    }
    //Меняем статус выполнения и отправляем его в главный поток
    currentStatus.currentStatus=SELECT_FUEL_NAME;
    emit signalSendStatus(currentStatus);

    //Создаем и подготавливаем запрос
    QSqlQuery q = QSqlQuery(db);
    q.prepare("select t.TANK_ID, f.FUEL_ID, f.SHORTNAME, f.NAME from FUELS f "
              "LEFT JOIN tanks t ON t.FUEL_ID = f.FUEL_ID "
              "where f.ISACTIVE='T' "
              "order by t.TANK_ID");
    //выполняем запрос
    if(!q.exec()) {
        //Запрос выполнить не удалось
        qCritical(logCritical()) << Q_FUNC_INFO << "Не возможно получить список видов топлива с АЗС." << m_connList[0] << q.lastError().text();
        //Меняем статус выполнения и отправляем его в главный поток
        currentStatus.currentStatus=ERROR_GET_FUEL_NAME;
        emit signalSendStatus(currentStatus);
        emit finisGetList();
        return;
    }
    AzsFuelName _fuelName;
    _fuelName.setTerminalID(m_connList[0].toInt());
    while(q.next()){
        _fuelName.insertFuelName(q.value(0).toInt(),q.value(1).toInt(),q.value(2).toString(),q.value(3).toString());
    }
    currentStatus.currentStatus=FINISHED;
    emit signalSendAzsFuelName(_fuelName);
    emit signalSendStatus(currentStatus);
    emit finisGetList();
}

Implementation of the dialog for displaying the process of obtaining the names of fuel types
viewfuelnamedialog.h

#ifndef VIEWFUELNAMEDIALOG_H
#define VIEWFUELNAMEDIALOG_H
#include "statusthread.h"
#include "azsfuelname.h"
#include <QDialog>
#include <QSqlQuery>
#include <QSqlError>

namespace Ui {
class ViewFuelNameDialog;
}

class ViewFuelNameDialog : public QDialog
{
    Q_OBJECT

public:
    explicit ViewFuelNameDialog(QList<int> *listTerm, QWidget *parent = nullptr);
    ~ViewFuelNameDialog();

private slots:

public slots:
    void slotGetStatusThread(statusThread status);      //Обработка статуса выполнения запроса
    void slotGetAzsFuelName(AzsFuelName azsFuelname);   //Получение списка наименований по терминалу
private:
    void createUI();
    void getConnectionsList();                 //Получения дагнных о подключении к базам данных АЗС
    void fuelNameList();                       //Наименования видов топлива

private:
    Ui::ViewFuelNameDialog *ui;
    QList<int> *m_terminalSList;              //Список терминалов с которыми будем работать
    QList<QStringList> m_connectionsList;     //Cписок данных для подключения к базе данных АЗС
    QList<AzsFuelName> m_listFuelName;        //Список наименований топлива
    QStringList statusText;                   //Список описанияй статуса подключений
};

#endif // VIEWFUELNAMEDIALOG_H

viewfuelnamedialog.cpp

#include "viewfuelnamedialog.h"
#include "ui_viewfuelnamedialog.h"
#include "passconv.h"
#include "getfuelnameclass.h"
#include "LoggingCategories/loggingcategories.h"
#include <QThread>

ViewFuelNameDialog::ViewFuelNameDialog(QList<int> *listTerm, QWidget *parent) :
    QDialog(parent),
    ui(new Ui::ViewFuelNameDialog),
    m_terminalSList(listTerm)
{
    ui->setupUi(this);

    //Описания статосов выполнения запроса
    statusText.insert(CONNECT_TO_DATABASE,"Подключение к базе данных АЗС...");
    statusText.insert(SELECT_FUEL_NAME,"Получение списка видов топлива....");
    statusText.insert(ERROR_OPEN_DATABASE,"Ошибка открытия базы данных АЗС!");
    statusText.insert(ERROR_GET_FUEL_NAME, "Ошибка получения списка наименований топлива!");
    statusText.insert(FINISHED,"Готово!");

    createUI();
    getConnectionsList();
    fuelNameList();
}

ViewFuelNameDialog::~ViewFuelNameDialog()
{
    delete ui;
}

void ViewFuelNameDialog::createUI()
{
    ui->tableWidget->setColumnCount(2);
    ui->tableWidget->verticalHeader()->hide();
    ui->tableWidget->setHorizontalHeaderLabels(QStringList() << "АЗС" << "Статус");
    ui->tableWidget->horizontalHeader()->setStretchLastSection(true);
    ui->tableWidget->verticalHeader()->setDefaultSectionSize(36);
}
//Получение параметров подключения к базам данных азс
void ViewFuelNameDialog::getConnectionsList()
{
    QSqlQuery q;
    QString strIN="";
    for(int i=0;i<m_terminalSList->size();++i){
        strIN += QString::number(m_terminalSList->at(i))+",";
    }
    strIN.resize(strIN.size()-1);
    QString strSQL = QString("select c.TERMINAL_ID, c.SERVER_NAME, c.DB_NAME, c.CON_PASSWORD from CONNECTIONS c "
                             "where c.TERMINAL_ID IN(%1) and c.CONNECT_ID=2").arg(strIN);
    QStringList list;
    if(!q.exec(strSQL)) qCritical(logCritical()) << "Не удалось получить список терминалов" << q.lastError().text();
    while(q.next()){
        list.clear();
        list << q.value(0).toString() << q.value(1).toString() << q.value(2).toString()  << passConv(q.value(3).toString());
        m_connectionsList.append(list);
    }
}

void ViewFuelNameDialog::fuelNameList()
{
    //Количетсво обрабатываемх АЗС
    int _azsCount = m_connectionsList.size();
    ui->progressBarGetFuel->setRange(0, _azsCount);
    ui->progressBarGetFuel->setValue(0);
    ui->progressBarGetFuel->setFormat("Обработано %v из %m");


    for(int i=0; i<_azsCount; i++){
        //Создаем объект класса получения наиметований и потока
        GetFuelNameClass *getFuel = new GetFuelNameClass(m_connectionsList.at(i));
        QThread *thread = new QThread();
        //помещаем класс в поток.
        getFuel->moveToThread(thread);
        //Связываем сигналы и слоты
        connect(thread,&QThread::started, getFuel, &GetFuelNameClass::getFuelList);
        connect(getFuel,&GetFuelNameClass::signalSendStatus,this,&ViewFuelNameDialog::slotGetStatusThread,Qt::UniqueConnection);
        connect(getFuel,&GetFuelNameClass::signalSendAzsFuelName,this,&ViewFuelNameDialog::slotGetAzsFuelName,Qt::DirectConnection);
        connect(getFuel, &GetFuelNameClass::finisGetList, getFuel, &GetFuelNameClass::deleteLater);
        connect(getFuel, &GetFuelNameClass::finisGetList, thread, &QThread::quit);
        connect(thread, &QThread::finished, thread, &QThread::deleteLater);
        thread->start();
    }
}

void ViewFuelNameDialog::slotGetStatusThread(statusThread status)
{
    if(status.currentStatus == CONNECT_TO_DATABASE){
        //Статус соединения с базой
        //Добавляем строки в TableWidget
        int row = ui->tableWidget->rowCount();
        ui->tableWidget->insertRow(row);
        ui->tableWidget->setItem(row,0, new QTableWidgetItem(QString::number(status.terminalId)));
        ui->tableWidget->setItem(row,1, new QTableWidgetItem(statusText[status.currentStatus]));
        ui->tableWidget->item(row,0)->setIcon(QIcon(":/Image/azs.png"));
        ui->tableWidget->item(row,1)->setIcon(QIcon(":/Image/database.png"));
        ui->tableWidget->item(row,1)->setBackground(QBrush("#F4FA58"));
        ui->tableWidget->sortByColumn(0,Qt::AscendingOrder);
        return;
    }

    int rowCount = ui->tableWidget->rowCount();
    for (int i=0;i<rowCount;++i) {
        //Находим строку в TableWidget и изменяем ее в соответсвии со статусом
        if(ui->tableWidget->item(i,0)->text().toInt() == status.terminalId){
            ui->tableWidget->item(i,1)->setText(statusText[status.currentStatus]);
            switch (status.currentStatus) {
            case SELECT_FUEL_NAME:
                 ui->tableWidget->item(i,1)->setBackground(QBrush("#D7DF01"));
                 ui->tableWidget->item(i,1)->setIcon(QIcon(":/Image/selectfuel.png"));
                break;
            case ERROR_OPEN_DATABASE:
                ui->tableWidget->item(i,1)->setBackground(QBrush("#FE2E2E"));
                ui->tableWidget->item(i,1)->setIcon(QIcon(":/Image/error.png"));
                ui->progressBarGetFuel->setValue(ui->progressBarGetFuel->value()+1);
               break;
            case ERROR_GET_FUEL_NAME:
                ui->tableWidget->item(i,1)->setBackground(QBrush("#DF01A5"));
                ui->tableWidget->item(i,1)->setIcon(QIcon(":/Image/error.png"));
                ui->progressBarGetFuel->setValue(ui->progressBarGetFuel->value()+1);
               break;
            case FINISHED:
                ui->tableWidget->item(i,1)->setBackground(QBrush("#BFFF00"));
                ui->tableWidget->item(i,1)->setIcon(QIcon(":/Image/Accept.png"));
                ui->progressBarGetFuel->setValue(ui->progressBarGetFuel->value()+1);
               break;
            default:
                break;
            }
            break;
        }
    }
}

void ViewFuelNameDialog::slotGetAzsFuelName(AzsFuelName azsFuelname)
{
    //Добавляем полученный список наименований
    m_listFuelName.append(azsFuelname);
}

As a result, we get the following

Upon completion of the survey of all gas stations, the status of the survey is displayed.

This way of implementing the interaction of threads and the main thread seemed clear to me. If someone has comments and suggestions for implementation with great gratitude I will listen to them.

Project archive:

iMposCh010.zip iMposCh010.zip

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.

Do you like it? Share on social networks!

Comments

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

C++ - Test 001. The first program and data types

  • Result:33points,
  • Rating points-10
г
  • ги
  • April 24, 2024, 1:51 a.m.

C++ - Test 005. Structures and Classes

  • Result:41points,
  • Rating points-8
l
  • laei
  • April 23, 2024, 7:19 p.m.

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

  • Result:10points,
  • Rating points-10
Last comments
k
kmssrFeb. 9, 2024, 5:43 a.m.
Qt Linux - Lesson 001. Autorun Qt application under Linux как сделать автозапуск для флэтпака, который не даёт создавать файлы в ~/.config - вот это вопрос ))
Qt WinAPI - Lesson 007. Working with ICMP Ping in Qt Без строки #include <QRegularExpressionValidator> в заголовочном файле не работает валидатор.
EVA
EVADec. 25, 2023, 9:30 p.m.
Boost - static linking in CMake project under Windows Ошибка LNK1104 часто возникает, когда компоновщик не может найти или открыть файл библиотеки. В вашем случае, это файл libboost_locale-vc142-mt-gd-x64-1_74.lib из библиотеки Boost для C+…
J
JonnyJoDec. 25, 2023, 7:38 p.m.
Boost - static linking in CMake project under Windows Сделал всё по-как у вас, но выдаёт ошибку [build] LINK : fatal error LNK1104: не удается открыть файл "libboost_locale-vc142-mt-gd-x64-1_74.lib" Хоть убей, не могу понять в чём дел…
G
GvozdikDec. 19, 2023, 8:01 a.m.
Qt/C++ - Lesson 056. Connecting the Boost library in Qt for MinGW and MSVC compilers Для решения твой проблемы добавь в файл .pro строчку "LIBS += -lws2_32" она решит проблему , лично мне помогло.
Now discuss on the forum
G
GarApril 22, 2024, 3:46 p.m.
Clipboard Как скопировать окно целиком в clipb?
DA
Dr Gangil AcademicsApril 20, 2024, 5:45 p.m.
Unlock Your Aesthetic Potential: Explore MSC in Facial Aesthetics and Cosmetology in India Embark on a transformative journey with an msc in facial aesthetics and cosmetology in india . Delve into the intricate world of beauty and rejuvenation, guided by expert faculty and …
a
a_vlasovApril 14, 2024, 4:41 p.m.
Мобильное приложение на C++Qt и бэкенд к нему на Django Rest Framework Евгений, добрый день! Такой вопрос. Верно ли следующее утверждение: Любое Android-приложение, написанное на Java/Kotlin чисто теоретически (пусть и с большими трудностями) можно написать и на C+…
Павел Дорофеев
Павел ДорофеевApril 14, 2024, 12:35 p.m.
QTableWidget с 2 заголовками Вот тут есть кастомный QTableView с многорядностью проект поддерживается, обращайтесь
f
fastrexApril 4, 2024, 2:47 p.m.
Вернуть старое поведение QComboBox, не менять индекс при resetModel Добрый день! У нас много проектов в которых используется QComboBox, в версии 5.5.1, когда модель испускает сигнал resetModel, currentIndex не менялся. В версии 5.15 при resetModel происходит try…

Follow us in social networks