fiffty-50 4 years ago
parent
commit
5524ea06c5
9 changed files with 2418 additions and 0 deletions
  1. 318 0
      calc.cpp
  2. 46 0
      calc.h
  3. 1031 0
      dbman.cpp
  4. 52 0
      easaview.cpp
  5. 42 0
      easaview.h
  6. 46 0
      easaview.ui
  7. 459 0
      editflight.cpp
  8. 77 0
      editflight.h
  9. 347 0
      editflight.ui

+ 318 - 0
calc.cpp

@@ -0,0 +1,318 @@
+/*
+ *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 <https://www.gnu.org/licenses/>.
+ */
+#include "calc.h"
+#include "dbman.cpp"
+/*!
+ * \brief calc::blocktime Calculates Block Time for a given departure and arrival time
+ * \param tofb QTime Time Off Blocks
+ * \param tonb QTime Time On Blocks
+ * \return Block Time in minutes
+ */
+QTime calc::blocktime(QTime tofb, QTime tonb)
+/* This function calculates block time for a given Departure Time and Arrival time.
+ */
+{
+    if(tonb > tofb)// landing same day
+    {
+        QTime blocktimeout(0,0); // initialise return value at midnight
+        int blockseconds = tofb.secsTo(tonb); // returns seconds between 2 time objects
+        blocktimeout = blocktimeout.addSecs(blockseconds);
+        return blocktimeout;
+
+    } else // landing next day
+    {
+        QTime midnight(0,0);
+        QTime blocktimeout(0,0); // initialise return value at midnight
+        int blockseconds = tofb.secsTo(midnight); // returns seconds passed until midnight
+        blocktimeout = blocktimeout.addSecs(blockseconds);
+        blockseconds = midnight.secsTo(tonb); // returns seconds passed after midnight
+        blocktimeout = blocktimeout.addSecs(blockseconds);
+        return blocktimeout;
+    }
+}
+
+
+/*!
+ * \brief calc::minutes_to_string Converts database time to String Time
+ * \param blockminutes int from database
+ * \return String hh:mm
+ */
+QString calc::minutes_to_string(QString blockminutes)
+/* Converts time from database (integer of minutes since midnight) to a QString "hh:mm"
+ */
+{
+    int minutes = blockminutes.toInt();
+    QString hour = QString::number(minutes/60);
+    if (hour.size() < 2) {hour.prepend("0");}
+    QString minute = QString::number(minutes % 60);
+    if (minute.size() < 2) {minute.prepend("0");}
+    QString blocktime = hour + ":" + minute;
+    return blocktime;
+};
+
+/*!
+ * \brief calc::time_to_minutes converts QTime to int minutes
+ * \param time QTime
+ * \return int time as number of minutes
+ */
+int calc::time_to_minutes(QTime time)
+{
+    QString timestring = time.toString("hh:mm");
+    int minutes = (timestring.left(2).toInt()) * 60;
+    minutes += timestring.right(2).toInt();
+    return minutes;
+}
+
+/*!
+ * \brief calc::string_to_minutes Converts String Time to String Number of Minutes
+ * \param timestring "hh:mm"
+ * \return String number of minutes
+ */
+int calc::string_to_minutes(QString timestring)
+{
+    int minutes = (timestring.left(2).toInt()) * 60;
+    minutes += timestring.right(2).toInt();
+    timestring = QString::number(minutes);
+    return minutes;
+}
+
+/*!
+ * The purpose of these functions is to provide functionality enabling the calculation of
+ * night flying time. EASA defines night as follows:
+ *
+ * ‘Night’  means  the  period  between  the  end  of  evening  civil  twilight  and  the  beginning  of
+ * morning  civil  twilight  or  such  other  period  between  sunset  and  sunrise  as  may  be  prescribed
+ * by  the  appropriate  authority,  as  defined  by  the  Member State.
+ *
+ *
+ *
+ * This is the proccess of calculating night time in this program:
+ *
+ * 1) A flight from A to B follows the Great Circle Track along these two points
+ *    at an average cruising height of 11km. (~FL 360)
+ *
+ * 2) Any time the Elevation of the Sun at the current position is less
+ *    than -6 degrees, night conditions are present.
+ * 3) The calculation is performed for every minute of flight time.
+ *
+ * In general, input and output for most functions is decimal degrees, like coordinates
+ * are stowed in the airports table. Calculations are normally done using
+ * Radians.
+ */
+
+
+
+
+/*!
+ * \brief radToDeg Converts radians to degrees
+ * \param rad
+ * \return degrees
+ */
+double calc::radToDeg(double rad)
+{
+    double deg = rad * (180 / M_PI);
+    return deg;
+}
+
+/*!
+ * \brief degToRad Converts degrees to radians
+ * \param deg
+ * \return radians
+ */
+double calc::degToRad(double deg)
+{
+    double rad = deg * (M_PI / 180);
+    return rad;
+}
+
+/*!
+ * \brief radToNauticalMiles Convert Radians to nautical miles
+ * \param rad
+ * \return nautical miles
+ */
+double calc::radToNauticalMiles(double rad)
+{
+    double nm = rad * 3440.06479482;
+    return nm;
+}
+
+/*!
+ * \brief greatCircleDistance Calculates Great Circle distance between two coordinates, return in Radians.
+ * \param lat1 Location Latitude in degrees -90:90 ;S(-) N(+)
+ * \param lon1 Location Longitude in degrees -180:180 W(-) E(+)
+ * \param lat2 Location Latitude in degrees -90:90 ;S(-) N(+)
+ * \param lon2 Location Longitude in degrees -180:180 W(-) E(+)
+ * \return
+ */
+double calc::greatCircleDistance(double lat1, double lon1, double lat2, double lon2)
+{
+    // Converting Latitude and Longitude to Radians
+    lat1 = degToRad(lat1);
+    lon1 = degToRad(lon1);
+    lat2 = degToRad(lat2);
+    lon2 = degToRad(lon2);
+
+    // Haversine Formula
+    double deltalon = lon2 - lon1;
+    double deltalat = lat2 - lat1;
+
+    double result = pow(sin(deltalat / 2), 2) +
+            cos(lat1) * cos(lat2) * pow(sin(deltalon / 2), 2);
+    result = 2 * asin(sqrt(result));
+    return result;
+}
+
+/*!
+ * \brief  Calculates a list of points (lat,lon) along the Great Circle between two points.
+ * The points are spaced equally, one minute of block time apart.
+ * \param lat1 Location Latitude in degrees -90:90 ;S(-) N(+)
+ * \param lon1 Location Longitude in degrees -180:180 W(-) E(+)
+ * \param lat2 Location Latitude in degrees -90:90 ;S(-) N(+)
+ * \param lon2 Location Longitude in degrees -180:180 W(-) E(+)
+ * \param tblk Total Blocktime in minutes
+ * \return coordinates {lat,lon} along the Great Circle Track
+ */
+QVector<QVector<double>> calc::intermediatePointsOnGreatCircle(double lat1, double lon1, double lat2, double lon2, int tblk)
+{
+    double d = greatCircleDistance(lat1, lon1, lat2, lon2); //calculate distance (radians)
+    // Converting Latitude and Longitude to Radians
+    lat1 = degToRad(lat1);
+    lon1 = degToRad(lon1);
+    lat2 = degToRad(lat2);
+    lon2 = degToRad(lon2);
+
+    //loop for creating one minute steps along the Great Circle
+    // 0 is departure point, 1 is end point
+    QVector<QVector<double>> coordinates;
+    double fraction = 1.0/tblk;
+    for(int i = 0; i <= tblk; i++) {
+        // Calculating intermediate point for fraction of distance
+        double A=sin((1-fraction * i) * d)/sin(d);
+        double B=sin(fraction * i * d)/sin(d);
+        double x = A*cos(lat1) * cos(lon1) + B * cos(lat2) * cos(lon2);
+        double y = A*cos(lat1) * sin(lon1) + B * cos(lat2) * sin(lon2);
+        double z = A*sin(lat1) + B * sin(lat2);
+        double lat = atan2(z, sqrt( pow(x, 2) + pow(y, 2) ));
+        double lon = atan2(y, x);
+
+        QVector<double> coordinate = {lat,lon};
+        coordinates.append(coordinate);
+    }
+    return coordinates;
+}
+
+/*!
+ * \brief Calculates solar elevation angle for a given point in time and latitude/longitude coordinates
+ *
+ * It is based on the formulas found here: http://stjarnhimlen.se/comp/tutorial.html#5
+ *
+ * Credit also goes to Darin C. Koblick for his matlab implementation of various of these
+ * formulas and to Kevin Godden for porting it to C++.
+ *
+ * Darin C. Koblock: https://www.mathworks.com/matlabcentral/profile/authors/1284781
+ * Kevin Godden: https://www.ridgesolutions.ie/index.php/about-us/
+ *
+ * \param utc_time_point - QDateTime (UTC) for which the elevation is calculated
+ * \param lat - Location Latitude in degrees -90:90 ;S(-) N(+)
+ * \param lon - Location Longitude in degrees -180:180 W(-) E(+)
+ * \return elevation - double of solar elevation in degrees.
+ */
+double calc::solarElevation(QDateTime utc_time_point, double lat, double lon)
+{
+    double Alt = 11; // I am taking 11 kilometers as an average cruising height for a commercial passenger airplane.
+    // convert current DateTime Object to a J2000 value used in the calculation
+    double d = utc_time_point.date().toJulianDay() - 2451544 + utc_time_point.time().hour()/24.0 + utc_time_point.time().minute()/1440.0;
+
+    // Orbital Elements (in degress)
+    double w = 282.9404 + 4.70935e-5 * d; // (longitude of perihelion)
+    double e = 0.016709 - 1.151e-9 * d; // (eccentricity)
+    double M = fmod(356.0470 + 0.9856002585 * d, 360.0); // (mean anomaly, needs to be between 0 and 360 degrees)
+    double oblecl = 23.4393 - 3.563e-7*d; // (Sun's obliquity of the ecliptic)
+    double L = w + M; // (Sun's mean longitude)
+    // auxiliary angle
+    double  E = M + (180 / M_PI)*e*sin(M*(M_PI / 180))*(1 + e*cos(M*(M_PI / 180)));
+    // The Sun's rectangular coordinates in the plane of the ecliptic
+    double x = cos(E*(M_PI / 180)) - e;
+    double y = sin(E*(M_PI / 180))*sqrt(1 - pow(e, 2));
+    // find the distance and true anomaly
+    double r = sqrt(pow(x,2) + pow(y,2));
+    double v = atan2(y, x)*(180 / M_PI);
+    // find the longitude of the sun
+    double solarlongitude = v + w;
+    // compute the ecliptic rectangular coordinates
+    double xeclip = r*cos(solarlongitude*(M_PI / 180));
+    double yeclip = r*sin(solarlongitude*(M_PI / 180));
+    double zeclip = 0.0;
+    //rotate these coordinates to equitorial rectangular coordinates
+    double xequat = xeclip;
+    double yequat = yeclip*cos(oblecl*(M_PI / 180)) + zeclip * sin(oblecl*(M_PI / 180));
+    double zequat = yeclip*sin(23.4406*(M_PI / 180)) + zeclip * cos(oblecl*(M_PI / 180));
+    // convert equatorial rectangular coordinates to RA and Decl:
+    r = sqrt(pow(xequat, 2) + pow(yequat, 2) + pow(zequat, 2)) - (Alt / 149598000); //roll up the altitude correction
+    double RA = atan2(yequat, xequat)*(180 / M_PI);
+    double delta = asin(zequat / r)*(180 / M_PI);
+
+    // GET UTH time
+    double UTH = utc_time_point.time().hour() + utc_time_point.time().minute()/60.0 + utc_time_point.time().second()/3600.0;
+    // Calculate local siderial time
+    double GMST0 = fmod(L + 180, 360.0) / 15;
+    double SIDTIME = GMST0 + UTH + lon / 15;
+    // Replace RA with hour angle HA
+    double HA = (SIDTIME*15 - RA);
+    // convert to rectangular coordinate system
+    x = cos(HA*(M_PI / 180))*cos(delta*(M_PI / 180));
+    y = sin(HA*(M_PI / 180))*cos(delta*(M_PI / 180));
+    double z = sin(delta*(M_PI / 180));
+    // rotate this along an axis going east - west.
+    double zhor = x*sin((90 - lat)*(M_PI / 180)) + z*cos((90 - lat)*(M_PI / 180));
+
+    // Find the Elevation
+    double elevation = asin(zhor)*(180 / M_PI);
+    return elevation;
+}
+
+/*!
+ * \brief Calculates which portion of a flight was conducted in night conditions.
+ * \param dept - ICAO 4-letter code of Departure Airport
+ * \param dest - ICAO 4-letter Code of Destination Airport
+ * \param departureTime - QDateTime of Departure (UTC)
+ * \param tblk - Total block time in minutes
+ * \return Total number of minutes under night flying conditions
+ */
+int calc::calculateNightTime(QString dept, QString dest, QDateTime departureTime, int tblk)
+{
+    double deptLat = db::retreiveIcaoCoordinates(dept)[0];
+    qDebug() << "calc::calculateNightTime deptLat = " << deptLat;
+    double deptLon = db::retreiveIcaoCoordinates(dept)[1];
+    qDebug() << "calc::calculateNightTime deptLon = " << deptLon;
+    double destLat = db::retreiveIcaoCoordinates(dest)[0];
+    qDebug() << "calc::calculateNightTime destLat = " << destLat;
+    double destLon = db::retreiveIcaoCoordinates(dest)[1];
+    qDebug() << "calc::calculateNightTime destLon = " << destLon;
+
+    QVector<QVector<double>> route = intermediatePointsOnGreatCircle(deptLat, deptLon, destLat, destLon, tblk);
+
+    int nightTime = 0;
+    for(int i = 0; i < tblk ; i++) {
+        if(solarElevation(departureTime.addSecs(60*i),radToDeg(route[i][0]),radToDeg(route[i][1])) < -0.6) {
+            nightTime ++;
+        }
+    }
+    qDebug() << "calc::calculateNightTime result: " << nightTime << " minutes night flying time.";
+    return nightTime;
+}

