1 // UnitsModel.cxx - part of GUI launcher using Qt5
2 //
3 // Written by James Turner, started July 2018
4 //
5 // Copyright (C) 2018 James Turner <james@flightgear.org>
6 //
7 // This program is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU General Public License as
9 // published by the Free Software Foundation; either version 2 of the
10 // License, or (at your option) any later version.
11 //
12 // This program is distributed in the hope that it will be useful, but
13 // WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 // General Public License for more details.
16 //
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software
19 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
20 
21 #ifndef UNITSMODEL_HXX
22 #define UNITSMODEL_HXX
23 
24 #include <vector>
25 
26 #include <QAbstractListModel>
27 
28 class QValidator;
29 class QDataStream;
30 
31 class Units : public QObject
32 {
33     Q_OBJECT
34 public:
35 
36 
37     /**
38      * @brief This enum stores units / types of values used in the
39      * simulator. They're not strictly all units, but they map to the
40      * same concept for the user: selecting the dimension of values they
41      * are inputting
42      */
43     enum Type
44     {
45         NoUnits = 0,
46         FeetMSL,
47         FeetAGL,
48         FeetAboveFieldElevation,
49         FlightLevel,
50         MetersMSL,
51         Knots,
52         Mach,
53         KilometersPerHour,
54         DegreesTrue,
55         DegreesMagnetic,
56         TimeUTC,
57         TimeLocal,
58         NauticalMiles,
59         Kilometers,
60         FreqMHz,    // for VORs, LOCs
61         FreqKHz     // for NDBs
62     };
63 
64     enum Mode
65     {
66         Altitude = 0,   // MSL, FlightLevel
67         AltitudeIncludingAGL,
68         AltitudeIncludingMeters,
69         Speed,  // Mach or knots or KM/H
70         SpeedWithoutMach = 4,
71         Heading, // degrees true or magnetic
72         Timezone,
73         Distance = 7, // Nm or Kilometers only for now
74         AltitudeIncludingMetersAndAboveField,
75         HeadingOnlyTrue
76     };
77 
78     Q_ENUMS(Mode)
79     Q_ENUMS(Type)
80 };
81 
82 
83 class QuantityValue
84 {
85     Q_GADGET
86 
87     Q_PROPERTY(double value MEMBER value)
88     Q_PROPERTY(Units::Type unit MEMBER unit)
89 
90 public:
91     QuantityValue();
92 
93     QuantityValue(Units::Type u, double v);
94 
95     QuantityValue(Units::Type u, int v);
96 
97     QuantityValue convertToUnit(Units::Type u) const;
98 
99     Q_INVOKABLE QuantityValue convertToUnit(int u) const;
100 
101     Q_INVOKABLE QString toString() const;
102 
103     Q_INVOKABLE bool isValid() const;
104 
105     // precision aware comparisom
106     bool operator==(const QuantityValue& v) const;
107     bool operator!=(const QuantityValue& v) const;
108 
109     double value = 0.0;
110     Units::Type unit = Units::NoUnits;
111 };
112 
113 QDataStream &operator<<(QDataStream &out, const QuantityValue &value);
114 QDataStream &operator>>(QDataStream &in, QuantityValue &value);
115 
116 Q_DECLARE_METATYPE(QuantityValue)
117 
118 class UnitsModel : public QAbstractListModel
119 {
120     Q_OBJECT
121 
122     Q_PROPERTY(Units::Mode mode READ mode WRITE setMode NOTIFY modeChanged)
123 
124     Q_PROPERTY(int numChoices READ numChoices NOTIFY modeChanged)
125 
126     Q_PROPERTY(int selectedIndex READ selectedIndex WRITE setSelectedIndex NOTIFY selectionChanged)
127     Q_PROPERTY(int selectedUnit READ selectedUnit WRITE setSelectedUnit NOTIFY selectionChanged)
128 
129     Q_PROPERTY(double minValue READ minValue NOTIFY selectionChanged)
130     Q_PROPERTY(double maxValue READ maxValue NOTIFY selectionChanged)
131     Q_PROPERTY(double stepSize READ stepSize NOTIFY selectionChanged)
132     Q_PROPERTY(int numDecimals READ numDecimals NOTIFY selectionChanged)
133     Q_PROPERTY(QString maxTextForMetrics READ maxTextForMetrics NOTIFY selectionChanged)
134     Q_PROPERTY(QString shortText READ shortText NOTIFY selectionChanged)
135     Q_PROPERTY(bool isPrefix READ isPrefix NOTIFY selectionChanged)
136     Q_PROPERTY(bool wraps READ doesWrap NOTIFY selectionChanged)
137 
138     Q_PROPERTY(QValidator* validator READ validator NOTIFY selectionChanged)
139 public:
140     UnitsModel();
141 
142     using UnitVec = std::vector<Units::Type>;
143 
144     int rowCount(const QModelIndex &parent) const override;
145 
146     QVariant data(const QModelIndex &index, int role) const override;
147 
148     QHash<int, QByteArray> roleNames() const override;
149 
mode() const150     Units::Mode mode() const
151     {
152         return m_mode;
153     }
154 
selectedIndex() const155     int selectedIndex() const
156     {
157         return static_cast<int>(m_activeIndex);
158     }
159 
160     double minValue() const;
161     double maxValue() const;
162     double stepSize() const;
163     int numDecimals() const;
164     QValidator *validator() const;
165     QString maxTextForMetrics() const;
166     bool isPrefix() const;
167     bool doesWrap() const;
168 
169     QString shortText() const;
170     Units::Type selectedUnit() const;
171     int numChoices() const;
172 
173     Q_INVOKABLE bool isUnitInMode(int unit) const;
174 public slots:
175     void setMode(Units::Mode mode);
176 
177     void setSelectedIndex(int selectedIndex);
178     void setSelectedUnit(int u);
179 
180 signals:
181     void modeChanged(Units::Mode mode);
182 
183     void selectionChanged(int selectedIndex);
184 
185 private:
186     Units::Mode m_mode = Units::Altitude;
187     quint32 m_activeIndex = 0;
188     UnitVec m_enabledUnits;
189 };
190 
191 #endif // UNITSMODEL_HXX
192