]> git.mxchange.org Git - flightgear.git/commitdiff
Location history re-instaed
authorJames Turner <zakalawe@mac.com>
Fri, 13 Nov 2015 21:54:50 +0000 (21:54 +0000)
committerJames Turner <zakalawe@mac.com>
Mon, 23 Nov 2015 00:48:20 +0000 (00:48 +0000)
src/GUI/LocationWidget.cxx
src/GUI/LocationWidget.hxx
src/GUI/LocationWidget.ui
src/GUI/NavaidDiagram.cxx

index d6dab1b5d5ad172228f1972d9e1510c4523515b1..167dd2265ced537a1b7c5a4a239c695cde5ac49a 100644 (file)
@@ -43,6 +43,8 @@
 
 using namespace flightgear;
 
+const unsigned int MAX_RECENT_LOCATIONS = 64;
+
 QString fixNavaidName(QString s)
 {
     // split into words
@@ -126,6 +128,46 @@ bool parseStringAsGeod(const QString& s, SGGeod& result)
     return true;
 }
 
+QVariant savePositionList(const FGPositionedList& posList)
+{
+    QVariantList vl;
+    FGPositionedList::const_iterator it;
+    for (it = posList.begin(); it != posList.end(); ++it) {
+        QVariantMap vm;
+        FGPositionedRef pos = *it;
+        vm.insert("ident", QString::fromStdString(pos->ident()));
+        vm.insert("type", pos->type());
+        vm.insert("lat", pos->geod().getLatitudeDeg());
+        vm.insert("lon", pos->geod().getLongitudeDeg());
+        vl.append(vm);
+    }
+    return vl;
+}
+
+FGPositionedList loadPositionedList(QVariant v)
+{
+    QVariantList vl = v.toList();
+    FGPositionedList result;
+    result.reserve(vl.size());
+    NavDataCache* cache = NavDataCache::instance();
+
+    Q_FOREACH(QVariant v, vl) {
+        QVariantMap vm = v.toMap();
+        std::string ident(vm.value("ident").toString().toStdString());
+        double lat = vm.value("lat").toDouble();
+        double lon = vm.value("lon").toDouble();
+        FGPositioned::Type ty(static_cast<FGPositioned::Type>(vm.value("type").toInt()));
+        FGPositioned::TypeFilter filter(ty);
+        FGPositionedRef pos = cache->findClosestWithIdent(ident,
+                                                          SGGeod::fromDeg(lon, lat),
+                                                          &filter);
+        if (pos)
+            result.push_back(pos);
+    }
+
+    return result;
+}
+
 class IdentSearchFilter : public FGPositioned::TypeFilter
 {
 public:
@@ -167,11 +209,9 @@ public:
         }
         endResetModel();
 
-
         m_search.reset(new NavDataCache::ThreadedGUISearch(term));
         QTimer::singleShot(100, this, &NavSearchModel::onSearchResultsPoll);
         m_searchActive = true;
-        endResetModel();
     }
 
     bool isSearchActive() const
@@ -227,6 +267,21 @@ public:
 
         return pos;
     }
+
+    void setItems(const FGPositionedList& items)
+    {
+        beginResetModel();
+        m_searchActive = false;
+        m_items = items;
+
+        m_ids.clear();
+        for (unsigned int i=0; i < items.size(); ++i) {
+            m_ids.push_back(m_items[i]->guid());
+        }
+
+        endResetModel();
+    }
+
 Q_SIGNALS:
     void searchComplete();
 
@@ -299,10 +354,8 @@ LocationWidget::LocationWidget(QWidget *parent) :
     connect(m_ui->locationSearchEdit, &QLineEdit::returnPressed,
             this, &LocationWidget::onSearch);
 
-    // disabled for now
-    m_ui->searchHistory->hide();
     connect(m_ui->searchHistory, &QPushButton::clicked,
-            this, &LocationWidget::onPopupHistory);
+            this, &LocationWidget::onShowHistory);
 
     connect(m_ui->trueBearing, &QCheckBox::toggled,
             this, &LocationWidget::onOffsetBearingTrueChanged);
