Wir haben eine Liste mit Tankstellen erhalten, mit denen wir weitere Aktionen durchführen werden.
Wir erstellen einen Slot, der aufgerufen wird, wenn Sie auf die CheckBox auf den GroupBox-Aktionen klicken.
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); }
Standardmäßig ist die Option Bericht anzeigen auf der Registerkarte Ansicht ausgewählt.
Wir weisen Slots zu, um Signale von buttonBoxView zu verarbeiten:
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(); }
Der allgemeine Algorithmus zum Abrufen von Daten zu den Namen von Kraftstofftypen lautet wie folgt:
- Verbindungsparameter zur Tankstellendatenbank abrufen;
- Mit Streams erhalten wir Verbindungsinformationen, indem wir den aktuellen Fortschritt für jede Tankstelle anzeigen;
- dem Benutzer das Ergebnis in Form einer Tabelle zur Verfügung stellen.
Um Informationen über den Namen zu speichern, erstellen wir den Datentyp FuelName, der Ihnen das Speichern und Empfangen von Informationen ermöglicht und die folgenden Felder enthält:
- Tanknummer;
- Code der Kraftstoffart;
- Kurzbezeichnung des Kraftstoffs;
- den vollständigen Namen des Kraftstoffs, der auf dem Steuerbeleg angegeben ist.
Wir erstellen die FuelName-Klasse. Fügen Sie der Header-Datei die folgenden Eigenschaften hinzu:
int m_tankID; // номер резервуара; int m_fuelID; // код вида топлива; QString m_shortName; // краткое наименование топлива; QString m_name; // полное наименование топлива которое отображается в фискальном чеке.
Mit Qt Creator können Sie schnell eine Property-Getter-Setter-Methode erstellen. Dazu rufen wir das Kontextmenü auf dem Property-Namen auf, wählen Refactoring Methoden zum Holen und Setzen von Werten erstellen. Wir wiederholen die Schritte für alle Eigenschaften unserer Klasse.
Als Ergebnis erhalten wir Folgendes:
Kraftstoffname.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
Kraftstoffname.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; }
Um Informationen zu allen Kraftstoffarten an Tankstellen zu speichern, erstellen wir eine weitere AzsFuelName-Klasse:
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; }
Lassen Sie uns eine Header-Datei erstellen, in der wir eine Struktur zum Speichern des aktuellen Anforderungsausführungsstatus im Stream definieren und die aktuellen Anforderungsausführungsstatus aufzählen.
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
Um den Empfang von Informationen im Fluss zu implementieren, erstellen wir eine Klasse, in der die Liste der Kraftstoffnamen GetFuelNameClass abgerufen wird.
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(); }
Implementierung des Dialogs zur Anzeige des Vorgangs zur Beschaffung der Kraftstoffsortennamen
viewfuelnamemedialog.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
viewfuelnamemedialog.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); }
Als Ergebnis erhalten wir folgendes
Nach Abschluss der Umfrage aller Tankstellen wird der Status der Umfrage angezeigt.
Diese Art der Umsetzung des Zusammenspiels von Fäden und Hauptfaden erschien mir klar. Wenn jemand Kommentare und Vorschläge zur Umsetzung mit großer Dankbarkeit hat, werde ich ihnen zuhören.
Projektarchiv: