diff --git a/src/blackgui/components/callsigncompleter.cpp b/src/blackgui/components/callsigncompleter.cpp index fb41d7a0e..c502c3da6 100644 --- a/src/blackgui/components/callsigncompleter.cpp +++ b/src/blackgui/components/callsigncompleter.cpp @@ -33,6 +33,7 @@ namespace BlackGui ui->setupUi(this); CUpperCaseValidator *ucv = new CUpperCaseValidator(ui->le_Callsign); ui->le_Callsign->setValidator(ucv); + ui->le_Callsign->setCompleter(*completer()); ui->led_Status->setToolTips("connected", "disconnected"); ui->led_Status->setShape(CLedWidget::Rounded); ui->led_Status->setToolTips("network connected", "network disconnected", "data"); @@ -68,19 +69,10 @@ namespace BlackGui { if (!sGui || sGui->isShuttingDown()) { return; } if (!sGui->getIContextNetwork()) { return; } + if (completer()->wasUpdatedWithinTime(1500)) { return; } // avoid context call via DBus 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); - } + completer()->updateData(modelData, 2000); ui->led_Status->setTriState(500); } @@ -102,15 +94,13 @@ namespace BlackGui void CCallsignCompleter::onChangedConnectionStatus(INetwork::ConnectionStatus from, INetwork::ConnectionStatus to) { Q_UNUSED(from); - const bool on = (INetwork::Connected == to); - ui->led_Status->setOn(on); + const bool connected = (INetwork::Connected == to); + ui->led_Status->setOn(connected); ui->le_Callsign->clear(); - ui->le_Callsign->setEnabled(on); - if (!on) + ui->le_Callsign->setEnabled(connected); + if (!connected) { - QStringListModel *model = qobject_cast(m_currentCompleter->model()); - Q_ASSERT(model); - model->setStringList(QStringList()); + completer()->clearData(); } } @@ -120,5 +110,11 @@ namespace BlackGui if (!CCallsign::isValidAircraftCallsign(callsignString)) { return false; } return m_validCallsigns.contains(CCallsign(callsignString)); } + + CSharedStringListCompleter *CCallsignCompleter::completer() + { + static CSharedStringListCompleter *c = new CSharedStringListCompleter(); + return c; + } } // ns } // ns diff --git a/src/blackgui/components/callsigncompleter.h b/src/blackgui/components/callsigncompleter.h index 22d1bde4b..b035fd511 100644 --- a/src/blackgui/components/callsigncompleter.h +++ b/src/blackgui/components/callsigncompleter.h @@ -13,6 +13,7 @@ #define BLACKGUI_COMPONENTS_CALLSIGNCOMPLETER_H #include "blackgui/blackguiexport.h" +#include "blackgui/sharedstringlistcompleter.h" #include "blackmisc/digestsignal.h" #include "blackmisc/aviation/callsignset.h" #include "blackcore/network.h" @@ -63,8 +64,10 @@ namespace BlackGui void onChangedConnectionStatus(BlackCore::INetwork::ConnectionStatus from, BlackCore::INetwork::ConnectionStatus to); bool isValidKnownCallsign(const QString &callsignString) const; + //! Shared completer data + static CSharedStringListCompleter *completer(); + QScopedPointer ui; - QCompleter *m_currentCompleter = nullptr; BlackMisc::Aviation::CCallsignSet m_validCallsigns; BlackMisc::CDigestSignal m_dsAircraftsInRangeChanged { this, &CCallsignCompleter::onChangedAircraftInRange, 5000, 5 }; }; diff --git a/src/blackgui/sharedstringlistcompleter.cpp b/src/blackgui/sharedstringlistcompleter.cpp new file mode 100644 index 000000000..ae5a01072 --- /dev/null +++ b/src/blackgui/sharedstringlistcompleter.cpp @@ -0,0 +1,42 @@ +/* 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 "sharedstringlistcompleter.h" +#include +#include + +namespace BlackGui +{ + bool CSharedStringListCompleter::updateData(const QStringList &data, int cacheTimeMs) + { + QStringListModel *model = qobject_cast(m_completer->model()); + Q_ASSERT_X(model, Q_FUNC_INFO, "Model missing"); + bool updated = false; + const qint64 now = QDateTime::currentMSecsSinceEpoch(); + if (model->rowCount() != data.size() || (now - m_lastUpdated) > cacheTimeMs) + { + // quick check, different size means data changed -> update + // otherwise rely on time + m_lastUpdated = now; + model->setStringList(data); + updated = true; + } + return updated; + } + + void CSharedStringListCompleter::clearData() + { + this->updateData(QStringList(), 0); + } + + bool CSharedStringListCompleter::wasUpdatedWithinTime(int checkTimeMs) const + { + return (QDateTime::currentMSecsSinceEpoch() - m_lastUpdated) <= checkTimeMs; + } +} // ns diff --git a/src/blackgui/sharedstringlistcompleter.h b/src/blackgui/sharedstringlistcompleter.h new file mode 100644 index 000000000..f4aa45f31 --- /dev/null +++ b/src/blackgui/sharedstringlistcompleter.h @@ -0,0 +1,54 @@ +/* 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_SHAREDSTRINGLISTCOMPLETER_H +#define BLACKGUI_SHAREDSTRINGLISTCOMPLETER_H + +#include "blackgui/blackguiexport.h" + +#include +#include +#include + +namespace BlackGui +{ + /*! + * Completer shared among multiple UI elements. + * Normally used as static member + */ + class BLACKGUI_EXPORT CSharedStringListCompleter + { + public: + //! Constructor + CSharedStringListCompleter() {} + + //! Update data + bool updateData(const QStringList &data, int cacheTimeMs); + + //! Clear completer data + void clearData(); + + //! Was updated within check time + bool wasUpdatedWithinTime(int checkTimeMs) const; + + //! Completer + QCompleter *completer() const { return m_completer.data(); } + + //! Convert to completer + operator QCompleter *() const { return m_completer.data(); } + + private: + qint64 m_lastUpdated = 0; + QScopedPointer m_completer { new QCompleter(QStringList()) }; // empty list required to init model + }; +} // ns + +#endif // guard