@@ -314,11 +367,12 @@ LocationWidget::LocationWidget(QWidget *parent) :
             this, SLOT(onOffsetDataChanged()));
     connect(m_ui->offsetNmSpinbox, SIGNAL(valueChanged(double)),
             this, SLOT(onOffsetDataChanged()));
+    connect(m_ui->headingSpinbox, SIGNAL(valueChanged(int)),
+            this, SLOT(onHeadingChanged()));
 
     m_backButton = new QToolButton(this);
     m_backButton->setGeometry(0, 0, 64, 32);
     m_backButton->setText("<< Back");
-    //m_backButton->setIcon(QIcon(":/search-icon"));
     m_backButton->raise();
 
     connect(m_backButton, &QAbstractButton::clicked,
@@ -347,11 +401,15 @@ void LocationWidget::restoreSettings()
         m_location = NavDataCache::instance()->loadById(settings.value("location-id").toULongLong());
     }
 
-    m_ui->altitudeSpinbox->setValue(settings.value("altitude").toInt());
-    m_ui->airspeedSpinbox->setValue(settings.value("speed").toInt());
+    m_ui->altitudeSpinbox->setValue(settings.value("altitude", 6000).toInt());
+    m_ui->airspeedSpinbox->setValue(settings.value("speed", 120).toInt());
+    m_ui->headingSpinbox->setValue(settings.value("heading").toInt());
     m_ui->offsetGroup->setChecked(settings.value("offset-enabled").toBool());
     m_ui->offsetBearingSpinbox->setValue(settings.value("offset-bearing").toInt());
-    m_ui->offsetNmSpinbox->setValue(settings.value("offset-distance").toInt());
+    m_ui->offsetNmSpinbox->setValue(settings.value("offset-distance", 10).toInt());
+
+    m_recentLocations = loadPositionedList(settings.value("recent-locations"));
+    m_searchModel->setItems(m_recentLocations);
 
     onLocationChanged();
     updateDescription();
@@ -392,6 +450,8 @@ void LocationWidget::saveSettings()
     settings.setValue("offset-enabled", m_ui->offsetGroup->isChecked());
     settings.setValue("offset-bearing", m_ui->offsetBearingSpinbox->value());
     settings.setValue("offset-distance", m_ui->offsetNmSpinbox->value());
+
+    // recent locations is saved on modification
 }
 
 void LocationWidget::setLocationOptions()
@@ -400,6 +460,14 @@ void LocationWidget::setLocationOptions()
 
     std::string altStr = QString::number(m_ui->altitudeSpinbox->value()).toStdString();
     std::string vcStr = QString::number(m_ui->airspeedSpinbox->value()).toStdString();
+    std::string headingStr = QString::number(m_ui->headingSpinbox->value()).toStdString();
+
+    // flip direction of azimuth to balance the flip done in fgApplyStartOffset
+    // I don't know why that flip exists but changing it there will break
+    // command-line compatability so compensating here instead
+    int offsetAzimuth = m_ui->offsetBearingSpinbox->value() - 180;
+    std::string azimuthStr = QString::number(offsetAzimuth).toStdString();
+    std::string distanceStr = QString::number(m_ui->offsetNmSpinbox->value()).toStdString();
 
     if (m_locationIsLatLon) {
         // bypass the options mechanism because converting to deg:min:sec notation
@@ -411,6 +479,12 @@ void LocationWidget::setLocationOptions()
 
         opt->addOption("altitude", altStr);
         opt->addOption("vc", vcStr);
+        opt->addOption("heading", headingStr);
+
+        if (m_ui->offsetGroup->isChecked()) {
+            opt->addOption("offset-azimuth", azimuthStr);
+            opt->addOption("offset-distance", distanceStr);
+        }
         return;
     }
 
