diff --git a/src/blackgui/components/flightplancomponent.cpp b/src/blackgui/components/flightplancomponent.cpp index c6d8628aa..1b8d76414 100644 --- a/src/blackgui/components/flightplancomponent.cpp +++ b/src/blackgui/components/flightplancomponent.cpp @@ -108,21 +108,25 @@ namespace BlackGui ui->le_EquipmentSuffix->setCompleter(completer); CUpperCaseEventFilter *ef = new CUpperCaseEventFilter(ui->pte_Route); + ef->setOnlyAscii(); ui->pte_Route->installEventFilter(ef); ef = new CUpperCaseEventFilter(ui->pte_Remarks); + ef->setOnlyAscii(); ui->pte_Remarks->installEventFilter(ef); ef = new CUpperCaseEventFilter(ui->pte_AdditionalRemarks); + ef->setOnlyAscii(); ui->pte_AdditionalRemarks->installEventFilter(ef); - ef = new CUpperCaseEventFilter(ui->pte_RemarksGenerated); - ui->pte_RemarksGenerated->installEventFilter(ef); + // readonly + // ef = new CUpperCaseEventFilter(ui->pte_RemarksGenerated); + // ui->pte_RemarksGenerated->installEventFilter(ef); // connect - connect(ui->pb_Send, &QPushButton::pressed, this, &CFlightPlanComponent::sendFlightPlan, Qt::QueuedConnection); - connect(ui->pb_Load, &QPushButton::pressed, this, &CFlightPlanComponent::loadFlightPlanFromNetwork, Qt::QueuedConnection); + connect(ui->pb_Send, &QPushButton::pressed, this, &CFlightPlanComponent::sendFlightPlan, Qt::QueuedConnection); + connect(ui->pb_Load, &QPushButton::pressed, this, &CFlightPlanComponent::loadFlightPlanFromNetwork, Qt::QueuedConnection); connect(ui->pb_Reset, &QPushButton::pressed, this, &CFlightPlanComponent::resetFlightPlan, Qt::QueuedConnection); connect(ui->pb_ValidateFlightPlan, &QPushButton::pressed, this, &CFlightPlanComponent::validateFlightPlan, Qt::QueuedConnection); connect(ui->tb_SyncWithSimulator, &QPushButton::released, this, &CFlightPlanComponent::syncWithSimulator, Qt::QueuedConnection); - connect(ui->pb_Prefill, &QPushButton::pressed, this, &CFlightPlanComponent::anticipateValues, Qt::QueuedConnection); + connect(ui->pb_Prefill, &QPushButton::pressed, this, &CFlightPlanComponent::anticipateValues, Qt::QueuedConnection); connect(ui->pb_SimBrief, &QPushButton::pressed, this, &CFlightPlanComponent::loadFromSimBrief, Qt::QueuedConnection); connect(ui->cb_VoiceCapabilities, &QComboBox::currentTextChanged, this, &CFlightPlanComponent::currentTextChangedToBuildRemarks, Qt::QueuedConnection); @@ -267,6 +271,10 @@ namespace BlackGui this->showOverlayMessage(m); } + if (!flightPlan.getRemarks().isEmpty()) + { + this->setRemarksUIValues(flightPlan.getRemarks()); + } } const CLogCategoryList &CFlightPlanComponent::getLogCategories() @@ -931,6 +939,47 @@ namespace BlackGui } } + void CFlightPlanComponent::setRemarksUIValues(const QString &remarks) + { + if (remarks.isEmpty()) { return; } + const QString r = remarks.toUpper(); + + if (remarks.contains("/V")) + { + CGuiUtility::setComboBoxValueByContainingString(ui->cb_VoiceCapabilitiesFirstPage, "FULL"); + CGuiUtility::setComboBoxValueByContainingString(ui->cb_VoiceCapabilities, "FULL"); + } + else if (remarks.contains("/T")) + { + CGuiUtility::setComboBoxValueByContainingString(ui->cb_VoiceCapabilitiesFirstPage, "TEXT ONLY"); + CGuiUtility::setComboBoxValueByContainingString(ui->cb_VoiceCapabilities, "FULL"); + } + else if (remarks.contains("/R")) + { + CGuiUtility::setComboBoxValueByContainingString(ui->cb_VoiceCapabilitiesFirstPage, "RECEIVE"); + CGuiUtility::setComboBoxValueByContainingString(ui->cb_VoiceCapabilities, "RECEIVE"); + } + + if (remarks.contains("NAV/GPSRNAV")) + { + CGuiUtility::setComboBoxValueByContainingString(ui->cb_NavigationEquipment, "GPS OR FMC"); + } + else if (remarks.contains("NAV/VORNDB")) + { + CGuiUtility::setComboBoxValueByContainingString(ui->cb_NavigationEquipment, "DIRECT VOR"); + } + + const int selcal = remarks.indexOf("SEL/"); + if (selcal >= 0 && remarks.length() > selcal + 7) + { + const QString code = remarks.mid(selcal + 4, 4); + if (code.length() == 4) + { + ui->frp_SelcalCode->setSelcal(code); + } + } + } + void CFlightPlanComponent::loadFromSimBrief() { if (!sGui || sGui->isShuttingDown()) { return; } @@ -1059,7 +1108,10 @@ namespace BlackGui { ui->cb_VoiceCapabilities->setCurrentText(text); const QString r = CFlightPlanRemarks::replaceVoiceCapabilities(CFlightPlanRemarks::textToVoiceCapabilitiesRemarks(text), ui->pte_Remarks->toPlainText()); - ui->pte_Remarks->setPlainText(r); + if (ui->pte_Remarks->toPlainText() != r) + { + ui->pte_Remarks->setPlainText(r); + } } } } // namespace diff --git a/src/blackgui/components/flightplancomponent.h b/src/blackgui/components/flightplancomponent.h index 5d25eb7bc..9f22fb025 100644 --- a/src/blackgui/components/flightplancomponent.h +++ b/src/blackgui/components/flightplancomponent.h @@ -224,6 +224,9 @@ namespace BlackGui //! Update the remarks histories void updateRemarksHistories(); + //! Set remark values + void setRemarksUIValues(const QString &remarks); + //! Load from SimBrief void loadFromSimBrief(); diff --git a/src/blackgui/components/flightplancomponent.ui b/src/blackgui/components/flightplancomponent.ui index f99234114..2e7f4847d 100644 --- a/src/blackgui/components/flightplancomponent.ui +++ b/src/blackgui/components/flightplancomponent.ui @@ -6,8 +6,8 @@ 0 0 - 425 - 512 + 392 + 510 @@ -42,9 +42,9 @@ 0 - 0 - 404 - 493 + -15 + 371 + 504 @@ -110,345 +110,7 @@ - - - - 4 - - - ICAO, e.g. EDDF - - - - - - - &Reset - - - - :/pastel/icons/pastel/16/arrow-refresh.png:/pastel/icons/pastel/16/arrow-refresh.png - - - - - - - 1. Type - - - - - - - 5. Departure airport - - - true - - - - - - - 2. Callsign - - - false - - - true - - - - - - - ICAO, e.g. A321 - - - - - - - 99:99 - - - 00:00 - - - 5 - - - hh:mm e.g. 02:30 - - - - - - - 6. Departure time - - - true - - - - - - - 99:99 - - - 00:00 - - - hh:mm e.g. 02:30 - - - - - - - pilot's name - - - 14. Pilot / homebase - - - true - - - - - - - Qt::Vertical - - - QSizePolicy::Fixed - - - - 20 - 10 - - - - - - - - goto generator page - - - goto gen. - - - - - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 40 - - - true - - - e.g. DLH1331 - - - - - - - Synchronize with simulator - - - Synchronize with simulator - - - - :/diagona/icons/diagona/icons/arrow-circle-225.png:/diagona/icons/diagona/icons/arrow-circle-225.png - - - - - - - - - - true - - - homebase (read only) - - - - - - - - - equipment code help - - - equipment code help - - - ... - - - - :/pastel/icons/pastel/16/help.png:/pastel/icons/pastel/16/help.png - - - - - - - 1 - - - equip.code - - - - - - - - - 7. Cruising altitude - - - true - - - - - - - Load flight plan from network - - - Download - - - - :/diagona/icons/diagona/icons/network-cloud.png:/diagona/icons/diagona/icons/network-cloud.png - - - - - - - Save to disk - - - Save - - - - :/pastel/icons/pastel/16/disk.png:/pastel/icons/pastel/16/disk.png - - - - - - 13. Alternate airport - - - true - - - - - - - Estimated time enroute - - - 10. Est.time enroute - - - true - - - - - - - true - - - sent time will go here (read only) - - - - - - - - 16777215 - 75 - - - - true - - - enter remarks here or use "generator" - - - - - - - Qt::Vertical - - - QSizePolicy::Fixed - - - - 20 - 10 - - - - - - - - True airspeed - - - 4. TAS - - - true - - - - 4 @@ -458,45 +120,17 @@ - - - - Send flight plan to network + + + + 40 - - Send - - - - :/diagona/icons/diagona/icons/network-cloud.png:/diagona/icons/diagona/icons/network-cloud.png + + e.g. 100 kts - - - - - - - - - altitude formats - - - altitude formats - - - ... - - - - :/pastel/icons/pastel/16/help.png:/pastel/icons/pastel/16/help.png - - - - - - + @@ -557,6 +191,26 @@ + + + + 12. Fuel on board + + + true + + + + + + + goto generator page + + + goto gen. + + + @@ -573,28 +227,321 @@ - + + + + + 16777215 + 75 + + + + true + + + + + + + 11.remarks + + + + + + + pilot's name + + + 14. Pilot / homebase + + + true + + + + + + + copy from generator page + + + from gen. + + + + + + + + + equipment code help + + + equipment code help + + + ... + + + + :/pastel/icons/pastel/16/help.png:/pastel/icons/pastel/16/help.png + + + + + + + 1 + + + equip.code + + + + + + + + + 1. Type + + + + + + + 99:99 + + + 00:00 + + + 5 + + + + + + + Estimated time enroute + + + 10. Est.time enroute + + + true + + + + + + + True airspeed + + + 4. TAS + + + true + + + + + + + true + + + homebase (read only) + + + + + + + true + + + sent time will go here (read only) + + + + + + + ICAO, e.g. A321 + + + + Sent - - - - Load from disk - + + - Load + 5. Departure airport - - - :/pastel/icons/pastel/16/disk.png:/pastel/icons/pastel/16/disk.png + + true - + + + + true + + + pilot's name (read only) + + + + + + + + 16777215 + 75 + + + + true + + + enter remarks here or use "generator" + + + + + + + 13. Alternate airport + + + true + + + + + + + 99:99 + + + 00:00 + + + 5 + + + hh:mm e.g. 02:30 + + + + + + + 9. Destination airport + + + true + + + + + + + true + + + P/ICAO/S + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + 40 + + + true + + + e.g. DLH1331 + + + + + + + Synchronize with simulator + + + Synchronize with simulator + + + + :/diagona/icons/diagona/icons/arrow-circle-225.png:/diagona/icons/diagona/icons/arrow-circle-225.png + + + + + + + + + + 4 + + + ICAO, e.g. EDDF + + + + + + + 2. Callsign + + + false + + + true + + + + + + + 7. Cruising altitude + + + true + + + + @@ -613,7 +560,51 @@ - + + + + + + + + + altitude formats + + + altitude formats + + + ... + + + + :/pastel/icons/pastel/16/help.png:/pastel/icons/pastel/16/help.png + + + + + + + + + 4 + + + ICAO, e.g. EDDF + + + + + + + 6. Departure time + + + true + + + + 8. Route @@ -623,150 +614,157 @@ - - - - - 16777215 - 75 - - - - true - - - - - + + 99:99 00:00 - - 5 - - - - - - - true - - P/ICAO/S - - - - - - - 40 - - - e.g. 100 kts - - - - - - - Anticipate (guess) some values - - - &Prefill - - - - :/diagona/icons/diagona/icons/compass--pencil.png:/diagona/icons/diagona/icons/compass--pencil.png - - - - - - - copy from generator page - - - from gen. - - - - - - - 12. Fuel on board - - - true - - - - - - - 9. Destination airport - - - true - - - - - - - true - - - pilot's name (read only) - - - - - - - 4 - - - ICAO, e.g. EDDF - - - - - - - 11.remarks - - - - - - - strict &check - - - - - - - SimBrief - - - - - - - &Validate - - - - :/diagona/icons/diagona/icons/abacus.png:/diagona/icons/diagona/icons/abacus.png + hh:mm e.g. 02:30 + + + + + 0 + 100 + + + + + 3 + + + 3 + + + 3 + + + 3 + + + 3 + + + + + strict check + + + strict &check + + + + + + + SimBrief + + + + + + + &Reset + + + + :/pastel/icons/pastel/16/arrow-refresh.png:/pastel/icons/pastel/16/arrow-refresh.png + + + + + + + Save to disk + + + Save + + + + :/pastel/icons/pastel/16/disk.png:/pastel/icons/pastel/16/disk.png + + + + + + + Load flight plan from network + + + Download + + + + :/diagona/icons/diagona/icons/network-cloud.png:/diagona/icons/diagona/icons/network-cloud.png + + + + + + + Send flight plan to network + + + Send + + + + :/diagona/icons/diagona/icons/network-cloud.png:/diagona/icons/diagona/icons/network-cloud.png + + + + + + + Load from disk + + + Load + + + + :/pastel/icons/pastel/16/disk.png:/pastel/icons/pastel/16/disk.png + + + + + + + Anticipate (guess) some values + + + &Prefill + + + + :/diagona/icons/diagona/icons/compass--pencil.png:/diagona/icons/diagona/icons/compass--pencil.png + + + + + + + &Validate + + + + :/diagona/icons/diagona/icons/abacus.png:/diagona/icons/diagona/icons/abacus.png + + + + + + @@ -800,8 +798,8 @@ 0 0 - 415 - 482 + 382 + 480 @@ -1089,14 +1087,7 @@ - - - QFrame::StyledPanel - - - QFrame::Raised - - + @@ -1260,12 +1251,6 @@ p, li { white-space: pre-wrap; } le_PilotsName le_PilotsHomeBase le_LastSent - pb_Prefill - pb_Reset - pb_Send - pb_Load - pb_SaveDisk - pb_LoadDisk sa_RemarksGenerator le_AirlineOperator le_AircraftRegistration diff --git a/src/blackgui/eventfilter.cpp b/src/blackgui/eventfilter.cpp index 52d9b2384..256761bf8 100644 --- a/src/blackgui/eventfilter.cpp +++ b/src/blackgui/eventfilter.cpp @@ -24,21 +24,30 @@ namespace BlackGui // processing proceed as it may be a control (e.g. cursor movement) // key. Otherwise convert the text to upper case and insert it at // the current cursor position. + QPlainTextEdit *pte = qobject_cast(object); + if (!pte) { return false; } + if (pte->isReadOnly()) { return false; } + if (e->text().length() == 1) { - QPlainTextEdit *pte = qobject_cast(object); - if (!pte) { return false; } - const QChar c = e->text().front(); - if (!c.isLower()) { return false; } - if (!c.isLetter()) { return false; } + if (m_illegalChars.contains(c)) { return true; } + if (c.isLetter()) + { + const ushort unicode = c.unicode(); + if (m_onlyAscii && unicode > 127) { return true; } - pte->insertPlainText(e->text().toUpper()); - - // return true to prevent further processing - return true; - } - } + pte->insertPlainText(e->text().toUpper()); + // return true to prevent further processing + return true; + } + else + { + // all codes like backspace etc. + return false; + } + } // length + } // key event } return false; } diff --git a/src/blackgui/eventfilter.h b/src/blackgui/eventfilter.h index 35367a66f..f6ca4e014 100644 --- a/src/blackgui/eventfilter.h +++ b/src/blackgui/eventfilter.h @@ -23,9 +23,19 @@ namespace BlackGui public: using QObject::QObject; + //! Not allowed characters + void setIllegalCharacters(const QString &illegal) { m_illegalChars = illegal; } + + //! Allow only ASCII + void setOnlyAscii() { m_onlyAscii = true; } + protected: //! Filter bool eventFilter(QObject *object, QEvent *event); + + private: + QString m_illegalChars; + bool m_onlyAscii = false; }; } // namespace diff --git a/src/blackgui/guiutility.cpp b/src/blackgui/guiutility.cpp index 8fd97201d..ed0891146 100644 --- a/src/blackgui/guiutility.cpp +++ b/src/blackgui/guiutility.cpp @@ -245,6 +245,36 @@ namespace BlackGui return false; } + bool CGuiUtility::setComboBoxValueByContainingString(QComboBox *box, const QString &candidate, const QString &unspecified) + { + if (!box) { return false; } + if (!candidate.isEmpty()) + { + for (int i = 0; i < box->count(); i++) + { + const QString t(box->itemText(i)); + if (t.contains(candidate, Qt::CaseInsensitive)) + { + box->setCurrentIndex(i); + return true; + } + } + } + + // not found + if (unspecified.isEmpty()) { return false; } + for (int i = 0; i < box->count(); i++) + { + const QString t(box->itemText(i)); + if (t.contains(unspecified, Qt::CaseInsensitive)) + { + box->setCurrentIndex(i); + return true; + } + } + return false; + } + bool CGuiUtility::hasSwiftVariantMimeType(const QMimeData *mime) { return mime && mime->hasFormat(swiftJsonDragAndDropMimeType()); diff --git a/src/blackgui/guiutility.h b/src/blackgui/guiutility.h index 1accdaf67..4c89918c3 100644 --- a/src/blackgui/guiutility.h +++ b/src/blackgui/guiutility.h @@ -100,6 +100,9 @@ namespace BlackGui //! Find best match in comboBox static bool setComboBoxValueByStartingString(QComboBox *box, const QString &candidate, const QString &unspecified = QString()); + //! Find best match in comboBox + static bool setComboBoxValueByContainingString(QComboBox *box, const QString &candidate, const QString &unspecified = QString()); + //! Mime data with swift type static bool hasSwiftVariantMimeType(const QMimeData *mime); diff --git a/src/blackmisc/aviation/flightplan.cpp b/src/blackmisc/aviation/flightplan.cpp index 4893727a6..7af892aab 100644 --- a/src/blackmisc/aviation/flightplan.cpp +++ b/src/blackmisc/aviation/flightplan.cpp @@ -45,6 +45,14 @@ namespace BlackMisc if (parse) { this->parseFlightPlanRemarks(); } } + bool CFlightPlanRemarks::setSelcalCode(const QString &selcal) + { + if (m_selcalCode == selcal || selcal.length() != 4) { return false; } + const QString r = CFlightPlanRemarks::replaceRemark(m_remarks, QStringLiteral("SEL/"), QStringLiteral("SEL/%1").arg(selcal)); + m_remarks = r; + return true; + } + void CFlightPlanRemarks::setVoiceCapabilities(const CVoiceCapabilities &capabilities) { m_voiceCapabilities = capabilities; @@ -67,9 +75,9 @@ namespace BlackMisc const QString s = (m_registration.isEmpty() ? QString() : u"reg.: " % m_registration.toQString(i18n)) % (!this->hasValidAirlineIcao() ? QString() : u" airline: " % m_airlineIcao.getDesignator()) - % (m_radioTelephony.isEmpty() ? QString() : u" radio tel.:" % m_radioTelephony) - % (m_flightOperator.isEmpty() ? QString() : u" operator: " % m_flightOperator) - % (!m_selcalCode.isValid() ? QString() : u" SELCAL: " % m_selcalCode.getCode()) + % (m_radioTelephony.isEmpty() ? QString() : u" radio tel.:" % m_radioTelephony) + % (m_flightOperator.isEmpty() ? QString() : u" operator: " % m_flightOperator) + % (!m_selcalCode.isValid() ? QString() : u" SELCAL: " % m_selcalCode.getCode()) % u" voice: " % m_voiceCapabilities.toQString(i18n); return s.simplified().trimmed(); } @@ -111,13 +119,13 @@ namespace BlackMisc m_isParsed = true; if (m_remarks.isEmpty()) { return; } const QString remarks = m_remarks.toUpper(); - const QString callsign = CCallsign::unifyCallsign(this->cut(remarks, "REG/")); // registration is a callsign + const QString callsign = CCallsign::unifyCallsign(this->getRemark(remarks, "REG/")); // registration is a callsign if (CCallsign::isValidAircraftCallsign(callsign)) { m_registration = CCallsign(callsign, CCallsign::Aircraft); } m_voiceCapabilities = m_voiceCapabilities.isUnknown() ? CVoiceCapabilities(m_remarks) : m_voiceCapabilities; - m_flightOperator = this->cut(remarks, "OPR/"); // operator, e.g. British airways, sometimes people use ICAO code here - m_selcalCode = CSelcal(this->cut(remarks, "SEL/")); - m_radioTelephony = cut(remarks, "CALLSIGN/"); // used similar to radio telephony - if (m_radioTelephony.isEmpty()) { m_radioTelephony = cut(remarks, "RT/"); } + m_flightOperator = this->getRemark(remarks, "OPR/"); // operator, e.g. British airways, sometimes people use ICAO code here + m_selcalCode = CSelcal(this->getRemark(remarks, "SEL/")); + m_radioTelephony = getRemark(remarks, "CALLSIGN/"); // used similar to radio telephony + if (m_radioTelephony.isEmpty()) { m_radioTelephony = getRemark(remarks, "RT/"); } if (!m_flightOperator.isEmpty() && CAirlineIcaoCode::isValidAirlineDesignator(m_flightOperator)) { // if people use ICAO code as flight operator swap with airline ICAO @@ -151,7 +159,7 @@ namespace BlackMisc this->parseFlightPlanRemarks(true); } - QString CFlightPlanRemarks::cut(const QString &remarks, const QString &marker) + QString CFlightPlanRemarks::getRemark(const QString &remarks, const QString &marker) { const int maxIndex = remarks.size() - 1; int f = remarks.indexOf(marker); @@ -168,12 +176,32 @@ namespace BlackMisc int to1 = remarks.indexOf(nextMarker, f + 1); // for case 2,3 if (to1 < 0) { to1 = maxIndex + 1; } int to2 = remarks.indexOf('/', f + 1); // for case 1 - if (to2 < 0) { to2 = maxIndex + 1; } // no more end markes, ends after last character + if (to2 < 0) { to2 = maxIndex + 1; } // no more end markers, ends after last character const int to = qMin(to1, to2); const QString cut = remarks.mid(f, to - f).simplified(); return cut; } + QString CFlightPlanRemarks::replaceRemark(const QString &remarks, const QString &marker, const QString &newRemark) + { + QString r(remarks); + const int maxIndex = remarks.size() - 1; + int f = remarks.indexOf(marker); + if (f >= 0) + { + f += marker.length(); + if (maxIndex <= f) { return remarks; } + thread_local const QRegularExpression nextMarker("\\s+\\w*/|$"); + int to1 = remarks.indexOf(nextMarker, f + 1); // for case 2,3 + if (to1 < 0) { to1 = maxIndex + 1; } + int to2 = remarks.indexOf('/', f + 1); // for case 1 + if (to2 < 0) { to2 = maxIndex + 1; } // no more end markers, ends after last character + const int to = qMin(to1, to2); + r.remove(f, to - f); + } + return r.isEmpty() ? newRemark : r % u" " % newRemark; + } + const CLogCategoryList &CFlightPlan::getLogCategories() { static const CLogCategoryList cats { CLogCategory::flightPlan() }; @@ -538,11 +566,24 @@ namespace BlackMisc const int b = equipment.indexOf('-'); const int e = equipment.indexOf('/'); + CFlightPlanRemarks r = fp.getFlightPlanRemarks(); + bool remarksChanged = false; if (e > b && e >= 0 && b >= 0 && equipment.size() > e) { - CFlightPlanRemarks r = fp.getFlightPlanRemarks(); const QString icao = equipment.mid(b + 1, e - b - 1); r.setIcaoEquipmentCodes(icao); + remarksChanged = true; + } + + const QString selcal = aircraft.firstChildElement("selcal").text(); + if (selcal.length() == 4) + { + const bool c = r.setSelcalCode(selcal); + remarksChanged = c || remarksChanged; + } + + if (remarksChanged) + { fp.setFlightPlanRemarks(r); } } diff --git a/src/blackmisc/aviation/flightplan.h b/src/blackmisc/aviation/flightplan.h index 18ccc8037..babc76b4c 100644 --- a/src/blackmisc/aviation/flightplan.h +++ b/src/blackmisc/aviation/flightplan.h @@ -72,6 +72,9 @@ namespace BlackMisc //! SELCAL code const CSelcal &getSelcalCode() const { return m_selcalCode; } + //! SELCAL code + bool setSelcalCode(const QString &selcal); + //! Get registration (a callsign, but normally not the flight callsign) const CCallsign &getRegistration() const { return m_registration; } @@ -141,7 +144,10 @@ namespace BlackMisc ); //! Cut the remarks part - static QString cut(const QString &remarks, const QString &marker); + static QString getRemark(const QString &remarks, const QString &marker); + + //! Replace a remark part + static QString replaceRemark(const QString &remarks, const QString &marker, const QString &newRemark); }; //! Value object for a flight plan