newflight.cpp 35 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124
  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 "newflight.h"
  19. #include "ui_newflight.h"
  20. #include "dbman.cpp"
  21. #define DEBUG(expr) \
  22. qDebug() << "~DEBUG" << __func__ << expr
  23. /*
  24. * Debug / WIP
  25. */
  26. void NewFlight::on_verifyButton_clicked()//debug
  27. {
  28. /*on_newDoft_editingFinished();// - activate slots in case user has been active in last input before clicking submit
  29. on_newTonb_editingFinished();
  30. on_newTofb_editingFinished();
  31. on_newDept_editingFinished();
  32. on_newDest_editingFinished();
  33. on_newAcft_editingFinished();
  34. on_newPic_editingFinished();
  35. verifyInput();*/
  36. fillExtrasLineEdits();
  37. }
  38. void NewFlight::on_tabWidget_tabBarClicked(int index)
  39. {
  40. if(index == 1){
  41. nope();
  42. }
  43. }
  44. /// Raw Input validation
  45. const QString TIME_REGEX_PATTERN = "([01]?[0-9]?|2[0-3]):?[0-5][0-9]?";// We only want to allow inputs that make sense as a time, e.g. 99:99 is not a valid time
  46. const QString IATA = "[\\w]{3}";
  47. const QString ICAO = "[\\w0-9]{4}";
  48. const QString LOC_REGEX_PATTERN = IATA + "|" + ICAO;
  49. const QString AIRCRAFT_REGEX_PATTERN = "([\\w0-9]+-)?[\\w0-9]+";
  50. const QString PILOT_NAME_REGEX_PATTERN = "[\\w]+ [\\w]+";
  51. /// Invalid characters (validators keep text even if it returns Invalid, see `onInputRejected` below)
  52. const QString TIME_INVALID_RGX = "[^\\d:]";
  53. const QString LOC_INVALID_RGX = "[^\\w0-9]";
  54. const QString AIRCRAFT_INVALID_RGX = "[^A-Z0-9\\-]";
  55. const QString PILOT_NAME_INVALID_RGX = "[^a-zA-Z ]";
  56. /// Input max lengths
  57. const qint8 TIME_MAX_LENGTH = 5; //to allow for ':' e.g. "08:45"
  58. const qint8 LOC_MAX_LENGTH = 4;
  59. const qint8 AIRCRAFT_MAX_LENGTH = 10;
  60. const qint8 PILOT_NAME_MAX_LENGTH = 15;
  61. /// Initialising variables used for storing user input
  62. QVector<QString> flight;
  63. QDate date(QDate::currentDate());
  64. QString doft(QDate::currentDate().toString(Qt::ISODate));
  65. QString dept;
  66. QString dest;
  67. QTime tofb;
  68. QTime tonb;
  69. QTime tblk;
  70. QString pic;
  71. QString acft;
  72. // extras
  73. QString secondPilot;
  74. QString thirdPilot;
  75. QString pilotFunction;
  76. QString pilotTask;
  77. QString takeoff;
  78. QString landing;
  79. QString autoland;
  80. QString approachType;
  81. bool hasOldInput = dbFlight::checkScratchpad();
  82. /*!
  83. * \brief setLineEditValidator set Validators for QLineEdits that end with Time, Loc,
  84. * Aircraft or Name
  85. */
  86. static inline void setLineEditValidator(QLineEdit* line_edit)
  87. {
  88. auto line_edit_objectName = line_edit->objectName();
  89. DEBUG("Setting validators for " << line_edit_objectName);
  90. static const
  91. QVector<QPair<QRegularExpression, QRegularExpression>> objectName_inputValidation_regexes = {
  92. {QRegularExpression("\\w+Time"), QRegularExpression(TIME_REGEX_PATTERN)},
  93. {QRegularExpression("\\w+Loc"), QRegularExpression(LOC_REGEX_PATTERN)},
  94. {QRegularExpression("\\w+Aircraft"), QRegularExpression(AIRCRAFT_REGEX_PATTERN)},
  95. {QRegularExpression("\\w+Name"), QRegularExpression(PILOT_NAME_REGEX_PATTERN)},
  96. };
  97. auto validator = new StrictRegularExpressionValidator();
  98. for(auto pair : objectName_inputValidation_regexes)
  99. {
  100. if(pair.first.match(line_edit_objectName).hasMatch()) {
  101. validator->setRegularExpression(pair.second);
  102. line_edit->setValidator(validator);
  103. return;
  104. }
  105. }
  106. DEBUG("Couldnt find QLineEdit" << line_edit_objectName);
  107. }
  108. /*!
  109. * \brief setLineEditMaxLength set Max Length for QLineEdits that end with Time, Loc,
  110. * Aircraft or Name
  111. */
  112. static inline void setLineEditMaxLength(QLineEdit* line_edit)
  113. {
  114. auto line_edit_objectName = line_edit->objectName();
  115. DEBUG("Setting Max Length for " << line_edit_objectName);
  116. static const
  117. QVector<QPair<QRegularExpression, int>> objectName_inputValidation_regexes = {
  118. {QRegularExpression("\\w+TimeLineEdit"), TIME_MAX_LENGTH},
  119. {QRegularExpression("\\w+LocLineEdit"), LOC_MAX_LENGTH},
  120. {QRegularExpression("\\w+AircraftLineEdit"), AIRCRAFT_MAX_LENGTH},
  121. {QRegularExpression("\\w+NameLineEdit"), PILOT_NAME_MAX_LENGTH},
  122. };
  123. for(auto pair : objectName_inputValidation_regexes)
  124. {
  125. if(pair.first.match(line_edit_objectName).hasMatch())
  126. {
  127. line_edit->setMaxLength(pair.second);
  128. return;
  129. }
  130. }
  131. DEBUG("Couldnt find QLineEdit" << line_edit_objectName);
  132. }
  133. /*
  134. * Window
  135. */
  136. NewFlight::NewFlight(QWidget *parent) :
  137. QDialog(parent),
  138. ui(new Ui::NewFlight)
  139. {
  140. ui->setupUi(this);
  141. ui->newDoft->setDate(QDate::currentDate());
  142. qDebug() << "Hasoldinput? = " << hasOldInput;
  143. if(hasOldInput) // Re-populate the Form
  144. {
  145. flight = dbFlight::retreiveScratchpad();
  146. qDebug() << "Re-Filling Form from Scratchpad";
  147. returnInput(flight);
  148. }
  149. for(auto line_edits = ui->flightDataTab->findChildren<QLineEdit*>();
  150. auto line_edit : line_edits)
  151. {
  152. setLineEditValidator(line_edit);
  153. setLineEditMaxLength(line_edit);
  154. }
  155. for(auto line_edits = ui->extraTimes->findChildren<QLineEdit*>();
  156. auto line_edit : line_edits)
  157. {
  158. setLineEditValidator(line_edit);
  159. setLineEditMaxLength(line_edit);
  160. }
  161. // Groups for CheckBoxes
  162. QButtonGroup *FlightRulesGroup = new QButtonGroup(this);
  163. FlightRulesGroup->addButton(ui->IfrCheckBox);
  164. FlightRulesGroup->addButton(ui->VfrCheckBox);
  165. QButtonGroup *PilotTaskGroup = new QButtonGroup(this);
  166. PilotTaskGroup->addButton(ui->PilotFlyingCheckBox);
  167. PilotTaskGroup->addButton(ui->PilotMonitoringCheckBox);
  168. restoreSettings();
  169. ui->deptTZ->setFocusPolicy(Qt::NoFocus);
  170. ui->destTZ->setFocusPolicy(Qt::NoFocus);
  171. // Visually mark mandatory fields
  172. ui->newDeptLocLineEdit->setStyleSheet("border: 1px solid orange");
  173. ui->newDestLocLineEdit->setStyleSheet("border: 1px solid orange");
  174. ui->newDeptTimeLineEdit->setStyleSheet("border: 1px solid orange");
  175. ui->newDestTimeLineEdit->setStyleSheet("border: 1px solid orange");
  176. ui->newPic->setStyleSheet("border: 1px solid orange");
  177. ui->newAcft->setStyleSheet("border: 1px solid orange");
  178. ui->newDeptLocLineEdit->setFocus();
  179. }
  180. NewFlight::~NewFlight()
  181. {
  182. delete ui;
  183. }
  184. /*
  185. * Functions
  186. */
  187. /// Input Validation
  188. /*!
  189. * \brief onInputRejected Set `line_edit`'s border to red and check if `rgx` matches
  190. * in order to keep text on line.
  191. */
  192. static void onInputRejected(QLineEdit* line_edit, QRegularExpression rgx){
  193. DEBUG("Input rejected" << line_edit->text());
  194. line_edit->setStyleSheet("border: 1px solid red");
  195. if(auto text = line_edit->text();
  196. rgx.match(text).hasMatch() == false)
  197. {
  198. line_edit->setText(line_edit->text());
  199. }
  200. }
  201. /*!
  202. * \brief onEditingFinished signal is emitted if input passed raw validation
  203. */
  204. static void onEditingFinished(QLineEdit* line_edit){
  205. DEBUG("Input accepted" << line_edit->text() << line_edit->metaObject()->className());
  206. line_edit->setStyleSheet("");
  207. }
  208. /*!
  209. * \brief NewFlight::nope for features that are not yet implemented
  210. */
  211. void NewFlight::nope()
  212. {
  213. QMessageBox nope(this); //error box
  214. nope.setText("This feature is not yet available!");
  215. nope.exec();
  216. }
  217. /*!
  218. * \brief NewFlight::fillExtrasLineEdits Fills the flight time line edits according to ui selections
  219. */
  220. void NewFlight::fillExtrasLineEdits()
  221. {
  222. QString blockTime = calc::blocktime(tofb,tonb).toString("hh:mm");
  223. // SP SE
  224. // SP ME
  225. // MP
  226. // TOTAL
  227. ui->totalTimeLineEdit->setText(blockTime);
  228. // IFR
  229. // VFR
  230. // Night
  231. QString deptDate = date.toString(Qt::ISODate) + 'T' + tofb.toString("hh:mm");
  232. QDateTime deptDateTime = QDateTime::fromString(deptDate,"yyyy-MM-ddThh:mm");
  233. int blocktime = calc::time_to_minutes(calc::blocktime(tofb,tonb));
  234. qDebug() << "Blocktime: " << blocktime;
  235. QString nightTime = calc::minutes_to_string(QString::number(calc::calculateNightTime(dept, dest, deptDateTime, blocktime)));
  236. ui->nightTimeLineEdit->setText(nightTime);
  237. // XC - Cross-country flight, if more than 50nm long
  238. if(calc::greatCircleDistanceBetweenAirports(dept,dest) >= 50){
  239. qDebug() << "Cross-country Flight: nm = " << calc::greatCircleDistanceBetweenAirports(dept,dest);
  240. ui->xcTimeLineEdit->setText(blockTime);
  241. }else{
  242. ui->xcTimeLineEdit->setText("00:00");
  243. }
  244. // PIC
  245. // Co-Pilot
  246. // Dual
  247. // FI
  248. // SIM
  249. }
  250. QVector<QString> NewFlight::collectInput()
  251. {
  252. // Collect input from the user fields and return a vector containing the flight information
  253. QString doft = date.toString(Qt::ISODate); // Format Date
  254. QTime tblk = calc::blocktime(tofb,tonb); // Calculate Blocktime
  255. // Prepare Vector for commit to database
  256. flight = dbFlight::createFlightVectorFromInput(doft, dept, tofb, dest, tonb, tblk, pic, acft);
  257. qDebug() << "Created flight vector:" << flight;
  258. return flight;
  259. }
  260. /*!
  261. * \brief NewFlight::verifyInput checks if input exists in database.
  262. * \return
  263. */
  264. bool NewFlight::verifyInput()
  265. {
  266. bool deptValid = false;
  267. bool tofbValid = false;
  268. bool destValid = false;
  269. bool tonbValid = false;
  270. bool tblkValid = false;
  271. bool picValid = false;
  272. bool acftValid = false;
  273. QTime tblk = calc::blocktime(tofb,tonb);
  274. int checktblk = calc::time_to_minutes(tblk);
  275. bool doftValid = true; //doft assumed to be always valid due to QDateTimeEdit constraints
  276. qDebug() << "NewFlight::verifyInput() says: Date:" << doft << " - Valid?\t" << doftValid;
  277. deptValid = dbAirport::checkICAOValid(dept);
  278. qDebug() << "NewFlight::verifyInput() says: Departure is:\t" << dept << " - Valid?\t" << deptValid;
  279. destValid = dbAirport::checkICAOValid(dest);
  280. qDebug() << "NewFlight::verifyInput() says: Destination is:\t" << dest << " - Valid?\t" << destValid;
  281. tofbValid = (unsigned)(calc::time_to_minutes(tofb)-0) <= (1440-0) && tofb.toString("hh:mm") != ""; // Make sure time is within range, DB 1 day = 1440 minutes. 0 is allowed (midnight) & that it is not empty.
  282. qDebug() << "NewFlight::verifyInput() says: tofb is:\t\t" << tofb.toString("hh:mm") << " - Valid?\t" << tofbValid;
  283. tonbValid = (unsigned)(calc::time_to_minutes(tonb)-0) <= (1440-0) && tonb.toString("hh:mm") != ""; // Make sure time is within range, DB 1 day = 1440 minutes
  284. qDebug() << "NewFlight::verifyInput() says: tonb is:\t\t" << tonb.toString("hh:mm")<< " - Valid?\t" << tonbValid;
  285. picValid = (pic.toInt() > 0); // pic should be a pilot_id retreived from the database
  286. qDebug() << "NewFlight::verifyInput() says: pic is pilotd_id:\t" << pic << " - Valid?\t" << picValid;
  287. if(!picValid)
  288. {
  289. QMessageBox msgBox(this);
  290. msgBox.setText("You cannot log a flight without a valid pilot");
  291. msgBox.exec();
  292. }
  293. acftValid = (acft.toInt() > 0);
  294. qDebug() << "NewFlight::verifyInput() says: acft is tail_id:\t" << acft << " - Valid?\t" << acftValid;
  295. if(!acftValid)
  296. {
  297. QMessageBox msgBox(this);
  298. msgBox.setText("You cannot log a flight without a valid aircraft");
  299. msgBox.exec();
  300. }
  301. tblkValid = checktblk != 0;
  302. qDebug() << "NewFlight::verifyInput() says: tblk is:\t\t" << tblk.toString("hh:mm") << " - Valid?\t" << tblkValid;
  303. if(deptValid && tofbValid && destValid && tonbValid
  304. && tblkValid && picValid && acftValid)
  305. {
  306. qDebug() << "====================================================";
  307. qDebug() << "NewFlight::verifyInput() says: All checks passed! Very impressive. ";
  308. return 1;
  309. }else
  310. {
  311. qDebug() << "====================================================";
  312. qDebug() << "NewFlight::verifyInput() says: Flight is invalid.";
  313. return 0;
  314. }
  315. return 0;
  316. }
  317. void NewFlight::returnInput(QVector<QString> flight)
  318. {
  319. // Re-populates the input masks with the selected fields if input was erroneous to allow for corrections to be made
  320. qDebug() << "return Input: " << flight;
  321. ui->newDoft->setDate(QDate::fromString(flight[1],Qt::ISODate));
  322. ui->newDeptLocLineEdit->setText(flight[2]);
  323. ui->newDeptTimeLineEdit->setText(flight[3]);
  324. ui->newDestLocLineEdit->setText(flight[4]);
  325. ui->newDestTimeLineEdit->setText(flight[5]);
  326. // flight[6] is blocktime
  327. ui->newPic->setText(dbPilots::retreivePilotNameFromID(flight[7]));
  328. ui->newAcft->setText(dbAircraft::retreiveRegistration(flight[8]));
  329. }
  330. void NewFlight::storeSettings()
  331. {
  332. qDebug() << "Storing Settings...";
  333. dbSettings::storeSetting(100, ui->FunctionComboBox->currentText());
  334. dbSettings::storeSetting(101, ui->ApproachComboBox->currentText());
  335. dbSettings::storeSetting(102, QString::number(ui->PilotFlyingCheckBox->isChecked()));
  336. dbSettings::storeSetting(103, QString::number(ui->PilotMonitoringCheckBox->isChecked()));
  337. dbSettings::storeSetting(104, QString::number(ui->TakeoffSpinBox->value()));
  338. dbSettings::storeSetting(105, QString::number(ui->TakeoffCheckBox->isChecked()));
  339. dbSettings::storeSetting(106, QString::number(ui->LandingSpinBox->value()));
  340. dbSettings::storeSetting(107, QString::number(ui->LandingCheckBox->isChecked()));
  341. dbSettings::storeSetting(108, QString::number(ui->AutolandSpinBox->value()));
  342. dbSettings::storeSetting(109, QString::number(ui->AutolandCheckBox->isChecked()));
  343. dbSettings::storeSetting(110, QString::number(ui->IfrCheckBox->isChecked()));
  344. dbSettings::storeSetting(111, QString::number(ui->VfrCheckBox->isChecked()));
  345. //dbSettings::storesetting(112, QString::number(ui->autoNightCheckBox->isChecked()));
  346. }
  347. void NewFlight::restoreSettings()
  348. {
  349. qDebug() << "Restoring Settings...";//crashes if db is empty due to QVector index out of range.
  350. ui->FunctionComboBox->setCurrentText(dbSettings::retreiveSetting(100));
  351. ui->ApproachComboBox->setCurrentText(dbSettings::retreiveSetting(101));
  352. ui->PilotFlyingCheckBox->setChecked(dbSettings::retreiveSetting(102).toInt());
  353. ui->PilotMonitoringCheckBox->setChecked(dbSettings::retreiveSetting(103).toInt());
  354. ui->TakeoffSpinBox->setValue(dbSettings::retreiveSetting(104).toInt());
  355. ui->TakeoffCheckBox->setChecked(dbSettings::retreiveSetting(105).toInt());
  356. ui->LandingSpinBox->setValue(dbSettings::retreiveSetting(106).toInt());
  357. ui->LandingCheckBox->setChecked(dbSettings::retreiveSetting(107).toInt());
  358. ui->AutolandSpinBox->setValue(dbSettings::retreiveSetting(108).toInt());
  359. ui->AutolandCheckBox->setChecked(dbSettings::retreiveSetting(109).toInt());
  360. ui->IfrCheckBox->setChecked(dbSettings::retreiveSetting(110).toInt());
  361. ui->VfrCheckBox->setChecked(dbSettings::retreiveSetting(111).toInt());
  362. ui->flightNumberPrefixLabel->setText(dbSettings::retreiveSetting(50) + QLatin1Char('-'));
  363. }
  364. /*
  365. * Slots
  366. */
  367. void NewFlight::on_deptTZ_currentTextChanged(const QString &arg1)
  368. {
  369. if(arg1 == "Local"){nope();}
  370. ui->deptTZ->setCurrentIndex(0);
  371. }
  372. void NewFlight::on_destTZ_currentIndexChanged(const QString &arg1)
  373. {
  374. if(arg1 == "Local"){nope();}
  375. ui->destTZ->setCurrentIndex(0);
  376. }
  377. /// newDeptLocLineEdit
  378. void NewFlight::on_newDeptLocLineEdit_inputRejected()
  379. {
  380. onInputRejected(ui->newDeptLocLineEdit, QRegularExpression(LOC_INVALID_RGX));
  381. }
  382. void NewFlight::on_newDeptLocLineEdit_textEdited(const QString &arg1)
  383. {
  384. ui->newDeptLocLineEdit->setText(arg1.toUpper());
  385. if(arg1.length()>2)
  386. {
  387. QStringList deptList = dbAirport::completeIcaoOrIata(arg1);
  388. qDebug() << "deptList = " << deptList;
  389. QCompleter *deptCompleter = new QCompleter(deptList, this);
  390. deptCompleter->setCaseSensitivity(Qt::CaseInsensitive);
  391. deptCompleter->setCompletionMode(QCompleter::UnfilteredPopupCompletion);
  392. ui->newDeptLocLineEdit->setCompleter(deptCompleter);
  393. }
  394. }
  395. void NewFlight::on_newDeptLocLineEdit_editingFinished()
  396. {
  397. QStringList deptList;
  398. if(ui->newDeptLocLineEdit->text().length()>1)
  399. {
  400. auto line_edit = ui->newDeptLocLineEdit;
  401. onEditingFinished(line_edit);
  402. QStringList deptList = dbAirport::completeIcaoOrIata(line_edit->text());
  403. if(deptList.length() != 0) {//exists in database
  404. dept = deptList.first();
  405. line_edit->setText(dept);
  406. }else{
  407. qWarning() << "Departure Location not in database. ";
  408. emit onInputRejected(line_edit, QRegularExpression(LOC_INVALID_RGX));
  409. }
  410. }
  411. }
  412. /// newDeptLocLineEdit
  413. void NewFlight::on_newDestLocLineEdit_inputRejected()
  414. {
  415. onInputRejected(ui->newDestLocLineEdit, QRegularExpression(LOC_INVALID_RGX));
  416. }
  417. void NewFlight::on_newDestLocLineEdit_textEdited(const QString &arg1)
  418. {
  419. ui->newDestLocLineEdit->setText(arg1.toUpper());
  420. if(arg1.length()>2)
  421. {
  422. QStringList destList = dbAirport::completeIcaoOrIata(arg1);
  423. QCompleter *destCompleter = new QCompleter(destList, this);
  424. destCompleter->setCaseSensitivity(Qt::CaseInsensitive);
  425. destCompleter->setCompletionMode(QCompleter::UnfilteredPopupCompletion);
  426. ui->newDestLocLineEdit->setCompleter(destCompleter);
  427. }
  428. }
  429. void NewFlight::on_newDestLocLineEdit_editingFinished()
  430. {
  431. QStringList destList;
  432. if(ui->newDestLocLineEdit->text().length()>1)
  433. {
  434. auto line_edit = ui->newDestLocLineEdit;
  435. onEditingFinished(line_edit);
  436. QStringList destList = dbAirport::completeIcaoOrIata(line_edit->text());
  437. if(destList.length() != 0) {
  438. dept = destList.first();
  439. ui->newDestLocLineEdit->setText(dept);
  440. }else{
  441. qWarning() << "Destination location not in database. ";
  442. emit onInputRejected(line_edit, QRegularExpression(LOC_INVALID_RGX));
  443. }
  444. }
  445. }
  446. /*
  447. void NewFlight::on_newDept_textEdited(const QString &arg1)
  448. {
  449. ui->newDept->setText(arg1.toUpper());
  450. if(arg1.length()>2)
  451. {
  452. QStringList deptList = dbAirport::completeIcaoOrIata(arg1);
  453. qDebug() << "deptList = " << deptList;
  454. QCompleter *deptCompleter = new QCompleter(deptList, this);
  455. deptCompleter->setCaseSensitivity(Qt::CaseInsensitive);
  456. deptCompleter->setCompletionMode(QCompleter::UnfilteredPopupCompletion);
  457. ui->newDept->setCompleter(deptCompleter);
  458. }
  459. }
  460. void NewFlight::on_newDept_editingFinished()
  461. {
  462. if(ui->newDept->text().length()<3)
  463. {
  464. QMessageBox msgBox(this);
  465. msgBox.setText("Please enter a 3- or 4-letter code.");
  466. msgBox.exec();
  467. ui->newDept->setText("");
  468. ui->newDept->setFocus();
  469. }
  470. QStringList deptList;
  471. if(ui->newDept->text().length()>1)
  472. {
  473. QStringList deptList = dbAirport::completeIcaoOrIata(ui->newDept->text());
  474. if(deptList.length() != 0)
  475. {
  476. dept = deptList.first();
  477. ui->newDept->setText(dept);
  478. }else
  479. {
  480. QMessageBox msgBox(this);
  481. msgBox.setText("No Airport with that name found.");
  482. msgBox.exec();
  483. ui->newDept->setText("");
  484. ui->newDept->setFocus();
  485. }
  486. }
  487. }
  488. void NewFlight::on_newDest_textEdited(const QString &arg1)
  489. {
  490. ui->newDest->setText(arg1.toUpper());
  491. if(arg1.length()>2)
  492. {
  493. QStringList destList = dbAirport::completeIcaoOrIata(arg1);
  494. QCompleter *destCompleter = new QCompleter(destList, this);
  495. destCompleter->setCaseSensitivity(Qt::CaseInsensitive);
  496. destCompleter->setCompletionMode(QCompleter::UnfilteredPopupCompletion);
  497. ui->newDest->setCompleter(destCompleter);
  498. }
  499. }
  500. void NewFlight::on_newDest_editingFinished()
  501. {
  502. if(ui->newDest->text().length()<3)
  503. {
  504. QMessageBox msgBox(this);
  505. msgBox.setText("Please enter a 3- or 4-letter code.");
  506. msgBox.exec();
  507. ui->newDest->setText("");
  508. ui->newDest->setFocus();
  509. }
  510. QStringList destList;
  511. if(ui->newDest->text().length()>1)
  512. {
  513. QStringList destList = dbAirport::completeIcaoOrIata(ui->newDest->text());
  514. if(destList.length() != 0)
  515. {
  516. dest = destList.first();
  517. ui->newDest->setText(dest);
  518. }else
  519. {
  520. QMessageBox msgBox(this);
  521. msgBox.setText("No Airport with that name found.");
  522. msgBox.exec();
  523. ui->newDest->setText("");
  524. ui->newDest->setFocus();
  525. }
  526. }
  527. }
  528. */
  529. void NewFlight::on_newDoft_editingFinished()
  530. {
  531. date = ui->newDoft->date();
  532. doft = date.toString(Qt::ISODate);
  533. }
  534. /// newDeptTimeLineEdit
  535. void NewFlight::on_newDeptTimeLineEdit_inputRejected()
  536. {
  537. onInputRejected(ui->newDeptTimeLineEdit, QRegularExpression(TIME_INVALID_RGX));
  538. }
  539. void NewFlight::on_newDeptTimeLineEdit_editingFinished()
  540. {
  541. ui->newDeptTimeLineEdit->setText(calc::formatTimeInput(ui->newDeptTimeLineEdit->text()));
  542. tofb = QTime::fromString(ui->newDeptTimeLineEdit->text(),"hh:mm");
  543. auto line_edit = ui->newDeptTimeLineEdit;
  544. onEditingFinished(line_edit);
  545. if(tofb.isValid()){
  546. // continue
  547. DEBUG("Time Off Blocks is valid:" << tofb);
  548. }else{
  549. emit line_edit->inputRejected();
  550. }
  551. }
  552. /// newDestTimeLineEdit
  553. void NewFlight::on_newDestTimeLineEdit_inputRejected()
  554. {
  555. onInputRejected(ui->newDestTimeLineEdit, QRegularExpression(TIME_INVALID_RGX));
  556. }
  557. void NewFlight::on_newDestTimeLineEdit_editingFinished()
  558. {
  559. ui->newDestTimeLineEdit->setText(calc::formatTimeInput(ui->newDestTimeLineEdit->text()));
  560. tonb = QTime::fromString(ui->newDestTimeLineEdit->text(),"hh:mm");
  561. auto line_edit = ui->newDestTimeLineEdit;
  562. onEditingFinished(line_edit);
  563. if(tonb.isValid()){
  564. // continue
  565. DEBUG("Time On Blocks is valid:" << tonb);
  566. }else{
  567. emit line_edit->inputRejected();
  568. }
  569. }
  570. void NewFlight::on_newAcft_textEdited(const QString &arg1)
  571. {
  572. if(arg1.length()>1)
  573. {
  574. QStringList acftList = dbAircraft::newAcftGetString(arg1);
  575. QCompleter *acftCompleter = new QCompleter(acftList, this);
  576. acftCompleter->setCaseSensitivity(Qt::CaseInsensitive);
  577. acftCompleter->setCompletionMode(QCompleter::UnfilteredPopupCompletion);
  578. ui->newAcft->setCompleter(acftCompleter);
  579. }
  580. }
  581. void NewFlight::on_newAcft_editingFinished()
  582. {
  583. acft = "-1";// set invalid
  584. if(ui->newAcft->text().contains(" "))// is input from QCompleter
  585. {
  586. QStringList input = ui->newAcft->text().split(" ");
  587. QString registration = input[0].trimmed();
  588. QStringList result = dbAircraft::newAcftGetString(registration);
  589. if(result.length() > 0)
  590. {
  591. ui->newAcft->setText(result[0]);
  592. acft = dbAircraft::newAcftGetId(registration);
  593. }else
  594. {
  595. acft = "-1";
  596. }
  597. }else // is input from user
  598. {
  599. QString input = ui->newAcft->text();
  600. QStringList result = dbAircraft::newAcftGetString(input);
  601. if(result.length() > 0)
  602. {
  603. ui->newAcft->setText(result[0]);
  604. QStringList input = ui->newAcft->text().split(" ");
  605. QString registration = input[0].trimmed();
  606. acft = dbAircraft::newAcftGetId(registration);
  607. }else
  608. {
  609. acft = "-1";
  610. }
  611. }
  612. if(acft == "-1")
  613. {
  614. QMessageBox::StandardButton reply;
  615. reply = QMessageBox::question(this, "No aircraft found", "No aircraft found.\n Would you like to add a new aircraft to the database?",
  616. QMessageBox::Yes|QMessageBox::No);
  617. if (reply == QMessageBox::Yes) {
  618. NewAcft na(this);
  619. na.exec();
  620. ui->newAcft->setText("");
  621. ui->newAcft->setFocus();
  622. }
  623. }
  624. qDebug() << "Editing finished. Acft: " << acft;
  625. }
  626. void NewFlight::on_newPic_textEdited(const QString &arg1)
  627. {
  628. if(arg1.length()>2)
  629. {
  630. QStringList picList = dbPilots::newPicGetString(arg1);
  631. QCompleter *picCompleter = new QCompleter(picList, this);
  632. picCompleter->setCaseSensitivity(Qt::CaseInsensitive);
  633. picCompleter->setCompletionMode(QCompleter::UnfilteredPopupCompletion);
  634. ui->newPic->setCompleter(picCompleter);
  635. }
  636. }
  637. void NewFlight::on_newPic_editingFinished()
  638. {
  639. pic = "-1"; // set invalid
  640. if(ui->newPic->text() == "self")
  641. {
  642. pic = "1";
  643. }else
  644. {
  645. QString picname;
  646. QStringList picList = dbPilots::newPicGetString(ui->newPic->text());
  647. qDebug() << picList;
  648. if(picList.length()!= 0)
  649. {
  650. picname = picList[0];
  651. ui->newPic->setText(picname);
  652. pic = dbPilots::newPicGetId(picname);
  653. }else
  654. {
  655. QMessageBox::StandardButton reply;
  656. reply = QMessageBox::question(this, "No Pilot found", "No pilot found.\n Would you like to add a new pilot to the database?",
  657. QMessageBox::Yes|QMessageBox::No);
  658. if (reply == QMessageBox::Yes)
  659. {
  660. qDebug() << "Add new pilot selected";
  661. nope();
  662. }
  663. }
  664. }
  665. }
  666. void NewFlight::on_secondPilotLineEdit_textEdited(const QString &arg1)
  667. {
  668. if(arg1.length()>2)
  669. {
  670. QStringList picList = dbPilots::newPicGetString(arg1);
  671. QCompleter *picCompleter = new QCompleter(picList, this);
  672. picCompleter->setCaseSensitivity(Qt::CaseInsensitive);
  673. picCompleter->setCompletionMode(QCompleter::UnfilteredPopupCompletion);
  674. ui->secondPilotLineEdit->setCompleter(picCompleter);
  675. }
  676. }
  677. void NewFlight::on_secondPilotLineEdit_editingFinished()
  678. {
  679. secondPilot = "-1"; // set invalid
  680. if(ui->secondPilotLineEdit->text() == "self")
  681. {
  682. secondPilot = "1";
  683. }else
  684. {
  685. QString picname;
  686. QStringList picList = dbPilots::newPicGetString(ui->secondPilotLineEdit->text());
  687. qDebug() << picList;
  688. if(picList.length()!= 0)
  689. {
  690. picname = picList[0];
  691. ui->secondPilotLineEdit->setText(picname);
  692. secondPilot = dbPilots::newPicGetId(picname);
  693. }else
  694. {
  695. QMessageBox::StandardButton reply;
  696. reply = QMessageBox::question(this, "No Pilot found", "No pilot found.\n Would you like to add a new pilot to the database?",
  697. QMessageBox::Yes|QMessageBox::No);
  698. if (reply == QMessageBox::Yes)
  699. {
  700. qDebug() << "Add new pilot selected";
  701. nope();
  702. }
  703. }
  704. }
  705. }
  706. void NewFlight::on_thirdPilotLineEdit_textEdited(const QString &arg1)
  707. {
  708. if(arg1.length()>2)
  709. {
  710. QStringList picList = dbPilots::newPicGetString(arg1);
  711. QCompleter *picCompleter = new QCompleter(picList, this);
  712. picCompleter->setCaseSensitivity(Qt::CaseInsensitive);
  713. picCompleter->setCompletionMode(QCompleter::UnfilteredPopupCompletion);
  714. ui->thirdPilotLineEdit->setCompleter(picCompleter);
  715. }
  716. }
  717. void NewFlight::on_thirdPilotLineEdit_editingFinished()
  718. {
  719. thirdPilot = "-1"; // set invalid
  720. if(ui->thirdPilotLineEdit->text() == "self")
  721. {
  722. thirdPilot = "1";
  723. }else
  724. {
  725. QString picname;
  726. QStringList picList = dbPilots::newPicGetString(ui->thirdPilotLineEdit->text());
  727. qDebug() << picList;
  728. if(picList.length()!= 0)
  729. {
  730. picname = picList[0];
  731. ui->thirdPilotLineEdit->setText(picname);
  732. thirdPilot = dbPilots::newPicGetId(picname);
  733. }else
  734. {
  735. QMessageBox::StandardButton reply;
  736. reply = QMessageBox::question(this, "No Pilot found", "No pilot found.\n Would you like to add a new pilot to the database?",
  737. QMessageBox::Yes|QMessageBox::No);
  738. if (reply == QMessageBox::Yes)
  739. {
  740. qDebug() << "Add new pilot selected";
  741. nope();
  742. }
  743. }
  744. }
  745. }
  746. void NewFlight::on_FlightNumberLineEdit_editingFinished()
  747. {
  748. qDebug() << "tbd: FlightNumber slot";
  749. // To Do: Store input in variable, perform some checks
  750. // Setting for optional Prefix (e.g. LH, LX etc.)
  751. }
  752. /*
  753. * Extras
  754. */
  755. void NewFlight::on_PilotFlyingCheckBox_stateChanged(int)
  756. {
  757. if(ui->PilotFlyingCheckBox->isChecked()){
  758. ui->TakeoffSpinBox->setValue(1);
  759. ui->TakeoffCheckBox->setCheckState(Qt::Checked);
  760. ui->LandingSpinBox->setValue(1);
  761. ui->LandingCheckBox->setCheckState(Qt::Checked);
  762. }else if(!ui->PilotFlyingCheckBox->isChecked()){
  763. ui->TakeoffSpinBox->setValue(0);
  764. ui->TakeoffCheckBox->setCheckState(Qt::Unchecked);
  765. ui->LandingSpinBox->setValue(0);
  766. ui->LandingCheckBox->setCheckState(Qt::Unchecked);
  767. }
  768. }
  769. void NewFlight::on_setAsDefaultButton_clicked()
  770. {
  771. storeSettings();
  772. }
  773. void NewFlight::on_restoreDefaultButton_clicked()
  774. {
  775. restoreSettings();
  776. }
  777. void NewFlight::on_ApproachComboBox_currentTextChanged(const QString &arg1)
  778. {
  779. if(arg1 == "ILS CAT III"){
  780. ui->AutolandCheckBox->setCheckState(Qt::Checked);
  781. ui->AutolandSpinBox->setValue(1);
  782. }else{
  783. ui->AutolandCheckBox->setCheckState(Qt::Unchecked);
  784. ui->AutolandSpinBox->setValue(0);
  785. }
  786. approachType = arg1;
  787. qDebug() << "Approach Type: " << approachType;
  788. }
  789. /*
  790. * Extra Times
  791. */
  792. void NewFlight::on_spseTimeLineEdit_editingFinished()
  793. {
  794. ui->spseTimeLineEdit->setText(calc::formatTimeInput(ui->spseTimeLineEdit->text()));
  795. if(ui->spseTimeLineEdit->text() == ""){
  796. ui->spseTimeLineEdit->setStyleSheet("border: 1px solid red");
  797. ui->spseTimeLineEdit->setFocus();
  798. }else{
  799. ui->spseTimeLineEdit->setStyleSheet("");
  800. }
  801. }
  802. void NewFlight::on_spmeTimeLineEdit_editingFinished()
  803. {
  804. ui->spmeTimeLineEdit->setText(calc::formatTimeInput(ui->spmeTimeLineEdit->text()));
  805. if(ui->spmeTimeLineEdit->text() == ""){
  806. ui->spmeTimeLineEdit->setStyleSheet("border: 1px solid red");
  807. ui->spmeTimeLineEdit->setFocus();
  808. }else{
  809. ui->spmeTimeLineEdit->setStyleSheet("");
  810. }
  811. }
  812. void NewFlight::on_mpTimeLineEdit_editingFinished()
  813. {
  814. ui->mpTimeLineEdit->setText(calc::formatTimeInput(ui->mpTimeLineEdit->text()));
  815. if(ui->mpTimeLineEdit->text() == ""){
  816. ui->mpTimeLineEdit->setStyleSheet("border: 1px solid red");
  817. ui->mpTimeLineEdit->setFocus();
  818. }else{
  819. ui->mpTimeLineEdit->setStyleSheet("");
  820. }
  821. }
  822. void NewFlight::on_totalTimeLineEdit_editingFinished()
  823. {
  824. ui->totalTimeLineEdit->setText(calc::formatTimeInput(ui->totalTimeLineEdit->text()));
  825. if(ui->totalTimeLineEdit->text() == ""){
  826. ui->totalTimeLineEdit->setStyleSheet("border: 1px solid red");
  827. ui->totalTimeLineEdit->setFocus();
  828. }else{
  829. ui->totalTimeLineEdit->setStyleSheet("");
  830. }
  831. }
  832. void NewFlight::on_ifrTimeLineEdit_editingFinished()
  833. {
  834. ui->ifrTimeLineEdit->setText(calc::formatTimeInput(ui->ifrTimeLineEdit->text()));
  835. if(ui->ifrTimeLineEdit->text() == ""){
  836. ui->ifrTimeLineEdit->setStyleSheet("border: 1px solid red");
  837. ui->ifrTimeLineEdit->setFocus();
  838. }else{
  839. ui->ifrTimeLineEdit->setStyleSheet("");
  840. }
  841. }
  842. void NewFlight::on_vfrTimeLineEdit_editingFinished()
  843. {
  844. ui->vfrTimeLineEdit->setText(calc::formatTimeInput(ui->vfrTimeLineEdit->text()));
  845. if(ui->vfrTimeLineEdit->text() == ""){
  846. ui->vfrTimeLineEdit->setStyleSheet("border: 1px solid red");
  847. ui->vfrTimeLineEdit->setFocus();
  848. }else{
  849. ui->vfrTimeLineEdit->setStyleSheet("");
  850. }
  851. }
  852. void NewFlight::on_nightTimeLineEdit_editingFinished()
  853. {
  854. ui->nightTimeLineEdit->setText(calc::formatTimeInput(ui->nightTimeLineEdit->text()));
  855. if(ui->nightTimeLineEdit->text() == ""){
  856. ui->nightTimeLineEdit->setStyleSheet("border: 1px solid red");
  857. ui->nightTimeLineEdit->setFocus();
  858. }else{
  859. ui->nightTimeLineEdit->setStyleSheet("");
  860. }
  861. }
  862. void NewFlight::on_xcTimeLineEdit_editingFinished()
  863. {
  864. ui->xcTimeLineEdit->setText(calc::formatTimeInput(ui->xcTimeLineEdit->text()));
  865. if(ui->xcTimeLineEdit->text() == ""){
  866. ui->xcTimeLineEdit->setStyleSheet("border: 1px solid red");
  867. ui->xcTimeLineEdit->setFocus();
  868. }else{
  869. ui->xcTimeLineEdit->setStyleSheet("");
  870. }
  871. }
  872. void NewFlight::on_picTimeLineEdit_editingFinished()
  873. {
  874. ui->picTimeLineEdit->setText(calc::formatTimeInput(ui->picTimeLineEdit->text()));
  875. if(ui->picTimeLineEdit->text() == ""){
  876. ui->picTimeLineEdit->setStyleSheet("border: 1px solid red");
  877. ui->picTimeLineEdit->setFocus();
  878. }else{
  879. ui->picTimeLineEdit->setStyleSheet("");
  880. }
  881. }
  882. void NewFlight::on_copTimeLineEdit_editingFinished()
  883. {
  884. ui->copTimeLineEdit->setText(calc::formatTimeInput(ui->copTimeLineEdit->text()));
  885. if(ui->copTimeLineEdit->text() == ""){
  886. ui->copTimeLineEdit->setStyleSheet("border: 1px solid red");
  887. ui->copTimeLineEdit->setFocus();
  888. }else{
  889. ui->copTimeLineEdit->setStyleSheet("");
  890. }
  891. }
  892. void NewFlight::on_dualTimeLineEdit_editingFinished()
  893. {
  894. ui->dualTimeLineEdit->setText(calc::formatTimeInput(ui->dualTimeLineEdit->text()));
  895. if(ui->dualTimeLineEdit->text() == ""){
  896. ui->dualTimeLineEdit->setStyleSheet("border: 1px solid red");
  897. ui->dualTimeLineEdit->setFocus();
  898. }else{
  899. ui->dualTimeLineEdit->setStyleSheet("");
  900. }
  901. }
  902. void NewFlight::on_fiTimeLineEdit_editingFinished()
  903. {
  904. ui->fiTimeLineEdit->setText(calc::formatTimeInput(ui->fiTimeLineEdit->text()));
  905. if(ui->fiTimeLineEdit->text() == ""){
  906. ui->fiTimeLineEdit->setStyleSheet("border: 1px solid red");
  907. ui->fiTimeLineEdit->setFocus();
  908. }else{
  909. ui->fiTimeLineEdit->setStyleSheet("");
  910. }
  911. }
  912. void NewFlight::on_simTimeLineEdit_editingFinished()
  913. {
  914. ui->simTimeLineEdit->setText(calc::formatTimeInput(ui->simTimeLineEdit->text()));
  915. if(ui->simTimeLineEdit->text() == ""){
  916. ui->simTimeLineEdit->setStyleSheet("border: 1px solid red");
  917. ui->simTimeLineEdit->setFocus();
  918. }else{
  919. ui->simTimeLineEdit->setStyleSheet("");
  920. }
  921. }
  922. /*
  923. * Control Buttons
  924. */
  925. void NewFlight::on_buttonBox_accepted()
  926. {
  927. on_newDoft_editingFinished();// - activate slots in case user has been active in last input before clicking submit
  928. //on_newTonb_editingFinished();
  929. //on_newTofb_editingFinished();
  930. //on_newDept_editingFinished();
  931. //on_newDest_editingFinished();
  932. on_newAcft_editingFinished();
  933. on_newPic_editingFinished();
  934. QVector<QString> flight;
  935. flight = collectInput();
  936. if(verifyInput())
  937. {
  938. dbFlight::commitFlight(flight);
  939. qDebug() << flight << "Has been commited.";
  940. QMessageBox msgBox(this);
  941. msgBox.setText("Flight has been commited.");
  942. msgBox.exec();
  943. }else
  944. {
  945. qDebug() << "Invalid Input. No entry has been made in the database.";
  946. dbFlight::commitToScratchpad(flight);
  947. QMessageBox msgBox(this);
  948. msgBox.setText("Invalid entries detected. Please check your input.");
  949. msgBox.exec();
  950. NewFlight nf(this);
  951. nf.exec();
  952. }
  953. }
  954. void NewFlight::on_buttonBox_rejected()
  955. {
  956. qDebug() << "NewFlight: Rejected\n";
  957. }