@@ -474,12 +548,17 @@ void LocationWidget::setLocationOptions()
 
         opt->addOption("altitude", altStr);
         opt->addOption("vc", vcStr);
+        opt->addOption("heading", headingStr);
 
         // set disambiguation property
         globals->get_props()->setIntValue("/sim/presets/navaid-id",
                                           static_cast<int>(m_location->guid()));
-    }
 
+        if (m_ui->offsetGroup->isChecked()) {
+            opt->addOption("offset-azimuth", azimuthStr);
+            opt->addOption("offset-distance", distanceStr);
+        }
+    } // of navaid location
 }
 
 void LocationWidget::setNavRadioOption()
@@ -538,6 +617,7 @@ void LocationWidget::onSearchComplete()
     if (numResults == 0) {
         m_ui->searchStatusText->setText(QString("No matches for '%1'").arg(search));
     } else if (numResults == 1) {
+        addToRecent(m_searchModel->itemAtRow(0));
         setBaseLocation(m_searchModel->itemAtRow(0));
     }
 }
@@ -598,6 +678,7 @@ void LocationWidget::onLocationChanged()
 void LocationWidget::onOffsetEnabledToggled(bool on)
 {
     m_ui->navaidDiagram->setOffsetEnabled(on);
+    updateDescription();
 }
 
 void LocationWidget::onAirportDiagramClicked(FGRunwayRef rwy)
@@ -612,6 +693,26 @@ void LocationWidget::onAirportDiagramClicked(FGRunwayRef rwy)
     updateDescription();
 }
 
+QString compassPointFromHeading(int heading)
+{
+    const int labelArc = 360 / 8;
+    heading += (labelArc >> 1);
+    SG_NORMALIZE_RANGE(heading, 0, 359);
+
+    switch (heading / labelArc) {
+    case 0: return "N";
+    case 1: return "NE";
+    case 2: return "E";
+    case 3: return "SE";
+    case 4: return "S";
+    case 5: return "SW";
+    case 6: return "W";
+    case 7: return "NW";
+    }
+
+    return QString();
+}
+
 QString LocationWidget::locationDescription() const
 {
     if (!m_location) {
@@ -651,6 +752,13 @@ QString LocationWidget::locationDescription() const
 
         return QString("%2 (%1): %3").arg(ident).arg(name).arg(locationOnAirport);
     } else {
+        QString offsetDesc = tr("at");
+        if (m_ui->offsetGroup->isChecked()) {
+            offsetDesc = QString("%1nm %2 of").
+                    arg(m_ui->offsetNmSpinbox->value(), 0, 'f', 1).
+                    arg(compassPointFromHeading(m_ui->offsetBearingSpinbox->value()));
+        }
+
         QString navaidType;
         switch (m_location->type()) {
         case FGPositioned::VOR:
@@ -658,16 +766,16 @@ QString LocationWidget::locationDescription() const
         case FGPositioned::NDB:
             navaidType = QString("NDB"); break;
         case FGPositioned::FIX:
-            return QString("at waypoint %1").arg(ident);
+            return QString("%2 waypoint %1").arg(ident).arg(offsetDesc);
         default:
             // unsupported type
             break;
         }
 
-        return QString("at %1 %2 (%3)").arg(navaidType).arg(ident).arg(name);
+        return QString("%4 %1 %2 (%3)").arg(navaidType).arg(ident).arg(name).arg(offsetDesc);
     }
 
-    return QString("No location selected");
+    return tr("No location selected");
 }
 
 
@@ -713,18 +821,40 @@ void LocationWidget::updateDescription()
 
 void LocationWidget::onSearchResultSelected(const QModelIndex& index)
 {
-    setBaseLocation(m_searchModel->itemAtRow(index.row()));
+    FGPositionedRef pos = m_searchModel->itemAtRow(index.row());
+    addToRecent(pos);
+    setBaseLocation(pos);
 }
 
 void LocationWidget::onOffsetBearingTrueChanged(bool on)
 {
     m_ui->offsetBearingLabel->setText(on ? tr("True bearing:") :
-                                      tr("Magnetic bearing:"));
+                                           tr("Magnetic bearing:"));
 }
 
