From a51f696bee7efe1265091e58030c9ef4e4914883 Mon Sep 17 00:00:00 2001 From: Klaus Basan Date: Fri, 13 Oct 2017 19:55:17 +0200 Subject: [PATCH] Ref T171, callsign completer class * completer used in 3 places, makes sense to encapsulate as class * automatically updating from network context --- src/blackgui/components/callsigncompleter.cpp | 124 ++++++++++++++++++ src/blackgui/components/callsigncompleter.h | 73 +++++++++++ src/blackgui/components/callsigncompleter.ui | 54 ++++++++ 3 files changed, 251 insertions(+) create mode 100644 src/blackgui/components/callsigncompleter.cpp create mode 100644 src/blackgui/components/callsigncompleter.h create mode 100644 src/blackgui/components/callsigncompleter.ui diff --git a/src/blackgui/components/callsigncompleter.cpp b/src/blackgui/components/callsigncompleter.cpp new file mode 100644 index 000000000..fb41d7a0e --- /dev/null +++ b/src/blackgui/components/callsigncompleter.cpp @@ -0,0 +1,124 @@ +/* Copyright (C) 2017 + * swift project Community / Contributors + * + * This file is part of swift Project. It is subject to the license terms in the LICENSE file found in the top-level + * directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project, + * including this file, may be copied, modified, propagated, or distributed except according to the terms + * contained in the LICENSE file. + */ + +#include "callsigncompleter.h" +#include "ui_callsigncompleter.h" +#include "blackcore/context/contextnetwork.h" +#include "blackgui/guiapplication.h" +#include "blackgui/led.h" +#include "blackgui/uppercasevalidator.h" +#include + +using namespace BlackMisc; +using namespace BlackMisc::Aviation; +using namespace BlackCore; +using namespace BlackCore::Context; + +namespace BlackGui +{ + namespace Components + { + CCallsignCompleter::CCallsignCompleter(QWidget *parent) : + QFrame(parent), + ui(new Ui::CCallsignCompleter) + { + Q_ASSERT_X(sGui, Q_FUNC_INFO, "Need sGui"); + Q_ASSERT_X(sGui->getIContextNetwork(), Q_FUNC_INFO, "Need network context"); + ui->setupUi(this); + CUpperCaseValidator *ucv = new CUpperCaseValidator(ui->le_Callsign); + ui->le_Callsign->setValidator(ucv); + ui->led_Status->setToolTips("connected", "disconnected"); + ui->led_Status->setShape(CLedWidget::Rounded); + ui->led_Status->setToolTips("network connected", "network disconnected", "data"); + ui->led_Status->setShape(CLedWidget::Rounded); + connect(ui->le_Callsign, &QLineEdit::editingFinished, this, &CCallsignCompleter::onEditingFinished); + connect(sGui->getIContextNetwork(), &IContextNetwork::changedAircraftInRange, &m_dsAircraftsInRangeChanged, &CDigestSignal::inputSignal); + connect(sGui->getIContextNetwork(), &IContextNetwork::connectionStatusChanged, this, &CCallsignCompleter::onChangedConnectionStatus, Qt::QueuedConnection); + m_dsAircraftsInRangeChanged.inputSignal(); // trigger + } + + CCallsignCompleter::~CCallsignCompleter() + { } + + BlackMisc::Aviation::CCallsign CCallsignCompleter::getCallsign() const + { + const QString csString = ui->le_Callsign->text().trimmed().toUpper(); + if (!this->isValidKnownCallsign(csString)) { return CCallsign(); } + return CCallsign(csString); + } + + QString CCallsignCompleter::getRawCallsignString() const + { + return ui->le_Callsign->text(); + } + + bool CCallsignCompleter::hasValidCallsign() const + { + const QString csString = ui->le_Callsign->text().trimmed().toUpper(); + return this->isValidKnownCallsign(csString); + } + + void CCallsignCompleter::updateCallsignsFromContext() + { + if (!sGui || sGui->isShuttingDown()) { return; } + if (!sGui->getIContextNetwork()) { return; } + m_validCallsigns = sGui->getIContextNetwork()->getAircraftInRangeCallsigns(); + const QStringList modelData = m_validCallsigns.getCallsignStrings(true); + if (!m_currentCompleter) + { + m_currentCompleter = new QCompleter(modelData, ui->le_Callsign); + ui->le_Callsign->setCompleter(m_currentCompleter); + } + else + { + QStringListModel *model = qobject_cast(m_currentCompleter->model()); + Q_ASSERT(model); + model->setStringList(modelData); + } + ui->led_Status->setTriState(500); + } + + void CCallsignCompleter::onEditingFinished() + { + const CCallsign cs = this->getCallsign(); + emit this->editingFinished(); + if (cs.isValid()) + { + emit this->validCallsignEntered(); + } + } + + void CCallsignCompleter::onChangedAircraftInRange() + { + this->updateCallsignsFromContext(); + } + + void CCallsignCompleter::onChangedConnectionStatus(INetwork::ConnectionStatus from, INetwork::ConnectionStatus to) + { + Q_UNUSED(from); + const bool on = (INetwork::Connected == to); + ui->led_Status->setOn(on); + ui->le_Callsign->clear(); + ui->le_Callsign->setEnabled(on); + if (!on) + { + QStringListModel *model = qobject_cast(m_currentCompleter->model()); + Q_ASSERT(model); + model->setStringList(QStringList()); + } + } + + bool CCallsignCompleter::isValidKnownCallsign(const QString &callsignString) const + { + if (m_validCallsigns.isEmpty()) { return false; } + if (!CCallsign::isValidAircraftCallsign(callsignString)) { return false; } + return m_validCallsigns.contains(CCallsign(callsignString)); + } + } // ns +} // ns diff --git a/src/blackgui/components/callsigncompleter.h b/src/blackgui/components/callsigncompleter.h new file mode 100644 index 000000000..22d1bde4b --- /dev/null +++ b/src/blackgui/components/callsigncompleter.h @@ -0,0 +1,73 @@ +/* Copyright (C) 2017 + * swift project Community / Contributors + * + * This file is part of swift Project. It is subject to the license terms in the LICENSE file found in the top-level + * directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project, + * including this file, may be copied, modified, propagated, or distributed except according to the terms + * contained in the LICENSE file. + */ + +//! \file + +#ifndef BLACKGUI_COMPONENTS_CALLSIGNCOMPLETER_H +#define BLACKGUI_COMPONENTS_CALLSIGNCOMPLETER_H + +#include "blackgui/blackguiexport.h" +#include "blackmisc/digestsignal.h" +#include "blackmisc/aviation/callsignset.h" +#include "blackcore/network.h" +#include +#include +#include +#include + +namespace Ui { class CCallsignCompleter; } +namespace BlackGui +{ + namespace Components + { + /** + * Completer for aircraft callsigns + */ + class BLACKGUI_EXPORT CCallsignCompleter : public QFrame + { + Q_OBJECT + + public: + //! Ctor + explicit CCallsignCompleter(QWidget *parent = nullptr); + + //! Dtor + virtual ~CCallsignCompleter(); + + //! Get the entered callsign + BlackMisc::Aviation::CCallsign getCallsign() const; + + //! String as entered + QString getRawCallsignString() const; + + //! Is valid callsign? + bool hasValidCallsign() const; + + signals: + //! Callsign entered + void validCallsignEntered(); + + //! Editing finished + void editingFinished(); + + private: + void updateCallsignsFromContext(); + void onEditingFinished(); + void onChangedAircraftInRange(); + void onChangedConnectionStatus(BlackCore::INetwork::ConnectionStatus from, BlackCore::INetwork::ConnectionStatus to); + bool isValidKnownCallsign(const QString &callsignString) const; + + QScopedPointer ui; + QCompleter *m_currentCompleter = nullptr; + BlackMisc::Aviation::CCallsignSet m_validCallsigns; + BlackMisc::CDigestSignal m_dsAircraftsInRangeChanged { this, &CCallsignCompleter::onChangedAircraftInRange, 5000, 5 }; + }; + } // ns +} // ns +#endif // guard diff --git a/src/blackgui/components/callsigncompleter.ui b/src/blackgui/components/callsigncompleter.ui new file mode 100644 index 000000000..ece6dfbc0 --- /dev/null +++ b/src/blackgui/components/callsigncompleter.ui @@ -0,0 +1,54 @@ + + + CCallsignCompleter + + + + 0 + 0 + 91 + 22 + + + + Frame + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + callsign + + + true + + + + + + + + + + + BlackGui::CLedWidget + QWidget +
blackgui/led.h
+ 1 +
+
+ + +