Procházet zdrojové kódy

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 před 4 roky
rodič
revize
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