+ 46 - 0
calc.h

@@ -0,0 +1,46 @@
+/*
+ *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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef CALC_H
+#define CALC_H
+#include <QDateTime>
+#include <cmath>
+#include <QDebug>
+/*!
+ * \brief The calc class provides functionality for various calculations that are performed
+ * outside of the database. This includes tasks like converting different units and formats,
+ * or functions calculating block time or night time.
+ */
+class calc
+{
+public:
+    static QTime blocktime(QTime tofb, QTime tonb);
+    static QString minutes_to_string(QString blockminutes);
+    static int string_to_minutes(QString time);
+    static int time_to_minutes(QTime time);
+    static double radToDeg(double rad);
+    static double degToRad(double deg);
+    static double radToNauticalMiles(double rad);
+    static double greatCircleDistance(double lat1, double lon1, double lat2, double lon2);
+    static QVector<QVector<double>> intermediatePointsOnGreatCircle(double lat1, double lon1, double lat2, double lon2, int tblk);
+    static double solarElevation(QDateTime utc_time_point, double lat, double lon);
+    static int calculateNightTime(QString dept, QString dest, QDateTime departureTime, int tblk);
+};
+
+
+#endif // CALC_H

+ 1031 - 0
dbman.cpp

@@ -0,0 +1,1031 @@
+/*
+ *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 <https://www.gnu.org/licenses/>.
+ */
+#include <QCoreApplication>
+#include <QDebug>
+#include <QSqlDatabase>
+#include <QSqlDriver>
+#include <QSqlError>
+#include <QSqlQuery>
+#include "calc.h"
+#include <chrono>
+#include <QRandomGenerator>
+#include <QStandardPaths>
+
+
+class db
+{
+public:
+    static void connect()
+    {
+        const QString DRIVER("QSQLITE");
+
+        if(QSqlDatabase::isDriverAvailable(DRIVER))
+        {
+            QSqlDatabase db = QSqlDatabase::addDatabase(DRIVER);
+
+            //QString pathtodb = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);
+            //db.setDatabaseName(pathtodb+"/flog.db");
+            //qDebug() << "Database: " << pathtodb+"/logbook.db";
+            db.setDatabaseName("logbook.db");
+
+
+            if(!db.open())
+                qWarning() << "MainWindow::DatabaseConnect - ERROR: " << db.lastError().text();
+        }
+        else
+            qWarning() << "MainWindow::DatabaseConnect - ERROR: no driver " << DRIVER << " available";
+    }
+    static void initexample()
+    {
+        QSqlQuery query("CREATE TABLE people (id INTEGER PRIMARY KEY, name TEXT)");
+
+        if(!query.isActive())
+            qWarning() << "MainWindow::DatabaseInit - ERROR: " << query.lastError().text();
+
+    }
+
+    static void queryexamplenamedbinding()
+    {
+        QSqlQuery query;
+        //query.prepare("SELECT * FROM people");
+        //query.prepare("SELECT * FROM people WHERE name LIKE 'Linus' OR id = :id");
+        query.prepare("SELECT * from people WHERE name LIKE :name");
+        query.bindValue(":name", "%Linus%");
+        query.bindValue(":id",2);
+        query.exec();
+        /*
+         * QSqlQuery provides access to the result set one record at a time. After the call to exec(),
+         * QSqlQuery's internal pointer is located one position before the first record.
+         * We must call QSqlQuery::next() once to advance to the first record, then next() again
+         * repeatedly to access the other records, until it returns false. Here's a typical loop that
+         * iterates over all the records in order:
+         * After a SELECT query is executed we have to browse the records (result rows) returned to access
+         * the data. In this case we try to retrieve the first record calling the function first which
+         * returns true when the query has been successful and false otherwise.
+         */
+        if(query.first());
+        else
+            qDebug() << ("No entry found");
+        query.previous();//To go back to index 0
+        while (query.next()) {
+            QString name = query.value(1).toString();
+            int id = query.value(0).toInt();
+            qDebug() << name << id;
+        }
+        /*
+         *The QSqlQuery::value() function returns the value of a field in the current record. Fields are
+         * specified as zero-based indexes. QSqlQuery::value() returns a QVariant, a type that can hold
+         * various C++ and core Qt data types such as int, QString, and QByteArray. The different database
+         * types are automatically mapped into the closest Qt equivalent. In the code snippet, we call
+         * QVariant::toString() and QVariant::toInt() to convert variants to QString and int.
+         */
+    }
+
+
+
+
+
+
+
+
+
+
+
+    /*
+     *
+     *
+     * Flights Database Related Functions
+     *
+     *
+     */
+
+
+    static QVector<QString> SelectFlightDate(QString doft)
+    {
+        QSqlQuery query;
+        if (doft == "ALL")
+        {
+            query.prepare("SELECT * FROM flights ORDER BY doft DESC, tofb ASC");
+            qDebug() << "All flights selected";
+        }else
+        {
+            query.prepare("SELECT * FROM flights WHERE doft = ? ORDER BY tofb ASC");
+            query.addBindValue(doft);
+            qDebug() << "Searching flights for " << doft;
+        }
+        //query.prepare("SELECT * FROM flights WHERE doft = ?");
+
+        query.exec();
+
+        if(query.first());
+        else
+        {
+            qDebug() << ("No flight with this date found");
+            QVector<QString> flight; //return empty
+            return flight;
+        }
+
+        query.previous();// To go back to index 0
+        query.last(); // this can be very slow, used to determine query size since .size is not supported by sqlite
+        int numRows = query.at() + 1; // Number of rows (flights) in the query
+        query.first();
+        query.previous();// Go back to index 0
+
+        QVector<QString> flight(numRows * 9); // Every flight has 9 fields in the database
+        int index = 0; // counter for output vector
+
+        while (query.next()) {
+            QString id = query.value(0).toString();
+            QString doft = query.value(1).toString();
+            QString dept = query.value(2).toString();
+            QString tofb = calc::minutes_to_string((query.value(3).toString()));
+            QString dest = query.value(4).toString();
+            QString tonb = calc::minutes_to_string((query.value(5).toString()));
+            QString tblk = calc::minutes_to_string((query.value(6).toString()));
+            QString pic = db::RetreivePilotNameFromID(query.value(7).toString());
+            QString acft = db::RetreiveRegistration(query.value(8).toString());
+            //qDebug() << id << doft << dept << tofb << dest << tonb << tblk << pic << acft << endl;
+            flight[index] = id;
+            ++index;
+            flight[index] = doft;
+            ++index;
+            flight[index] = dept;
+            ++index;
+            flight[index] = tofb;
+            ++index;
+            flight[index] = dest;
+            ++index;
+            flight[index] = tonb;
+            ++index;
+            flight[index] = tblk;
+            ++index;
+            flight[index] = pic;
+            ++index;
+            flight[index] = acft;
+            ++index;
+        }
+        //QString minutes = calc::minutes_to_string(flight[3]);
+        //flight.replace(3, minutes);
+        //qDebug() << "Length of flight vector " << flight.size();
+        return flight;
+
+    }
+    static QVector<QString> SelectFlightById(QString flight_id)
+    {
+        QSqlQuery query;
+        query.prepare("SELECT * FROM flights WHERE id = ?");
+        query.addBindValue(flight_id);
+        query.exec();
+
+        if(query.first());
+        else
+        {
+            qDebug() << "db::SelectFlightById - No Flight with this ID found";
+            QVector<QString> flight; //return empty
+            return flight;
+        }
+
+        QVector<QString> flight;
+        flight.append(query.value(0).toString());
+        flight.append(query.value(1).toString());
+        flight.append(query.value(2).toString());
+        flight.append(query.value(3).toString());
+        flight.append(query.value(4).toString());
+        flight.append(query.value(5).toString());
+        flight.append(query.value(6).toString());
+        flight.append(query.value(7).toString());
+        flight.append(query.value(8).toString());
+        /*
+        flight.append(calc::minutes_to_string((query.value(3).toString())));
+        flight.append(query.value(4).toString());
+        flight.append(calc::minutes_to_string((query.value(5).toString())));
+        flight.append(calc::minutes_to_string((query.value(6).toString())));
+        flight.append(db::RetreivePilotNameFromID(query.value(7).toString()));
+        flight.append(db::RetreiveRegistration(query.value(8).toString()));
+        */
+
+
+        qDebug() << "db::SelectFlightById - retreived flight: " << flight;
+        return flight;
+
+    }
+    static QVector<QString> CreateFlightVectorFromInput(QString doft, QString dept, QTime tofb, QString dest, QTime tonb, QTime tblk, QString pic, QString acft)
+    {
+
+        QVector<QString> flight;
+        flight.insert(0, ""); // ID, created as primary key during commit
+        flight.insert(1, doft);
+        flight.insert(2, dept);
+        flight.insert(3, QString::number(calc::time_to_minutes(tofb)));
+        flight.insert(4, dest);
+        flight.insert(5, QString::number(calc::time_to_minutes(tonb)));
+        flight.insert(6, QString::number(calc::time_to_minutes(tblk)));
+        flight.insert(7, pic); // lookup and matching tbd
+        flight.insert(8, acft);// lookup and matching tbd
+        //qDebug() << flight;
+        return flight;
+    }
+    static int CommitFlight(QVector<QString> flight)// flight vector shall always have length 9
+    {
+        QSqlQuery query;
+        query.prepare("INSERT INTO flights (doft, dept, tofb, dest, tonb, tblk, pic, acft) "
+                      "VALUES (:doft, :dept, :tofb, :dest, :tonb, :tblk, :pic, :acft)");
+        //flight[0] is primary key, not required for commit
+        query.bindValue(":doft", flight[1]); //string
+        query.bindValue(":dept", flight[2]);
+        query.bindValue(":tofb", flight[3].toInt()); //int
+        query.bindValue(":dest", flight[4]);
+        query.bindValue(":tonb", flight[5].toInt());
+        query.bindValue(":tblk", flight[6].toInt());
+        query.bindValue(":pic", flight[7].toInt());
+        query.bindValue(":acft", flight[8].toInt());
+        query.exec();
+        qDebug() << "Error message for commiting flight: " << query.lastError().text();
+
+        QSqlQuery query2;
+        query2.prepare("INSERT INTO extras DEFAULT VALUES");
+        query2.exec();
+
+        qDebug() << "Creating extras entry" << query2.lastError().text();
+        return 0;
+    }
+
+    static int CommitToScratchpad(QVector<QString> flight)// to store input mask
+    {
+        //qDebug() << "Saving invalid flight to scratchpad";
+        QSqlQuery query;
+        query.prepare("INSERT INTO scratchpad (doft, dept, tofb, dest, tonb, tblk, pic, acft) "
+                      "VALUES (:doft, :dept, :tofb, :dest, :tonb, :tblk, :pic, :acft)");
+        //flight[0] is primary key, not required for commit
+        query.bindValue(":doft", flight[1]); //string
+        query.bindValue(":dept", flight[2]);
+        query.bindValue(":tofb", flight[3].toInt()); //int
+        query.bindValue(":dest", flight[4]);
+        query.bindValue(":tonb", flight[5].toInt());
+        query.bindValue(":tblk", flight[6].toInt());
+        query.bindValue(":pic", flight[7].toInt());
+        query.bindValue(":acft", flight[8].toInt());
+        query.exec();
+        qDebug() << query.lastError().text();
+        return 0;
+    }
+    static bool CheckScratchpad() // see if scratchpad is empty
+    {
+        //qDebug() << "Checking if scratchpad contains data";
+        QSqlQuery query;
+        query.prepare("SELECT * FROM scratchpad");
+        query.exec();
+
+        if(query.first())
+        {
+            //qDebug() << "Scratchpad contains data";
+            return 1;
+        }
+        else
+        {
+            //qDebug() << ("Scratchpad contains NO data");
+            return 0;
+        }
+    }
+    static QVector<QString> RetreiveScratchpad()
+    {
+        //qDebug() << "Retreiving invalid flight from scratchpad";
+        QSqlQuery query;
+        query.prepare("SELECT * FROM scratchpad");
+        query.exec();
+
+        if(query.first());
+        else
+        {
+            //qDebug() << ("scratchpad empty");
+            QVector<QString> flight; //return empty
+            return flight;
+        }
+
+        query.previous();// To go back to index 0
+        //query.last(); // this can be very slow, used to determine query size since .size is not supported by sqlite
+        //int numRows = query.at() + 1; // Number of rows (flights) in the query
+        //query.first();
+        //query.previous();// Go back to index 0
+
+        //QVector<QString> flight(numRows * 9); // Every flight has 9 fields in the database
+        QVector<QString> flight(9);
+        int index = 0; // counter for output vector
+
+        while (query.next()) {
+            QString id = query.value(0).toString();
+            QString doft = query.value(1).toString();
+            QString dept = query.value(2).toString();
+            QString tofb = calc::minutes_to_string((query.value(3).toString()));
+            QString dest = query.value(4).toString();
+            QString tonb = calc::minutes_to_string((query.value(5).toString()));
+            QString tblk = calc::minutes_to_string((query.value(6).toString()));
+            QString pic = query.value(7).toString();
+            QString acft = query.value(8).toString();
+            //qDebug() << id << doft << dept << tofb << dest << tonb << tblk << pic << acft << endl;
+            flight[index] = id;
+            ++index;
+            flight[index] = doft;
+            ++index;
+            flight[index] = dept;
+            ++index;
+            flight[index] = tofb;
+            ++index;
+            flight[index] = dest;
+            ++index;
+            flight[index] = tonb;
+            ++index;
+            flight[index] = tblk;
+            ++index;
+            flight[index] = pic;
+            ++index;
+            flight[index] = acft;
+            ++index;
+        }
+
+        ClearScratchpad();
+        return flight;
+    }
+    static void ClearScratchpad()
+    {
+        qDebug() << "Deleting scratchpad";
+        QSqlQuery query;
+        query.prepare("DELETE FROM scratchpad;");
+        query.exec();
+    }
+
+    static bool DeleteFlightById(QString flight_id)
+    {
+        QSqlQuery query;
+        query.prepare("DELETE FROM flights WHERE id = ?");
+        query.addBindValue(flight_id);
+        query.exec();
+        QString error = query.lastError().text();
+        qDebug() << "db::DeleteFlightById: Removing flight with ID#: " << flight_id << "Query Error: " << error;
+        if(error.length() > 0)
+        {
+            return false;
+        }else
+        {
+            return true;
+        }
+
+    }
+
+    /*
+     *
+     *
+     * Pilots Database Related Functions
+     *
+     *
+     */
+
+    static QString RetreivePilotNameFromID(QString pilotID)
+    /* Looks up the pilot ID in the Database and returns the name as a string
+     * unless the pilot in command is the logbook owner.
+     */
+    {
+        QString pilotName("");
+        if (pilotID == "1")
+        {
+            pilotName = "self";
+            return pilotName;
+        }
+        QSqlQuery query;
+        query.prepare("SELECT piclastname, picfirstname, alias FROM pilots WHERE pilot_id == ?");
+        query.addBindValue(pilotID.toInt());
+        query.exec();
+
+        //if(query.first());
+        //else
+        //  qDebug() << ("No Pilot with this ID found");
+        //query.previous();//To go back to index 0
+        while (query.next()) {
+            pilotName.append(query.value(0).toString());
+            pilotName.append(", ");
+            pilotName.append(query.value(1).toString());//.left(1));
+            //pilotName.append(".");
+        }
+
+        if(pilotName.length() == 0)
+        {
+            qDebug() << ("No Pilot with this ID found");
+        }
+        return pilotName;
+    }
+
+    static QString RetreivePilotIdFromString(QString lastname, QString firstname)
+    {
+        QSqlQuery query;
+        query.prepare("SELECT pilot_id from pilots "
+                      "WHERE piclastname = ? AND picfirstname LIKE ?");
+        query.addBindValue(lastname);
+        firstname.prepend("%"); firstname.append("%");
+        query.addBindValue(firstname);
+        query.exec();
+
+        QString id;
+        if(query.first()){id.append(query.value(0).toString());}
+
+        return id;
+
+    }
+
+    static QStringList RetreivePilotNameFromString(QString searchstring)
+    /* Searches the pilot Name in the Database and returns the name as a vector of results
+     * unless the pilot in command is the logbook owner.
+     */
+    {
+        QString firstname = searchstring; //To Do: Two control paths, one for single word, query as before with only searchstring
+        QString lastname = searchstring;  // second control path with comma, lastname like AND firstname like
+        if(searchstring.contains(QLatin1Char(',')))
+        {
+            QStringList namelist = searchstring.split(QLatin1Char(','));
+            QString lastname = namelist[0].trimmed();
+            lastname = lastname.toLower();
+            lastname[0] = lastname[0].toUpper();
+            lastname.prepend("%"), lastname.append("%");
+
+            QString firstname = namelist[1].trimmed();
+            if(firstname.length()>1)
+            {
+                firstname = firstname.toLower();
+                firstname[0] = firstname[0].toUpper();
+                firstname.prepend("%"), firstname.append("%");
+            }
+            qDebug() << "db::RetreivePilotNameFromString: first last after comma";
+            qDebug() << firstname << lastname;
+        }
+        QSqlQuery query;
+        query.prepare("SELECT piclastname, picfirstname, alias "
+                      "FROM pilots WHERE  "
+                      "picfirstname LIKE ? OR piclastname LIKE ? OR alias LIKE ?");
+        searchstring.prepend("%");
+        searchstring.append("%");
+        query.addBindValue(firstname);
+        query.addBindValue(lastname);
+        query.addBindValue(searchstring);
+        query.exec();
+
+
+        QStringList result;
+        while (query.next()) {
+            QString piclastname = query.value(0).toString();
+            QString picfirstname = query.value(1).toString();
+            QString alias = query.value(2).toString();
+            QString name = piclastname + ", " + picfirstname;
+            result.append(name);
+        }
+        qDebug() << "db::RetreivePilotNameFromString Result: "  << result;
+        //qDebug() << query.lastError();
+
+
+        if(result.size() == 0)
+        {
+            qDebug() << ("db::RetreivePilotNameFromString: No Pilot found");
+            return result;
+        }
+
+
+        return result;
+    }
+    static QStringList newPicGetString(QString searchstring)
+    /*
+     * This function is returning a QStringList for the QCompleter in the NewFlight::newPic line edit.
+     * A regular expression limits the input possibilities to only characters, followed by an optional ',' and 1 whitespace, e.g.:
+     * Miller, Jim ->valid / Miller,  Jim -> invalid / Miller,, Jim -> invalid
+     * Miller Jim -> valid / Miller  Jim ->invalid
+     * Jim Miller-> valid
+     */
+    {
+        QStringList result;
+        QStringList searchlist;
+
+        if(searchstring == "self")
+        {
+            result.append("self");
+            qDebug() << "Pilot is self";
+            return result;
+        }
+
+
+
+        //Fall 1) Nachname, Vorname
+        if(searchstring.contains(QLatin1Char(',')))
+        {
+            QStringList namelist = searchstring.split(QLatin1Char(','));
+
+            QString name1 = namelist[0].trimmed();
+            name1 = name1.toLower();
+            name1[0] = name1[0].toUpper();
+            searchlist.append(name1);
+
+            if(namelist[1].length() > 1)
+            {
+                QString name2 = namelist[1].trimmed();
+                name2 = name2.toLower();
+                name2[0] = name2[0].toUpper();
+                searchlist.append(name2);
+            }
+
+
+
+        }
+        //Fall 2) Vorname Nachname
+        if(searchstring.contains(" ") && !searchstring.contains(QLatin1Char(',')))
+        {
+            QStringList namelist = searchstring.split(" ");
+
+            QString name1 = namelist[0].trimmed();
+            name1 = name1.toLower();
+            name1[0] = name1[0].toUpper();
+            searchlist.append(name1);
+
+            if(namelist[1].length() > 1) //To avoid index out of range if the searchstring is one word followed by only one whitespace
+            {
+                QString name2 = namelist[1].trimmed();
+                name2 = name2.toLower();
+                name2[0] = name2[0].toUpper();
+                searchlist.append(name2);
+
+            }
+
+        }
+        //Fall 3) Name
+        if(!searchstring.contains(" ") && !searchstring.contains(QLatin1Char(',')))
+        {
+
+            QString name1 = searchstring.toLower();
+            name1[0] = name1[0].toUpper();
+            searchlist.append(name1);
+        }
+
+        if(searchlist.length() == 1)
+        {
+            QSqlQuery query;
+            query.prepare("SELECT piclastname, picfirstname FROM pilots "
+                          "WHERE piclastname LIKE ?");
+            query.addBindValue(searchlist[0] + '%');
+            query.exec();
+
+
+
+            while(query.next())
+            {
+                result.append(query.value(0).toString() + ", " + query.value(1).toString());
+            }
+
+            QSqlQuery query2;
+            query2.prepare("SELECT piclastname, picfirstname FROM pilots "
+                           "WHERE picfirstname LIKE ?");
+            query2.addBindValue(searchlist[0] + '%');
+            query2.exec();
+
+            while(query2.next())
+            {
+                result.append(query2.value(0).toString() + ", " + query2.value(1).toString());
+            }
+
+        }else
+        {
+            QSqlQuery query;
+            query.prepare("SELECT piclastname, picfirstname FROM pilots "
+                          "WHERE piclastname LIKE ? AND picfirstname LIKE ?");
+            query.addBindValue(searchlist[0] + '%');
+            query.addBindValue(searchlist[1] + '%');
+            query.exec();
+
+            while(query.next())
+            {
+                result.append(query.value(0).toString() + ", " + query.value(1).toString());
+            }
+
+            QSqlQuery query2;
+            query2.prepare("SELECT piclastname, picfirstname FROM pilots "
+                          "WHERE picfirstname LIKE ? AND piclastname LIKE ?");
+            query2.addBindValue(searchlist[0] + '%');
+            query2.addBindValue(searchlist[1] + '%');
+            query2.exec();
+
+            while(query2.next())
+            {
+                result.append(query2.value(0).toString() + ", " + query2.value(1).toString());
+            }
+
+        }
+
+
+        qDebug() << "db::newPic Result" << result.length() << result;
+        if(result.length() == 0)
+        {
+            //try first name search
+            qDebug() << "No Pilot with this last name found. trying first name search.";
+            return result;
+        }else
+        {
+            return result;
+        }
+
+    }
+    static QString newPicGetId(QString name)
+    {
+        QString result;
+
+        QStringList nameparts = name.split(QLatin1Char(','));
+        QString lastname = nameparts[0].trimmed();
+        lastname = lastname.toLower(); lastname[0] = lastname[0].toUpper();
+        QString firstname = nameparts[1].trimmed();
+        firstname = firstname.toLower(); firstname[0] = firstname[0].toUpper();
+        firstname.prepend("%"); firstname.append("%");
+
+        QSqlQuery query;
+        query.prepare("SELECT pilot_id FROM pilots "
+                      "WHERE piclastname = ? AND picfirstname LIKE ?");
+        query.addBindValue(lastname);
+        query.addBindValue(firstname);
+        query.exec();
+
+        while (query.next())
+        {
+            result.append(query.value(0).toString());
+        }
+
+        qDebug() << "newPicGetId: result = " << result;
+        return result;
+    }
+/*
+ *
+ *
+ * Airport Database Related Functions
+ *
+ *
+ */
+    static QString RetreiveAirportNameFromIcaoOrIata(QString identifier)
+    /*
+     * 'EDDF' gets looked up and 'Frankfurt International Airport' returned
+     *
+     */
+    {
+        QString result = "";
+        QSqlQuery query;
+        query.prepare("SELECT name "
+                      "FROM airports WHERE icao LIKE ? OR iata LIKE ?");
+        identifier.append("%");
+        identifier.prepend("%");
+        query.addBindValue(identifier);
+        query.addBindValue(identifier);
+        query.exec();
+        if(query.first())
+        {
+            result.append(query.value(0).toString());
+            return result;
+        }else
+        {
+            result = result.left(result.length()-1);
+            result.append("No matching airport found.");
+            return  result;
+        }
+    }
+
+    static QString RetreiveAirportIdFromIcao(QString identifier)
+    {
+        QString result;
+        QSqlQuery query;
+        query.prepare("SELECT airport_id FROM airports WHERE icao = ?");
+        query.addBindValue(identifier);
+        query.exec();
+
+        while(query.next())
+        {
+            result.append(query.value(0).toString());
+            //qDebug() << "db::RetreiveAirportIdFromIcao says Airport found! #" << result;
+        }
+
+        return result;
+    }
+    static QStringList CompleteIcaoOrIata(QString icaoStub)
+    {
+        QStringList result;
+        QSqlQuery query;
+        query.prepare("SELECT icao FROM airports WHERE icao LIKE ? OR iata LIKE ?");
+        icaoStub.prepend("%"); icaoStub.append("%");
+        query.addBindValue(icaoStub);
+        query.addBindValue(icaoStub);
+        query.exec();
+
+        while(query.next())
+        {
+            result.append(query.value(0).toString());
+            qDebug() << "db::CompleteIcaoOrIata says... Result:" << result;
+        }
+
+        return result;
+    }
+
+    static bool CheckICAOValid(QString identifier)
+    // Verifies if a user input airport exists in the database
+    {
+        if(identifier.length() == 4)
+        {
+            QString check = RetreiveAirportIdFromIcao(identifier);
+            if(check.length() > 0)
+            {
+                //qDebug() << "db::CheckICAOValid says: Check passed!";
+                return 1;
+            }else
+            {
+                //qDebug() << "db::CheckICAOValid says: Check NOT passed! Lookup unsuccessful";
+                return 0;
+            }
+        }else
+        {
+            //qDebug() << "db::CheckICAOValid says: Check NOT passed! Empty String NOT epico!";
+            return 0;
+        }
+    }
+    static QVector<double> retreiveIcaoCoordinates(QString icao)
+    {
+        QSqlQuery query;
+        query.prepare("SELECT lat, long "
+                      "FROM airports "
+                      "WHERE icao = ?");
+        query.addBindValue(icao);
+        query.exec();
+
+        QVector<double> result;
+        while(query.next()) {
+            result.append(query.value(0).toDouble());
+            result.append(query.value(1).toDouble());
+        }
+        return result;
+    }
+
+
+/*
+ *
+ *
+ * Aircraft Database Related Functions
+ *
+ *
+ */
+
+    static QString RetreiveRegistration(QString tail_ID)
+    /* Looks up the Aircraft Registration in the Database and returns it as a string
+     *
+     */
+    {
+        QString acftRegistration("");
+
+        QSqlQuery query;
+        query.prepare("SELECT registration FROM tails WHERE tail_id == ?");
+        query.addBindValue(tail_ID.toInt());
+        query.exec();
+
+        if(query.first());
+        else
+            qDebug() << ("No Aircraft with this ID found");
+        query.previous();//To go back to index 0
+        while (query.next()) {
+            acftRegistration.append(query.value(0).toString());
+        }
+
+        return acftRegistration;
+    }
+    static QStringList newAcftGetString(QString searchstring)
+    {
+        QStringList result;
+        if(searchstring.length()<2){return result;}
+        QSqlQuery query;
+        query.prepare("SELECT registration, make, model, variant "
+                      "FROM aircraft "
+                      "INNER JOIN tails on tails.aircraft_ID = aircraft.aircraft_id "
+                      "WHERE tails.registration LIKE ?");
+        searchstring.append("%"); searchstring.prepend("%");
+        query.addBindValue(searchstring);
+        query.exec();
+
+        while(query.next())
+        {
+            result.append(query.value(0).toString() + " (" + query.value(1).toString() + "-" + query.value(2).toString() + "-" + query.value(3).toString() + ")");
+        }
+        qDebug() << "newAcftGetString: " << result.length() << result;
+        return result;
+
+    }
+    static QString newAcftGetId(QString registration)
+    {
+        QString result;
+        QSqlQuery query;
+        query.prepare("SELECT tail_id "
+                      "FROM tails "
+                      "WHERE registration LIKE ?");
+        registration.prepend("%"); registration.append("%");
+        query.addBindValue(registration);
+        query.exec();
+
+        while(query.next())
+        {
+            result.append(query.value(0).toString());
+        }
+        qDebug() << "newAcftGetId: " << result;
+        return result;
+
+    }
+
+    static QVector<QString> RetreiveAircraftTypeFromReg(QString searchstring)
+    /*
+     * Searches the tails Database and returns the aircraft Type.
+     */
+    {
+
+        QSqlQuery query;
+        query.prepare("SELECT Name, iata, registration, tail_id " //"SELECT Registration, Name, icao, iata "
+                      "FROM aircraft "
+                      "INNER JOIN tails on tails.aircraft_ID = aircraft.aircraft_id "
+                      "WHERE tails.registration LIKE ?");
+        // Returns Registration/Name/icao/iata
+        searchstring.prepend("%");
+        searchstring.append("%");
+        query.addBindValue(searchstring);
+        query.exec();
+
+        //qDebug() << "SQL Error: " << query.lastError().text();
+        //qDebug() << "Query result: " << query.first();
+        //qDebug() << query.value(2);
+
+        QVector<QString> result;
+
+        if(query.first())
+        {
+            QString acType = query.value(0).toString();
+            QString iataCode = query.value(1).toString();
+            QString registration = query.value(2).toString();
+            QString tail_id = query.value(3).toString();
+            //QString formatted = acType + " [ " + registration + " | " + iataCode + " ]";
+            //qDebug() << formatted;
+            result.append(registration); result.append(acType);
+            result.append(iataCode); result.append(tail_id);
+            return result;
+        }else
+        {
+            return  result; // empty vector
+        }
+
+
+    }
+
+    static QStringList RetreiveAircraftMake(QString searchstring)
+    {
+        QStringList result;
+        QSqlQuery query;
+        query.prepare("SELECT make from aircraft WHERE make LIKE ?");
+        searchstring.prepend("%"); searchstring.append("%");
+        query.addBindValue(searchstring);
+        query.exec();
+
+
+        while(query.next())
+        {
+            result.append(query.value(0).toString());
+        }
+        qDebug() << "db::RetreiveAircraftMake says... Result:" << result;
+        return result;
+    }
+
+    static QStringList RetreiveAircraftModel(QString make, QString searchstring)
+    {
+        QStringList result;
+        QSqlQuery query;
+        query.prepare("SELECT model FROM aircraft WHERE make = ? AND model LIKE ?");
+        query.addBindValue(make);
+        searchstring.prepend("%"); searchstring.append("%");
+        query.addBindValue(searchstring);
+        query.exec();
+
+        while(query.next())
+        {
+            result.append(query.value(0).toString());
+            qDebug() << "db::RetreiveAircraftModel says... Result:" << result;
+        }
+
+        return result;
+    }
+
+    static QStringList RetreiveAircraftVariant(QString make, QString model, QString searchstring)
+    {
+        QStringList result;
+        QSqlQuery query;
+        query.prepare("SELECT variant from aircraft WHERE make = ? AND model = ? AND variant LIKE ?");
+        query.addBindValue(make);
+        query.addBindValue(model);
+        searchstring.prepend("%"); searchstring.append("%");
+        query.addBindValue(searchstring);
+        query.exec();
+
+        while(query.next())
+        {
+            result.append(query.value(0).toString());
+            qDebug() << "db::RetreiveAircraftVariant says... Result:" << result;
+        }
+
+        return result;
+    }
+    static QString RetreiveAircraftIdFromMakeModelVariant(QString make, QString model, QString variant)
+    {
+        QString result;
+        QSqlQuery query;
+        query.prepare("SELECT aircraft_id FROM aircraft WHERE make = ? AND model = ? AND variant = ?");
+        query.addBindValue(make);
+        query.addBindValue(model);
+        query.addBindValue(variant);
+        query.exec();
+
+        if(query.first())
+        {
+            result.append(query.value(0).toString());
+            qDebug() << "db::RetreiveAircraftIdFromMakeModelVariant: Aircraft found! ID# " << result;
+            return result;
+        }else
+        {
+            result = result.left(result.length()-1);
+            result.append("0");
+            qDebug() << "db::RetreiveAircraftIdFromMakeModelVariant: ERROR - no AircraftId found.";
+            return  result;
+        }
+
+
+    }
+    static bool CommitTailToDb(QString registration, QString aircraft_id, QString company)
+    {
+        QSqlQuery commit;
+        commit.prepare("INSERT INTO tails (registration, aircraft_id, company) VALUES (?,?,?)");
+        commit.addBindValue(registration);
+        commit.addBindValue(aircraft_id);
+        commit.addBindValue(company);
+        commit.exec();
+        QString error = commit.lastError().text();
+        if(error.length() < 0)
+        {
+            qDebug() << "db::CommitAircraftToDb:: SQL error:" << error;
+            return false;
+        }else
+        {
+            return true;
+        }
+
+
+    }
+
+    /*
+     *
+     *
+     * Aircraft Database Related Functions
+     *
+     *
+     */
+
+    static QVector<QString> retreiveSetting(QString setting_id)
+    {
+        QSqlQuery query;
+        query.prepare("SELECT * FROM settings WHERE setting_id = ?");
+        query.addBindValue(setting_id);
+        query.exec();
+
+        QVector<QString> setting;
+
+        while(query.next()){
+            setting.append(query.value(0).toString());
+            setting.append(query.value(1).toString());
+            setting.append(query.value(2).toString());
+        }
+        return setting;
+    }
+
+    static void storesetting(int setting_id, QString setting_value)
+    {
+        QSqlQuery query;
+        query.prepare("UPDATE settings "
+                      "SET  setting = ? "
+                      "WHERE setting_id = ?");
+        query.addBindValue(setting_value);
+        query.addBindValue(setting_id);
+        query.exec();
+    }
+
+};
+

