swift
dbaircrafticaoselectorcomponent.cpp
1 // SPDX-FileCopyrightText: Copyright (C) 2015 swift Project Community / Contributors
2 // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-swift-pilot-client-1
3 
5 
6 #include <QCompleter>
7 #include <QDragEnterEvent>
8 #include <QDragLeaveEvent>
9 #include <QDragMoveEvent>
10 #include <QDropEvent>
11 #include <QLabel>
12 #include <QLineEdit>
13 #include <QMetaType>
14 #include <QPalette>
15 #include <Qt>
16 
17 #include "ui_dbaircrafticaoselectorcomponent.h"
18 
19 #include "core/application.h"
20 #include "core/webdataservices.h"
21 #include "gui/guiapplication.h"
22 #include "gui/uppercasevalidator.h"
26 #include "misc/stringutils.h"
27 #include "misc/variant.h"
28 
29 using namespace swift::gui;
30 using namespace swift::core;
31 using namespace swift::misc;
32 using namespace swift::misc::aviation;
33 using namespace swift::misc::db;
34 using namespace swift::misc::network;
35 
36 namespace swift::gui::components
37 {
38  CDbAircraftIcaoSelectorComponent::CDbAircraftIcaoSelectorComponent(QWidget *parent)
39  : QFrame(parent), ui(new Ui::CDbAircraftIcaoSelectorComponent)
40  {
41  ui->setupUi(this);
42  this->setFocusProxy(ui->le_Aircraft);
43  this->setAcceptDrops(true);
44  this->setAcceptedMetaTypeIds({ qMetaTypeId<CAircraftIcaoCode>(), qMetaTypeId<CAircraftIcaoCodeList>() });
45  ui->le_Aircraft->setValidator(new CUpperCaseValidator(this));
46 
47  connect(ui->le_Aircraft, &QLineEdit::editingFinished, this, &CDbAircraftIcaoSelectorComponent::onDataChanged);
48  if (sApp && sApp->hasWebDataServices())
49  {
50  connect(sApp->getWebDataServices(), &CWebDataServices::dataRead, this,
51  &CDbAircraftIcaoSelectorComponent::onCodesRead, Qt::QueuedConnection);
52  this->onCodesRead(CEntityFlags::AircraftIcaoEntity, CEntityFlags::ReadFinished,
54  }
55  }
56 
58 
60  {
61  CAircraftIcaoCode setIcao(icao);
62  if (!icao.isLoadedFromDb())
63  {
64  // resolve against DB
66  }
67 
68  const QString icaoStr(m_display == DisplayIcaoAndId ? setIcao.getDesignatorDbKey() :
70  ui->le_Aircraft->setText(icaoStr);
71  ui->lbl_Description->setText(setIcao.getManufacturer());
72  if (setIcao == m_currentIcao) { return false; }
73 
74  m_currentIcao = setIcao;
75  emit changedAircraftIcao(setIcao);
76  return true;
77  }
78 
80  {
82  ui->lbl_Description->setText("");
83  return icao.hasCompleteData() ? this->setAircraftIcao(icao) : false;
84  }
85 
87  {
88  const QString text(ui->le_Aircraft->text().trimmed().toUpper());
89  const int key = CDatastoreUtility::extractIntegerKey(text);
90  if (key < 0)
91  {
92  const QString icaoOnly = CDatastoreUtility::stripKeyInParentheses(text);
93  if (m_currentIcao.getDesignator() == icaoOnly) { return m_currentIcao; }
94  return CAircraftIcaoCode(icaoOnly);
95  }
97  if (icao.isNull())
98  {
99  // did not find by key
100  const QString icaoOnly = CDatastoreUtility::stripKeyInParentheses(text);
101  if (m_currentIcao.getDesignator() == icaoOnly) { return m_currentIcao; }
102  return CAircraftIcaoCode(icaoOnly);
103  }
104  return icao;
105  }
106 
107  void CDbAircraftIcaoSelectorComponent::setReadOnly(bool readOnly) { ui->le_Aircraft->setReadOnly(readOnly); }
108 
110  {
111  return stripDesignatorFromCompleterString(ui->le_Aircraft->text());
112  }
113 
115  {
116  ui->lbl_Description->setVisible(description);
117  }
118 
120  {
121  const CAircraftIcaoCode icao(this->getAircraftIcao());
122  return icao.isLoadedFromDb() || icao.hasCompleteData();
123  }
124 
125  void CDbAircraftIcaoSelectorComponent::clear() { ui->le_Aircraft->clear(); }
126 
128  {
129  if (!event || !acceptDrop(event->mimeData())) { return; }
130  setBackgroundRole(QPalette::Highlight);
131  event->acceptProposedAction();
132  }
133 
135  {
136  if (!event || !acceptDrop(event->mimeData())) { return; }
137  event->acceptProposedAction();
138  }
139 
141  {
142  if (!event) { return; }
143  event->accept();
144  }
145 
147  {
148  if (!event || !acceptDrop(event->mimeData())) { return; }
149  const CVariant valueVariant(toCVariant(event->mimeData()));
150  if (valueVariant.isValid())
151  {
152  if (valueVariant.canConvert<CAircraftIcaoCode>())
153  {
154  CAircraftIcaoCode icao(valueVariant.value<CAircraftIcaoCode>());
155  if (!icao.hasValidDbKey()) { return; }
156  this->setAircraftIcao(icao);
157  }
158  else if (valueVariant.canConvert<CAircraftIcaoCodeList>())
159  {
160  CAircraftIcaoCodeList icaos(valueVariant.value<CAircraftIcaoCodeList>());
161  if (icaos.isEmpty()) { return; }
162  this->setAircraftIcao(icaos.front());
163  }
164  }
165  }
166 
167  const QStringList &CDbAircraftIcaoSelectorComponent::completerStrings()
168  {
169  static const QStringList empty;
170  if (!sGui || sGui->isShuttingDown() || !sGui->getWebDataServices()) { return empty; }
172  if (c != m_completerStrings.size())
173  {
175  icaos.removeInvalidCombinedCodes();
176  m_completerStrings = icaos.toCompleterStrings(true, true, true, true);
177  }
178  return m_completerStrings;
179  }
180 
181  void CDbAircraftIcaoSelectorComponent::onCodesRead(CEntityFlags::Entity entity, CEntityFlags::ReadState readState,
182  int count)
183  {
184  if (!sGui || sGui->isShuttingDown() || !sGui->hasWebDataServices()) { return; }
185  if (entity.testFlag(CEntityFlags::AircraftIcaoEntity) && CEntityFlags::isFinishedReadState(readState))
186  {
187  if (count > 0)
188  {
189  QCompleter *c = new QCompleter(this->completerStrings(), this);
190  c->setCaseSensitivity(Qt::CaseInsensitive);
191  c->setCompletionMode(QCompleter::PopupCompletion);
192  c->setMaxVisibleItems(10);
193  const int w5chars = c->popup()->fontMetrics().size(Qt::TextSingleLine, "FooBa").width();
194  c->popup()->setMinimumWidth(w5chars * 10);
195 
196  connect(c, qOverload<const QString &>(&QCompleter::activated), this,
197  &CDbAircraftIcaoSelectorComponent::onCompleterActivated);
198 
199  ui->le_Aircraft->setCompleter(c);
200  m_completerIcaoDescription.reset(c); // deletes any old completer
201  this->setReadOnly(false);
202  }
203  else { m_completerIcaoDescription.reset(nullptr); }
204  }
205  }
206 
207  void CDbAircraftIcaoSelectorComponent::onDataChanged()
208  {
209  if (!sGui || !sGui->hasWebDataServices()) { return; }
210  const int key = CDatastoreUtility::extractIntegerKey(ui->le_Aircraft->text());
211  CAircraftIcaoCode icao;
212  if (key >= 0)
213  {
214  // with valid key
216  }
217  else
218  {
219  const QString designator(this->getRawDesignator());
221  }
222  this->setAircraftIcao(icao);
223  }
224 
225  void CDbAircraftIcaoSelectorComponent::onCompleterActivated(const QString &icaoString)
226  {
227  const int dbKey = CDatastoreUtility::extractIntegerKey(icaoString);
228  if (dbKey < 0) { return; }
229  this->setAircraftIcao(dbKey);
230  }
231 } // namespace swift::gui::components
SWIFT_CORE_EXPORT swift::core::CApplication * sApp
Single instance of application object.
Definition: application.cpp:71
bool hasWebDataServices() const
Web data services available?
bool isShuttingDown() const
Is application shutting down?
CWebDataServices * getWebDataServices() const
Get the web data services.
swift::misc::aviation::CAircraftIcaoCode smartAircraftIcaoSelector(const swift::misc::aviation::CAircraftIcaoCode &icao) const
Use an ICAO object to select the best complete ICAO object from DB for it.
swift::misc::aviation::CAircraftIcaoCode getAircraftIcaoCodeForDbKey(int id) const
ICAO code for id.
int getAircraftIcaoCodesCount() const
Aircraft ICAO codes count.
swift::misc::aviation::CAircraftIcaoCodeList getAircraftIcaoCodes() const
Aircraft ICAO codes.
bool acceptDrop(const QMimeData *mime) const
Accept drop?
Definition: dropbase.cpp:24
swift::misc::CVariant toCVariant(const QMimeData *mime) const
Mime data to CVariant (normally encapsulating a value object)
Definition: dropbase.cpp:43
void setAcceptedMetaTypeIds(const QList< int > &ids)
Accepted ids.
Definition: dropbase.cpp:20
swift::misc::aviation::CAircraftIcaoCode getAircraftIcao() const
ICAO code.
void displayWithIcaoDescription(bool description)
Display distributor description.
void changedAircraftIcao(const swift::misc::aviation::CAircraftIcaoCode &icao)
ICAO was changed.
bool setAircraftIcao(const swift::misc::aviation::CAircraftIcaoCode &icao)
Current aircraft ICAO.
reference front()
Access the first element.
Definition: sequence.h:225
bool isEmpty() const
Synonym for empty.
Definition: sequence.h:285
Wrapper around QVariant which provides transparent access to CValueObject methods of the contained ob...
Definition: variant.h:66
T value() const
Return the value converted to the type T.
Definition: variant.h:169
bool isValid() const
True if this variant is valid.
Definition: variant.h:252
bool canConvert(int typeId) const
True if this variant can be converted to the type with the given metatype ID.
Value object for ICAO classification.
QString getCombinedIcaoStringWithKey() const
Combined ICAO descriptive string with key.
const QString & getDesignator() const
Get ICAO designator, e.g. "B737".
QString getDesignatorDbKey() const
Designator and DB key.
const QString & getManufacturer() const
Get manufacturer, e.g. "Airbus".
Value object encapsulating a list of ICAO codes.
bool isLoadedFromDb() const
Loaded from DB.
Definition: datastore.cpp:49
bool hasValidDbKey() const
Has valid DB key.
Definition: datastore.h:102
SWIFT_GUI_EXPORT swift::gui::CGuiApplication * sGui
Single instance of GUI application object.
Backend services of the swift project, like dealing with the network or the simulators.
Definition: actionbind.cpp:7
High level reusable GUI components.
Definition: aboutdialog.cpp:13
GUI related classes.
Free functions in swift::misc.
SWIFT_MISC_EXPORT QString stripDesignatorFromCompleterString(const QString &candidate)
Strip a designator from a combined string.