+void LocationWidget::addToRecent(FGPositionedRef pos)
+{
+    FGPositionedList::iterator it = std::find(m_recentLocations.begin(),
+                                              m_recentLocations.end(),
+                                              pos);
+    if (it != m_recentLocations.end()) {
+        m_recentLocations.erase(it);
+    }
+
+    if (m_recentLocations.size() >= MAX_RECENT_LOCATIONS) {
+        m_recentLocations.pop_back();
+    }
+
+    m_recentLocations.insert(m_recentLocations.begin(), pos);
+    QSettings settings;
+    settings.setValue("recent-locations", savePositionList(m_recentLocations));
+}
 
-void LocationWidget::onPopupHistory()
+
+void LocationWidget::onShowHistory()
 {
+    qDebug() << Q_FUNC_INFO;
+    m_searchModel->setItems(m_recentLocations);
 }
 
 void LocationWidget::setBaseLocation(FGPositionedRef ref)
@@ -743,6 +873,13 @@ void LocationWidget::onOffsetDataChanged()
     m_ui->navaidDiagram->setOffsetEnabled(m_ui->offsetGroup->isChecked());
     m_ui->navaidDiagram->setOffsetBearingDeg(m_ui->offsetBearingSpinbox->value());
     m_ui->navaidDiagram->setOffsetDistanceNm(m_ui->offsetNmSpinbox->value());
+
+    updateDescription();
+}
+
+void LocationWidget::onHeadingChanged()
+{
+    m_ui->navaidDiagram->setHeadingDeg(m_ui->headingSpinbox->value());
 }
 
 void LocationWidget::onBackToSearch()
index d6910d036cf38ddda4af16946dcb45492cf827e0..5df4d62a25633ce895f4c80a14507480a09fceb4 100644 (file)
@@ -24,6 +24,7 @@
 #include <QWidget>
 
 #include <QToolButton>
+
 #include <Navaids/positioned.hxx>
 #include <Airports/airports_fwd.hxx>
 
@@ -56,23 +57,24 @@ Q_SIGNALS:
 
 private Q_SLOTS:
     void updateDescription();
-
     void onLocationChanged();
-
     void onOffsetDataChanged();
-
+    void onHeadingChanged();
 private:
 
     void onSearch();
-
-
     void onSearchResultSelected(const QModelIndex& index);
-    void onPopupHistory();
     void onSearchComplete();
 
     void onAirportDiagramClicked(FGRunwayRef rwy);
     void onOffsetBearingTrueChanged(bool on);
 
+    void addToRecent(FGPositionedRef pos);
+
+    void onOffsetEnabledToggled(bool on);
+    void onBackToSearch();
+    void setNavRadioOption();
+    void onShowHistory();
 
     Ui::LocationWidget *m_ui;
 
@@ -82,13 +84,11 @@ private:
     bool m_locationIsLatLon;
     SGGeod m_geodLocation;
 
-    QVector<PositionedID> m_recentAirports;
-
     QToolButton* m_backButton;
 
-    void onOffsetEnabledToggled(bool on);
-    void onBackToSearch();
-    void setNavRadioOption();
+    FGPositionedList m_recentLocations;
+
+
 };
 
 #endif // LOCATIONWIDGET_H
index f68766eeff0053925eb1ceb47cbf191c799cd4ad..10a41365f6a945cf8822ab15eefaecd86f4b4217 100644 (file)
@@ -26,7 +26,7 @@
    <item>
     <widget class="QStackedWidget" name="stack">
      <property name="currentIndex">