+ 52 - 0
easaview.cpp

@@ -0,0 +1,52 @@
+/*
+ *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 <https://www.gnu.org/licenses/>.
+ */
+#include "easaview.h"
+#include "ui_easaview.h"
+#include "dbman.cpp"
+#include <QSqlTableModel>
+
+EasaView::EasaView(QWidget *parent) :
+    QDialog(parent),
+    ui(new Ui::EasaView)
+{
+    ui->setupUi(this);
+
+
+    QSqlTableModel *model = new QSqlTableModel;
+    model->setTable("ViewEasa");
+    model->select();
+
+
+    QTableView *view = ui->EasaTableView;
+    view->setModel(model);
+    view->setAlternatingRowColors(true);
+    view->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
+    view->verticalHeader()->hide();
+    view->hideColumn(0);
+    view->show();
+}    //model->setEditStrategy(QSqlTableModel::OnManualSubmit);
+
+EasaView::~EasaView()
+{
+    delete ui;
+}
+
+void EasaView::on_QuitButton_clicked()
+{
+    EasaView::reject();
+}

+ 42 - 0
easaview.h

@@ -0,0 +1,42 @@
+/*
+ *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 <https://www.gnu.org/licenses/>.
+ */
+#ifndef EASAVIEW_H
+#define EASAVIEW_H
+
+#include <QDialog>
+
+namespace Ui {
+class EasaView;
+}
+
+class EasaView : public QDialog
+{
+    Q_OBJECT
+
+public:
+    explicit EasaView(QWidget *parent = nullptr);
+    ~EasaView();
+
+private slots:
+    void on_QuitButton_clicked();
+
+private:
+    Ui::EasaView *ui;
+};
+
+#endif // EASAVIEW_H

