/*
*openPilot Log - A FOSS Pilot Logbook Application
*Copyright (C) 2020 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 .
*/
#include "pilotswidget.h"
#include "ui_pilotswidget.h"
#include "src/testing/adebug.h"
#include "src/database/adatabase.h"
#include "src/classes/apilotentry.h"
PilotsWidget::PilotsWidget(QWidget *parent) :
QWidget(parent),
ui(new Ui::PilotsWidget)
{
ui->setupUi(this);
setupModelAndView();
}
PilotsWidget::~PilotsWidget()
{
delete ui;
}
void PilotsWidget::setupModelAndView()
{
sortColumn = ASettings::read("userdata/pilSortColumn").toInt();
model = new QSqlTableModel(this);
model->setTable("viewPilots");
model->setFilter("ID > 1");//to not allow editing of self, shall be done via settings
model->select();
view = ui->pilotsTableView;
view->setModel(model);
view->setSelectionBehavior(QAbstractItemView::SelectRows);
view->setSelectionMode(QAbstractItemView::SingleSelection);
view->setEditTriggers(QAbstractItemView::NoEditTriggers);
view->horizontalHeader()->setStretchLastSection(QHeaderView::Stretch);
view->hideColumn(0);
view->setColumnWidth(1, 180);
view->setColumnWidth(2, 180);
view->verticalHeader()->hide();
view->setAlternatingRowColors(true);
view->setSortingEnabled(true);
view->sortByColumn(sortColumn, Qt::AscendingOrder);
view->show();
selectionModel = view->selectionModel();
QObject::connect(ui->pilotsTableView->selectionModel(), &QItemSelectionModel::selectionChanged,
this, &PilotsWidget::tableView_selectionChanged);
QObject::connect(ui->pilotsTableView->horizontalHeader(), &QHeaderView::sectionClicked,
this, &PilotsWidget::tableView_headerClicked);
}
void PilotsWidget::on_pilotSearchLineEdit_textChanged(const QString &arg1)
{
model->setFilter("\"" + ui->pilotsSearchComboBox->currentText() + "\" LIKE \"%" + arg1 + "%\" AND ID > 1");
}
void PilotsWidget::onDisplayModel_dataBaseUpdated()
{
//refresh view to reflect changes the user has made via a dialog.
model->select();
}
void PilotsWidget::tableView_selectionChanged()//const QItemSelection &index, const QItemSelection &
{
if (this->findChild() != nullptr) {
DEB("Selection changed. Deleting orphaned dialog.");
delete this->findChild();
/// [F] if the user changes the selection without making any changes,
/// if(selectedPilots.length() == 1) spawns a new dialog without the
/// old one being deleted, since neither accept() nor reject() was emitted.
/// Is this a reasonable way of avoiding pollution? Creating the widgets on the
/// stack does not seem to solve the problem since the Dialog does not get deleted
/// until either accept() or reject() is emitted so I went for this solution.
}
auto *selection = ui->pilotsTableView->selectionModel();
selectedPilots.clear();
for (const auto& row : selection->selectedRows()) {
selectedPilots.append(row.data().toInt());
DEB("Selected Tails(s) with ID: " << selectedPilots);
}
if(selectedPilots.length() == 1) {
NewPilotDialog* np = new NewPilotDialog(selectedPilots.first(), this);
QObject::connect(np, &QDialog::accepted,
this, &PilotsWidget::pilot_editing_finished);
QObject::connect(np, &QDialog::rejected,
this, &PilotsWidget::pilot_editing_finished);
np->setWindowFlag(Qt::Widget);
np->setAttribute(Qt::WA_DeleteOnClose);
ui->stackedWidget->addWidget(np);
ui->stackedWidget->setCurrentWidget(np);
np->exec();
}
}
void PilotsWidget::tableView_headerClicked(int column)
{
sortColumn = column;
ASettings::write("userdata/pilSortColumn", column);
}
void PilotsWidget::on_newPilotButton_clicked()
{
NewPilotDialog* np = new NewPilotDialog(this);
QObject::connect(np, &QDialog::accepted,
this, &PilotsWidget::pilot_editing_finished);
QObject::connect(np, &QDialog::rejected,
this, &PilotsWidget::pilot_editing_finished);
np->setAttribute(Qt::WA_DeleteOnClose);
np->exec();
}
void PilotsWidget::on_deletePilotButton_clicked()
{
if (selectedPilots.length() == 0) {
auto mb = QMessageBox(this);
mb.setText("No Pilot selected.");
mb.exec();
} else if (selectedPilots.length() > 1) {
auto mb = QMessageBox(this);
mb.setText("Deleting multiple entries is currently not supported");
mb.exec();
/// [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 (selectedPilots.length() == 1) {
auto entry = aDB()->getPilotEntry(selectedPilots.first());
auto message_box = QMessageBox(this);
QString message = "You are deleting the following pilot:
";
message.append(entry.name());
message.append(QStringLiteral("
Are you sure?"));
message_box.setText(message);
message_box.exec();
if(!aDB()->remove(entry))
onDeleteUnsuccessful();
}
model->select();
}
void PilotsWidget::onDeleteUnsuccessful()
{
/// [F]: To do: Some logic to display a warning if too many entries exists, so that
/// the messagebox doesn't grow too tall.
QList foreign_key_constraints = aDB()->getForeignKeyConstraints(selectedPilots.first(), ADatabaseTarget::pilots);
QList constrained_flights;
for (const auto &row_id : foreign_key_constraints) {
constrained_flights.append(aDB()->getFlightEntry(row_id));
}
QString message = "
Unable to delete.
";
if(!constrained_flights.isEmpty()){
message.append(QStringLiteral("This is most likely the case because a flight exists with the Pilot "
"you are trying to delete as PIC.
"
"The following flight(s) with this pilot have been found:
"));
for (auto &flight : constrained_flights) {
message.append(flight.summary() + QStringLiteral("
"));
}
}
message.append(QStringLiteral("
You have to change or remove the conflicting flight(s) "
"before removing this pilot from the database.
"));
QMessageBox message_box(this);
message_box.setText(message);
message_box.setIcon(QMessageBox::Critical);
message_box.exec();
}
void PilotsWidget::pilot_editing_finished()
{
model->select();
}