2
0

pilotswidget.cpp 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. /*
  2. *openPilot Log - A FOSS Pilot Logbook Application
  3. *Copyright (C) 2020 Felix Turowsky
  4. *
  5. *This program is free software: you can redistribute it and/or modify
  6. *it under the terms of the GNU General Public License as published by
  7. *the Free Software Foundation, either version 3 of the License, or
  8. *(at your option) any later version.
  9. *
  10. *This program is distributed in the hope that it will be useful,
  11. *but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. *MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. *GNU General Public License for more details.
  14. *
  15. *You should have received a copy of the GNU General Public License
  16. *along with this program. If not, see <https://www.gnu.org/licenses/>.
  17. */
  18. #include "pilotswidget.h"
  19. #include "ui_pilotswidget.h"
  20. #include "src/testing/adebug.h"
  21. #include "src/database/adatabase.h"
  22. #include "src/classes/apilotentry.h"
  23. PilotsWidget::PilotsWidget(QWidget *parent) :
  24. QWidget(parent),
  25. ui(new Ui::PilotsWidget)
  26. {
  27. ui->setupUi(this);
  28. setupModelAndView();
  29. }
  30. PilotsWidget::~PilotsWidget()
  31. {
  32. delete ui;
  33. }
  34. void PilotsWidget::setupModelAndView()
  35. {
  36. sortColumn = ASettings::read("userdata/pilSortColumn").toInt();
  37. model = new QSqlTableModel(this);
  38. model->setTable("viewPilots");
  39. model->setFilter("ID > 1");//to not allow editing of self, shall be done via settings
  40. model->select();
  41. view = ui->pilotsTableView;
  42. view->setModel(model);
  43. view->setSelectionBehavior(QAbstractItemView::SelectRows);
  44. view->setSelectionMode(QAbstractItemView::SingleSelection);
  45. view->setEditTriggers(QAbstractItemView::NoEditTriggers);
  46. view->horizontalHeader()->setStretchLastSection(QHeaderView::Stretch);
  47. view->hideColumn(0);
  48. view->setColumnWidth(1, 180);
  49. view->setColumnWidth(2, 180);
  50. view->verticalHeader()->hide();
  51. view->setAlternatingRowColors(true);
  52. view->setSortingEnabled(true);
  53. view->sortByColumn(sortColumn, Qt::AscendingOrder);
  54. view->show();
  55. selectionModel = view->selectionModel();
  56. QObject::connect(ui->pilotsTableView->selectionModel(), &QItemSelectionModel::selectionChanged,
  57. this, &PilotsWidget::tableView_selectionChanged);
  58. QObject::connect(ui->pilotsTableView->horizontalHeader(), &QHeaderView::sectionClicked,
  59. this, &PilotsWidget::tableView_headerClicked);
  60. }
  61. void PilotsWidget::on_pilotSearchLineEdit_textChanged(const QString &arg1)
  62. {
  63. model->setFilter("\"" + ui->pilotsSearchComboBox->currentText() + "\" LIKE \"%" + arg1 + "%\" AND ID > 1");
  64. }
  65. void PilotsWidget::onDisplayModel_dataBaseUpdated()
  66. {
  67. //refresh view to reflect changes the user has made via a dialog.
  68. model->select();
  69. }
  70. void PilotsWidget::tableView_selectionChanged()//const QItemSelection &index, const QItemSelection &
  71. {
  72. if (this->findChild<NewPilotDialog*>() != nullptr) {
  73. DEB("Selection changed. Deleting orphaned dialog.");
  74. delete this->findChild<NewPilotDialog*>();
  75. /// [F] if the user changes the selection without making any changes,
  76. /// if(selectedPilots.length() == 1) spawns a new dialog without the
  77. /// old one being deleted, since neither accept() nor reject() was emitted.
  78. /// Is this a reasonable way of avoiding pollution? Creating the widgets on the
  79. /// stack does not seem to solve the problem since the Dialog does not get deleted
  80. /// until either accept() or reject() is emitted so I went for this solution.
  81. }
  82. auto *selection = ui->pilotsTableView->selectionModel();
  83. selectedPilots.clear();
  84. for (const auto& row : selection->selectedRows()) {
  85. selectedPilots.append(row.data().toInt());
  86. DEB("Selected Tails(s) with ID: " << selectedPilots);
  87. }
  88. if(selectedPilots.length() == 1) {
  89. NewPilotDialog* np = new NewPilotDialog(selectedPilots.first(), this);
  90. QObject::connect(np, &QDialog::accepted,
  91. this, &PilotsWidget::pilot_editing_finished);
  92. QObject::connect(np, &QDialog::rejected,
  93. this, &PilotsWidget::pilot_editing_finished);
  94. np->setWindowFlag(Qt::Widget);
  95. np->setAttribute(Qt::WA_DeleteOnClose);
  96. ui->stackedWidget->addWidget(np);
  97. ui->stackedWidget->setCurrentWidget(np);
  98. np->exec();
  99. }
  100. }
  101. void PilotsWidget::tableView_headerClicked(int column)
  102. {
  103. sortColumn = column;
  104. ASettings::write("userdata/pilSortColumn", column);
  105. }
  106. void PilotsWidget::on_newPilotButton_clicked()
  107. {
  108. NewPilotDialog* np = new NewPilotDialog(this);
  109. QObject::connect(np, &QDialog::accepted,
  110. this, &PilotsWidget::pilot_editing_finished);
  111. QObject::connect(np, &QDialog::rejected,
  112. this, &PilotsWidget::pilot_editing_finished);
  113. np->setAttribute(Qt::WA_DeleteOnClose);
  114. np->exec();
  115. }
  116. void PilotsWidget::on_deletePilotButton_clicked()
  117. {
  118. if (selectedPilots.length() == 0) {
  119. auto mb = QMessageBox(this);
  120. mb.setText("No Pilot selected.");
  121. mb.exec();
  122. } else if (selectedPilots.length() > 1) {
  123. auto mb = QMessageBox(this);
  124. mb.setText("Deleting multiple entries is currently not supported");
  125. mb.exec();
  126. /// [F] to do: for (const auto& row_id : selectedPilots) { do batchDelete }
  127. /// I am not sure if enabling this functionality for this widget is a good idea.
  128. /// On the one hand, deleting many entries could be useful in a scenario where
  129. /// for example, the user has changed airlines and does not want to have his 'old'
  130. /// colleagues polluting his logbook anymore.
  131. /// On the other hand we could run into issues with foreign key constraints on the
  132. /// flights table (see on_delete_unsuccessful) below.
  133. /// I think batch-editing should be implemented at some point, but batch-deleting should not.
  134. } else if (selectedPilots.length() == 1) {
  135. auto entry = aDB()->getPilotEntry(selectedPilots.first());
  136. auto message_box = QMessageBox(this);
  137. QString message = "You are deleting the following pilot:<br><br><b><tt>";
  138. message.append(entry.name());
  139. message.append(QStringLiteral("</b></tt><br><br>Are you sure?"));
  140. message_box.setText(message);
  141. message_box.exec();
  142. if(!aDB()->remove(entry))
  143. onDeleteUnsuccessful();
  144. }
  145. model->select();
  146. }
  147. void PilotsWidget::onDeleteUnsuccessful()
  148. {
  149. /// [F]: To do: Some logic to display a warning if too many entries exists, so that
  150. /// the messagebox doesn't grow too tall.
  151. QList<int> foreign_key_constraints = aDB()->getForeignKeyConstraints(selectedPilots.first(), ADatabaseTarget::pilots);
  152. QList<AFlightEntry> constrained_flights;
  153. for (const auto &row_id : foreign_key_constraints) {
  154. constrained_flights.append(aDB()->getFlightEntry(row_id));
  155. }
  156. QString message = "<br>Unable to delete.<br><br>";
  157. if(!constrained_flights.isEmpty()){
  158. message.append(QStringLiteral("This is most likely the case because a flight exists with the Pilot "
  159. "you are trying to delete as PIC.<br>"
  160. "The following flight(s) with this pilot have been found:<br><br><br><b><tt>"));
  161. for (auto &flight : constrained_flights) {
  162. message.append(flight.summary() + QStringLiteral("&nbsp;&nbsp;&nbsp;&nbsp;<br>"));
  163. }
  164. }
  165. message.append(QStringLiteral("</b></tt><br><br>You have to change or remove the conflicting flight(s) "
  166. "before removing this pilot from the database.<br><br>"));
  167. QMessageBox message_box(this);
  168. message_box.setText(message);
  169. message_box.setIcon(QMessageBox::Critical);
  170. message_box.exec();
  171. }
  172. void PilotsWidget::pilot_editing_finished()
  173. {
  174. model->select();
  175. }