+ 46 - 0
easaview.ui

@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>EasaView</class>
+ <widget class="QDialog" name="EasaView">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>1280</width>
+    <height>480</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Dialog</string>
+  </property>
+  <layout class="QGridLayout" name="gridLayout">
+   <item row="1" column="0" colspan="2">
+    <widget class="QTableView" name="EasaTableView"/>
+   </item>
+   <item row="0" column="0" colspan="2">
+    <widget class="QLabel" name="label">
+     <property name="font">
+      <font>
+       <pointsize>24</pointsize>
+      </font>
+     </property>
+     <property name="text">
+      <string>Work in Progress</string>
+     </property>
+     <property name="alignment">
+      <set>Qt::AlignCenter</set>
+     </property>
+    </widget>
+   </item>
+   <item row="2" column="0" colspan="2">
+    <widget class="QPushButton" name="QuitButton">
+     <property name="text">
+      <string>Quit</string>
+     </property>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>

+ 459 - 0
editflight.cpp

@@ -0,0 +1,459 @@
+/*
+ *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 <https://www.gnu.org/licenses/>.
+ */
+#include "editflight.h"
+#include "ui_editflight.h"
+#include "calc.h"
+#include "dbman.cpp"
+#include <QMessageBox>
+#include <QDebug>
+
+/*
+ * Initialise variables
+ */
+QDate editdate(QDate::currentDate());
+QString editdoft(QDate::currentDate().toString(Qt::ISODate));
+QString editdept;
+QString editdest;
+QTime edittofb;
+QTime edittonb;
+QTime edittblk;
+QString editpic;
+QString editacft;
+QVector<QString> editflight;
+
+
+
+
+
+
+/*
+ * Window
+ */
+
+EditFlight::EditFlight(QWidget *parent) :
+    QDialog(parent),
+    ui(new Ui::EditFlight)
+{
+    ui->setupUi(this);
+
+    editflight = db::RetreiveScratchpad();
+    qDebug() << "EditFlight: Re-assigning variables from vector " << editflight;
+
+    editdate = QDate::fromString(editflight[1],Qt::ISODate);
+    editdoft = editflight[1];
+    editdept = editflight[2];
+    edittofb = QTime::fromString(editflight[3], "hh:mm");
+    editdest = editflight[4];
+    edittonb = QTime::fromString(editflight[5], "hh:mm");
+    // flight[6] is blocktime
+    editpic = editflight[7];
+    editacft = editflight[8];
+    qDebug() << "Reassigned:" << editdate << editdoft << editdept << edittofb << editdest << edittonb << editpic << editacft;
+
+    qDebug() << "Re-Filling Form from Scratchpad";
+    returnInput(editflight);
+
+
+
+    // Validators for Line Edits
+    QRegExp icao_rx("[a-zA-Z]?[a-zA-Z]?[a-zA-Z]?[a-zA-Z]"); // allow only letters (upper and lower)
+    QValidator *ICAOvalidator = new QRegExpValidator(icao_rx, this);
+    ui->newDept->setValidator(ICAOvalidator);
+    ui->newDest->setValidator(ICAOvalidator);
+    QRegExp timehhmm("([01]?[0-9]|2[0-3]):?[0-5][0-9]"); //allows time in 24h format with optional leading 0 and with or without seperator
+    QValidator *timeInputValidator = new QRegExpValidator(timehhmm, this);
+    ui->newTofb->setValidator(timeInputValidator);
+    ui->newTonb->setValidator(timeInputValidator);
+    ui->deptHintlineEdit->setFocusPolicy(Qt::NoFocus);
+    ui->destHintlineEdit->setFocusPolicy(Qt::NoFocus);
+    ui->acftHintLineEdit->setFocusPolicy(Qt::NoFocus);
+    ui->picHintLineEdit->setFocusPolicy(Qt::NoFocus);
+    ui->deptTZ->setFocusPolicy(Qt::NoFocus);
+    ui->desTZ->setFocusPolicy(Qt::NoFocus);
+    ui->newDept->setFocus();
+
+}
+
+EditFlight::~EditFlight()
+{
+    delete ui;
+}
+
+/*
+ * Functions
+ */
+
+void EditFlight::nope()
+{
+    QMessageBox nope; //error box
+    nope.setText("This feature is not yet available!");
+    nope.exec();
+}
+
+
+QVector<QString> EditFlight::collectInput()
+{
+    // Collect input from the user fields and return a vector containing the flight information
+    QString editdoft = editdate.toString(Qt::ISODate); // Format Date
+    QTime tblk = calc::blocktime(edittofb,edittonb);   // Calculate Blocktime
+
+
+    // Prepare Vector for commit to database
+    editflight = db::CreateFlightVectorFromInput(editdoft, editdept, edittofb, editdest, edittonb, tblk, editpic, editacft);
+    qDebug() << "Created flight vector:" << editflight;
+
+    return editflight;
+}
+
+bool EditFlight::verifyInput()
+    //check if the input is correctly formatted and all required fields are filled
+{
+
+    bool deptValid = false;
+    bool tofbValid = false;
+    bool destValid = false;
+    bool tonbValid = false;
+    bool tblkValid = false;
+    bool picValid = false;
+    bool acftValid = false;
+
+    QTime tblk = calc::blocktime(edittofb,edittonb);
+    int checktblk = calc::time_to_minutes(tblk);
+
+    bool doftValid = true; //doft assumed to be always valid due to QDateTimeEdit constraints
+    qDebug() << "EditFlight::verifyInput() says: Date:" << editdoft << " - Valid?\t" << doftValid;
+
+    deptValid = db::CheckICAOValid(editdept);
+    qDebug() << "EditFlight::verifyInput() says: Departure is:\t" << editdept << " - Valid?\t" << deptValid;
+
+    destValid = db::CheckICAOValid(editdest);
+    qDebug() << "EditFlight::verifyInput() says: Destination is:\t" << editdest << " - Valid?\t" << destValid;
+
+    tofbValid = (unsigned)(calc::time_to_minutes(edittofb)-0) <= (1440-0) && edittofb.toString("hh:mm") != ""; // Make sure time is within range, DB 1 day = 1440 minutes. 0 is allowed (midnight) & that it is not empty.
+    qDebug() << "EditFlight::verifyInput() says: tofb is:\t\t" << edittofb.toString("hh:mm") << " - Valid?\t" << tofbValid;
+
+    tonbValid = (unsigned)(calc::time_to_minutes(edittonb)-0) <= (1440-0) && edittofb.toString("hh:mm") != ""; // Make sure time is within range, DB 1 day = 1440 minutes
+    qDebug() << "EditFlight::verifyInput() says: tonb is:\t\t" << edittonb.toString("hh:mm")<< " - Valid?\t" << tonbValid;
+
+    picValid = (editpic.toInt() != 0); // pic should be a pilot_id retreived from the database
+    qDebug() << "EditFlight::verifyInput() says: pic is pilotd_id:\t" << editpic << " - Valid?\t" << picValid;
+
+    acftValid = (editacft.toInt() != 0);
+    qDebug() << "EditFlight::verifyInput() says: acft is tail_id:\t" << editacft << " - Valid?\t" << acftValid;
+
+    tblkValid = checktblk != 0;
+    qDebug() << "EditFlight::verifyInput() says: tblk is:\t\t" << tblk.toString("hh:mm") << " - Valid?\t" << tblkValid;
+
+
+
+    if(deptValid && tofbValid  && destValid && tonbValid
+             && tblkValid && picValid && acftValid)
+    {
+        qDebug() << "====================================================";
+        qDebug() << "EditFlight::verifyInput() says: All checks passed! Very impressive. ";
+        return 1;
+    }else
+    {
+        qDebug() << "====================================================";
+        qDebug() << "EditFlight::verifyInput() says: Flight is invalid.";
+        qDebug() << "EditFlight::verifyInput() says: I will call the cops.";
+        return 0;
+    }
+    return 0;
+
+}
+
+void EditFlight::returnInput(QVector<QString> flight)
+{
+    // Re-populates the input masks with the selected fields if input was erroneous to allow for corrections to be made
+    ui->newDoft->setDate(QDate::fromString(flight[1],Qt::ISODate));
+    ui->newDept->setText(flight[2]);
+    ui->newTofb->setText(flight[3]);
+    ui->newDest->setText(flight[4]);
+    ui->newTonb->setText(flight[5]);
+    // flight[6] is blocktime
+    ui->newPic->setText(db::RetreivePilotNameFromID(flight[7]));
+    ui->newAcft->setText(db::RetreiveRegistration(flight[8]));
+}
+
+/*
+ * Slots
+ */
+
+void EditFlight::on_newDoft_editingFinished()
+{
+    editdate = ui->newDoft->date();
+    editdoft = editdate.toString(Qt::ISODate);
+    //ui->dateHintLineEdit->setText(doft);
+}
+
+void EditFlight::on_newDept_textChanged(const QString &arg1)
+{
+    if(arg1.length() > 2)
+    {
+        QString result;
+        result = db::RetreiveAirportNameFromIcaoOrIata(arg1);
+        ui->deptHintlineEdit->setPlaceholderText(result);
+    }
+}
+
+void EditFlight::on_newDest_textChanged(const QString &arg1)
+{
+    if(arg1.length() > 2)
+    {
+        QString result;
+        result = db::RetreiveAirportNameFromIcaoOrIata(arg1);
+        ui->destHintlineEdit->setPlaceholderText(result);
+    }
+}
+
+void EditFlight::on_newDept_editingFinished()
+{
+    editdept = ui->newDept->text().toUpper();
+    ui->newDept->setText(editdept);
+    if (!ui->deptHintlineEdit->placeholderText().compare("No matching airport found.", Qt::CaseInsensitive))
+    {
+        QMessageBox msgBox;
+        msgBox.setText("Airport not found.\nCreate new entry in Database?");
+        msgBox.exec();
+    }else if (editdept.length() < 4)
+    {
+        qDebug() << "on_new_Dept_editingFinished() Incomplete entry. Completing.";
+        //editdept = db::CompleteIcaoOrIata(editdept);
+        ui->newDept->setText(editdept);
+    }
+
+}
+
+void EditFlight::on_newTofb_editingFinished()
+{
+    bool containsSeperator = ui->newTofb->text().contains(":");
+    if(ui->newTofb->text().length() == 4 && !containsSeperator)
+    {
+        qDebug() << "1) Contains seperator: " << containsSeperator << "Length = " << ui->newTofb->text().length();
+        edittofb = QTime::fromString(ui->newTofb->text(),"hhmm");
+        qDebug() << edittofb;
+    }else if(ui->newTofb->text().length() == 3 && !containsSeperator)
+    {
+        if(ui->newTofb->text().toInt() < 240) //Qtime is invalid if time is between 000 and 240 for this case
+        {
+            QString tempstring = ui->newTofb->text().prepend("0");
+            edittofb = QTime::fromString(tempstring,"hhmm");
+            qDebug() << tempstring << "is the tempstring (Special Case) " << edittofb;
+        }else
+        {
+            qDebug() << "2) Contains seperator: " << containsSeperator << "Length = " << ui->newTofb->text().length();
+            qDebug() << "Tofb = " << ui->newTofb->text();
+            edittofb = QTime::fromString(ui->newTofb->text(),"Hmm");
+            qDebug() << edittofb;
+        }
+    }else if(ui->newTofb->text().length() == 4 && containsSeperator)
+    {
+        qDebug() << "3) Contains seperator: " << containsSeperator << "Length = " << ui->newTofb->text().length();
+        edittofb = QTime::fromString(ui->newTofb->text(),"h:mm");
+        qDebug() << edittofb;
+
+    }else if(ui->newTofb->text().length() == 5 && containsSeperator)
+    {
+        qDebug() << "4) Contains seperator: " << containsSeperator << "Length = " << ui->newTofb->text().length();
+        edittofb = QTime::fromString(ui->newTofb->text(),"hh:mm");
+        qDebug() << edittofb;
+    }
+    ui->newTofb->setText(edittofb.toString("hh:mm"));
+}
+
+void EditFlight::on_newDest_editingFinished()
+{
+    editdest = ui->newDest->text().toUpper();
+    ui->newDest->setText(editdest);
+    if (!ui->destHintlineEdit->placeholderText().compare("No matching airport found.", Qt::CaseInsensitive))
+    {
+        QMessageBox msgBox;
+        msgBox.setText("Airport not found.\nCreate new entry in Database?");
+        msgBox.exec();
+    }else if (editdest.length() < 4)
+    {
+        qDebug() << "on_new_Dest_editingFinished() Incomplete entry. Completing.";
+        //editdest = db::CompleteIcaoOrIata(editdest);
+        ui->newDest->setText(editdest);
+        //ui->newDest->setText(db::CompleteIcaoOrIata(dest));
+    }
+}
+
+void EditFlight::on_newTonb_editingFinished()
+{
+    bool containsSeperator = ui->newTonb->text().contains(":");
+    if(ui->newTonb->text().length() == 4 && !containsSeperator)
+    {
+        edittonb = QTime::fromString(ui->newTonb->text(),"hhmm");
+        qDebug() << edittonb;
+    }else if(ui->newTonb->text().length() == 3 && !containsSeperator)
+    {
+        if(ui->newTonb->text().toInt() < 240) //Qtime is invalid if time is between 000 and 240 for this case
+        {
+            QString tempstring = ui->newTonb->text().prepend("0");
+            edittonb = QTime::fromString(tempstring,"hhmm");
+            qDebug() << tempstring << "is the tempstring (Special Case) " << edittonb;
+        }else
+        {
+            qDebug() << "Tofb = " << ui->newTonb->text();
+            edittonb = QTime::fromString(ui->newTonb->text(),"Hmm");
+            qDebug() << edittonb;
+        }
+    }else if(ui->newTonb->text().length() == 4 && containsSeperator)
+    {
+        edittonb = QTime::fromString(ui->newTonb->text(),"h:mm");
+        qDebug() << edittonb;
+
+    }else if(ui->newTonb->text().length() == 5 && containsSeperator)
+    {
+        edittonb = QTime::fromString(ui->newTonb->text(),"hh:mm");
+        qDebug() << edittonb;
+    }
+    ui->newTonb->setText(edittonb.toString("hh:mm"));
+}
+
+void EditFlight::on_newPic_textChanged(const QString &arg1)
+{
+    qDebug() << arg1;
+    /*{
+        if(arg1.length() > 3)
+        {
+            QVector<QString> hint = db::RetreivePilotNameFromString(arg1);
+            if(hint.size()!= 0)
+            {
+                QString combinedname = hint[0] + ", " + hint[1] + " [ " + hint[2] + " ]";
+                ui->picHintLineEdit->setPlaceholderText(combinedname);
+            }
+        }
+    }*/
+
+}
+void EditFlight::on_newPic_editingFinished()
+{
+    /*QString input = ui->newPic->text();
+    if(input.length()>2)
+    {
+        QVector<QString> result;
+        result = db::RetreivePilotNameFromString(input);
+        qDebug() << result;
+        if(result.size()!=0)
+        {
+            QString lastname = result[0];
+            ui->newPic->setText(lastname);// to do: pop up to navigate result set, here first result is selected
+
+            editpic = db::RetreivePilotIdFromString(lastname);// to do, adjust before commit
+            //qDebug() << "on_newPic_editingFinished() says: Pilot ID = " << pic;
+        }else
+        {
+            QMessageBox msgBox;
+            msgBox.setText("No Pilot found!");// to do: add new pilot
+            msgBox.exec();
+            ui->newPic->setText("");
+            ui->newPic->setFocus();
+        }
+
+    }else if (input.length() == 0)
+    {
+
+    }else
+    {
+        QMessageBox msgBox;
+        msgBox.setText("For Auto-Completion, please enter 3 or more characters!");
+        msgBox.exec();
+        ui->newPic->setFocus();
+    }*/
+
+}
+
+void EditFlight::on_newAcft_textChanged(const QString &arg1)
+{
+    if(arg1.length() > 2)
+    {
+        QVector<QString> hint = db::RetreiveAircraftTypeFromReg(arg1);
+        if(hint.size() != 0)
+        {
+            ui->acftHintLineEdit->setPlaceholderText(hint[1] + " [ " + hint[0] + " | " + hint[2] + " ]");
+        }
+
+    }
+}
+
+void EditFlight::on_newAcft_editingFinished()
+{
+    editacft = ui->newAcft->text();
+    if(ui->newAcft->text().length()>2)
+    {
+        QVector<QString> result;
+        result = db::RetreiveAircraftTypeFromReg(editacft);
+        if(result.size()!=0)
+        {
+            ui->newAcft->setText(result[0]);// to do: pop up to navigate result set, here first result is selected
+            editacft = result[3];
+        }else
+        {
+            QMessageBox msgBox;
+            msgBox.setText("No Aircraft found!");
+            msgBox.exec();
+            ui->newAcft->setText("");
+            ui->newAcft->setFocus();
+        }
+    }
+}
+
+
+void EditFlight::on_buttonBox_accepted()
+{
+    QVector<QString> flight;
+    flight = collectInput();
+    if(verifyInput())
+    {
+        //!x db::CommitFlight(flight);
+        qDebug() << flight << "Has been commited.";
+        QMessageBox msgBox;
+        msgBox.setText("Flight successfully edited. (At least once I wrote that function. Now nothing has happened.)\nlol\nWhat a troll.");
+        msgBox.exec();
+    }else
+    {
+        qDebug() << "Invalid Input. No entry has been made in the database.";
+        db::CommitToScratchpad(flight);
+        QMessageBox msgBox;
+        msgBox.setText("La Base de datos se niega a ser violada!");
+        msgBox.exec();
+        EditFlight nf(this);
+        nf.exec();
+    }
+
+}
+
+void EditFlight::on_buttonBox_rejected()
+{
+    db::ClearScratchpad();
+}
+
+void EditFlight::on_verifyButton_clicked()
+{
+    editflight = collectInput();
+    if (verifyInput())
+    {
+        ui->verifyEdit->setPlaceholderText("No Errors detected.");
+    }else
+    {
+    ui->verifyEdit->setPlaceholderText("Invalid Input.");
+    }
+}

