Диалог изменения наименований топлива.
Внешний вид диалога.
Диалог полностью создавался в Qt Designer.
В главное меню добавляем раздел
Утилиты
с пунктом
Наименования топлива
, также добавляем соответствующую кнопку на панель инструментов.
Слот вызова диалога в mainwindow.cpp
void MainWindow::on_actionFuelName_triggered() { FuelNameDialog *fuelDlg = new FuelNameDialog(); //Устанавливаем диалог центральным виджетом гланого окна this->setCentralWidget(fuelDlg); this->setWindowTitle(this->windowTitle()+" - "+fuelDlg->windowTitle()); fuelDlg->exec(); }
Первый шагом необходимо реализовать возможность выбора пользователем терминалов (АЗС), на которых будет производится изменение наименований топлива.
Для реализации взаимодействия используем кнопки добавления терминалов в нижней части диалога. Первая кнопка добавляет один терминал, вторая позволяет выбрать терминалы определенного региона и третья выбрать регион целиком.
Кнопки в верхней части GroupBox позволяют выбрать все терминалы в табличной части или снять выделения со всех терминалов. Также реализована кнопка удаления всех выбранных терминалов из табличной части.
Реализация диалога
fuelname.h
#ifndef FUELNAMEDIALOG_H #define FUELNAMEDIALOG_H #include <QDialog> #include <QGroupBox> #include <QSqlQuery> #include <QSqlError> namespace Ui { class FuelNameDialog; } class FuelNameDialog : public QDialog { Q_OBJECT public: explicit FuelNameDialog(QWidget *parent = nullptr); ~FuelNameDialog(); private slots: void on_toolButtonSelectTerminal_clicked(); void on_pushButtonSelectAll_clicked(); void on_pushButtonDeSelectAll_clicked(); void on_pushButtonDeleteSelected_clicked(); void on_toolButtonSelectTermRegions_clicked(); void on_toolButtonSelectRegion_clicked(); private: void createUI(); //Создание начального интерфейса void fillingTerminals(int terminalID); //Зполнение TableWidget выбранным терминалом void fillingTerminals(QList<int> listTerm); //Зполнение TableWidget выбранными терминалами private: Ui::FuelNameDialog *ui; }; #endif // FUELNAMEDIALOG_H
fuelname.cpp
#include "fuelnamedialog.h" #include "ui_fuelnamedialog.h" #include "addterminaldialog.h" #include "addregionterminalsdialog.h" #include "addregionsdialog.h" #include "LoggingCategories/loggingcategories.h" #include <QGroupBox> #include <QDate> FuelNameDialog::FuelNameDialog(QWidget *parent) : QDialog(parent), ui(new Ui::FuelNameDialog) { ui->setupUi(this); createUI(); } FuelNameDialog::~FuelNameDialog() { delete ui; } void FuelNameDialog::createUI() { //Раскрашиваем кнопки QDialogButtonBox ui->buttonBox->button(QDialogButtonBox::Apply)->setStyleSheet("background: #00FF80"); ui->buttonBox->button(QDialogButtonBox::Cancel)->setStyleSheet("background: #FA5858"); ui->buttonBox->button(QDialogButtonBox::Reset)->setStyleSheet("background: #A9BCF5"); //Деактивируем кнопки управления пока нет добавленных терминалов ui->pushButtonSelectAll->setEnabled(false); ui->pushButtonDeSelectAll->setEnabled(false); ui->pushButtonDeleteSelected->setEnabled(false); //Устанавливаем текущую дату и запрещаем выделять дату меньше текущей ui->dateEdit->setDate(QDate::currentDate()); ui->dateEdit->setMinimumDate(QDate::currentDate()); //Настраиваем внешний вид TableWidget ui->tableWidgetTerm->setColumnCount(3); ui->tableWidgetTerm->setHorizontalHeaderLabels(QStringList() << "" << "АЗС" << "Наименование"); ui->tableWidgetTerm->verticalHeader()->hide(); ui->tableWidgetTerm->resizeColumnsToContents(); ui->tableWidgetTerm->horizontalHeader()->setStretchLastSection(true); } //Добавление информации о выбранном терминале void FuelNameDialog::fillingTerminals(int terminalID) { ui->pushButtonSelectAll->setEnabled(true); ui->pushButtonDeSelectAll->setEnabled(true); ui->pushButtonDeleteSelected->setEnabled(true); int row = ui->tableWidgetTerm->rowCount(); //Если терминал есть в списке его не добавляем. for (int i = 0; i<row; ++i) { if( terminalID == ui->tableWidgetTerm->item(i,1)->data(Qt::DisplayRole).toInt()) return; } ui->tableWidgetTerm->insertRow(row); //В столбце 0 добавляем CheckBox QWidget *checkBoxWidget = new QWidget(); QCheckBox *checkBox = new QCheckBox(); QHBoxLayout *layoutCheckBox = new QHBoxLayout(checkBoxWidget); layoutCheckBox->addWidget(checkBox); layoutCheckBox->setAlignment(Qt::AlignCenter); layoutCheckBox->setContentsMargins(0,0,0,0); checkBox->setChecked(true); ui->tableWidgetTerm->setCellWidget(row,0,checkBoxWidget); //Получаем данные о терминале из базы данных и добавляем их в TableWidget QSqlQuery q; q.prepare("select TRIM(t.NAME) from TERMINALS t where t.TERMINAL_ID=:terminalID"); q.bindValue(":terminalID", terminalID); if(!q.exec()) qCritical(logCritical()) << "Не возможно получит данные по терминалу" << terminalID << q.lastError().text(); q.next(); ui->tableWidgetTerm->setItem(row,1, new QTableWidgetItem(QString::number(terminalID))); ui->tableWidgetTerm->setItem(row,2,new QTableWidgetItem(q.value(0).toString())); ui->tableWidgetTerm->sortByColumn(1,Qt::AscendingOrder); ui->tableWidgetTerm->resizeColumnsToContents(); ui->tableWidgetTerm->horizontalHeader()->setStretchLastSection(true); ui->tableWidgetTerm->verticalHeader()->setDefaultSectionSize(ui->tableWidgetTerm->verticalHeader()->minimumSectionSize()); } //Добавление информации о выбранном списке терминалов void FuelNameDialog::fillingTerminals(QList<int> listTerm) { foreach(int terminalID, listTerm){ fillingTerminals(terminalID); } } //Вызываем диалог добавления одного терминала void FuelNameDialog::on_toolButtonSelectTerminal_clicked() { AddTerminalDialog *addTermDlg = new AddTerminalDialog(this); addTermDlg->move(this->parentWidget()->geometry().center().x() - addTermDlg->geometry().center().x(), this->parentWidget()->geometry().center().y() - addTermDlg->geometry().center().y()); if(addTermDlg->exec() == QDialog::Accepted){ fillingTerminals(addTermDlg->getTerminals()); } } //Вызываем диалог добавления терминалов региона void FuelNameDialog::on_toolButtonSelectTermRegions_clicked() { AddRegionTerminalsDialog *addRegTermDlg = new AddRegionTerminalsDialog(this); addRegTermDlg->move(this->parentWidget()->geometry().center().x() - addRegTermDlg->geometry().center().x(), this->parentWidget()->geometry().center().y() - addRegTermDlg->geometry().center().y()); if(addRegTermDlg->exec() == QDialog::Accepted){ fillingTerminals(addRegTermDlg->getTerminalsLists()); } } //Вызываем диалог добавления региона void FuelNameDialog::on_toolButtonSelectRegion_clicked() { AddRegionsDialog *addRegDlg = new AddRegionsDialog(this); addRegDlg->move(this->parentWidget()->geometry().center().x() - addRegDlg->geometry().center().x(), this->parentWidget()->geometry().center().y() - addRegDlg->geometry().center().y()); if(addRegDlg->exec() == QDialog::Accepted){ fillingTerminals(addRegDlg->getTerminalsLists()); } } //Устанавливаем выбор на всех CheckBox в таблице void FuelNameDialog::on_pushButtonSelectAll_clicked() { const 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()); checkBox->setChecked(true); } } //Удаляем выбор на на всех CheckBox в таблице void FuelNameDialog::on_pushButtonDeSelectAll_clicked() { const 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()); checkBox->setChecked(false); } } //Удаление выбранных терминалов из TableWidget void FuelNameDialog::on_pushButtonDeleteSelected_clicked() { int rowCount = ui->tableWidgetTerm->rowCount(); int uncheckCount=0; //Колличество не выбранных строк 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()){ uncheckCount++; } } int currentRow = 0; //Перебираем строки таблицы и если CheckBox выбран удалянм строку //если не выбран переходим на следующую строку while(rowCount != uncheckCount){ QWidget *item = ui->tableWidgetTerm->cellWidget(currentRow,0); QCheckBox *checkBox = qobject_cast<QCheckBox*>(item->layout()->itemAt(0)->widget()); if(checkBox->isChecked()){ ui->tableWidgetTerm->removeRow(currentRow); rowCount = ui->tableWidgetTerm->rowCount(); } else { currentRow++; } } if(rowCount == 0){ ui->pushButtonSelectAll->setEnabled(false); ui->pushButtonDeSelectAll->setEnabled(false); ui->pushButtonDeleteSelected->setEnabled(false); } }
Реализация диалога выбора терминала определенного региона
addregionterminalsdialog.h
#ifndef ADDREGIONTERMINALSDIALOG_H #define ADDREGIONTERMINALSDIALOG_H #include <QDialog> #include <QSqlQueryModel> #include <QSqlQuery> #include <QSqlError> namespace Ui { class AddRegionTerminalsDialog; } class AddRegionTerminalsDialog : public QDialog { Q_OBJECT public: explicit AddRegionTerminalsDialog(QWidget *parent = nullptr); ~AddRegionTerminalsDialog(); QList<int> getTerminalsLists(); private slots: void on_comboBoxRegions_activated(int idx); void on_pushButtonSelectAll_clicked(); void on_pushButtonDeSelectAll_clicked(); void on_buttonBox_rejected(); void on_buttonBox_accepted(); private: void createModel(); void createUI(); private: Ui::AddRegionTerminalsDialog *ui; QSqlQueryModel *modelRegions; QList<int> checkedTerminals; //Список выбранных терминалов }; #endif // ADDREGIONTERMINALSDIALOG_H
addregionterminalsdialog.сpp
#include "addregionterminalsdialog.h" #include "ui_addregionterminalsdialog.h" #include "LoggingCategories/loggingcategories.h" #include "DataBases/options.h" #include <QCheckBox> AddRegionTerminalsDialog::AddRegionTerminalsDialog(QWidget *parent) : QDialog(parent), ui(new Ui::AddRegionTerminalsDialog) { ui->setupUi(this); checkedTerminals.clear(); //Очищаем список createModel(); createUI(); } AddRegionTerminalsDialog::~AddRegionTerminalsDialog() { delete ui; } QList<int> AddRegionTerminalsDialog::getTerminalsLists() { return checkedTerminals; } void AddRegionTerminalsDialog::createModel() { modelRegions = new QSqlQueryModel(this); Options opt; if(opt.getOption(1010).toBool()){ modelRegions->setQuery("select t.region_id, trim(t.NAME) from TERMINALS t " "where t.TERMINALTYPE=2 " "order by t.TERMINAL_ID "); } else { modelRegions->setQuery("select t.terminal_id, trim(t.NAME) from TERMINALS t " "where t.TERMINALTYPE=2 " "order by t.TERMINAL_ID "); } } void AddRegionTerminalsDialog::createUI() { ui->comboBoxRegions->setModel(modelRegions); ui->comboBoxRegions->setModelColumn(1); ui->comboBoxRegions->setCurrentIndex(0); ui->tableWidgetTerm->setColumnCount(3); ui->tableWidgetTerm->setHorizontalHeaderLabels(QStringList() << "" << "АЗС" << "Наименование"); ui->tableWidgetTerm->verticalHeader()->hide(); ui->tableWidgetTerm->resizeColumnsToContents(); ui->tableWidgetTerm->horizontalHeader()->setStretchLastSection(true); ui->comboBoxRegions->activated(0); ui->tableWidgetTerm->setFocus(); } void AddRegionTerminalsDialog::on_comboBoxRegions_activated(int idx) { //Получаем код региона из Модели привязанной к ComboBox int ownerid = modelRegions->data(modelRegions->index(idx,0,QModelIndex())).toInt(); //Очищаем TableWidget ui->tableWidgetTerm->clear(); ui->tableWidgetTerm->setRowCount(0); ui->tableWidgetTerm->setHorizontalHeaderLabels(QStringList() << "" << "АЗС" << "Наименование"); //Получаем список терминалов выбранного региона и заполняем ими табличную часть QSqlQuery q; q.prepare("select DISTINCT t.terminal_id, TRIM(t.NAME) from TERMINALS t " "LEFT JOIN shifts s ON s.TERMINAL_ID = t.TERMINAL_ID " "where t.OWNER_ID=:ownerid and s.SHIFT_ID>1 " "order by t.TERMINAL_ID"); q.bindValue(":ownerid", ownerid); if(!q.exec()) qCritical(logCritical()) << "Не возможно получит данные по региону" << ownerid << q.lastError().text(); int row = 0; while(q.next()) { ui->tableWidgetTerm->insertRow(row); QWidget *checkBoxWidget = new QWidget(); QCheckBox *checkBox = new QCheckBox(); QHBoxLayout *layoutCheckBox = new QHBoxLayout(checkBoxWidget); layoutCheckBox->addWidget(checkBox); layoutCheckBox->setAlignment(Qt::AlignCenter); layoutCheckBox->setContentsMargins(0,0,0,0); checkBox->setChecked(true); ui->tableWidgetTerm->setCellWidget(row,0,checkBoxWidget); ui->tableWidgetTerm->setItem(row,1, new QTableWidgetItem(q.value(0).toString())); ui->tableWidgetTerm->setItem(row,2,new QTableWidgetItem(q.value(1).toString())); ++row; } ui->tableWidgetTerm->resizeColumnsToContents(); ui->tableWidgetTerm->horizontalHeader()->setStretchLastSection(true); ui->tableWidgetTerm->verticalHeader()->setDefaultSectionSize(ui->tableWidgetTerm->verticalHeader()->minimumSectionSize()); } //Выбор всех терминалов void AddRegionTerminalsDialog::on_pushButtonSelectAll_clicked() { const 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()); checkBox->setChecked(true); } } //Снятие выбора у всех терминалов void AddRegionTerminalsDialog::on_pushButtonDeSelectAll_clicked() { const 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()); checkBox->setChecked(false); } } void AddRegionTerminalsDialog::on_buttonBox_rejected() { this->reject(); } //Получаем список выбранных терминалов для передачи в родительский виджет void AddRegionTerminalsDialog::on_buttonBox_accepted() { checkedTerminals.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()){ checkedTerminals.append(ui->tableWidgetTerm->item(i,1)->data(Qt::DisplayRole).toInt()); } } this->accept(); }
Остальные диалоги выбора терминалов организованы аналогичным способом.
В результате пользователю предоставлен интерфейс для быстрого выбора терминалов для дальнейшей работы с наименованиями видов топлива.
Архив проекта
iMposCh009.zip
Добрый день. Вижу все слоты добавляли через дизайнер. Почему не делаете это через код?
Проблема добавления слотов через диайнер в том, что если поменять в дизайнере имя объекта, то слоты сразу протухают, при этом проект компилируется. Иногда можно забыться и очень много времен потратить не понимая, почему не работает.
Добрый день. Наступал на эти грабли.
Сейчас обязательные действия это присвоениям всем элементам управления диалога осмысленных имен в процесе проектирования внешнего вида. Вернее сначала присваиваю а вотом уже занимаюсь размещением.