Jelajahi Sumber

Removed usage of displayname

Displayname is no longer required, creating it is now done in the database itself.

Minor changes, renaming of variables, removing whitespaces
Felix Turo 4 tahun lalu
induk
melakukan
8131eb62b4

+ 1 - 0
assets/database/templates/changelog.csv

@@ -10,3 +10,4 @@ revision,comment,date
 9,changed column id to flight_id in table flights for consistency in naming,2020-11-23
 10,added viewDefault as a copy of Logbook (deprecated),2020-11-23
 11,added viewQCompleter as a copy of QCompleterView (deprecated),2020-11-23
+12,reworked views to display self or picname according CASE,2020-12-11

+ 13 - 3
src/database/dbsetup.cpp

@@ -142,8 +142,12 @@ const QString createViewDefault = "CREATE VIEW viewDefault AS "
         "dept AS 'Dept', "
         "printf('%02d',(tofb/60))||':'||printf('%02d',(tofb%60)) AS 'Time', "
         "dest AS 'Dest', printf('%02d',(tonb/60))||':'||printf('%02d',(tonb%60)) AS 'Time ', "
-        "printf('%02d',(tblk/60))||':'||printf('%02d',(tblk%60)) AS 'Total', "
-        "displayname AS 'Name PIC', "
+        "printf('%02d',(tblk/60))||':'||printf('%02d',(tblk%60)) AS 'Total', " 
+        "CASE "
+        "WHEN pilot_id = 1 THEN alias "
+        "ELSE piclastname||', '||substr(picfirstname, 1, 1)||'.' "
+        "END "
+        "AS 'Name PIC', "
         "make||' '||model||'-'||variant AS 'Type', "
         "registration AS 'Registration', "
         "FlightNumber AS 'Flight #', "
@@ -153,6 +157,8 @@ const QString createViewDefault = "CREATE VIEW viewDefault AS "
         "INNER JOIN tails on flights.acft = tails.tail_id "
         "ORDER BY date DESC ";
 
+
+
 const QString createViewEASA = "CREATE VIEW viewEASA AS "
         "SELECT "
         "flight_id, doft as 'Date', "
@@ -165,7 +171,11 @@ const QString createViewEASA = "CREATE VIEW viewEASA AS "
         "(SELECT printf('%02d',(tSPME/60))||':'||printf('%02d',(tSPME%60)) WHERE tSPME IS NOT \"\") AS 'SP ME', "
         "(SELECT printf('%02d',(tMP/60))||':'||printf('%02d',(tMP%60)) WHERE tMP IS NOT \"\") AS 'MP', "
         "printf('%02d',(tblk/60))||':'||printf('%02d',(tblk%60)) AS 'Total', "
-        "displayname AS 'Name PIC', "
+        "CASE "
+        "WHEN pilot_id = 1 THEN alias "
+        "ELSE piclastname||', '||substr(picfirstname, 1, 1)||'.' "
+        "END "
+        "AS 'Name PIC', "
         "ldgDay AS 'L/D', "
         "ldgNight AS 'L/N', "
         "(SELECT printf('%02d',(tNight/60))||':'||printf('%02d',(tNight%60)) WHERE tNight IS NOT \"\")  AS 'Night', "

+ 19 - 43
src/gui/dialogues/newpilotdialog.cpp

@@ -35,25 +35,21 @@
  * Mathias d'Arras
  * Martin Luther King, Jr.
  */