-      <number>2</number>
+      <number>1</number>
      </property>
      <widget class="QWidget" name="airportPage">
       <layout class="QGridLayout" name="gridLayout" columnstretch="1,0,0,0">
       </layout>
      </widget>
      <widget class="QWidget" name="navaidPage">
-      <layout class="QGridLayout" name="gridLayout_3" rowstretch="1,0,0,0">
+      <layout class="QGridLayout" name="gridLayout_3" rowstretch="1,0,0,0" columnstretch="1,0,0,1,0,1,0,0,0,0">
        <property name="leftMargin">
         <number>0</number>
        </property>
          </property>
         </widget>
        </item>
-       <item row="2" column="4" colspan="2">
+       <item row="2" column="6" colspan="2">
         <widget class="QSpinBox" name="altitudeSpinbox">
          <property name="suffix">
           <string>ft</string>
          </property>
         </widget>
        </item>
-       <item row="2" column="3">
+       <item row="2" column="5">
         <widget class="QLabel" name="altitudeLabel">
          <property name="text">
           <string>Altitude:</string>
          </property>
         </widget>
        </item>
-       <item row="0" column="0" rowspan="2" colspan="8">
+       <item row="0" column="0" rowspan="2" colspan="10">
         <widget class="NavaidDiagram" name="navaidDiagram" native="true">
          <property name="sizePolicy">
           <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
          </property>
         </widget>
        </item>
-       <item row="2" column="6" colspan="2">
+       <item row="2" column="8" colspan="2">
         <widget class="QComboBox" name="altitudeModeCombo">
          <item>
           <property name="text">
          </property>
         </widget>
        </item>
-       <item row="3" column="0" colspan="8">
+       <item row="3" column="0" colspan="10">
         <widget class="QGroupBox" name="offsetGroup">
          <property name="title">
           <string>Offset</string>
          <property name="checked">
           <bool>false</bool>
          </property>
-         <layout class="QHBoxLayout" name="horizontalLayout_2">
+         <layout class="QHBoxLayout" name="horizontalLayout_2" stretch="1,0,0,1,0">
           <property name="leftMargin">
            <number>4</number>
           </property>
          </layout>
         </widget>
        </item>
+       <item row="2" column="3">
+        <widget class="QLabel" name="label">
+         <property name="text">
+          <string>Heading:</string>
+         </property>
+         <property name="alignment">
+          <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+         </property>
+        </widget>
+       </item>
+       <item row="2" column="4">
+        <widget class="QSpinBox" name="headingSpinbox">
+         <property name="wrapping">
+          <bool>true</bool>
+         </property>
+         <property name="maximum">
+          <number>359</number>
+         </property>
+        </widget>
+       </item>
       </layout>
      </widget>
      <widget class="QWidget" name="searchPage">
index c2b139ef6d3a45aea4793e84c48ad3b6858f1feb..29857991e5cbd47b396d153574c8febe24b4887b 100644 (file)
@@ -73,6 +73,12 @@ void NavaidDiagram::setOffsetBearingDeg(int bearingDeg)
     update();
 }
 
+void NavaidDiagram::setHeadingDeg(int headingDeg)
+{
+    m_headingDeg = headingDeg;
+    update();
+}
+
 void NavaidDiagram::paintContents(QPainter *painter)
 {
     QPointF base = project(m_geod);
@@ -95,8 +101,12 @@ void NavaidDiagram::paintContents(QPainter *painter)
     QPixmap pix(":/airplane-icon");
     airplaneIconPos = painter->transform().map(airplaneIconPos);
     painter->resetTransform();
+    painter->translate(airplaneIconPos.x(), airplaneIconPos.y());
+    painter->rotate(m_headingDeg);
+
+    painter->setRenderHint(QPainter::SmoothPixmapTransform, true);
     QRect airplaneIconRect = pix.rect();
-    airplaneIconRect.moveCenter(airplaneIconPos.toPoint());
+    airplaneIconRect.moveCenter(QPoint(0,0));
     painter->drawPixmap(airplaneIconRect, pix);
 }