+ 77 - 0
editflight.h

@@ -0,0 +1,77 @@
+/*
+ *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 <https://www.gnu.org/licenses/>.
+ */
+#ifndef EDITFLIGHT_H
+#define EDITFLIGHT_H
+
+#include <QDialog>
+
+namespace Ui {
+class EditFlight;
+}
+
+class EditFlight : public QDialog
+{
+    Q_OBJECT
+
+public:
+    explicit EditFlight(QWidget *parent = nullptr);
+    ~EditFlight();
+
+private slots:
+    void nope();//error box
+
+    QVector<QString> collectInput();
+
+    bool verifyInput();
+
+    void returnInput(QVector<QString> flight);
+
+    void on_verifyButton_clicked();
+
+    void on_buttonBox_accepted();
+
+    void on_buttonBox_rejected();
+
+    void on_newDept_editingFinished();
+
+    void on_newDoft_editingFinished();
+
+    void on_newTofb_editingFinished();
+
+    void on_newDest_editingFinished();
+
+    void on_newTonb_editingFinished();
+
+    void on_newAcft_editingFinished();
+
+    void on_newPic_editingFinished();
+
+    void on_newDept_textChanged(const QString &arg1);
+
+    void on_newDest_textChanged(const QString &arg1);
+
+    void on_newAcft_textChanged(const QString &arg1);
+
+    void on_newPic_textChanged(const QString &arg1);
+    
+    
+private:
+    Ui::EditFlight *ui;
+};
+
+#endif // EDITFLIGHT_H