-// [F] I think we don't even need static here at all, as it should be implicitly static anyway?
-// [G] Thats not how it works. Its such a leap of assumption to make them static.
-// in this context static declare that the variables will only be used by this cpp file (translation unit)
-// which is where they are used anyway so we should keep the static and be explicit.
-// The same thing happens to static functions (outside of classes). They are "local" functions.
+
 static const auto NAME_RX = QLatin1String("(\\p{L}+(\\s|'|\\-)?\\s?(\\p{L}+)?\\s?)");
 static const auto FIRSTNAME_VALID = QPair<QString, QRegularExpression> {
-    "picfirstnameLineEdit", QRegularExpression(NAME_RX + NAME_RX + NAME_RX)};
+     "picfirstnameLineEdit", QRegularExpression(NAME_RX + NAME_RX + NAME_RX)};
 static const auto LASTNAME_VALID = QPair<QString, QRegularExpression> {
-    "piclastnameLineEdit", QRegularExpression(NAME_RX + NAME_RX + NAME_RX)};
+     "piclastnameLineEdit", QRegularExpression(NAME_RX + NAME_RX + NAME_RX)};
 static const auto PHONE_VALID = QPair<QString, QRegularExpression> {
-    "phoneLineEdit", QRegularExpression("^[+]{0,1}[0-9\\-\\s]+")};
+     "phoneLineEdit", QRegularExpression("^[+]{0,1}[0-9\\-\\s]+")};
 static const auto EMAIL_VALID = QPair<QString, QRegularExpression> {
-    "emailLineEdit", QRegularExpression("\\A[a-z0-9!#$%&'*+/=?^_‘{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_‘{|}~-]+)*@"
-                                        "(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\z")};
+     "emailLineEdit", QRegularExpression("\\A[a-z0-9!#$%&'*+/=?^_‘{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_‘{|}~-]+)*@"
+                                         "(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\z")};
 static const auto COMPANY_VALID = QPair<QString, QRegularExpression> {
-    "companyLineEdit", QRegularExpression("\\w+(\\s|\\-)?(\\w+(\\s|\\-)?)?(\\w+(\\s|\\-)?)?")};
+     "companyLineEdit", QRegularExpression("\\w+(\\s|\\-)?(\\w+(\\s|\\-)?)?(\\w+(\\s|\\-)?)?")};
 static const auto EMPLOYEENR_VALID = QPair<QString, QRegularExpression> {
-    "employeeidLineEdit", QRegularExpression("\\w+")};
+     "employeeidLineEdit", QRegularExpression("\\w+")};
 
 static const auto LINE_EDIT_VALIDATORS = QVector{
         FIRSTNAME_VALID,
@@ -69,7 +65,7 @@ NewPilotDialog::NewPilotDialog(QWidget *parent) :
     QDialog(parent),
     ui(new Ui::NewPilot)
 {
-    DEB("New NewPilotDialog\n");
+    DEB("New NewPilotDialog (newEntry)");
     setup();
 
     using namespace experimental;
@@ -81,6 +77,7 @@ NewPilotDialog::NewPilotDialog(int rowId, QWidget *parent) :
     QDialog(parent),
     ui(new Ui::NewPilot)
 {
+    DEB("New NewPilotDialog (editEntry)");
     setup();
 
     using namespace experimental;
@@ -92,7 +89,7 @@ NewPilotDialog::NewPilotDialog(int rowId, QWidget *parent) :
 
 NewPilotDialog::~NewPilotDialog()
 {
-    DEB("Deleting New NewPilotDialog\n");
+    DEB("Deleting New NewPilotDialog");
     delete ui;
 }
 
@@ -101,12 +98,12 @@ void NewPilotDialog::setup()
     ui->setupUi(this);
 
     DEB("Setting up Validators...");
-    for(const auto& pair : LINE_EDIT_VALIDATORS){
+    for (const auto& pair : LINE_EDIT_VALIDATORS) {
         auto line_edit = parent()->findChild<QLineEdit*>(pair.first);
-        if(line_edit != nullptr){
+        if (line_edit != nullptr) {
             auto validator = new QRegularExpressionValidator(pair.second,line_edit);
             line_edit->setValidator(validator);
-        }else{
+        } else {
             DEB("Error: Line Edit not found: "<< pair.first << " - skipping.");
         }
     }
@@ -156,39 +153,18 @@ void NewPilotDialog::formFiller()
 
 void NewPilotDialog::submitForm()
 {
-    DEB("Creating Database Object...");
-    QMap<QString, QString> newData;
+    DEB("Collecting User Input...");
+    using namespace experimental;
+    TableData new_data;
 
     auto line_edits = this->findChildren<QLineEdit *>();
-
     for(auto& le : line_edits) {
         auto key = le->objectName().remove("LineEdit");
         auto value = le->text();
-        newData.insert(key, value);
+        new_data.insert(key, value);
     }
 
-    // [G]: If this formating is Entry-Subclass specific
-    // shouldnt PilotEntry know what to do with the database-centric pilot name?
-    // [F]: That's one way of looking at it - I see it more as something derived
-    // from a QLineEdit included in the 'package' of data the entry gets from the
-    // Dialo. Where in the PilotEntry would you see it as more appropriate?
-    // [G]: Not sure i get exactly what you mean but my point is that we have leak of 
-    // logic again. I see two alternatives. encapsulate the displayname "creation" in the PilotEntry,
-    // or remove it from the database all together. In my eyes displayname doesnt provide anything intersting
-    // for the database. It might aswell just be the output of the function that takes the actual interesting
-    // data that is the picfirst and piclast names. I suggest we go for the second. 
-    // TL;DR displayname is useless, remove it even from the database. Any "display name" required
-    // will be the output of a function/method that takes the actual data picfirst piclast name.
-    QString display_name;
-    display_name.append(ui->piclastnameLineEdit->text());
-    display_name.append(QLatin1String(", "));
-    display_name.append(ui->picfirstnameLineEdit->text().left(1));
-    display_name.append(QLatin1Char('.'));
-    newData.insert("displayname", display_name);
-
-    using namespace experimental;
-
-    pilotEntry.setData(newData);
+    pilotEntry.setData(new_data);
     DEB("Pilot entry position: " << pilotEntry.getPosition());
     DEB("Pilot entry data: " << pilotEntry.getData());
     DB()->commit(pilotEntry);

+ 47 - 33
src/gui/widgets/pilotswidget.cpp

@@ -35,6 +35,14 @@ PilotsWidget::~PilotsWidget()
 
 void PilotsWidget::tableView_selectionChanged()//const QItemSelection &index, const QItemSelection &
 {   
+    if (this->findChild<NewPilotDialog*>("NewPilot") != nullptr) {
+        DEB("Selection changed. Deleting orphaned dialog.");
+        delete this->findChild<NewPilotDialog*>("NewPilot");
+        /// [F] if the user changes the selection without making any changes,
+        /// if(selectedPilots.length() == 1) spawns a new dialog without the
+        /// old one being deleted, since neither accept() nor reject() was emitted.
+        /// Is this a reasonable way of avoiding pollution?
+    }
     auto *selection = ui->tableView->selectionModel();
     selectedPilots.clear();
 
@@ -45,6 +53,7 @@ void PilotsWidget::tableView_selectionChanged()//const QItemSelection &index, co
     if(selectedPilots.length() == 1) {
 
         NewPilotDialog* np = new NewPilotDialog(selectedPilots.first(), this);
+        DEB("new dialog: " << np->objectName());
         using namespace experimental;
         QObject::connect(DB(), &DataBase::commitSuccessful,
                          np,   &NewPilotDialog::onCommitSuccessful);
@@ -82,41 +91,47 @@ void PilotsWidget::on_newButton_clicked()
 
 void PilotsWidget::on_deletePushButton_clicked()
 {
-    if(selectedPilots.length() == 1){
-        for(const auto& selectedPilot : selectedPilots){
-            if (selectedPilot > 0) {
-                auto pil = Pilot(selectedPilot);
-                if(!pil.remove()) {
-                    QVector<QString> columns = {"doft","dept","dest"};
-                    QVector<QString> details = Db::multiSelect(columns, "flights", "pic",
-                                                               QString::number(selectedPilot), Db::exactMatch);
-                    auto mb = QMessageBox(this);
-                    QString message = "\nUnable to delete. The following error has ocurred:\n\n";
-                    if(!details.isEmpty()){
-                        message += pil.error + QLatin1String("\n\n");
-                        message += "This is most likely the case because a flight exists with the Pilot "
-                                   "you are trying to delete. You have to change or remove this flight "
-                                   "before being able to remove this pilot from the database.\n\n"
-                                   "The following flight(s) with this pilot have been found:\n\n";
-                        auto space = QLatin1Char(' ');
-                        for(int i = 0; i <= 30 && i <=details.length()-3; i+=3){
-                            message += details[i] + space
-                                    + details[i+1] + space
-                                    + details[i+2] + QLatin1String("\n");
-                        }
-                    }
-                    mb.setText(message);
-                    mb.setIcon(QMessageBox::Critical);
-                    mb.exec();
+    if (selectedPilots.length() == 0) {
+        auto mb = QMessageBox(this);
+        mb.setText("No Pilot selected.");
+        mb.exec();
+
+    } else if (selectedPilots.length() > 1) {
+        auto mb = QMessageBox(this);
+        mb.setText("Deleting multiple entries is currently not supported");
+        mb.exec();
+        // to do: for (const auto& selectedPilot : selectedPilots) { do batchDelete }
+
+    } else if (selectedPilots.length() == 1) {
+        using namespace experimental;
+        auto entry = DB()->getPilotEntry(selectedPilots.first());
+        if (!DB()->remove(entry)) {
+            QVector<QString> columns = {"doft","dept","dest"};
+            QVector<QString> details = Db::multiSelect(columns, "flights", "pic",
+                                                       QString::number(selectedPilots.first()), Db::exactMatch);
+            auto mb = QMessageBox(this);
+            QString message = "\nUnable to delete.\n\n";
+            // [F] to do: create unsuccessful delete signal and include error info
+            if(!details.isEmpty()){
+                message += "This is most likely the case because a flight exists with the Pilot "
+                           "you are trying to delete. You have to change or remove this flight "
+                           "before being able to remove this pilot from the database.\n\n"
+                           "The following flight(s) with this pilot have been found:\n\n";
+                auto space = QLatin1Char(' ');
+                for(int i = 0; i <= 30 && i <=details.length()-3; i+=3){
+                    message += details[i] + space
+                            + details[i+1] + space
+                            + details[i+2] + QLatin1String("\n");
                 }
             }
+            mb.setText(message);
+            mb.setIcon(QMessageBox::Critical);
+            mb.exec();
         }
-        refreshModelAndView();
-    } else {
-        auto mb = QMessageBox(this);
-        mb.setText("No Pilot selected.");
-        mb.show();
     }
+
+    refreshModelAndView();
+
 }
 
 void PilotsWidget::pilot_editing_finished()
@@ -126,8 +141,7 @@ void PilotsWidget::pilot_editing_finished()
 
 void PilotsWidget::refreshModelAndView()
 {
-    ui->stackedWidget->addWidget(parent()->findChild<QWidget*>("welcomePage"));
-    ui->stackedWidget->setCurrentWidget(parent()->findChild<QWidget*>("welcomePage"));
+    ui->stackedWidget->setCurrentWidget(this->findChild<QWidget*>("welcomePage"));
 
     model->setTable("viewPilots");
     model->setFilter("ID > 1");//to not allow editing of self, shall be done via settings