/*
*openPilotLog - A FOSS Pilot Logbook Application
*Copyright (C) 2020-2022 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 "newtaildialog.h"
#include "ui_newtail.h"
#include "src/functions/alog.h"
#include "src/opl.h"
#include "src/database/dbcompletiondata.h"
NewTailDialog::NewTailDialog(const QString &new_registration, QWidget *parent) :
QDialog(parent),
ui(new Ui::NewTail)
{
ui->setupUi(this);
setupCompleter();
setupValidators();
ui->registrationLineEdit->setText(new_registration);
ui->searchLineEdit->setStyleSheet(QStringLiteral("border: 1px solid blue"));
ui->searchLineEdit->setFocus();
//entry = OPL::TailEntry();
}
NewTailDialog::NewTailDialog(int row_id, QWidget *parent) :
QDialog(parent),
ui(new Ui::NewTail)
{
ui->setupUi(this);
ui->searchLabel->hide();
ui->searchLineEdit->hide();
ui->line->hide();
setupValidators();
entry = DB->getTailEntry(row_id);
LOG << "Editing: " << entry;
fillForm(entry, false);
}
NewTailDialog::~NewTailDialog()
{
delete ui;
}
/*!
* \brief NewTail::setupCompleter obtains a QHash for auto completion
* and obtains a QStringList for QCompleter. This function then sets up the search line edit where
* the user can select a template from the aircraft database to pre-fill the form with the details
* for the selected type.
*/
void NewTailDialog::setupCompleter()
{
idMap = OPL::DbCompletionData::getIdMap(OPL::CompleterTarget::AircraftTypes);
aircraftList = OPL::DbCompletionData::getCompletionList(OPL::CompleterTarget::AircraftTypes);
QCompleter *completer = new QCompleter(aircraftList, ui->searchLineEdit);
completer->setCaseSensitivity(Qt::CaseInsensitive);
completer->setCompletionMode(QCompleter::PopupCompletion);
completer->setFilterMode(Qt::MatchContains);
ui->searchLineEdit->setCompleter(completer);
QObject::connect(completer, static_cast(&QCompleter::activated),
this, &NewTailDialog::onSearchCompleterActivated);
QObject::connect(completer, static_cast(&QCompleter::highlighted),
this, &NewTailDialog::onSearchCompleterActivated);
}
void NewTailDialog::setupValidators()
{
const QHash line_edit_validators = {
{QLatin1String("registrationLineEdit"), QRegularExpression(QLatin1String("\\w+-\\w+"))},
{QLatin1String("makeLineEdit"), QRegularExpression(QLatin1String("[-a-zA-Z\\s]+"))},
{QLatin1String("modelLineEdit"), QRegularExpression(QLatin1String("[\\s\\w-]+"))},
{QLatin1String("variantLineEdit"), QRegularExpression(QLatin1String("[\\s\\w-]+"))},
};
QHash::const_iterator i;
for (i = line_edit_validators.constBegin(); i != line_edit_validators.constEnd(); ++i) {
const auto line_edit = this->findChild(i.key());
auto validator = new QRegularExpressionValidator(i.value(), line_edit);
line_edit->setValidator(validator);
}
}
/*!
* \brief NewTailDialog::fillForm populates the Dialog with the
* information contained in an entry object. This can be either
* a template (AircraftEntry, used when creating a new entry) or
* a tail (TailEntry, used when editing an existing entry)
* \param is_template - determines whether we are adding a new entry
* or editing an existing one.
*/
void NewTailDialog::fillForm(OPL::Row entry, bool is_template)
{
DEB << "Filling Form for a/c" << entry;
//fill Line Edits
auto line_edits = this->findChildren();
if (is_template)
line_edits.removeOne(ui->registrationLineEdit);
auto data = entry.getData();
for (const auto &le : qAsConst(line_edits)) {
auto key = le->objectName().remove(QStringLiteral("LineEdit"));
le->setText(data.value(key).toString());
}
ui->operationComboBox->setCurrentIndex(data.value(OPL::Db::TAILS_MULTIPILOT).toInt() + 1);
ui->ppNumberComboBox ->setCurrentIndex(data.value(OPL::Db::TAILS_MULTIENGINE).toInt() + 1);
ui->ppTypeComboBox->setCurrentIndex(data.value(OPL::Db::TAILS_ENGINETYPE).toInt() + 1);
ui->weightComboBox->setCurrentIndex(data.value(OPL::Db::TAILS_WEIGHTCLASS).toInt() + 1);
}
/*!
* \brief NewTail::verify A simple check for empty recommended fields in the form
* \return true if all reconmmended fields are populated
*/
bool NewTailDialog::verify()
{
auto recommended_line_edits = this->findChildren(QStringLiteral("registrationLineEdit"));
recommended_line_edits.append(this->findChild(QStringLiteral("makeLineEdit")));
recommended_line_edits.append(this->findChild(QStringLiteral("modelLineEdit")));
auto recommended_combo_boxes = this->findChildren(QStringLiteral("operationComboBox"));
recommended_combo_boxes.append(this->findChild(QStringLiteral("ppNumberComboBox")));
recommended_combo_boxes.append(this->findChild(QStringLiteral("ppTypeComboBox")));
for (const auto &le : qAsConst(recommended_line_edits)) {
if (le->text() != "") {
DEB << "Good: " << le;
recommended_line_edits.removeOne(le);
le->setStyleSheet("");
} else {
le->setStyleSheet(QStringLiteral("border: 1px solid red"));
DEB << "Not Good: " << le;
}
}
for (const auto &cb : qAsConst(recommended_combo_boxes)) {
if (cb->currentIndex() != 0) {
recommended_combo_boxes.removeOne(cb);
cb->setStyleSheet(QString());
} else {
cb->setStyleSheet(QStringLiteral("background: orange"));
DEB << "Not Good: " << cb;
}
}
if (recommended_line_edits.isEmpty() && recommended_combo_boxes.isEmpty()) {
return true;
} else {
return false;
}
}
/*!
* \brief NewTail::submitForm collects input from Line Edits and creates
* or updates a database entry and commits or updates the database
* \param edRole editExisting or createNew
*/
void NewTailDialog::submitForm()
{
OPL::RowData_T new_data;
//retreive Line Edits
auto line_edits = this->findChildren();
line_edits.removeOne(this->findChild(QStringLiteral("searchLineEdit")));
for (const auto &le : qAsConst(line_edits)) {
auto key = le->objectName().remove(QStringLiteral("LineEdit"));
new_data.insert(key, le->text());
}
if (ui->operationComboBox->currentIndex() != 0) { // bool Multipilot
new_data.insert(OPL::Db::TAILS_MULTIPILOT, ui->operationComboBox->currentIndex() - 1);
}
if (ui->ppNumberComboBox->currentIndex() != 0) { // bool MultiEngine
new_data.insert(OPL::Db::TAILS_MULTIENGINE, ui->ppNumberComboBox->currentIndex() - 1);
}
if (ui->ppTypeComboBox->currentIndex() != 0) { // int 0=unpowered,....4=jet
new_data.insert(OPL::Db::TAILS_ENGINETYPE, ui->ppTypeComboBox->currentIndex() - 1);
}
if (ui->weightComboBox->currentIndex() != 0) { // int 0=light...3=super
new_data.insert(OPL::Db::TAILS_WEIGHTCLASS, ui->weightComboBox->currentIndex() - 1);
}
//create db object
entry.setData(new_data);
LOG << "Commiting: " << entry;
if (!DB->commit(entry)) {
QMessageBox message_box(this);
message_box.setText(tr("The following error has ocurred:"
"
%1
"
"The entry has not been saved."
).arg(DB->lastError.text()));
message_box.exec();
return;
} else {
emit tailDataChanged();
QDialog::accept();
}
}
/// Slots
void NewTailDialog::on_operationComboBox_currentIndexChanged(int index)
{
if (index != 0)
ui->operationComboBox->setStyleSheet(QString());
}
void NewTailDialog::on_ppTypeComboBox_currentIndexChanged(int index)
{
if (index != 0)
ui->ppTypeComboBox->setStyleSheet(QString());
}
void NewTailDialog::on_ppNumberComboBox_currentIndexChanged(int index)
{
if (index != 0)
ui->ppNumberComboBox->setStyleSheet(QString());
}
void NewTailDialog::on_weightComboBox_currentIndexChanged(int index)
{
if (index != 0)
ui->weightComboBox->setStyleSheet(QString());
}
void NewTailDialog::on_buttonBox_accepted()
{
DEB << "Button Box Accepted.";
if (ui->registrationLineEdit->text().isEmpty()) {
QMessageBox message_box(this);
message_box.setText(tr("Registration cannot be empty."));
message_box.exec();
return;
}
if (!verify()) {
QMessageBox message_box(this);
message_box.setIcon(QMessageBox::Warning);
message_box.setText(tr("Some or all recommended fields are empty.
"
"Please fill out the mandatory fields. You can use "
"the search function to automatically fill out all "
"the required fields for a known aircraft type."));
message_box.exec();
return;
}
submitForm();
}
void NewTailDialog::onSearchCompleterActivated()
{
const auto &text = ui->searchLineEdit->text();
if (aircraftList.contains(text)) {
DEB << "Template Selected. aircraft_id is: " << idMap.key(text);
//call autofiller for dialog
fillForm(DB->getAircraftEntry(idMap.key(text)), true);
ui->searchLineEdit->setStyleSheet(QStringLiteral("border: 1px solid green"));
ui->searchLabel->setText(text);
} else {
//for example, editing finished without selecting a result from Qcompleter
ui->searchLineEdit->setStyleSheet(QStringLiteral("border: 1px solid orange"));
}
}
void NewTailDialog::on_registrationLineEdit_textChanged(const QString &arg1)
{
ui->registrationLineEdit->setText(arg1.toUpper());
}