diff --git a/src/GUI/AircraftSearchFilterModel.cxx b/src/GUI/AircraftSearchFilterModel.cxx new file mode 100644 index 000000000..fd3784231 --- /dev/null +++ b/src/GUI/AircraftSearchFilterModel.cxx @@ -0,0 +1,113 @@ +#include "AircraftSearchFilterModel.hxx" + +#include "AircraftModel.hxx" +#include + +AircraftProxyModel::AircraftProxyModel(QObject *pr) : + QSortFilterProxyModel(pr) +{ +} + +void AircraftProxyModel::setRatings(int *ratings) +{ + ::memcpy(m_ratings, ratings, sizeof(int) * 4); + invalidate(); +} + +void AircraftProxyModel::setAircraftFilterString(QString s) +{ + m_filterString = s; + + m_filterProps = new SGPropertyNode; + int index = 0; + Q_FOREACH(QString term, s.split(' ')) { + m_filterProps->getNode("all-of/text", index++, true)->setStringValue(term.toStdString()); + } + + invalidate(); +} + +void AircraftProxyModel::setRatingFilterEnabled(bool e) +{ + if (e == m_ratingsFilter) { + return; + } + + m_ratingsFilter = e; + invalidate(); +} + +void AircraftProxyModel::setInstalledFilterEnabled(bool e) +{ + if (e == m_onlyShowInstalled) { + return; + } + + m_onlyShowInstalled = e; + invalidate(); +} + +bool AircraftProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const +{ + QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent); + QVariant v = index.data(AircraftPackageStatusRole); + AircraftItemStatus status = static_cast(v.toInt()); + if (status == MessageWidget) { + return true; + } + + if (!filterAircraft(index)) { + return false; + } + + if (m_onlyShowInstalled) { + QVariant v = index.data(AircraftPackageStatusRole); + AircraftItemStatus status = static_cast(v.toInt()); + if (status == PackageNotInstalled) { + return false; + } + } + + if (!m_onlyShowInstalled && m_ratingsFilter) { + for (int i=0; i<4; ++i) { + if (m_ratings[i] > index.data(AircraftRatingRole + i).toInt()) { + return false; + } + } + } + + return true; +} + +bool AircraftProxyModel::filterAircraft(const QModelIndex &sourceIndex) const +{ + if (m_filterString.isEmpty()) { + return true; + } + + simgear::pkg::PackageRef pkg = sourceIndex.data(AircraftPackageRefRole).value(); + if (pkg) { + return pkg->matches(m_filterProps.ptr()); + } + + QString baseName = sourceIndex.data(Qt::DisplayRole).toString(); + if (baseName.contains(m_filterString, Qt::CaseInsensitive)) { + return true; + } + + QString longDesc = sourceIndex.data(AircraftLongDescriptionRole).toString(); + if (longDesc.contains(m_filterString, Qt::CaseInsensitive)) { + return true; + } + + const int variantCount = sourceIndex.data(AircraftVariantCountRole).toInt(); + for (int variant = 0; variant < variantCount; ++variant) { + QString desc = sourceIndex.data(AircraftVariantDescriptionRole + variant).toString(); + if (desc.contains(m_filterString, Qt::CaseInsensitive)) { + return true; + } + } + + return false; +} + diff --git a/src/GUI/AircraftSearchFilterModel.hxx b/src/GUI/AircraftSearchFilterModel.hxx new file mode 100644 index 000000000..6390ff50d --- /dev/null +++ b/src/GUI/AircraftSearchFilterModel.hxx @@ -0,0 +1,36 @@ +#ifndef AIRCRAFTSEARCHFILTERMODEL_HXX +#define AIRCRAFTSEARCHFILTERMODEL_HXX + +#include + +#include + +class AircraftProxyModel : public QSortFilterProxyModel +{ + Q_OBJECT +public: + AircraftProxyModel(QObject* pr); + + void setRatings(int* ratings); + + void setAircraftFilterString(QString s); + +public slots: + void setRatingFilterEnabled(bool e); + + void setInstalledFilterEnabled(bool e); + +protected: + bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override; + +private: + bool filterAircraft(const QModelIndex& sourceIndex) const; + + bool m_ratingsFilter = true; + bool m_onlyShowInstalled = false; + int m_ratings[4] = {3, 3, 3, 3}; + QString m_filterString; + SGPropertyNode_ptr m_filterProps; +}; + +#endif // AIRCRAFTSEARCHFILTERMODEL_HXX diff --git a/src/GUI/CMakeLists.txt b/src/GUI/CMakeLists.txt index 0db53282f..406a4ec24 100644 --- a/src/GUI/CMakeLists.txt +++ b/src/GUI/CMakeLists.txt @@ -143,6 +143,10 @@ if (HAVE_QT) EnvironmentPage.h AdditionalSettings.cpp AdditionalSettings.h + LauncherArgumentTokenizer.cxx + LauncherArgumentTokenizer.hxx + AircraftSearchFilterModel.cxx + AircraftSearchFilterModel.hxx ${uic_sources} ${qrc_sources}) diff --git a/src/GUI/LauncherArgumentTokenizer.cxx b/src/GUI/LauncherArgumentTokenizer.cxx new file mode 100644 index 000000000..34d33e412 --- /dev/null +++ b/src/GUI/LauncherArgumentTokenizer.cxx @@ -0,0 +1,97 @@ +#include "LauncherArgumentTokenizer.hxx" + +LauncherArgumentTokenizer::LauncherArgumentTokenizer() +{ + +} + +QList LauncherArgumentTokenizer::tokenize(QString in) const +{ + int index = 0; + const int len = in.count(); + QChar c, nc; + State state = Start; + QString key, value; + QList result; + + for (; index < len; ++index) { + c = in.at(index); + nc = index < (len - 1) ? in.at(index + 1) : QChar(); + + switch (state) { + case Start: + if (c == QChar('-')) { + if (nc == QChar('-')) { + state = Key; + key.clear(); + ++index; + } else { + // should we pemit single hyphen arguments? + // choosing to fail for now + return QList(); + } + } else if (c == QChar('#')) { + state = Comment; + break; + } else if (c.isSpace()) { + break; + } + break; + + case Key: + if (c == QChar('=')) { + state = Value; + value.clear(); + } else if (c.isSpace()) { + state = Start; + result.append(Arg(key)); + } else { + // could check for illegal charatcers here + key.append(c); + } + break; + + case Value: + if (c == QChar('"')) { + state = Quoted; + } else if (c.isSpace()) { + state = Start; + result.append(Arg(key, value)); + } else { + value.append(c); + } + break; + + case Quoted: + if (c == QChar('\\')) { + // check for escaped double-quote inside quoted value + if (nc == QChar('"')) { + ++index; + } + } else if (c == QChar('"')) { + state = Value; + } else { + value.append(c); + } + break; + + case Comment: + if ((c == QChar('\n')) || (c == QChar('\r'))) { + state = Start; + break; + } else { + // nothing to do, eat comment chars + } + break; + } // of state switch + } // of character loop + + // ensure last argument isn't lost + if (state == Key) { + result.append(Arg(key)); + } else if (state == Value) { + result.append(Arg(key, value)); + } + + return result; +} diff --git a/src/GUI/LauncherArgumentTokenizer.hxx b/src/GUI/LauncherArgumentTokenizer.hxx new file mode 100644 index 000000000..9ce034ad7 --- /dev/null +++ b/src/GUI/LauncherArgumentTokenizer.hxx @@ -0,0 +1,34 @@ +#ifndef LAUNCHERARGUMENTTOKENIZER_HXX +#define LAUNCHERARGUMENTTOKENIZER_HXX + +#include +#include + +class LauncherArgumentTokenizer +{ +public: + LauncherArgumentTokenizer(); + + class Arg + { + public: + explicit Arg(QString k, QString v = QString()) : arg(k), value(v) {} + + QString arg; + QString value; + }; + + QList tokenize(QString in) const; + +private: + enum State { + Start = 0, + Key, + Value, + Quoted, + Comment + }; +}; + + +#endif // LAUNCHERARGUMENTTOKENIZER_HXX diff --git a/src/GUI/QtLauncher.cxx b/src/GUI/QtLauncher.cxx index c804c2076..ffbe8f776 100644 --- a/src/GUI/QtLauncher.cxx +++ b/src/GUI/QtLauncher.cxx @@ -35,7 +35,6 @@ #include #include #include -#include #include #include #include @@ -70,6 +69,8 @@ #include "PathsDialog.hxx" #include "EditCustomMPServerDialog.hxx" #include "previewwindow.h" +#include "LauncherArgumentTokenizer.hxx" +#include "AircraftSearchFilterModel.hxx" #include
#include
@@ -162,119 +163,6 @@ void initNavCache() } } -class ArgumentsTokenizer -{ -public: - class Arg - { - public: - explicit Arg(QString k, QString v = QString()) : arg(k), value(v) {} - - QString arg; - QString value; - }; - - QList tokenize(QString in) const - { - int index = 0; - const int len = in.count(); - QChar c, nc; - State state = Start; - QString key, value; - QList result; - - for (; index < len; ++index) { - c = in.at(index); - nc = index < (len - 1) ? in.at(index + 1) : QChar(); - - switch (state) { - case Start: - if (c == QChar('-')) { - if (nc == QChar('-')) { - state = Key; - key.clear(); - ++index; - } else { - // should we pemit single hyphen arguments? - // choosing to fail for now - return QList(); - } - } else if (c == QChar('#')) { - state = Comment; - break; - } else if (c.isSpace()) { - break; - } - break; - - case Key: - if (c == QChar('=')) { - state = Value; - value.clear(); - } else if (c.isSpace()) { - state = Start; - result.append(Arg(key)); - } else { - // could check for illegal charatcers here - key.append(c); - } - break; - - case Value: - if (c == QChar('"')) { - state = Quoted; - } else if (c.isSpace()) { - state = Start; - result.append(Arg(key, value)); - } else { - value.append(c); - } - break; - - case Quoted: - if (c == QChar('\\')) { - // check for escaped double-quote inside quoted value - if (nc == QChar('"')) { - ++index; - } - } else if (c == QChar('"')) { - state = Value; - } else { - value.append(c); - } - break; - - case Comment: - if ((c == QChar('\n')) || (c == QChar('\r'))) { - state = Start; - break; - } else { - // nothing to do, eat comment chars - } - break; - } // of state switch - } // of character loop - - // ensure last argument isn't lost - if (state == Key) { - result.append(Arg(key)); - } else if (state == Value) { - result.append(Arg(key, value)); - } - - return result; - } - -private: - enum State { - Start = 0, - Key, - Value, - Quoted, - Comment - }; -}; - class NaturalEarthDataLoaderThread : public QThread { Q_OBJECT @@ -333,139 +221,13 @@ private: flightgear::PolyLineList lines; flightgear::SHPParser::parsePolyLines(path, aType, m_parsedLines, areClosed); } - + flightgear::PolyLineList m_parsedLines; unsigned int m_lineInsertCount; }; } // of anonymous namespace -class AircraftProxyModel : public QSortFilterProxyModel -{ - Q_OBJECT -public: - AircraftProxyModel(QObject* pr) : - QSortFilterProxyModel(pr), - m_ratingsFilter(true), - m_onlyShowInstalled(false) - { - for (int i=0; i<4; ++i) { - m_ratings[i] = 3; - } - } - - void setRatings(int* ratings) - { - ::memcpy(m_ratings, ratings, sizeof(int) * 4); - invalidate(); - } - - void setAircraftFilterString(QString s) - { - m_filterString = s; - - m_filterProps = new SGPropertyNode; - int index = 0; - Q_FOREACH(QString term, s.split(' ')) { - m_filterProps->getNode("all-of/text", index++, true)->setStringValue(term.toStdString()); - } - - invalidate(); - } - -public slots: - void setRatingFilterEnabled(bool e) - { - if (e == m_ratingsFilter) { - return; - } - - m_ratingsFilter = e; - invalidate(); - } - - void setInstalledFilterEnabled(bool e) - { - if (e == m_onlyShowInstalled) { - return; - } - - m_onlyShowInstalled = e; - invalidate(); - } - -protected: - bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const - { - QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent); - QVariant v = index.data(AircraftPackageStatusRole); - AircraftItemStatus status = static_cast(v.toInt()); - if (status == MessageWidget) { - return true; - } - - if (!filterAircraft(index)) { - return false; - } - - if (m_onlyShowInstalled) { - QVariant v = index.data(AircraftPackageStatusRole); - AircraftItemStatus status = static_cast(v.toInt()); - if (status == PackageNotInstalled) { - return false; - } - } - - if (!m_onlyShowInstalled && m_ratingsFilter) { - for (int i=0; i<4; ++i) { - if (m_ratings[i] > index.data(AircraftRatingRole + i).toInt()) { - return false; - } - } - } - - return true; - } - -private: - bool filterAircraft(const QModelIndex& sourceIndex) const - { - if (m_filterString.isEmpty()) { - return true; - } - - simgear::pkg::PackageRef pkg = sourceIndex.data(AircraftPackageRefRole).value(); - if (pkg) { - return pkg->matches(m_filterProps.ptr()); - } - - QString baseName = sourceIndex.data(Qt::DisplayRole).toString(); - if (baseName.contains(m_filterString, Qt::CaseInsensitive)) { - return true; - } - - QString longDesc = sourceIndex.data(AircraftLongDescriptionRole).toString(); - if (longDesc.contains(m_filterString, Qt::CaseInsensitive)) { - return true; - } - - const int variantCount = sourceIndex.data(AircraftVariantCountRole).toInt(); - for (int variant = 0; variant < variantCount; ++variant) { - QString desc = sourceIndex.data(AircraftVariantDescriptionRole + variant).toString(); - if (desc.contains(m_filterString, Qt::CaseInsensitive)) { - return true; - } - } - - return false; - } - - bool m_ratingsFilter; - bool m_onlyShowInstalled; - int m_ratings[4]; - QString m_filterString; - SGPropertyNode_ptr m_filterProps; -}; class NoOfficialHangarMessage : public QWidget { @@ -576,7 +338,7 @@ private: return VISIT_CONTINUE; } - + std::string _aircraftId; SGPath _foundPath; }; @@ -1589,7 +1351,7 @@ void QtLauncher::onPopupAircraftHistory() if (nm.isEmpty()) { continue; } - + QAction* act = m.addAction(nm); act->setData(uri); }