123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293 |
- /*
- *openPilotLog - A FOSS Pilot Logbook Application
- *Copyright (C) 2020-2023 Felix Turowsky
- *
- *This program is free software: you can redistribute it and/or modify
- *it under the terms of the GNU General Public License as published by
- *the Free Software Foundation, either version 3 of the License, or
- *(at your option) any later version.
- *
- *This program is distributed in the hope that it will be useful,
- *but WITHOUT ANY WARRANTY; without even the implied warranty of
- *MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- *GNU General Public License for more details.
- *
- *You should have received a copy of the GNU General Public License
- *along with this program. If not, see <https://www.gnu.org/licenses/>.
- */
- #include "tailswidget.h"
- #include "src/classes/time.h"
- #include "ui_aircraftwidget.h"
- #include "src/opl.h"
- #include "src/classes/settings.h"
- #include "src/database/database.h"
- #include "src/gui/dialogues/newtaildialog.h"
- TailsWidget::TailsWidget(QWidget *parent) :
- QWidget(parent),
- ui(new Ui::AircraftWidget)
- {
- ui->setupUi(this);
- ui->tableView->setMinimumWidth(this->width()/2);
- ui->stackedWidget->setMinimumWidth(this->width()/2);
- setupModelAndView();
- }
- TailsWidget::~TailsWidget()
- {
- delete ui;
- }
- void TailsWidget::setupModelAndView()
- {
- model = new QSqlTableModel(this);
- model->setTable(QStringLiteral("viewTails"));
- model->select();
- view = ui->tableView;
- view->setModel(model);
- view->setSelectionBehavior(QAbstractItemView::SelectRows);
- view->setSelectionMode(QAbstractItemView::SingleSelection); // For now, editing multiple entries is not supported.
- view->setEditTriggers(QAbstractItemView::NoEditTriggers);
- view->horizontalHeader()->setStretchLastSection(QHeaderView::Stretch);
- view->hideColumn(0);
- view->resizeColumnsToContents();
- view->verticalHeader()->hide();
- view->setAlternatingRowColors(true);
- sortColumn = Settings::getTailSortColumn();
- view->setSortingEnabled(true);
- view->sortByColumn(sortColumn, Qt::DescendingOrder);
- view->show();
- selection = view->selectionModel();
- connectSignalsAndSlots();
- }
- void TailsWidget::connectSignalsAndSlots()
- {
- QObject::connect(ui->tableView->selectionModel(), &QItemSelectionModel::selectionChanged,
- this, &TailsWidget::tableView_selectionChanged);
- QObject::connect(ui->tableView->horizontalHeader(), &QHeaderView::sectionClicked,
- this, &TailsWidget::tableView_headerClicked);
- }
- /*
- * Slots
- */
- void TailsWidget::onAircraftWidget_settingChanged(SettingsWidget::SettingSignal signal)
- {
- if (signal != SettingsWidget::AircraftWidget)
- return;
- setupModelAndView();
- }
- void TailsWidget::onAircraftWidget_dataBaseUpdated()
- {
- refreshView();
- }
- void TailsWidget::changeEvent(QEvent *event)
- {
- if (event != nullptr)
- if(event->type() == QEvent::LanguageChange)
- ui->retranslateUi(this);
- }
- void TailsWidget::on_newAircraftButton_clicked()
- {
- NewTailDialog nt(QString(), this);
- setUiEnabled(false);
- nt.exec();
- refreshView();
- setUiEnabled(true);
- }
- /*!
- * \brief Displays a dialog in which the Tail can be edited
- */
- void TailsWidget::tableView_selectionChanged()
- {
- if (this->findChild<NewTailDialog*>() != nullptr)
- delete this->findChild<NewTailDialog*>();
- selectedTails.clear();
- const auto selected_rows = selection->selectedRows();
- for (const auto& row : selected_rows) {
- selectedTails << row.data().toInt();
- DEB << "Selected Tails(s) with ID: " << selectedTails;
- }
- if(selectedTails.length() == 1) {
- NewTailDialog nt(selectedTails.first(), this);
- nt.setWindowFlag(Qt::Widget);
- ui->stackedWidget->addWidget(&nt);
- ui->stackedWidget->setCurrentWidget(&nt);
- setUiEnabled(false);
- nt.exec();
- refreshView();
- setUiEnabled(true);
- }
- }
- /*!
- * \brief Acts as a filter on the display model
- */
- void TailsWidget::on_aircraftSearchLineEdit_textChanged(const QString &arg1)
- {
- if(ui->aircraftSearchComboBox->currentIndex() == 0){
- ui->aircraftSearchLineEdit->setText(arg1.toUpper());
- }
- model->setFilter(ui->aircraftSearchComboBox->currentText()
- + QLatin1String(" LIKE \"%")
- + arg1 + QLatin1String("%\""));
- }
- void TailsWidget::tableView_headerClicked(int column)
- {
- Settings::setTailSortColumn(column);
- }
- void TailsWidget::on_deleteAircraftButton_clicked()
- {
- if (selectedTails.length() == 0) {
- INFO(tr("No Aircraft selected."));
- } else if (selectedTails.length() > 1) {
- WARN(tr("Deleting multiple entries is currently not supported"));
- /// [F] to do: for (const auto& row_id : selectedPilots) { do batchDelete }
- /// I am not sure if enabling this functionality for this widget is a good idea.
- /// On the one hand, deleting many entries could be useful in a scenario where
- /// for example, the user has changed airlines and does not want to have his 'old'
- /// colleagues polluting his logbook anymore.
- /// On the other hand we could run into issues with foreign key constraints on the
- /// flights table (see on_delete_unsuccessful) below.
- /// I think batch-editing should be implemented at some point, but batch-deleting should not.
- } else if (selectedTails.length() == 1) {
- auto entry = DB->getTailEntry(selectedTails.first());
- QMessageBox message_box(this);
- message_box.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
- message_box.setDefaultButton(QMessageBox::No);
- message_box.setIcon(QMessageBox::Question);
- message_box.setWindowTitle(tr("Delete Aircraft"));
- message_box.setText(tr("You are deleting the following aircraft:<br><br><b><tt>"
- "%1 - (%2)</b></tt><br><br>Are you sure?"
- ).arg(entry.getData().value(OPL::TailEntry::REGISTRATION).toString(),
- getAircraftTypeString(entry)));
- if (message_box.exec() == QMessageBox::Yes) {
- if(!DB->remove(entry))
- onDeleteUnsuccessful();
- }
- }
- refreshView();
- ui->stackedWidget->setCurrentIndex(0);
- ui->aircraftSearchLineEdit->setText(QString());
- }
- /*!
- * \brief Informs the user that deleting a database entry has been unsuccessful
- *
- * \details Normally, when one of these entries can not be deleted, it is because of
- * a [foreign key constraint](https://sqlite.org/foreignkeys.html), meaning that a flight
- * is associated with the aircraft that was supposed to be deleted.
- *
- * This function is used to inform the user and give hints on how to solve the problem.
- */
- void TailsWidget::onDeleteUnsuccessful()
- {
- QList<int> foreign_key_constraints = DB->getForeignKeyConstraints(selectedTails.first(),
- OPL::DbTable::Tails);
- QList<OPL::FlightEntry> constrained_flights;
- for (const auto &row_id : qAsConst(foreign_key_constraints)) {
- constrained_flights.append(DB->getFlightEntry(row_id));
- }
- QMessageBox message_box(this);
- if (constrained_flights.isEmpty()) {
- message_box.setText(tr("<br>Unable to delete.<br><br>The following error has ocurred: %1"
- ).arg(DB->lastError.text()));
- message_box.exec();
- return;
- } else {
- QString constrained_flights_string;
- for (int i=0; i<constrained_flights.length(); i++) {
- constrained_flights_string.append(getFlightSummary(constrained_flights[i]) + QLatin1String(" <br>"));
- if (i>10) {
- constrained_flights_string.append(QLatin1String("<br>[...]<br>"));
- break;
- }
- }
- message_box.setText(tr("Unable to delete.<br><br>"
- "This is most likely the case because a flight exists with the aircraft "
- "you are trying to delete.<br><br>"
- "%1 flight(s) with this aircraft have been found:<br><br><br><b><tt>"
- "%2"
- "</b></tt><br><br>You have to change or remove the conflicting flight(s) "
- "before removing this aircraft from the database.<br><br>"
- ).arg(QString::number(constrained_flights.length()), constrained_flights_string));
- message_box.setIcon(QMessageBox::Critical);
- message_box.exec();
- }
- }
- void TailsWidget::setUiEnabled(bool enabled)
- {
- ui->newAircraftButton->setEnabled(enabled);
- ui->deleteAircraftButton->setEnabled(enabled);
- ui->tableView->setEnabled(enabled);
- ui->aircraftSearchComboBox->setEnabled(enabled);
- ui->aircraftSearchComboBox->setEnabled(enabled);
- }
- void TailsWidget::repopulateModel()
- {
- // unset the current model and delete it to avoid leak
- view->setModel(nullptr);
- delete model;
- // create a new model and populate it
- model = new QSqlTableModel(this);
- setupModelAndView();
- connectSignalsAndSlots();
- }
- const QString TailsWidget::getAircraftTypeString(const OPL::Row &row) const
- {
- QString type_string;
- if (!row.getData().value(OPL::TailEntry::MAKE).toString().isEmpty())
- type_string.append(row.getData().value(OPL::TailEntry::MAKE).toString() + QLatin1Char(' '));
- if (!row.getData().value(OPL::TailEntry::MODEL).toString().isEmpty())
- type_string.append(row.getData().value(OPL::TailEntry::MODEL).toString());
- if (!row.getData().value(OPL::TailEntry::VARIANT).toString().isEmpty())
- type_string.append(QLatin1Char('-') + row.getData().value(OPL::TailEntry::VARIANT).toString());
- return type_string;
- }
- const QString TailsWidget::getFlightSummary(const OPL::FlightEntry &flight) const
- {
- if(!flight.isValid())
- return QString();
- auto tableData = flight.getData();
- QString flight_summary;
- auto space = QLatin1Char(' ');
- flight_summary.append(tableData.value(OPL::FlightEntry::DOFT).toString() + space);
- flight_summary.append(tableData.value(OPL::FlightEntry::DEPT).toString() + space);
- flight_summary.append(OPL::Time(tableData.value(OPL::FlightEntry::TOFB).toInt()).toString()
- + space);
- flight_summary.append(OPL::Time(tableData.value(OPL::FlightEntry::TONB).toInt()).toString()
- + space);
- flight_summary.append(tableData.value(OPL::FlightEntry::DEST).toString());
- return flight_summary;
- }
|