Kaynağa Gözat

Redesigning NewFlightDialog

Felix Turo 3 yıl önce
ebeveyn
işleme
2e587f9603

+ 192 - 13
src/gui/dialogues/newnewflightdialog.cpp

@@ -4,6 +4,7 @@
 #include "src/functions/alog.h"
 #include <QDateTime>
 #include <QCompleter>
+#include <QKeyEvent>
 
 NewNewFlightDialog::NewNewFlightDialog(ACompletionData &completion_data,
                                        QWidget *parent)
@@ -23,29 +24,51 @@ NewNewFlightDialog::~NewNewFlightDialog()
 void NewNewFlightDialog::init()
 {
     // Initialise line edit lists
-    QList<QLineEdit*> time_line_edits = {ui->tofbTimeLineEdit, ui->tonbTimeLineEdit};
-    timeLineEdits = &time_line_edits;
-    QList<QLineEdit*> location_line_edits = {ui->deptLocationLineEdit, ui->destLocationLineEdit};
-    locationLineEdits = &location_line_edits;
-    QList<QLineEdit*> pilot_name_line_edits = {ui->picNameLineEdit, ui->sicNameLineEdit, ui->thirdPilotNameLineEdit};
-    pilotNameLineEdits = &pilot_name_line_edits;
+    timeLineEdits = {ui->tofbTimeLineEdit, ui->tonbTimeLineEdit};
+    locationLineEdits = {ui->deptLocationLineEdit, ui->destLocationLineEdit};
+    pilotNameLineEdits = {ui->picNameLineEdit, ui->sicNameLineEdit, ui->thirdPilotNameLineEdit};
+
+    // {doft = 0, dept = 1, dest = 2, tofb = 3, tonb = 4, pic = 5, acft = 6}
+    mandatoryLineEdits = {ui->doftLineEdit, ui->deptLocationLineEdit, ui->destLocationLineEdit,
+                          ui->tofbTimeLineEdit, ui->tonbTimeLineEdit,
+                          ui->picNameLineEdit, ui->acftLineEdit};
 
     setupRawInputValidation();
-    //setupSignalsAndSlots();
+    setupSignalsAndSlots();
     //readSettings();
 
     ui->doftLineEdit->setText(QDate::currentDate().toString(Qt::ISODate));
 }
 
