/*
*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 "newflight.h"
#include "ui_newflight.h"
#include
/// =======================================================
/// Debug / WIP section
/// =======================================================
#define DEBUG(expr) \
qDebug() << "~DEBUG" << __func__ << expr
void NewFlight::on_verifyButton_clicked()//debug button
{
//fillExtrasLineEdits();
collectBasicData();
collectAdditionalData();
}
static const auto IATA_RX = QLatin1String("[a-zA-Z0-9]{3}");
static const auto ICAO_RX = QLatin1String("[a-zA-Z0-9]{4}");
static const auto NAME_RX = QLatin1String("(\\p{L}+('|\\-)?)");//(\\p{L}+(\\s|'|\\-)?\\s?(\\p{L}+)?\\s?)
static const auto ADD_NAME_RX = QLatin1String("(\\s?(\\p{L}+('|\\-)?))?");
static const auto SELF_RX = QLatin1String("(self|SELF)");
/// Raw Input validation
static const auto TIME_VALID_RGX = QRegularExpression("([01]?[0-9]|2[0-3]):?[0-5][0-9]?");// We only want to allow inputs that make sense as a time, e.g. 99:99 is not a valid time
static const auto LOC_VALID_RGX = QRegularExpression(IATA_RX + "|" + ICAO_RX);
static const auto AIRCRAFT_VALID_RGX = QRegularExpression("[A-Z0-9]+\\-?[A-Z0-9]+");
static const auto PILOT_NAME_VALID_RGX = QRegularExpression(SELF_RX + QLatin1Char('|')
+ NAME_RX + ADD_NAME_RX + ADD_NAME_RX + ADD_NAME_RX + ",?\\s?" // up to 4 first names
+ NAME_RX + ADD_NAME_RX + ADD_NAME_RX + ADD_NAME_RX );// up to 4 last names
/// Invalid characters (validators keep text even if it returns Invalid, see `onInputRejected` below)
static const auto TIME_INVALID_RGX = QRegularExpression("[^0-9:]");
static const auto LOC_INVALID_RGX = QRegularExpression("[^A-Z0-9]");
static const auto AIRCRAFT_INVALID_RGX = QRegularExpression("[^a-zA-Z0-9\\-]");
static const auto PILOT_NAME_INVALID_RGX = QRegularExpression("[^\\p{L}|\\s|,]");
static const auto INVALID_CHARS_RGX = QRegularExpression("[^\\p{L}|\\s|,|\\-|'|0-9|:]");
/// Sql columns
static const auto LOC_SQL_COL = SqlColumnNum(1); // TODO: locations are iata/icao so 1,2 merge columns in sql?
static const auto AIRCRAFT_SQL_COL = SqlColumnNum(4);
static const auto PILOT_NAME_SQL_COL = SqlColumnNum(6);
/*
* Window Construction
*/
//For adding a new Flight to the logbook
NewFlight::NewFlight(QWidget *parent, Db::editRole edRole) :
QDialog(parent),
ui(new Ui::NewFlight)
{
ui->setupUi(this);
role = edRole;
doUpdate = true;
setup();
//set date for new object
auto date = QDate::currentDate();
ui->doftDateEdit->setDate(date);
// Visually mark mandatory fields
ui->deptLocLineEdit->setStyleSheet("border: 1px solid orange");
ui->destLocLineEdit->setStyleSheet("border: 1px solid orange");
ui->tofbTimeLineEdit->setStyleSheet("border: 1px solid orange");
ui->tonbTimeLineEdit->setStyleSheet("border: 1px solid orange");
ui->picNameLineEdit->setStyleSheet("border: 1px solid orange");
ui->acftLineEdit->setStyleSheet("border: 1px solid orange");
readSettings();
}
//For editing an existing flight
NewFlight::NewFlight(QWidget *parent, Flight oldFlight, Db::editRole edRole) :
QDialog(parent),
ui(new Ui::NewFlight)
{
ui->setupUi(this);
role=edRole;
entry = oldFlight;
doUpdate = true;
setup();
formFiller(oldFlight);
}
NewFlight::~NewFlight()
{
delete ui;
}
void NewFlight::setup(){
auto db = Db::Database();
const auto location_settings = \
LineEditSettings(LOC_VALID_RGX, LOC_INVALID_RGX, LOC_SQL_COL);
const auto aircraft_settings = \
LineEditSettings(AIRCRAFT_VALID_RGX, AIRCRAFT_INVALID_RGX, AIRCRAFT_SQL_COL);
const auto pilot_name_settings = \
LineEditSettings(PILOT_NAME_VALID_RGX, PILOT_NAME_INVALID_RGX, PILOT_NAME_SQL_COL);
const auto time_settings = \
LineEditSettings(TIME_VALID_RGX, TIME_INVALID_RGX, SqlColumnNum());
// Set up Line Edits with QValidators, QCompleters
auto line_edits = ui->flightDataTab->findChildren();
auto le_size = line_edits.size();
for(auto i = 0; i < le_size; ++i){
// auto bit_array = new QBitArray(le_size);
// bit_array->setBit(i, true);
this->lineEditBitMap[line_edits[i]] = i;
}
this->allOkBits.resize(line_edits.size());
this->mandatoryLineEdits = {
ui->deptLocLineEdit,
ui->destLocLineEdit,
ui->tofbTimeLineEdit,
ui->tonbTimeLineEdit,
ui->picNameLineEdit,
ui->acftLineEdit,
};
for(auto line_edit : line_edits)
{
auto le_name = line_edit->objectName();
if(QRegularExpression("Loc").match(le_name).hasMatch()){
setupLineEdit(line_edit, location_settings);
}
else if (QRegularExpression("Time").match(le_name).hasMatch())
{
setupLineEdit(line_edit, time_settings);
}
else if (QRegularExpression("acft").match(le_name).hasMatch())
{
setupLineEdit(line_edit, aircraft_settings);
}
else if (QRegularExpression("Name").match(le_name).hasMatch())
{
setupLineEdit(line_edit, pilot_name_settings);
}
}
//fill Lists
pilots = CompletionList(CompleterTarget::pilots).list;
tails = CompletionList(CompleterTarget::registrations).list;
airports = CompletionList(CompleterTarget::airports).list;
QString statement = "SELECT iata, icao FROM airports";
auto result = Db::customQuery(statement,2);
for(int i=0; iaddButton(ui->IfrCheckBox);
FlightRulesGroup->addButton(ui->VfrCheckBox);
QButtonGroup *PilotTaskGroup = new QButtonGroup(this);
PilotTaskGroup->addButton(ui->PilotFlyingCheckBox);
PilotTaskGroup->addButton(ui->PilotMonitoringCheckBox);
ui->flightDataTabWidget->setCurrentIndex(0);
ui->deptLocLineEdit->setFocus();
}
void NewFlight::formFiller(Flight oldFlight)
{
DEBUG("Filling Line Edits...");
DEBUG("With Data: " << oldFlight.data);
// Date
ui->doftDateEdit->setDate(QDate::fromString(oldFlight.data.value("doft"), Qt::ISODate));
QStringList filled;
// Line Edits
auto line_edits = parent()->findChildren();
QStringList line_edits_names;
for(const auto& le : line_edits){
line_edits_names << le->objectName();
}
const QString& acft = Db::singleSelect("registration", "tails", "tail_id",
oldFlight.data.value("acft"),
Db::exactMatch);
ui->acftLineEdit->setText(acft);
line_edits_names.removeOne("acftLineEdit");
for(const auto& key : oldFlight.data.keys()){
auto rx = QRegularExpression(key + "LineEdit");//acftLineEdit
for(const auto& leName : line_edits_names){
if(rx.match(leName).hasMatch()) {
//DEBUG("Loc Match found: " << key << " - " << leName);
auto le = parent()->findChild(leName);
if(le != nullptr){
le->setText(oldFlight.data.value(key));
filled << leName;
line_edits_names.removeOne(leName);
}
break;
}
}
rx = QRegularExpression(key + "Loc\\w+?");
for(const auto& leName : line_edits_names){
if(rx.match(leName).hasMatch()) {
//DEBUG("Loc Match found: " << key << " - " << leName);
auto le = parent()->findChild(leName);
if(le != nullptr){
le->setText(oldFlight.data.value(key));
filled << leName;
line_edits_names.removeOne(leName);
}
break;
}
}
rx = QRegularExpression(key + "Time\\w+?");
for(const auto& leName : line_edits_names){
if(rx.match(leName).hasMatch()) {
//DEBUG("Time Match found: " << key << " - " << leName);
auto le = parent()->findChild(leName);
if(le != nullptr){
DEBUG("Setting " << le->objectName() << " to " << Calc::minutesToString(oldFlight.data.value(key)));
le->setText(Calc::minutesToString(
oldFlight.data.value(key)));
filled << leName;
line_edits_names.removeOne(leName);
}
break;
}
}
rx = QRegularExpression(key + "Name\\w+?");
for(const auto& leName : line_edits_names){
if(rx.match(leName).hasMatch()) {
//DEBUG("Time Match found: " << key << " - " << leName);
auto le = parent()->findChild(leName);
if(le != nullptr){
const QString& column = "piclastname||', '||picfirstname";
const QString& name = Db::singleSelect(column, "pilots", "pilot_id",
oldFlight.data.value(key),
Db::exactMatch);
le->setText(name);
filled << leName;
line_edits_names.removeOne(leName);
}
break;
}
}
}
//FunctionComboBox
QList FCB = {ui->tPICTimeLineEdit, ui->tPICUSTimeLineEdit, ui->tSICTimeLineEdit,
ui->tDualTimeLineEdit, ui->tFITimeLineEdit};
for(const auto& le : FCB){
if(le->text() != "00:00"){
QString name = le->objectName();
name.chop(12);
name.remove(0,1);
ui->FunctionComboBox->setCurrentText(name);
}
}
// Approach Combo Box
const QString& app = oldFlight.data.value("ApproachType");
if(app != " "){
ui->ApproachComboBox->setCurrentText(app);
}
// Task and Rules
qint8 PF = oldFlight.data.value("pilotFlying").toInt();
if (PF > 0) {
ui->PilotFlyingCheckBox->setChecked(true);
} else {
ui->PilotMonitoringCheckBox->setChecked(true);
}
qint8 FR = oldFlight.data.value("tIFR").toInt();
if (FR > 0) {
ui->IfrCheckBox->setChecked(true);
} else {
ui->tIFRTimeLineEdit->setText("00:00");
ui->VfrCheckBox->setChecked(true);
}
// Take Off and Landing
qint8 TO = oldFlight.data.value("toDay").toInt() + oldFlight.data.value("toNight").toInt();
qint8 LDG = oldFlight.data.value("ldgDay").toInt() + oldFlight.data.value("ldgNight").toInt();
DEBUG("TO and LDG:" << TO << LDG);
if(TO > 0) {
ui->TakeoffCheckBox->setChecked(true);
ui->TakeoffSpinBox->setValue(TO);
} else {
ui->TakeoffCheckBox->setChecked(false);
ui->TakeoffSpinBox->setValue(0);
}
if(LDG > 0) {
ui->LandingCheckBox->setChecked(true);
ui->LandingSpinBox->setValue(LDG);
} else {
ui->LandingCheckBox->setChecked(false);
ui->LandingSpinBox->setValue(0);
}
qint8 AL = oldFlight.data.value("autoland").toInt();
if(AL > 0) {
ui->AutolandCheckBox->setChecked(true);
ui->AutolandSpinBox->setValue(AL);
}
for(const auto& le : mandatoryLineEdits){
emit le->editingFinished();
}
//DEBUG("Filled: ");
//DEBUG(filled);
//DEBUG("Unfilled: ");
//DEBUG(line_edits_names);
}
/*
* ============================================================================
* Functions
* ============================================================================
*/
/*!
* \brief setLineEditValidator set Validators for QLineEdits that end with Time, Loc,
* Aircraft or Name
*/
inline void NewFlight::setupLineEdit(QLineEdit* line_edit, LineEditSettings settings)
{
auto db = QSqlDatabase::database("qt_sql_default_connection");
auto line_edit_objectName = line_edit->objectName();
DEBUG("Setting validators for " << line_edit_objectName);
auto [valid_rgx, invalid_rgx, sql_col] = settings.getAll();
auto validator = new StrictRxValidator(valid_rgx, line_edit);
auto comp_model = new QSqlRelationalTableModel(line_edit, db);
comp_model->database().open();
comp_model->setTable("QCompleterView");
comp_model->select();
auto completer = new QCompleter(comp_model, line_edit);
completer->setCaseSensitivity(Qt::CaseInsensitive);
completer->setCompletionMode(QCompleter::PopupCompletion);
completer->setCompletionColumn(sql_col.column());
completer->setFilterMode(Qt::MatchContains);
/*if(QRegularExpression("\\w+Loc").match(line_edit_objectName).hasMatch()) { completer->setFilterMode(Qt::MatchContains); }
if(QRegularExpression("\\w+Acft").match(line_edit_objectName).hasMatch()) { completer->setFilterMode(Qt::MatchContains); }
if(QRegularExpression("\\w+Name").match(line_edit_objectName).hasMatch()) { completer->setFilterMode(Qt::MatchContains); }*/
line_edit->setValidator(validator);
line_edit->setCompleter(completer);
}
/*!
* \brief NewFlight::writeSettings Writes current selection for auto-logging
* to settings file.
*/
void NewFlight::writeSettings()
{
DEBUG("Writing Settings...");
Settings::write("NewFlight/FunctionComboBox",ui->FunctionComboBox->currentText());
Settings::write("NewFlight/ApproachComboBox",ui->ApproachComboBox->currentText());
Settings::write("NewFlight/PilotFlyingCheckBox",ui->PilotFlyingCheckBox->isChecked());
Settings::write("NewFlight/PilotMonitoringCheckBox",ui->PilotMonitoringCheckBox->isChecked());
Settings::write("NewFlight/TakeoffSpinBox",ui->TakeoffSpinBox->value());
Settings::write("NewFlight/TakeoffCheckBox",ui->TakeoffCheckBox->isChecked());
Settings::write("NewFlight/LandingSpinBox",ui->LandingSpinBox->value());
Settings::write("NewFlight/LandingCheckBox",ui->LandingCheckBox->isChecked());
Settings::write("NewFlight/AutolandSpinBox",ui->AutolandSpinBox->value());
Settings::write("NewFlight/AutolandCheckBox",ui->AutolandCheckBox->isChecked());
Settings::write("NewFlight/IfrCheckBox",ui->IfrCheckBox->isChecked());
Settings::write("NewFlight/VfrCheckBox",ui->VfrCheckBox->isChecked());
}
/*!
* \brief NewFlight::readSettings Retreives auto-logging settings
* and sets up ui accordingly
*/
void NewFlight::readSettings()
{
DEBUG("Reading Settings...");
QSettings settings;
ui->FunctionComboBox->setCurrentText(Settings::read("NewFlight/FunctionComboBox").toString());
ui->ApproachComboBox->setCurrentText(Settings::read("NewFlight/ApproachComboBox").toString());
ui->PilotFlyingCheckBox->setChecked(Settings::read("NewFlight/PilotFlyingCheckBox").toInt());
ui->PilotMonitoringCheckBox->setChecked(Settings::read("NewFlight/PilotMonitoringCheckBox").toInt());
ui->TakeoffSpinBox->setValue(Settings::read("NewFlight/TakeoffSpinBox").toInt());
ui->TakeoffCheckBox->setChecked(Settings::read("NewFlight/TakeoffCheckBox").toInt());
ui->LandingSpinBox->setValue(Settings::read("NewFlight/LandingSpinBox").toInt());
ui->LandingCheckBox->setChecked(Settings::read("NewFlight/LandingCheckBox").toInt());
ui->AutolandSpinBox->setValue(Settings::read("NewFlight/AutolandSpinBox").toInt());
ui->AutolandCheckBox->setChecked(Settings::read("NewFlight/AutolandCheckBox").toInt());
ui->IfrCheckBox->setChecked(Settings::read("NewFlight/IfrCheckBox").toInt());
ui->VfrCheckBox->setChecked(Settings::read("NewFlight/VfrCheckBox").toInt());
ui->FlightNumberLineEdit->setText(Settings::read("flightlogging/flightnumberPrefix").toString());
if(Settings::read("NewFlight/FunctionComboBox").toString() == "PIC"){
ui->picNameLineEdit->setText("self");
ui->secondPilotNameLineEdit->setText("");
}else if (Settings::read("NewFlight/FunctionComboBox").toString() == "Co-Pilot") {
ui->picNameLineEdit->setText("");
ui->secondPilotNameLineEdit->setText("self");
}
}
/*!
* \brief NewFlight::addNewPilotMessageBox If the user input is not in the pilotNameList, the user
* is prompted if he wants to add a new entry to the database
*/
void NewFlight::addNewPilotMessageBox(QLineEdit *parent)
{
QMessageBox::StandardButton reply;
reply = QMessageBox::question(this, "No Pilot found",
"No pilot found.
Please enter the Name as"
"
Lastname, Firstname
"
"If this is the first time you log a flight with this pilot, you have to "
"add the name to the database first.
Would you like to add a new pilot to the database?",
QMessageBox::Yes|QMessageBox::No);
if (reply == QMessageBox::Yes)
{
qDebug() << "Add new pilot selected";
// create and open new pilot dialog
auto np = NewPilot(Db::createNew, this);
np.exec();
QString statement = "SELECT MAX(pilot_id) FROM pilots";
QString id = Db::customQuery(statement,1).first();
Pilot newPilot = Pilot(id.toInt());
parent->setText(newPilot.data.value("displayname"));
emit parent->editingFinished();
}
}
/*!
* \brief NewFlight::addNewAircraftMessageBox If the user input is not in the aircraftList, the user
* is prompted if he wants to add a new entry to the database
*/
void NewFlight::addNewAircraftMessageBox(QLineEdit *parent)
{
QMessageBox::StandardButton reply;
reply = QMessageBox::question(this, "No Aircraft found",
"No aircraft with this registration found.
"
"If this is the first time you log a flight with this aircraft, you have to "
"add the registration to the database first.
Would you like to add a new aircraft to the database?",
QMessageBox::Yes|QMessageBox::No);
if (reply == QMessageBox::Yes)
{
DEBUG("Add new aircraft selected");
// create and open new aircraft dialog
auto na = NewTail(ui->acftLineEdit->text(), Db::createNew, this);
na.exec();
QString statement = "SELECT MAX(tail_id) FROM tails";
QString id = Db::customQuery(statement,1).first();
auto newAcft = Aircraft(id.toInt());
parent->setText(newAcft.data.value("registration"));
emit parent->editingFinished();
}
}
/// Input Verification and Collection
/*!
* \brief NewFlight::update check if needed inputs are available and update form
*/
void NewFlight::update()
{
if(doUpdate){
QVector notFilled;
for(auto lineEdit : mandatoryLineEdits)
{
if(!allOkBits.testBit(lineEditBitMap[lineEdit]))
{
notFilled.push_back(lineEdit);
}
}
if(notFilled.empty()){
collectBasicData();
fillExtras();
} else {
DEBUG("No update - not enough variables known.");
}
}
}
/*!
* \brief NewFlight::collectBasicInput After mandatory inputs have passed
* validation, collect values from line edits and combo boxes to create new Data
* for flight object.
*/
void NewFlight::collectBasicData()
{
// purge old data to ensure database integrity
newData.clear();
DEBUG("Collecting Basic Input...");
// Date of Flight
auto date = ui->doftDateEdit->date();
auto doft = date.toString(Qt::ISODate);
newData.insert("doft",doft);
// Departure Loc
newData.insert("dept",ui->deptLocLineEdit->text());
// Time Off Blocks
auto timeOff = QTime::fromString(ui->tofbTimeLineEdit->text(),"hh:mm");
if(timeOff.isValid()){
int tofb = timeOff.hour() * 60 + timeOff.minute();
newData.insert("tofb",QString::number(tofb));
}
// Destination Loc
newData.insert("dest",ui->destLocLineEdit->text());
// Time On Blocks
auto timeOn = QTime::fromString(ui->tonbTimeLineEdit->text(),"hh:mm");
if(timeOn.isValid()){
int tonb = timeOn.hour() * 60 + timeOn.minute();
newData.insert("tonb",QString::number(tonb));
}
//Block Time
auto tofb = QTime::fromString(ui->tofbTimeLineEdit->text(),"hh:mm");
auto tonb = QTime::fromString(ui->tonbTimeLineEdit->text(),"hh:mm");
QString blockTime = Calc::blocktime(tofb, tonb).toString("hh:mm");
QString blockMinutes = QString::number(Calc::stringToMinutes(blockTime));
newData.insert("tblk",blockMinutes);
// Aircraft
QString reg = ui->acftLineEdit->text();
QString acft = Db::singleSelect("tail_id","tails","registration",reg,Db::exactMatch);
if(!acft.isEmpty()){
newData.insert("acft",acft);
} else {
emit ui->acftLineEdit->inputRejected();
}
// Pilot
if(ui->picNameLineEdit->text() == "self" || ui->picNameLineEdit->text() == "self"){
newData.insert("pic","1");
} else {
QString name = ui->picNameLineEdit->text();
QStringList names = name.split(',');
if(names.length()==2){
QString firstNames = names[1].simplified();
QString lastNames = names[0].simplified();
QString query = "SELECT pilot_id FROM pilots WHERE piclastname = \"" + lastNames
+ "\" AND picfirstname = \"" + firstNames + "\"";
QVector pic = Db::customQuery(query,1);
if(!pic.isEmpty()){
newData.insert("pic",pic.first());
}else {
emit ui->picNameLineEdit->inputRejected();
}
}
}
}
void NewFlight::collectAdditionalData()
{
// Pilot 2
if(!ui->secondPilotNameLineEdit->text().isEmpty()){
if(ui->secondPilotNameLineEdit->text() == "self" || ui->secondPilotNameLineEdit->text() == "self"){
newData.insert("secondPilot","1");
} else {
QString name = ui->secondPilotNameLineEdit->text();
QStringList names = name.split(',');
if(names.length()==2){
QString firstNames = names[1].simplified();
QString lastNames = names[0].simplified();
QString query = "SELECT pilot_id FROM pilots WHERE piclastname = \"" + lastNames
+ "\" AND picfirstname = \"" + firstNames + "\"";
QVector pic = Db::customQuery(query,1);
if(!pic.isEmpty()){
newData.insert("secondPilot",pic.first());
}else {
emit ui->secondPilotNameLineEdit->inputRejected();
}
}
}
}
// Pilot 3
if(!ui->thirdPilotNameLineEdit->text().isEmpty()){
if(ui->thirdPilotNameLineEdit->text() == "self" || ui->thirdPilotNameLineEdit->text() == "self"){
newData.insert("thirdPilot","1");
} else {
QString name = ui->thirdPilotNameLineEdit->text();
QStringList names = name.split(',');
if(names.length()==2){
QString firstNames = names[1].simplified();
QString lastNames = names[0].simplified();
QString query = "SELECT pilot_id FROM pilots WHERE piclastname = \"" + lastNames
+ "\" AND picfirstname = \"" + firstNames + "\"";
QVector pic = Db::customQuery(query,1);
if(!pic.isEmpty()){
newData.insert("thirdPilot",pic.first());
}else {
emit ui->thirdPilotNameLineEdit->inputRejected();
}
}
}
}
// Extra Times
auto tofb = QTime::fromString(ui->tofbTimeLineEdit->text(),"hh:mm");
auto tonb = QTime::fromString(ui->tonbTimeLineEdit->text(),"hh:mm");
QString blockTime = Calc::blocktime(tofb, tonb).toString("hh:mm");
QString blockMinutes = QString::number(Calc::stringToMinutes(blockTime));
auto acft = Aircraft(newData.value("acft").toInt());
if(!acft.data.isEmpty()){// valid aircraft
// SP SE
if(acft.data.value("singlepilot") == "1" && acft.data.value("singleengine") == "1"){
newData.insert("tSPSE", blockMinutes);
newData.insert("tSPME", "");
newData.insert("tMP", "");
}
// SP ME
if(acft.data.value("singlepilot") == "1" && acft.data.value("multiengine") == "1"){
newData.insert("tSPSE", "");
newData.insert("tSPME", blockMinutes);
newData.insert("tMP", "");
}
// MP
if(acft.data.value("multipilot") == "1"){
newData.insert("tSPSE", "");
newData.insert("tSPME", "");
newData.insert("tMP", blockMinutes);
}
}else{DEBUG("Aircraft Details Empty");}//invalid aircraft
// IFR
if(ui->IfrCheckBox->isChecked()){
newData.insert("tIFR",blockMinutes);
} else {
newData.insert("tIFR","");
}
// Night
QString deptDate = ui->doftDateEdit->date().toString(Qt::ISODate) + 'T' + tofb.toString("hh:mm");
QDateTime deptDateTime = QDateTime::fromString(deptDate,"yyyy-MM-ddThh:mm");
int tblk = blockMinutes.toInt();
const int nightAngle = Settings::read("flightlogging/nightangle").toInt();
QString nightTime = QString::number(
Calc::calculateNightTime(
newData.value("dept"), newData.value("dest"),
deptDateTime, tblk, nightAngle));
newData.insert("tNIGHT", nightTime);
// Function times
switch (ui->FunctionComboBox->currentIndex()) {
case 0://PIC
newData.insert("tPIC", blockMinutes);
newData.insert("tPICUS", "");
newData.insert("tSIC", "");
newData.insert("tDual", "");
newData.insert("tFI", "");
break;
case 1://PICUS
newData.insert("tPIC", "");
newData.insert("tPICUS", blockMinutes);
newData.insert("tSIC", "");
newData.insert("tDual", "");
newData.insert("tFI", "");
break;
case 2://Co-Pilot
newData.insert("tPIC", "");
newData.insert("tPICUS", "");
newData.insert("tSIC", blockMinutes);
newData.insert("tDual", "");
newData.insert("tFI", "");
break;
case 3://Dual
newData.insert("tPIC", "");
newData.insert("tPICUS", "");
newData.insert("tSIC", "");
newData.insert("tDual", blockMinutes);
newData.insert("tFI", "");
break;
case 4://Instructor
newData.insert("tPIC", "");
newData.insert("tPICUS", "");
newData.insert("tSIC", "");
newData.insert("tDual", "");
newData.insert("tFI", blockMinutes);
}
// Pilot Flying
newData.insert("pilotFlying", QString::number(ui->PilotFlyingCheckBox->isChecked()));
// TO and LDG
if(ui->TakeoffCheckBox->isChecked()) {
if(nightTime == "0"){ // all day
newData.insert("toDay", QString::number(ui->TakeoffSpinBox->value()));
newData.insert("toNight", "0");
}else if (nightTime == blockTime) { // all night
newData.insert("toDay", "0");
newData.insert("toNight", QString::number(ui->TakeoffSpinBox->value()));
} else { //check
if(Calc::isNight(ui->deptLocLineEdit->text(), deptDateTime, nightAngle)){
newData.insert("toDay", "0");
newData.insert("toNight", QString::number(ui->TakeoffSpinBox->value()));
}else{
newData.insert("toDay", QString::number(ui->TakeoffSpinBox->value()));
newData.insert("toNight", "0");
}
}
} else {
newData.insert("toDay", "0");
newData.insert("toNight", "0");
}
if(ui->LandingCheckBox->isChecked()) {
if(nightTime == "0"){ // all day
newData.insert("ldgDay", QString::number(ui->LandingSpinBox->value()));
newData.insert("ldgNight", "0");
}else if (nightTime == blockTime) { // all night
newData.insert("ldgDay", "0");
newData.insert("ldgNight", QString::number(ui->LandingSpinBox->value()));
} else { //check
QString destDate = ui->doftDateEdit->date().toString(Qt::ISODate) + 'T' + tonb.toString("hh:mm");
QDateTime destDateTime = QDateTime::fromString(destDate,"yyyy-MM-ddThh:mm");
if(Calc::isNight(ui->destLocLineEdit->text(), destDateTime, nightAngle)){
newData.insert("ldgDay", "0");
newData.insert("ldgNight", QString::number(ui->LandingSpinBox->value()));
}else{
newData.insert("ldgDay", QString::number(ui->LandingSpinBox->value()));
newData.insert("ldgNight", "0");
}
}
} else {
newData.insert("ldgDay", "0");
newData.insert("ldgNight", "0");
}
newData.insert("autoland", QString::number(ui->AutolandSpinBox->value()));
newData.insert("ApproachType", ui->ApproachComboBox->currentText());
newData.insert("FlightNumber", ui->FlightNumberLineEdit->text());
newData.insert("Remarks", ui->RemarksLineEdit->text());
}
/*!
* \brief NewFlight::fillExtrasLineEdits Fills the deductable items in the newData map and
* additional flight time line edits according to ui selections.
* Neccessary prerequisites are valid Date, Departure Time and Place, Destination Time and Place,
* PIC name (pilot_id) and Aircraft (tail_id)
*/
void NewFlight::fillExtras()
{
//zero labels and line edits
QList LE = {ui->tSPSETimeLineEdit, ui->tSPMETimeLineEdit, ui->tMPTimeLineEdit, ui->tIFRTimeLineEdit,
ui->tNIGHTTimeLineEdit,ui->tPICTimeLineEdit, ui->tPICUSTimeLineEdit, ui->tSICTimeLineEdit,
ui->tDualTimeLineEdit, ui->tFITimeLineEdit,};
QList LB = {ui->tSPSELabel, ui->tSPMELabel, ui->tMPLabel, ui->tIFRLabel, ui->tNIGHTLabel,
ui->tPICLabel, ui->tPICUSLabel, ui->tSICLabel, ui->tDualLabel, ui->tFILabel};
for(const auto& widget : LE) {widget->setText("");}
for(const auto& widget : LB) {widget->setText("00:00");}
//Times
auto tofb = QTime::fromString(ui->tofbTimeLineEdit->text(),"hh:mm");
auto tonb = QTime::fromString(ui->tonbTimeLineEdit->text(),"hh:mm");
QString blockTime = Calc::blocktime(tofb, tonb).toString("hh:mm");
QString blockMinutes = QString::number(Calc::stringToMinutes(blockTime));
ui->tblkTimeLineEdit->setText(blockTime);
auto acft = Aircraft(newData.value("acft").toInt());
if(!acft.data.isEmpty()){// valid aircraft
// SP SE
if(acft.data.value("singlepilot") == "1" && acft.data.value("singleengine") == "1"){
ui->tSPSETimeLineEdit->setText(blockTime);
ui->tSPSELabel->setText(blockTime);
}
// SP ME
if(acft.data.value("singlepilot") == "1" && acft.data.value("multiengine") == "1"){
ui->tSPMETimeLineEdit->setText(blockTime);
ui->tSPMELabel->setText(blockTime);
}
// MP
if(acft.data.value("multipilot") == "1"){
ui->tMPTimeLineEdit->setText(blockTime);
ui->tMPLabel->setText(blockTime);
}
}else{DEBUG("Aircraft Details Empty");}//invalid aircraft
// TOTAL
ui->tblkLabel->setText("" + blockTime + "");
ui->tblkLabel->setStyleSheet("color: green;");
// IFR
if(ui->IfrCheckBox->isChecked()){
ui->tIFRTimeLineEdit->setText(blockTime);
ui->tIFRLabel->setText(blockTime);
}
// Night
QString deptDate = ui->doftDateEdit->date().toString(Qt::ISODate) + 'T' + tofb.toString("hh:mm");
QDateTime deptDateTime = QDateTime::fromString(deptDate,"yyyy-MM-ddThh:mm");
int tblk = blockMinutes.toInt();
const int nightAngle = Settings::read("flightlogging/nightangle").toInt();
QString nightTime = QString::number(
Calc::calculateNightTime(
newData.value("dept"), newData.value("dest"),
deptDateTime, tblk, nightAngle));
ui->tNIGHTTimeLineEdit->setText(Calc::minutesToString(nightTime));
ui->tNIGHTLabel->setText(Calc::minutesToString(nightTime));
// Function times
switch (ui->FunctionComboBox->currentIndex()) {
case 0://PIC
ui->tPICTimeLineEdit->setText(blockTime);
ui->tPICLabel->setText(blockTime);
break;
case 1://PICus
ui->tPICUSTimeLineEdit->setText(blockTime);
ui->tPICUSLabel->setText(blockTime);
break;
case 2://Co-Pilot
ui->tSICTimeLineEdit->setText(blockTime);
ui->tSICLabel->setText(blockTime);
break;
case 3://Dual
ui->tDualTimeLineEdit->setText(blockTime);
ui->tDualLabel->setText(blockTime);
break;
case 4://Instructor
ui->tFITimeLineEdit->setText(blockTime);
ui->tFILabel->setText(blockTime);
}
}
bool NewFlight::verifyInput()
{
QVector notFilled;
for(auto lineEdit : mandatoryLineEdits)
{
if(!allOkBits.testBit(lineEditBitMap[lineEdit]))
{
notFilled.push_back(lineEdit);
}
}
if(!notFilled.empty()){
QMessageBox notFilledMessageBox(this);
auto errorMsg = QString("Not all required fields are filled out.\n\n"
"Plase make sure the following are not empty:\n\n"
"Departure\nDestination\nTime Off Blocks\nTime On Blocks\n"
"Pilot in Command\nAircraft Registration\n\n");
notFilledMessageBox.setText(errorMsg);
notFilledMessageBox.exec();
return false;
} else {
QStringList lineEditText;
for(auto line_edit : mandatoryLineEdits)
{
lineEditText.push_back(line_edit->text());
}
this->result = lineEditText;
emit mandatoryFieldsValid(this);
return true;
}
}
/*!
* ============================================================================
* ============================================================================
* Slots
* ============================================================================
* ============================================================================
*/
void NewFlight::on_buttonBox_accepted()
{
DEBUG("OK pressed");
if(verifyInput()){
DEBUG("Input verified");
collectBasicData();
collectAdditionalData();
switch (role) {
case Db::editExisting:
entry.setData(newData);
DEBUG("Editing entry: " << entry.position.first << " - " << entry.position.second);
DEBUG("with Data: " << newData);
DEBUG("Function Times: " << newData.value("tPIC") << newData.value("tPICus") << newData.value("tSIC")
<< newData.value("tDual") << newData.value("tFI"));
break;
case Db::createNew:
entry = Flight(newData);
DEBUG("Creating New entry: " << entry.position.first << " - " << entry.position.second);
DEBUG("with Data: " << newData);
break;
}
if(entry.commit()){
accept();
}else{
auto mb = new QMessageBox(this);
auto errorMsg = QString("Unable to commit Flight to Logbook."
"The following error has ocurred:\n\n");
errorMsg.append(entry.error);
mb->setText(errorMsg);
mb->show();
}
}
}
void NewFlight::on_buttonBox_rejected()
{
DEBUG("CANCEL pressed." << newData);
reject();
}
/*!
* \brief onInputRejected Set `line_edit`'s border to red and check if `rgx` matches
* in order to keep text on line. Ensures corresponding LineEdit bit is 0. Only
* valid characters are kept on the line edit.
*/
void NewFlight::onInputRejected(QLineEdit* line_edit, QRegularExpression rgx){
//DEBUG("Input rejected" << line_edit->text());
line_edit->setStyleSheet("border: 1px solid red");
this->allOkBits.setBit(this->lineEditBitMap[line_edit], false);
auto text = line_edit->text();
if(!rgx.match(text).hasMatch())
{
line_edit->setText(text);
}
if(INVALID_CHARS_RGX.match(text).hasMatch()){//remove globaly inacceptable chars
text.chop(1);
line_edit->setText(text);
}
}
/*!
* \brief onEditingFinishedCleanup resets styles and sets the corresponding bit to 1
*/
void NewFlight::onEditingFinishedCleanup(QLineEdit* line_edit)
{
//DEBUG("Input accepted" << line_edit << line_edit->text());
line_edit->setStyleSheet("");
this->allOkBits.setBit(this->lineEditBitMap[line_edit], true);
}
QStringList* NewFlight::getResult() { return &this->result; }
void NewFlight::on_deptTZ_currentTextChanged(const QString &arg1)
{
DEBUG(arg1);
// currently only UTC time logging is supported
ui->deptTZ->setCurrentIndex(0);
}
void NewFlight::on_destTZ_currentIndexChanged(const QString &arg1)
{
DEBUG(arg1);
// currently only UTC time logging is supported
ui->destTZ->setCurrentIndex(0);
}
/// Departure
void NewFlight::on_deptLocLineEdit_inputRejected()
{
//DEBUG("SENDER --->" << sender());
ui->deptLocLineEdit->setText(ui->deptLocLineEdit->text().toUpper());
onInputRejected(ui->deptLocLineEdit, QRegularExpression(LOC_INVALID_RGX));
}
void NewFlight::on_deptLocLineEdit_textEdited(const QString &arg1)
{
ui->deptLocLineEdit->setText(arg1.toUpper());
}
void NewFlight::on_deptLocLineEdit_editingFinished()
{
//DEBUG(sender()->objectName() << "EDITING FINISHED");
auto line_edit = ui->deptLocLineEdit;
auto text = ui->deptLocLineEdit->text();
// check if iata exists, replace with icao code if it does.
if(text.length() == 3){
text = airportMap.value(text);
}
// Check if 4-letter code is in locationList
if(text.length() == 4 && airports.indexOf(text) == -1){
//DEBUG("Airport not found.");
emit line_edit->inputRejected();
return;
}else{
//DEBUG("Departure accepted: " << text);
line_edit->setText(text);
onEditingFinishedCleanup(line_edit); //reset style sheet
ui->deptNameLabel->setText(Db::singleSelect("name","airports","icao",text,Db::exactMatch));
update();
}
}
void NewFlight::on_tofbTimeLineEdit_inputRejected()
{
onInputRejected(ui->tofbTimeLineEdit, QRegularExpression(TIME_INVALID_RGX));
}
void NewFlight::on_tofbTimeLineEdit_editingFinished()
{
ui->tofbTimeLineEdit->setText(Calc::formatTimeInput(ui->tofbTimeLineEdit->text()));
const auto time = QTime::fromString(ui->tofbTimeLineEdit->text(),"hh:mm");
auto line_edit = ui->tofbTimeLineEdit;
onEditingFinishedCleanup(line_edit);
if(time.isValid()){
int minutes = time.hour() * 60 + time.minute();
QString tofb = QString::number(minutes);
//DEBUG("Time Off Blocks accepted: " << tofb << " minutes - " << Calc::minutesToString(tofb));
}else{
emit line_edit->inputRejected();
}
onEditingFinishedCleanup(line_edit);
update();
}
/// Destination
void NewFlight::on_destLocLineEdit_inputRejected()
{
ui->destLocLineEdit->setText(ui->destLocLineEdit->text().toUpper());
onInputRejected(ui->destLocLineEdit, QRegularExpression(LOC_INVALID_RGX));
}
void NewFlight::on_destLocLineEdit_textEdited(const QString &arg1)
{
ui->destLocLineEdit->setText(arg1.toUpper());
}
void NewFlight::on_destLocLineEdit_editingFinished()
{
//DEBUG(sender()->objectName() << "EDITING FINISHED");
auto line_edit = ui->destLocLineEdit;
auto text = ui->destLocLineEdit->text();
// check if iata exists, replace with icao code if it does.
if(text.length() == 3){
text = airportMap.value(text);
}
// Check if 4-letter code is in locationList
if(text.length() == 4 && airports.indexOf(text) == -1){
//DEBUG("Airport not found.");
emit line_edit->inputRejected();
return;
}else{
//DEBUG("Destination accepted: " << text);
line_edit->setText(text);
onEditingFinishedCleanup(line_edit); //reset style sheet
ui->destNameLabel->setText(Db::singleSelect("name","airports","icao",text,Db::exactMatch));
update();
}
}
void NewFlight::on_tonbTimeLineEdit_inputRejected()
{
onInputRejected(ui->tonbTimeLineEdit, QRegularExpression(TIME_INVALID_RGX));
}
void NewFlight::on_tonbTimeLineEdit_editingFinished()
{
ui->tonbTimeLineEdit->setText(Calc::formatTimeInput(ui->tonbTimeLineEdit->text()));
auto line_edit = ui->tonbTimeLineEdit;
const auto time = QTime::fromString(ui->tonbTimeLineEdit->text(),"hh:mm");
if(time.isValid()){
int minutes = time.hour() * 60 + time.minute();
QString tonb = QString::number(minutes);
newData.insert("tonb",tonb);
//DEBUG("Time On Blocks accepted: " << tonb << " minutes - " << Calc::minutesToString(tonb));
}else{
emit line_edit->inputRejected();
}
onEditingFinishedCleanup(line_edit);
update();
}
/// Date
void NewFlight::on_doftTimeEdit_editingFinished()
{
update();
}
/// Aircraft
void NewFlight::on_acftLineEdit_inputRejected()
{
ui->acftLineEdit->setText(ui->acftLineEdit->text().toUpper());
onInputRejected(ui->acftLineEdit, QRegularExpression(AIRCRAFT_INVALID_RGX));
}
void NewFlight::on_acftLineEdit_editingFinished()
{
auto registrationList = CompletionList(CompleterTarget::registrations).list;
auto line_edit = ui->acftLineEdit;
auto text = ui->acftLineEdit->text();
QStringList match = registrationList.filter(line_edit->text(), Qt::CaseInsensitive);
//DEBUG("aircraft accepted: " << match);
if(match.length() != 0) {
text = match[0];
line_edit->setText(text.toUpper());
onEditingFinishedCleanup(line_edit);
QString column = "make||' '||model||'-'||variant";
ui->acftTypeLabel->setText(
Db::singleSelect(column,"tails","registration",text,Db::exactMatch));
update();
}else{
emit line_edit->inputRejected();
addNewAircraftMessageBox(line_edit);
}
}
/// Pilot(s)
void NewFlight::on_picNameLineEdit_inputRejected()
{
onInputRejected(ui->picNameLineEdit, QRegularExpression(PILOT_NAME_INVALID_RGX));
}
void NewFlight::on_picNameLineEdit_editingFinished()
{
auto line_edit = ui->picNameLineEdit;
auto text = line_edit->text();
if(text == "self" || text == "SELF") // Logbook owner is PIC
{
//DEBUG("Pilot selected: " << text);
onEditingFinishedCleanup(line_edit);
ui->FunctionComboBox->setCurrentIndex(0);
update();
return;
}else //check if entry is in pilotList
{
QStringList pilotList = CompletionList(CompleterTarget::pilots).list;
QStringList match = pilotList.filter(line_edit->text().remove(" "), Qt::CaseInsensitive);
if(match.length()!= 0)
{
QString pic = match[0];
line_edit->setText(pic.insert(pic.indexOf(',')+1," "));
//DEBUG("Pilot selected: " << pic);
onEditingFinishedCleanup(line_edit);
update();
}else
{
DEBUG("Pilot not found.");
emit line_edit->inputRejected();
addNewPilotMessageBox(line_edit);
}
}
}
/*
* ============================================================================
* The above entris are mandatory for logging a flight,
* the rest of the entries are either optional or can
* be determined from the entries already made.
* ============================================================================
*/
void NewFlight::on_secondPilotNameLineEdit_inputRejected()
{
onInputRejected(ui->secondPilotNameLineEdit, QRegularExpression(PILOT_NAME_INVALID_RGX));
}
void NewFlight::on_secondPilotNameLineEdit_editingFinished()
{
auto line_edit = ui->secondPilotNameLineEdit;
auto text = line_edit->text();
if(text == "self" || text == "SELF") // Logbook owner is Pilot
{
//DEBUG("Pilot selected: " << text);
onEditingFinishedCleanup(line_edit);
ui->FunctionComboBox->setCurrentIndex(1);
return;
}else //check if entry is in pilotList
{
QStringList pilotList = CompletionList(CompleterTarget::pilots).list;
QStringList match = pilotList.filter(line_edit->text().remove(" "), Qt::CaseInsensitive);
if(match.length()!= 0)
{
QString pic = match[0];
line_edit->setText(pic.insert(pic.indexOf(',')+1," "));
//DEBUG("Pilot selected: " << pic);
onEditingFinishedCleanup(line_edit);
}else
{
DEBUG("Pilot not found.");
emit line_edit->inputRejected();
addNewPilotMessageBox(line_edit);
}
}
}
void NewFlight::on_thirdPilotNameLineEdit_inputRejected()
{
onInputRejected(ui->thirdPilotNameLineEdit, QRegularExpression(PILOT_NAME_INVALID_RGX));
}
void NewFlight::on_thirdPilotNameLineEdit_editingFinished()
{
auto line_edit = ui->thirdPilotNameLineEdit;
auto text = line_edit->text();
if(text == "self" || text == "SELF") // Logbook owner is Pilot
{
//DEBUG("Pilot selected: " << text);
onEditingFinishedCleanup(line_edit);
return;
}else //check if entry is in pilotList
{
QStringList pilotList = CompletionList(CompleterTarget::pilots).list;
QStringList match = pilotList.filter(line_edit->text().remove(" "), Qt::CaseInsensitive);
if(match.length()!= 0)
{
QString pic = match[0];
line_edit->setText(pic.insert(pic.indexOf(',')+1," "));
//DEBUG("Pilot selected: " << pic);
onEditingFinishedCleanup(line_edit);
}else
{
DEBUG("Pilot not found.");
emit line_edit->inputRejected();
addNewPilotMessageBox(line_edit);
}
}
}
void NewFlight::on_FlightNumberLineEdit_textChanged(const QString &arg1)
{
ui->FlightNumberLineEdit->setText(arg1.toUpper());
}
/*
* ============================================================================
* Extras Tab - These are for user convenience. From many of
* these selections, determinations can be made on how to log
* details, so that the user does not have to enter each item
* manually. See also fillExtrasLineEdits()
* ============================================================================
*/
void NewFlight::on_setAsDefaultButton_clicked()
{
writeSettings();
}
void NewFlight::on_restoreDefaultButton_clicked()
{
readSettings();
}
/*!
* \brief On a given flight, time can either be logged as Pilot Flying (PF) or
* Pilot Monitoring (PM). Cases where controls are changed during the flight
* are rare and can be logged by manually editing the extras.
*/
void NewFlight::on_PilotFlyingCheckBox_stateChanged(int)
{
DEBUG("PF checkbox state changed.");
if(ui->PilotFlyingCheckBox->isChecked()){
ui->TakeoffSpinBox->setValue(1);
ui->TakeoffCheckBox->setCheckState(Qt::Checked);
ui->LandingSpinBox->setValue(1);
ui->LandingCheckBox->setCheckState(Qt::Checked);
}else if(!ui->PilotFlyingCheckBox->isChecked()){
ui->TakeoffSpinBox->setValue(0);
ui->TakeoffCheckBox->setCheckState(Qt::Unchecked);
ui->LandingSpinBox->setValue(0);
ui->LandingCheckBox->setCheckState(Qt::Unchecked);
}
}
void NewFlight::on_IfrCheckBox_stateChanged()
{
update();
}
void NewFlight::on_ApproachComboBox_currentTextChanged(const QString &arg1)
{
if(arg1 == "ILS CAT III"){ //for a CAT III approach an Autoland is mandatory, so we can preselect it.
ui->AutolandCheckBox->setCheckState(Qt::Checked);
ui->AutolandSpinBox->setValue(1);
}else{
ui->AutolandCheckBox->setCheckState(Qt::Unchecked);
ui->AutolandSpinBox->setValue(0);
}
}
/*
* Extra Times - These line edits should be filled out automatically,
* based on the ui selections and the user provided input. However,
* manual adjustments are possible to cater for situations where for
* example one portion of the flight is logged under different rules
* than the rest of it.
*
* For example,
* if we know the aircraft details we can determine how to log these times.
* Some times are mutually exclusive, others can be combined.
*
* For example,
* for a commercial Passenger flight, the commander can log all time as
* Total Time and PIC time. If the aircraft is a multi-engine jet he can
* also log Multi-Pilot time, and if he is an instructor, instructor time.
*
* It is not possible, however to log flight time as VFR or IFR time
* simultaneously, as a flight at any given point in time can only follow
* one set of rules. It is possible, to change flight rules and log the first
* x minutes as VFR and the rest of it as IFR, for example. Hence the need
* for the possibility to edit these times manually.
*
* The most complex time to determine is night time, see documentation of
* the calc class for details.
*
* In General, the idea is to automatically fill as much as possible, but
* if the user decides to change these times, accept the inputs, as long as
* they are generally valid. We cannot cater for all possibilities, so as long
* as the time the user has put in is a valid time <= Total Time, it can be
* accepted to the database.
*/
inline bool NewFlight::isLessOrEqualToTotalTime(QString timeString)
{
if(newData.value("tblk").isEmpty()){
DEBUG("Total Time not set.");
auto mb = new QMessageBox(this);
mb->setText("Please fill out Departure and Arrival Time\n"
"before manually editing these times.");
mb->show();
return false;
} else {
int minutes = Calc::stringToMinutes(timeString);
if (minutes <= newData.value("tblk").toInt()) {
return true;
} else {
auto mb = new QMessageBox(this);
mb->setText("Cannot be more than Total Time of Flight:
"
+ Calc::minutesToString(newData.value("tblk"))
+ "
");
mb->show();
return false;
}
}
}
void NewFlight::on_tblkTimeLineEdit_editingFinished()
{
const auto &le = ui->tblkTimeLineEdit;
le->setText(Calc::formatTimeInput(le->text()));
const auto &text = le->text();
newData.insert("tblk",QString::number(Calc::stringToMinutes(text)));
le->setText(QString());
}
void NewFlight::on_tSPSETimeLineEdit_editingFinished()
{
const auto &le = ui->tSPSETimeLineEdit;
le->setText(Calc::formatTimeInput(le->text()));
const auto &text = le->text();
if(isLessOrEqualToTotalTime(text)){
newData.insert("tSPSE",QString::number(Calc::stringToMinutes(text)));
} else {
le->setText(QString());
}
}
void NewFlight::on_tSPMETimeLineEdit_editingFinished()
{
const auto &le = ui->tSPMETimeLineEdit;
le->setText(Calc::formatTimeInput(le->text()));
const auto &text = le->text();
if(isLessOrEqualToTotalTime(text)){
newData.insert("tSPME",QString::number(Calc::stringToMinutes(text)));
} else {
le->setText(QString());
}
}
void NewFlight::on_tMPTimeLineEdit_editingFinished()
{
const auto &le = ui->tMPTimeLineEdit;
le->setText(Calc::formatTimeInput(le->text()));
const auto &text = le->text();
if(isLessOrEqualToTotalTime(text)){
newData.insert("tMP",QString::number(Calc::stringToMinutes(text)));
} else {
le->setText(QString());
}
}
void NewFlight::on_tIFRTimeLineEdit_editingFinished()
{
const auto &le = ui->tIFRTimeLineEdit;
le->setText(Calc::formatTimeInput(le->text()));
const auto &text = le->text();
if(isLessOrEqualToTotalTime(text)){
newData.insert("tIFR",QString::number(Calc::stringToMinutes(text)));
} else {
le->setText(QString());
}
}
void NewFlight::on_tNIGHTTimeLineEdit_editingFinished()
{
const auto &le = ui->tNIGHTTimeLineEdit;
le->setText(Calc::formatTimeInput(le->text()));
const auto &text = le->text();
if(isLessOrEqualToTotalTime(text)){
newData.insert("tNIGHT",QString::number(Calc::stringToMinutes(text)));
} else {
le->setText(QString());
}
}
void NewFlight::on_tPICTimeLineEdit_editingFinished()
{
const auto &le = ui->tPICTimeLineEdit;
le->setText(Calc::formatTimeInput(le->text()));
const auto &text = le->text();
if(isLessOrEqualToTotalTime(text)){
newData.insert("tPIC",QString::number(Calc::stringToMinutes(text)));
} else {
le->setText(QString());
}
}
void NewFlight::on_tSICTimeLineEdit_editingFinished()
{
const auto &le = ui->tSICTimeLineEdit;
le->setText(Calc::formatTimeInput(le->text()));
const auto &text = le->text();
if(isLessOrEqualToTotalTime(text)){
newData.insert("tSIC",QString::number(Calc::stringToMinutes(text)));
} else {
le->setText(QString());
}
}
void NewFlight::on_tDualTimeLineEdit_editingFinished()
{
const auto &le = ui->tDualTimeLineEdit;
le->setText(Calc::formatTimeInput(le->text()));
const auto &text = le->text();
if(isLessOrEqualToTotalTime(text)){
newData.insert("tDual",QString::number(Calc::stringToMinutes(text)));
} else {
le->setText(QString());
}
}
void NewFlight::on_tFITimeLineEdit_editingFinished()
{
const auto &le = ui->tFITimeLineEdit;
le->setText(Calc::formatTimeInput(le->text()));
const auto &text = le->text();
if(isLessOrEqualToTotalTime(text)){
newData.insert("tFI",QString::number(Calc::stringToMinutes(text)));
} else {
le->setText(QString());
}
}
void NewFlight::on_manualEditingCheckBox_stateChanged(int arg1)
{
QList LE = {ui->tSPSETimeLineEdit, ui->tSPMETimeLineEdit, ui->tMPTimeLineEdit, ui->tIFRTimeLineEdit,
ui->tNIGHTTimeLineEdit,ui->tPICTimeLineEdit, ui->tPICUSTimeLineEdit, ui->tSICTimeLineEdit,
ui->tDualTimeLineEdit, ui->tFITimeLineEdit,};
switch (arg1) {
case 0:
for(const auto& le : LE){
le->setFocusPolicy(Qt::NoFocus);
doUpdate = true;
update();
}
break;
case 2:
for(const auto& le : LE){
le->setFocusPolicy(Qt::StrongFocus);
doUpdate = false;
}
break;
default:
break;
}
}
void NewFlight::on_FunctionComboBox_currentTextChanged()
{
DEBUG("Current Index:" << ui->FunctionComboBox->currentIndex());
update();
}
void NewFlight::on_TakeoffSpinBox_valueChanged(int arg1)
{
if(arg1 > 0) {
ui->TakeoffCheckBox->setChecked(true);
}
}
void NewFlight::on_LandingSpinBox_valueChanged(int arg1)
{
if(arg1 > 0) {
ui->LandingCheckBox->setChecked(true);
}
}
void NewFlight::on_AutolandSpinBox_valueChanged(int arg1)
{
if(arg1 > 0) {
ui->AutolandCheckBox->setChecked(true);
}
}
void NewFlight::on_TakeoffCheckBox_stateChanged(int arg1)
{
if(arg1 == 0) {
ui->TakeoffSpinBox->setValue(0);
} else if ( arg1 == 2) {
ui->TakeoffSpinBox->setValue(1);
}
}
void NewFlight::on_LandingCheckBox_stateChanged(int arg1)
{
if(arg1 == 0) {
ui->LandingSpinBox->setValue(0);
} else if ( arg1 == 2) {
ui->LandingSpinBox->setValue(1);
}
}
void NewFlight::on_AutolandCheckBox_stateChanged(int arg1)
{
if(arg1 == 0) {
ui->AutolandSpinBox->setValue(0);
} else if ( arg1 == 2) {
ui->AutolandSpinBox->setValue(1);
}
}