aircraftwidget.cpp 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  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 "aircraftwidget.h"
  19. #include "ui_aircraftwidget.h"
  20. // Debug Makro
  21. #define DEB(expr) \
  22. qDebug() << __PRETTY_FUNCTION__ << "\t" << expr
  23. AircraftWidget::AircraftWidget(QWidget *parent) :
  24. QWidget(parent),
  25. ui(new Ui::AircraftWidget)
  26. {
  27. DEB("New AircraftWidet");
  28. ui->setupUi(this);
  29. ui->stackedWidget->addWidget(this->findChild<QWidget*>("welcomePageTails"));
  30. ui->stackedWidget->setCurrentWidget(this->findChild<QWidget*>("welcomePageTails"));
  31. setupModelAndView();
  32. }
  33. AircraftWidget::~AircraftWidget()
  34. {
  35. DEB("Deleting NewAircraftWidget");
  36. delete ui;
  37. }
  38. /*
  39. * Functions
  40. */
  41. void AircraftWidget::setupModelAndView()
  42. {
  43. sortColumn = ASettings::read("userdata/acSortColumn").toInt();
  44. model = new QSqlTableModel(this);
  45. model->setTable("viewTails");
  46. model->select();
  47. view = ui->tableView;
  48. view->setModel(model);
  49. view->setSelectionBehavior(QAbstractItemView::SelectRows);
  50. view->setSelectionMode(QAbstractItemView::SingleSelection);
  51. view->setEditTriggers(QAbstractItemView::NoEditTriggers);
  52. view->horizontalHeader()->setStretchLastSection(QHeaderView::Stretch);
  53. view->hideColumn(0);
  54. view->setColumnWidth(1, 180);
  55. view->setColumnWidth(2, 180);
  56. view->verticalHeader()->hide();
  57. view->setAlternatingRowColors(true);
  58. view->setSortingEnabled(true);
  59. view->sortByColumn(sortColumn, Qt::DescendingOrder);
  60. view->show();
  61. selection = view->selectionModel();
  62. QObject::connect(ui->tableView->selectionModel(), &QItemSelectionModel::selectionChanged,
  63. this, &AircraftWidget::tableView_selectionChanged);
  64. QObject::connect(ui->tableView->horizontalHeader(), &QHeaderView::sectionClicked,
  65. this, &AircraftWidget::tableView_headerClicked);
  66. }
  67. /*
  68. * Slots
  69. */
  70. void AircraftWidget::on_deleteButton_clicked()
  71. {
  72. if (selectedTails.length() > 0) {
  73. for(const auto& selectedTail : selectedTails){
  74. auto ac = Aircraft(selectedTail);
  75. auto& warningMsg = "Deleting Aircraft with registration:<br><center><b>"
  76. + ac.data.value("registration")
  77. + "<br></center></b>Do you want to proceed?";
  78. QMessageBox confirm;
  79. confirm.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
  80. confirm.setDefaultButton(QMessageBox::No);
  81. confirm.setIcon(QMessageBox::Question);
  82. confirm.setWindowTitle("Delete Aircraft");
  83. confirm.setText(warningMsg);
  84. int reply = confirm.exec();
  85. if(reply == QMessageBox::Yes) {
  86. if(!ac.remove()) {
  87. QVector<QString> columns = {"doft","dept","dest"};
  88. QVector<QString> details = Db::multiSelect(columns, "flights", "acft",
  89. QString::number(selectedTail), Db::exactMatch);
  90. auto mb = QMessageBox(this);
  91. QString message = "\nUnable to delete. The following error has ocurred:\n\n";
  92. if(!details.isEmpty()){
  93. message += ac.error + QLatin1String("\n\n");
  94. message += "This is most likely the case because a flight exists with the aircaft "
  95. "you are trying to delete. In order to maintain database integrity, you have to\n"
  96. "change or remove this flight before being able to remove this aircraft.\n\n"
  97. "The following flight(s) with this tail have been found:\n\n";
  98. auto space = QLatin1Char(' ');
  99. for(int i = 0; i <= 30 && i <=details.length()-3; i+=3){
  100. message += details[i] + space
  101. + details[i+1] + space
  102. + details[i+2] + QLatin1String("\n");
  103. }
  104. }
  105. mb.setText(message);
  106. mb.setIcon(QMessageBox::Critical);
  107. mb.show();
  108. }
  109. }
  110. }
  111. model->select();
  112. } else {
  113. auto mb = QMessageBox(this);
  114. mb.setText("No aircraft selected.");
  115. mb.show();
  116. }
  117. }
  118. void AircraftWidget::on_newAircraftButton_clicked()
  119. {
  120. auto nt = NewTailDialog(QString(), this);
  121. connect(&nt, SIGNAL(accepted()), this, SLOT(acft_editing_finished()));
  122. connect(&nt, SIGNAL(rejected()), this, SLOT(acft_editing_finished()));
  123. nt.exec();
  124. }
  125. void AircraftWidget::on_aircraftSearchLineEdit_textChanged(const QString &arg1)
  126. {
  127. if(ui->aircraftSearchComboBox->currentIndex() == 0){
  128. ui->aircraftSearchLineEdit->setText(arg1.toUpper());
  129. }
  130. model->setFilter(ui->aircraftSearchComboBox->currentText() + " LIKE \"%" + arg1 + "%\"");
  131. }
  132. void AircraftWidget::onDatabaseChanged()
  133. {
  134. //refresh view to reflect changes the user has made via a dialog.
  135. model->select();
  136. }
  137. void AircraftWidget::tableView_selectionChanged()
  138. {
  139. if (this->findChild<NewTailDialog*>() != nullptr) {
  140. DEB("Selection changed. Deleting orphaned dialog.");
  141. delete this->findChild<NewTailDialog*>();
  142. /// [F] if the user changes the selection without making any changes,
  143. /// if(selectedTails.length() == 1) spawns a new dialog without the
  144. /// old one being deleted, since neither accept() nor reject() was emitted.
  145. /// Is this a reasonable way of avoiding pollution? Creating the widgets on the
  146. /// stack does not seem to solve the problem since the Dialog does not get destroyed
  147. /// until either accept() or reject() is emitted so I went for this solution.
  148. }
  149. selectedTails.clear();
  150. for (const auto& row : selection->selectedRows()) {
  151. selectedTails << row.data().toInt();
  152. DEB("Selected Tails(s) with ID: " << selectedTails);
  153. }
  154. if(selectedTails.length() == 1) {
  155. auto* nt = new NewTailDialog(selectedTails.first(), this);
  156. QObject::connect(nt, &QDialog::accepted,
  157. this, &AircraftWidget::acft_editing_finished);
  158. QObject::connect(nt, &QDialog::rejected,
  159. this, &AircraftWidget::acft_editing_finished);
  160. ui->stackedWidget->addWidget(nt);
  161. ui->stackedWidget->setCurrentWidget(nt);
  162. nt->setWindowFlag(Qt::Widget);
  163. nt->setAttribute(Qt::WA_DeleteOnClose);
  164. nt->exec();
  165. }
  166. }
  167. void AircraftWidget::tableView_headerClicked(int column)
  168. {
  169. sortColumn = column;
  170. ASettings::write("userdata/acSortColumn", column);
  171. }
  172. void AircraftWidget::acft_editing_finished()
  173. {
  174. model->select();
  175. }