+/*!
+ * \brief NewNewFlightDialog::eventFilter the event filter is used to invalidate mandatory line edits on entering. This acts as a double-check against
+ * false inputs for cases when the editingFinished() signal is not emitted due to the QValidators blocking it.
+ */
+bool NewNewFlightDialog::eventFilter(QObject* object, QEvent* event)
+{
+    auto line_edit = qobject_cast<QLineEdit*>(object);
+    if (line_edit != nullptr) {
+        if (mandatoryLineEdits.contains(line_edit) && event->type() == QEvent::FocusIn) {
+            //DEB << "Invalidating " << line_edit->objectName() << "(Focus In Event)";
+            validationState.invalidate(mandatoryLineEdits.indexOf(line_edit));
+            return false;
+        }
+    }
+    return false;
+}
+
+/*!
+ * \brief NewNewFlightDialog::setupRawInputValidation outfits the line edits with QRegularExpresionValidators and QCompleters
+ */
 void NewNewFlightDialog::setupRawInputValidation()
 {
-    for (const auto& line_edit : *timeLineEdits) {
-        DEB << "Setting up: " << line_edit->objectName();
+    // Time Line Edits
+    for (const auto& line_edit : qAsConst(timeLineEdits)) {
         auto validator = new QRegularExpressionValidator(QRegularExpression("([01]?[0-9]|2[0-3]):?[0-5][0-9]?"), line_edit);
         line_edit->setValidator(validator);
     }
-
-    for (const auto& line_edit : *locationLineEdits) {
+    // Location Line Edits
+    for (const auto& line_edit : qAsConst(locationLineEdits)) {
         auto validator = new QRegularExpressionValidator(QRegularExpression("[a-zA-Z0-9]{1,4}"), line_edit);
         line_edit->setValidator(validator);
 
@@ -55,12 +78,168 @@ void NewNewFlightDialog::setupRawInputValidation()
         completer->setFilterMode(Qt::MatchContains);
         line_edit->setCompleter(completer);
     }
-
-    for (const auto& line_edit : *pilotNameLineEdits) {
+    // Name Line Edits
+    for (const auto& line_edit : qAsConst(pilotNameLineEdits)) {
         auto completer = new QCompleter(completionData.pilotList, line_edit);
         completer->setCaseSensitivity(Qt::CaseInsensitive);
         completer->setCompletionMode(QCompleter::PopupCompletion);
         completer->setFilterMode(Qt::MatchContains);
         line_edit->setCompleter(completer);
     }
+    // Acft Line Edit
+    auto completer = new QCompleter(completionData.tailsList, ui->acftLineEdit);
+    completer->setCaseSensitivity(Qt::CaseInsensitive);
+    completer->setCompletionMode(QCompleter::PopupCompletion);
+    completer->setFilterMode(Qt::MatchContains);
+    ui->acftLineEdit->setCompleter(completer);
+
+}
+
+void NewNewFlightDialog::setupSignalsAndSlots()
+{
+    for (const auto& line_edit : qAsConst(timeLineEdits))
+        QObject::connect(line_edit, &QLineEdit::editingFinished,
+                         this, &NewNewFlightDialog::onTimeLineEdit_editingFinished);
+    // Change text to upper case for location and acft line edits
+    QObject::connect(ui->acftLineEdit, &QLineEdit::textChanged,
+                     this, &NewNewFlightDialog::toUpper);
+    for (const auto& line_edit : qAsConst(locationLineEdits)) {
+        QObject::connect(line_edit, &QLineEdit::textChanged,
+                         this, &NewNewFlightDialog::toUpper);
+        QObject::connect(line_edit, &QLineEdit::editingFinished,
+                         this, &NewNewFlightDialog::onLocationLineEdit_editingFinished);
+    }
+    for (const auto& line_edit : qAsConst(pilotNameLineEdits))
+        QObject::connect(line_edit, &QLineEdit::editingFinished,
+                         this, &NewNewFlightDialog::onPilotNameLineEdit_editingFinshed);
+
+    // install event filter for focus in vent
+    for (const auto& line_edit : qAsConst(mandatoryLineEdits)) {
+        line_edit->installEventFilter(this);
+    }
+}
+
+void NewNewFlightDialog::onGoodInputReceived(QLineEdit *line_edit)
+{
+    DEB << line_edit->objectName() << " - Good input received - " << line_edit->text();
+    line_edit->setStyleSheet(QString());
+
+    if (mandatoryLineEdits.contains(line_edit))
+        validationState.validate(mandatoryLineEdits.indexOf(line_edit));
+    if (validationState.allValid())
+        DEB << "All mandatory Line Edits valid!";
+        // Go to onMandatoryLineEditsFilled?
+    else
+        validationState.printValidationStatus();
+}
+
+void NewNewFlightDialog::onBadInputReceived(QLineEdit *line_edit)
+{
+    DEB << line_edit->objectName() << " - Bad input received - " << line_edit->text();
+    line_edit->setStyleSheet(QStringLiteral("border: 1px solid red"));
+    line_edit->setText(QString());
+
+    if (mandatoryLineEdits.contains(line_edit))
+        validationState.invalidate(mandatoryLineEdits.indexOf(line_edit));
+
+    validationState.printValidationStatus();
+}
+// # Slots
+void NewNewFlightDialog::toUpper(const QString &text)
+{
+    const auto line_edit = this->findChild<QLineEdit*>(sender()->objectName());
+    {
+        const QSignalBlocker blocker(line_edit);
+        line_edit->setText(text.toUpper());
+    }
+}
+
+void NewNewFlightDialog::onTimeLineEdit_editingFinished()
+{
+    auto line_edit = this->findChild<QLineEdit*>(sender()->objectName());
+    DEB << line_edit->objectName() << "Editing finished -" << line_edit->text();
+
+    const QString time_string = ATime::formatTimeInput(line_edit->text());
+    const QTime time = ATime::fromString(time_string);
+
+    if (time.isValid()) {
+        line_edit->setText(time_string);
+        onGoodInputReceived(line_edit);
+    } else {
+        onBadInputReceived(line_edit);
+        line_edit->setText(QString());
+    }
+
+}
+
+void NewNewFlightDialog::onPilotNameLineEdit_editingFinshed()
+{
+    auto line_edit = this->findChild<QLineEdit*>(sender()->objectName());
+    DEB << line_edit->objectName() << "Editing Finished -" << line_edit->text();
+
+    if(line_edit->text().contains(self, Qt::CaseInsensitive)) {
+        DEB << "self recognized.";
+        line_edit->setText(completionData.pilotsIdMap.value(1));
+        onGoodInputReceived(line_edit);
+        return;
+    }
+
+    if(completionData.pilotsIdMap.key(line_edit->text()) != 0) {
+        DEB << "Mapped: " << line_edit->text() << completionData.pilotsIdMap.key(line_edit->text());
+        onGoodInputReceived(line_edit);
+        return;
+    }
+
+    if (line_edit->text().isEmpty()) {
+        return;
+    }
+
+    if (!line_edit->completer()->currentCompletion().isEmpty()) {
+        DEB << "Trying to fix input...";
+        line_edit->setText(line_edit->completer()->currentCompletion());
+        emit line_edit->editingFinished();
+        return;
+    }
+
+    onBadInputReceived(line_edit);
+    TODO << "Add new Pilot...";
+    //addNewPilot(line_edit);
+}
+
+void NewNewFlightDialog::onLocationLineEdit_editingFinished()
+{
+    const QString line_edit_name = sender()->objectName();
+    const auto line_edit = this->findChild<QLineEdit*>(line_edit_name);
+    DEB << line_edit->objectName() << "Editing Finished -" << line_edit->text();
+    QLabel* name_label;
+    if (line_edit_name.contains(QLatin1String("dept"))) {
+        name_label = ui->deptNameLabel;
+    } else {
+        name_label = ui->destNameLabel;
+    }
+
+    const auto &text = line_edit->text();
+    int airport_id = 0;
+
+    // try to map iata or icao code to airport id;
+    if (text.length() == 3) {
+        airport_id = completionData.airportIataIdMap.key(text);
+    } else {
+        airport_id = completionData.airportIcaoIdMap.key(text);
+    }
+    // check result
+    if (airport_id == 0) {
+        // to do: prompt user how to handle unknown airport
+        name_label->setText(tr("Unknown airport identifier"));
+        onBadInputReceived(line_edit);
+        return;
+    }
+    line_edit->setText(completionData.airportIcaoIdMap.value(airport_id));
+    name_label->setText(completionData.airportNameIdMap.value(airport_id));
+    onGoodInputReceived(line_edit);
+}
+
+void NewNewFlightDialog::on_acftLineEdit_editingFinished()
+{
+    TODO << "Fix looking up and matching...";
 }

+ 19 - 4
src/gui/dialogues/newnewflightdialog.h

@@ -18,7 +18,7 @@
  * \brief The ValidationItem enum contains the items that are mandatory for logging a flight:
  * Date of Flight, Departure, Destination, Time Off Blocks, Time On Blocks, Pilot in Command, Aircraft Registration
  */
-enum ValidationItem {doft, dept, dest, tofb, tonb, pic, acft};
+enum ValidationItem {doft = 0, dept = 1, dest = 2, tofb = 3, tonb = 4, pic = 5, acft = 6};
 
 /*!
  * \brief The ValidationState class encapsulates a QBitArray that has a bit set (or unset) depending on wether the
@@ -30,7 +30,9 @@ public:
     ValidationState() = default;
 
     void validate(ValidationItem line_edit)   { validationArray[line_edit] = true;};
+    void validate(int index)                  { validationArray[index] = true;};
     void invalidate(ValidationItem line_edit) { validationArray[line_edit] = false;}
+    void invalidate(int index)                { validationArray[index] = false;}
     bool allValid()                           { return validationArray.count(true) == 6;};
     bool timesValid()                         { return validationArray[ValidationItem::tofb] && validationArray[ValidationItem::tonb];}
     bool locationsValid()                     { return validationArray[ValidationItem::dept] && validationArray[ValidationItem::dest];}
@@ -89,16 +91,29 @@ private:
     ACompletionData completionData;
     ValidationState validationState;
 
-    static const inline QList<QLineEdit*>* timeLineEdits;
-    static const inline QList<QLineEdit*>* locationLineEdits;
-    static const inline QList<QLineEdit*>* pilotNameLineEdits;
+    QList<QLineEdit*> timeLineEdits;
+    QList<QLineEdit*> locationLineEdits;
+    QList<QLineEdit*> pilotNameLineEdits;
+    QList<QLineEdit*> mandatoryLineEdits;
     static const inline QLatin1String self = QLatin1String("self");
 
+    bool eventFilter(QObject *object, QEvent *event) override;
     void init();
     void setupRawInputValidation();
     void setupSignalsAndSlots();
     void readSettings();
 
+    void onGoodInputReceived(QLineEdit *line_edit);
+    void onBadInputReceived(QLineEdit *line_edit);
+
+
+private slots:
+    void toUpper(const QString& text);
+    void onTimeLineEdit_editingFinished();
+    void onPilotNameLineEdit_editingFinshed();
+    void onLocationLineEdit_editingFinished();
+    void on_acftLineEdit_editingFinished();
 };
 
+
 #endif // NEWNEWFLIGHTDIALOG_H

+ 139 - 10
src/gui/dialogues/newnewflightdialog.ui

@@ -60,8 +60,19 @@
          <property name="enabled">
           <bool>false</bool>
          </property>
+         <property name="minimumSize">
+          <size>
+           <width>120</width>
+           <height>0</height>
+          </size>
+         </property>
+         <property name="font">
+          <font>
+           <italic>true</italic>
+          </font>
+         </property>
          <property name="text">
-          <string>DestName</string>
+          <string/>
          </property>
         </widget>
        </item>
@@ -70,8 +81,14 @@
          <property name="enabled">
           <bool>false</bool>
          </property>
+         <property name="minimumSize">
+          <size>
+           <width>120</width>
+           <height>0</height>
+          </size>
+         </property>
          <property name="text">
-          <string>invis</string>
+          <string/>
          </property>
         </widget>
        </item>
@@ -80,6 +97,9 @@
          <property name="text">
           <string>PIC</string>
          </property>
+         <property name="alignment">
+          <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
+         </property>
         </widget>
        </item>
        <item row="0" column="1">
@@ -107,8 +127,14 @@
          <property name="enabled">
           <bool>false</bool>
          </property>
+         <property name="minimumSize">
+          <size>
+           <width>120</width>
+           <height>0</height>
+          </size>
+         </property>
          <property name="text">
-          <string>SicName</string>
+          <string/>
          </property>
         </widget>
        </item>
@@ -127,13 +153,30 @@
          <property name="enabled">
           <bool>false</bool>
          </property>
+         <property name="minimumSize">
+          <size>
+           <width>120</width>
+           <height>0</height>
+          </size>
+         </property>
+         <property name="font">
+          <font>
+           <italic>true</italic>
+          </font>
+         </property>
          <property name="text">
-          <string>DeptName</string>
+          <string/>
          </property>
         </widget>
        </item>
        <item row="5" column="2">
         <widget class="QLabel" name="submissionReadyLabel">
+         <property name="minimumSize">
+          <size>
+           <width>120</width>
+           <height>0</height>
+          </size>
+         </property>
          <property name="text">
           <string>Data Missing</string>
          </property>
@@ -144,8 +187,14 @@
          <property name="enabled">
           <bool>false</bool>
          </property>
+         <property name="minimumSize">
+          <size>
+           <width>120</width>
+           <height>0</height>
+          </size>
+         </property>
          <property name="text">
-          <string>PicName</string>
+          <string/>
          </property>
         </widget>
        </item>
@@ -171,6 +220,12 @@
        </item>
        <item row="0" column="2">
         <widget class="QPushButton" name="calendarPushButton">
+         <property name="minimumSize">
+          <size>
+           <width>120</width>
+           <height>0</height>
+          </size>
+         </property>
          <property name="text">
           <string>Calendar</string>
          </property>
@@ -191,8 +246,14 @@
          <property name="enabled">
           <bool>false</bool>
          </property>
+         <property name="minimumSize">
+          <size>
+           <width>120</width>
+           <height>0</height>
+          </size>
+         </property>
          <property name="text">
-          <string>invis</string>
+          <string/>
          </property>
         </widget>
        </item>
@@ -208,6 +269,9 @@
          <property name="text">
           <string>Aircraft</string>
          </property>
+         <property name="alignment">
+          <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
+         </property>
         </widget>
        </item>
        <item row="2" column="0">
@@ -239,6 +303,9 @@
          <property name="text">
           <string>Flight Number</string>
          </property>
+         <property name="alignment">
+          <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
+         </property>
         </widget>
        </item>
        <item row="0" column="5">
@@ -246,8 +313,19 @@
          <property name="enabled">
           <bool>false</bool>
          </property>
+         <property name="minimumSize">
+          <size>
+           <width>120</width>
+           <height>0</height>
+          </size>
+         </property>
+         <property name="font">
+          <font>
+           <italic>true</italic>
+          </font>
+         </property>
          <property name="text">
-          <string>AircraftName</string>
+          <string/>
          </property>
         </widget>
        </item>
@@ -276,8 +354,14 @@
          <property name="enabled">
           <bool>false</bool>
          </property>
+         <property name="minimumSize">
+          <size>
+           <width>120</width>
+           <height>0</height>
+          </size>
+         </property>
          <property name="text">
-          <string>invis</string>
+          <string/>
          </property>
         </widget>
        </item>
@@ -293,6 +377,9 @@
          <property name="text">
           <string>Third Pilot</string>
          </property>
+         <property name="alignment">
+          <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
+         </property>
         </widget>
        </item>
        <item row="2" column="4">
@@ -310,6 +397,9 @@
          <property name="text">
           <string>Remarks</string>
          </property>
+         <property name="alignment">
+          <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
+         </property>
         </widget>
        </item>
        <item row="5" column="1">
@@ -324,8 +414,14 @@
          <property name="enabled">
           <bool>false</bool>
          </property>
+         <property name="minimumSize">
+          <size>
+           <width>120</width>
+           <height>0</height>
+          </size>
+         </property>
          <property name="text">
-          <string>invis</string>
+          <string/>
          </property>
         </widget>
        </item>
@@ -344,6 +440,9 @@
          <property name="text">
           <string>SIC</string>
          </property>
+         <property name="alignment">
+          <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
+         </property>
         </widget>
        </item>
        <item row="3" column="5">
@@ -351,8 +450,14 @@
          <property name="enabled">
           <bool>false</bool>
          </property>
+         <property name="minimumSize">
+          <size>
+           <width>120</width>
+           <height>0</height>
+          </size>
+         </property>
          <property name="text">
-          <string>ThirdName</string>
+          <string/>
          </property>
         </widget>
        </item>
@@ -482,6 +587,30 @@
    </item>
   </layout>
  </widget>
+ <tabstops>
+  <tabstop>doftLineEdit</tabstop>
+  <tabstop>deptLocationLineEdit</tabstop>
+  <tabstop>destLocationLineEdit</tabstop>
+  <tabstop>tofbTimeLineEdit</tabstop>
+  <tabstop>tonbTimeLineEdit</tabstop>
+  <tabstop>acftLineEdit</tabstop>
+  <tabstop>picNameLineEdit</tabstop>
+  <tabstop>sicNameLineEdit</tabstop>
+  <tabstop>thirdPilotNameLineEdit</tabstop>
+  <tabstop>flightNumberLineEdit</tabstop>
+  <tabstop>remarksLineEdit</tabstop>
+  <tabstop>pilotFlyingCheckBox</tabstop>
+  <tabstop>ifrCheckBox</tabstop>
+  <tabstop>takeOffSpinBox</tabstop>
+  <tabstop>toNightCheckBox</tabstop>
+  <tabstop>landingSpinBox</tabstop>
+  <tabstop>ldgNightCheckBox</tabstop>
+  <tabstop>functionComboBox</tabstop>
+  <tabstop>approachComboBox</tabstop>
+  <tabstop>pushButton_2</tabstop>
+  <tabstop>toolButton</tabstop>
+  <tabstop>calendarPushButton</tabstop>
+ </tabstops>
  <resources/>
  <connections>
   <connection>