+ 347 - 0
editflight.ui

@@ -0,0 +1,347 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>EditFlight</class>
+ <widget class="QDialog" name="EditFlight">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>695</width>
+    <height>395</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Edit Flight</string>
+  </property>
+  <layout class="QGridLayout" name="gridLayout">
+   <item row="2" column="3" colspan="2">
+    <widget class="QLabel" name="tofbLabel">
+     <property name="text">
+      <string>Time</string>
+     </property>
+    </widget>
+   </item>
+   <item row="4" column="3" colspan="2">
+    <widget class="QLabel" name="tonbLabel">
+     <property name="text">
+      <string>Time</string>
+     </property>
+    </widget>
+   </item>
+   <item row="6" column="0" colspan="2">
+    <widget class="QLabel" name="picLabel">
+     <property name="text">
+      <string>Name PIC</string>
+     </property>
+    </widget>
+   </item>
+   <item row="6" column="3">
+    <widget class="QLabel" name="searchLabelpic">
+     <property name="text">
+      <string>Search</string>
+     </property>
+    </widget>
+   </item>
+   <item row="4" column="9">
+    <widget class="QComboBox" name="desTZ">
+     <item>
+      <property name="text">
+       <string>UTC</string>
+      </property>
+     </item>
+    </widget>
+   </item>
+   <item row="3" column="3" colspan="2">
+    <widget class="QLabel" name="placeLabel2">
+     <property name="text">
+      <string>Place</string>
+     </property>
+    </widget>
+   </item>
+   <item row="4" column="10">
+    <spacer name="horizontalSpacer_5">
+     <property name="orientation">
+      <enum>Qt::Horizontal</enum>
+     </property>
+     <property name="sizeHint" stdset="0">
+      <size>
+       <width>288</width>
+       <height>20</height>
+      </size>
+     </property>
+    </spacer>
+   </item>
+   <item row="3" column="0" colspan="3">
+    <widget class="QLabel" name="destLabel">
+     <property name="text">
+      <string>Destination</string>
+     </property>
+    </widget>
+   </item>
+   <item row="2" column="9">
+    <widget class="QComboBox" name="deptTZ">
+     <item>
+      <property name="text">
+       <string>UTC</string>
+      </property>
+     </item>
+    </widget>
+   </item>
+   <item row="2" column="10">
+    <spacer name="horizontalSpacer_6">
+     <property name="orientation">
+      <enum>Qt::Horizontal</enum>
+     </property>
+     <property name="sizeHint" stdset="0">
+      <size>
+       <width>288</width>
+       <height>20</height>
+      </size>
+     </property>
+    </spacer>
+   </item>
+   <item row="5" column="0">
+    <widget class="QLabel" name="acftLabel">
+     <property name="text">
+      <string>Aircraft</string>
+     </property>
+    </widget>
+   </item>
+   <item row="1" column="3" colspan="2">
+    <widget class="QLabel" name="placeLabel1">
+     <property name="text">
+      <string>Place</string>
+     </property>
+    </widget>
+   </item>
+   <item row="7" column="7" colspan="4">
+    <widget class="QDialogButtonBox" name="buttonBox">
+     <property name="orientation">
+      <enum>Qt::Horizontal</enum>
+     </property>
+     <property name="standardButtons">
+      <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+     </property>
+    </widget>
+   </item>
+   <item row="3" column="9" colspan="2">
+    <widget class="QLineEdit" name="destHintlineEdit">
+     <property name="maxLength">
+      <number>0</number>
+     </property>
+     <property name="readOnly">
+      <bool>true</bool>
+     </property>
+     <property name="placeholderText">
+      <string>Frankfurt International Airport</string>
+     </property>
+    </widget>
+   </item>
+   <item row="5" column="3">
+    <widget class="QLabel" name="searchLabelacft">
+     <property name="text">
+      <string>Search</string>
+     </property>
+    </widget>
+   </item>
+   <item row="7" column="5" colspan="2">
+    <widget class="QLineEdit" name="verifyEdit"/>
+   </item>
+   <item row="1" column="0" colspan="2">
+    <widget class="QLabel" name="deptLabel">
+     <property name="text">
+      <string>Departure</string>
+     </property>
+    </widget>
+   </item>
+   <item row="5" column="8" colspan="3">
+    <widget class="QLineEdit" name="acftHintLineEdit">
+     <property name="readOnly">
+      <bool>true</bool>
+     </property>
+     <property name="placeholderText">
+      <string>Boeing 737-800</string>
+     </property>
+    </widget>
+   </item>
+   <item row="5" column="5" colspan="2">
+    <widget class="QLineEdit" name="newAcft">
+     <property name="placeholderText">
+      <string>D-LMAO</string>
+     </property>
+    </widget>
+   </item>
+   <item row="3" column="5" colspan="3">
+    <widget class="QLineEdit" name="newDest">
+     <property name="toolTip">
+      <string>Enter the ICAO 4-letter Identifier of the Airport</string>
+     </property>
+     <property name="inputMethodHints">
+      <set>Qt::ImhNone</set>
+     </property>
+     <property name="maxLength">
+      <number>4</number>
+     </property>
+     <property name="placeholderText">
+      <string>EDDF</string>
+     </property>
+    </widget>
+   </item>
+   <item row="7" column="0" colspan="2">
+    <widget class="QPushButton" name="verifyButton">
+     <property name="text">
+      <string>Verify</string>
+     </property>
+    </widget>
+   </item>
+   <item row="0" column="0" colspan="3">
+    <widget class="QLabel" name="doftLabel">
+     <property name="text">
+      <string>Date of Flight</string>
+     </property>
+    </widget>
+   </item>
+   <item row="6" column="5" colspan="2">
+    <widget class="QLineEdit" name="newPic">
+     <property name="placeholderText">
+      <string>self</string>
+     </property>
+    </widget>
+   </item>
+   <item row="1" column="5" colspan="3">
+    <widget class="QLineEdit" name="newDept">
+     <property name="toolTip">
+      <string>Enter the ICAO 4-letter Identifier of the Airport</string>
+     </property>
+     <property name="inputMethodHints">
+      <set>Qt::ImhNone</set>
+     </property>
+     <property name="maxLength">
+      <number>4</number>
+     </property>
+     <property name="placeholderText">
+      <string>KJFK</string>
+     </property>
+    </widget>
+   </item>
+   <item row="1" column="9" colspan="2">
+    <widget class="QLineEdit" name="deptHintlineEdit">
+     <property name="maxLength">
+      <number>0</number>
+     </property>
+     <property name="readOnly">
+      <bool>true</bool>
+     </property>
+     <property name="placeholderText">
+      <string>John F. Kennedy Intl. Airport</string>
+     </property>
+    </widget>
+   </item>
+   <item row="6" column="8" colspan="3">
+    <widget class="QLineEdit" name="picHintLineEdit">
+     <property name="readOnly">
+      <bool>true</bool>
+     </property>
+     <property name="placeholderText">
+      <string>Sullenberger, C.</string>
+     </property>
+    </widget>
+   </item>
+   <item row="0" column="4" colspan="3">
+    <widget class="QDateEdit" name="newDoft">
+     <property name="dateTime">
+      <datetime>
+       <hour>23</hour>
+       <minute>0</minute>
+       <second>0</second>
+       <year>2019</year>
+       <month>12</month>
+       <day>24</day>
+      </datetime>
+     </property>
+     <property name="displayFormat">
+      <string>yyyy/MM/dd</string>
+     </property>
+     <property name="calendarPopup">
+      <bool>true</bool>
+     </property>
+     <property name="timeSpec">
+      <enum>Qt::UTC</enum>
+     </property>
+    </widget>
+   </item>
+   <item row="2" column="5">
+    <widget class="QLineEdit" name="newTofb">
+     <property name="maxLength">
+      <number>5</number>
+     </property>
+    </widget>
+   </item>
+   <item row="4" column="5">
+    <widget class="QLineEdit" name="newTonb"/>
+   </item>
+   <item row="0" column="9">
+    <widget class="QLineEdit" name="dateHintLineEdit">
+     <property name="readOnly">
+      <bool>true</bool>
+     </property>
+     <property name="placeholderText">
+      <string>YYYY/MM/DD</string>
+     </property>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <tabstops>
+  <tabstop>newDoft</tabstop>
+  <tabstop>newDept</tabstop>
+  <tabstop>newTofb</tabstop>
+  <tabstop>newDest</tabstop>
+  <tabstop>newTonb</tabstop>
+  <tabstop>newAcft</tabstop>
+  <tabstop>newPic</tabstop>
+  <tabstop>verifyEdit</tabstop>
+  <tabstop>deptHintlineEdit</tabstop>
+  <tabstop>deptTZ</tabstop>
+  <tabstop>destHintlineEdit</tabstop>
+  <tabstop>desTZ</tabstop>
+  <tabstop>acftHintLineEdit</tabstop>
+  <tabstop>picHintLineEdit</tabstop>
+  <tabstop>verifyButton</tabstop>
+ </tabstops>
+ <resources/>
+ <connections>
+  <connection>
+   <sender>buttonBox</sender>
+   <signal>accepted()</signal>
+   <receiver>EditFlight</receiver>
+   <slot>accept()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>248</x>
+     <y>254</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>157</x>
+     <y>274</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>buttonBox</sender>
+   <signal>rejected()</signal>
+   <receiver>EditFlight</receiver>
+   <slot>reject()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>316</x>
+     <y>260</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>286</x>
+     <y>274</y>
+    </hint>
+   </hints>
+  </connection>
+ </connections>
+</ui>