diff --git a/src/blackgui/components/countryselector.cpp b/src/blackgui/components/countryselector.cpp new file mode 100644 index 000000000..c77956902 --- /dev/null +++ b/src/blackgui/components/countryselector.cpp @@ -0,0 +1,78 @@ +/* Copyright (C) 2018 + * 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 "countryselector.h" +#include "ui_countryselector.h" + +#include "blackgui/guiapplication.h" +#include "blackgui/uppercasevalidator.h" +#include "blackcore/webdataservices.h" +#include "blackmisc/countrylist.h" +#include + +using namespace BlackMisc; +using namespace BlackCore; + +namespace BlackGui +{ + namespace Components + { + CCountrySelector::CCountrySelector(QWidget *parent) : + QFrame(parent), + ui(new Ui::CCountrySelector) + { + Q_ASSERT_X(sGui, Q_FUNC_INFO, "Missing sGui"); + ui->setupUi(this); + ui->le_Iso->setValidator(new CUpperCaseValidator(ui->le_Iso)); + + connect(sGui->getWebDataServices(), &CWebDataServices::swiftDbAllDataRead, this, &CCountrySelector::onCountriesLoaded); + connect(ui->cb_Country, &QComboBox::currentTextChanged, this, &CCountrySelector::onCountryNameChanged); + connect(ui->le_Iso, &QLineEdit::editingFinished, this, &CCountrySelector::onIsoChanged); + + this->onCountriesLoaded(); + } + + CCountrySelector::~CCountrySelector() + { } + + void CCountrySelector::setCountry(const CCountry &country) + { + if (country == m_current) { return; } + m_current = country; + if (country.getIsoCode() != ui->le_Iso->text()) { ui->le_Iso->setText(country.getIsoCode()); } + if (country.getName() != ui->cb_Country->currentText()) { ui->cb_Country->setCurrentText(country.getName()); } + emit this->countryChanged(m_current); + } + + void CCountrySelector::onCountriesLoaded() + { + if (!sGui || !sGui->hasWebDataServices()) { return; } + const CCountryList countries = sGui->getWebDataServices()->getCountries(); + + ui->le_Iso->setCompleter(new QCompleter(countries.toIsoList(true))); + ui->cb_Country->clear(); + ui->cb_Country->addItems(countries.toNameList(true)); + } + + void CCountrySelector::onIsoChanged() + { + if (!sGui || !sGui->hasWebDataServices()) { return; } + const QString iso(ui->le_Iso->text().trimmed().toUpper()); + if (m_current.getIsoCode() == iso) { return; } + this->setCountry(sGui->getWebDataServices()->getCountryForIsoCode(iso)); + } + + void CCountrySelector::onCountryNameChanged(const QString &name) + { + if (!sGui || !sGui->hasWebDataServices()) { return; } + if (m_current.getName() == name) { return; } + this->setCountry(sGui->getWebDataServices()->getCountryForName(name)); + } + } // ns +} // ns diff --git a/src/blackgui/components/countryselector.h b/src/blackgui/components/countryselector.h new file mode 100644 index 000000000..9cf6ed071 --- /dev/null +++ b/src/blackgui/components/countryselector.h @@ -0,0 +1,63 @@ +/* Copyright (C) 2018 + * 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_COUNTRYSELECTOR_H +#define BLACKGUI_COMPONENTS_COUNTRYSELECTOR_H + +#include "blackmisc/country.h" +#include +#include + +namespace Ui { class CCountrySelector; } +namespace BlackGui +{ + namespace Components + { + /** + * @brief Select a valid country + */ + class CCountrySelector : public QFrame + { + Q_OBJECT + + public: + //! Constructor + explicit CCountrySelector(QWidget *parent = nullptr); + + //! Destructor + virtual ~CCountrySelector(); + + //! Set country + void setCountry(const BlackMisc::CCountry &country); + + //! Get country + const BlackMisc::CCountry &getCountry() const { return m_current; } + + signals: + //! Changed country + void countryChanged(const BlackMisc::CCountry &country); + + private: + //! Countries loaded + void onCountriesLoaded(); + + //! ISO has been changed + void onIsoChanged(); + + //! Country name has been changed + void onCountryNameChanged(const QString &name); + + BlackMisc::CCountry m_current; + QScopedPointer ui; + }; + } // ns +} // ns +#endif // guard diff --git a/src/blackgui/components/countryselector.ui b/src/blackgui/components/countryselector.ui new file mode 100644 index 000000000..8ecd55d72 --- /dev/null +++ b/src/blackgui/components/countryselector.ui @@ -0,0 +1,50 @@ + + + CCountrySelector + + + + 0 + 0 + 134 + 22 + + + + Frame + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + 5 + + + ISO, e.g. "DE" + + + + + + + true + + + + + + + + diff --git a/src/blackmisc/countrylist.cpp b/src/blackmisc/countrylist.cpp index b8fdcbf79..72362c2ea 100644 --- a/src/blackmisc/countrylist.cpp +++ b/src/blackmisc/countrylist.cpp @@ -25,7 +25,7 @@ namespace BlackMisc CCountry CCountryList::findByIsoCode(const QString &isoCode) const { - QString iso(isoCode.trimmed().toUpper()); + const QString iso(isoCode.trimmed().toUpper()); if (!CCountry::isValidIsoCode(iso)) { return CCountry(); } return IDatastoreObjectList::findByKey(isoCode); } @@ -35,7 +35,7 @@ namespace BlackMisc if (countryName.isEmpty()) { return CCountry(); } thread_local const QRegularExpression reg("^[a-z]+", QRegularExpression::CaseInsensitiveOption); - QRegularExpressionMatch match = reg.match(countryName); + const QRegularExpressionMatch match = reg.match(countryName); const QString cn(match.hasMatch() ? match.captured(0) : countryName); const CCountryList countries = this->findBy([&](const CCountry & country) { @@ -65,39 +65,68 @@ namespace BlackMisc return CCountry(); } - QStringList CCountryList::toIsoNameList() const + QStringList CCountryList::toIsoNameList(bool sorted) const { QStringList sl; for (const CCountry &country : (*this)) { - QString s = country.getCombinedStringIsoName(); + const QString s = country.getCombinedStringIsoName(); if (s.isEmpty()) { continue; } sl.append(s); } + if (sorted) { sl.sort(); } return sl; } - QStringList CCountryList::toNameIsoList() const + QStringList CCountryList::toNameIsoList(bool sorted) const { QStringList sl; for (const CCountry &country : (*this)) { - QString s = country.getCombinedStringNameIso(); + const QString s = country.getCombinedStringNameIso(); if (s.isEmpty()) { continue; } sl.append(s); } + if (sorted) { sl.sort(); } return sl; } - QStringList CCountryList::toNameList() const + QStringList CCountryList::toNameList(bool sorted) const { QStringList sl; for (const CCountry &country : (*this)) { - QString s = country.getName(); + const QString s = country.getName(); if (s.isEmpty()) { continue; } sl.append(s); } + if (sorted) { sl.sort(); } + return sl; + } + + QStringList CCountryList::toIsoList(bool sorted) const + { + QStringList sl; + for (const CCountry &country : (*this)) + { + const QString s = country.getIsoCode(); + if (s.length() != 2) { continue; } + sl.append(s); + } + if (sorted) { sl.sort(); } + return sl; + } + + QStringList CCountryList::toIso3List(bool sorted) const + { + QStringList sl; + for (const CCountry &country : (*this)) + { + const QString s = country.getIso3Code(); + if (s.length() != 3) { continue; } + sl.append(s); + } + if (sorted) { sl.sort(); } return sl; } diff --git a/src/blackmisc/countrylist.h b/src/blackmisc/countrylist.h index cec143b90..ff0932344 100644 --- a/src/blackmisc/countrylist.h +++ b/src/blackmisc/countrylist.h @@ -53,18 +53,23 @@ namespace BlackMisc CCountry findFirstByAlias(const QString &alias) const; //! ISO/name string list - QStringList toIsoNameList() const; + QStringList toIsoNameList(bool sorted = false) const; //! Name/ISO string list - QStringList toNameIsoList() const; + QStringList toNameIsoList(bool sorted = false) const; //! Name string list - QStringList toNameList() const; + QStringList toNameList(bool sorted = false) const; + + //! All ISO codes + QStringList toIsoList(bool sorted = false) const; + + //! All ISO 3 codes + QStringList toIso3List(bool sorted = false) const; //! From our database JSON format static CCountryList fromDatabaseJson(const QJsonArray &array); }; - } //namespace Q_DECLARE_METATYPE(BlackMisc::CCountryList)