Fork me on GitHub
2.15.20
FGx
A cross-platform launcher for FlightGear
airportswidget.cpp
Go to the documentation of this file.
1 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-
2 // FGx FlightGear Launcher // airportswidget.cpp
3 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-
4 // (c) 2010-2012
5 // Yves Sablonier, Pete Morgan
6 // Geoff McLane
7 // GNU GPLv2, see main.cpp and shipped licence.txt for further information
8 
9 
10 #include <QtCore/QString>
11 #include <QtSql/QSqlQuery>
12 #include <QtSql/QSqlError>
13 
14 #include <QtXml/QXmlStreamReader>
15 #include <QtXml/QDomDocument>
16 #include <QtXml/QDomNodeList>
17 
18 #include <QDesktopServices>
19 #include <QMessageBox>
20 #include <QSizePolicy>
21 #include <QFont>
22 
23 #include <QHBoxLayout>
24 #include <QGridLayout>
25 #include <QSplitter>
26 
27 #include <QToolBar>
28 #include <QToolButton>
29 #include <QPushButton>
30 #include <QAction>
31 #include <QLabel>
32 #include <QLineEdit>
33 
34 #include <QStandardItemModel>
35 #include <QItemSelection>
36 #include <QItemSelectionModel>
37 #include <QAbstractItemView>
38 #include <QHeaderView>
39 
40 #include <QProgressDialog>
41 
42 
43 
45 #include "airports/airportsdata.h"
48 #include "utilities/helpers.h"
49 
50 
52  QWidget(parent)
53 {
54 
55  mainObject = mOb;
56 
57  //= Metar widget
59  metarWidget->hide();
60 
61 
62  //* Main Layout
63  QHBoxLayout *mainLayout = new QHBoxLayout();
64  setLayout(mainLayout);
65  mainLayout->setSpacing(10);
66  int m = 10;
67  mainLayout->setContentsMargins(m,m,m,m);
68 
69 
70  //= Tab Widget
71  //tabWidget = new QTabWidget();
72  //mainLayout->addWidget(tabWidget);
73  //connect(tabWidget, SIGNAL(currentChanged(int)), this, SLOT(on_tab_changed()));
74 
75 
76 
77  //=================================================================================
78  //* Airport Details
79  groupBoxAirport = new XGroupVBox("Start at airport");
80  //tabWidget->addTab(groupBoxAirport, QIcon(":/icon/XXX"), tr("Start At Aiport"));
81 
82  groupBoxAirport->xLayout->setContentsMargins(10,10,10,10);
83  groupBoxAirport->xLayout->setSpacing(0);
84  mainLayout->addWidget(groupBoxAirport);
85 
86  //==================================================================
87  //** Airports Filter and Actions Top Bar
88  QHBoxLayout *layoutAptTopBar = new QHBoxLayout();
89  layoutAptTopBar->setContentsMargins(0,0,0,0);
90  layoutAptTopBar->setSpacing(10);
91  groupBoxAirport->addLayout(layoutAptTopBar);
92 
93  //** Filter Code
94  layoutAptTopBar->addWidget(new QLabel(tr("Filter").append(":")));
95 
96  //** Filter Buttons - TODO
97  buttonGroupFilter = new QButtonGroup(this);
98  buttonGroupFilter->setExclusive(true);
99  connect( buttonGroupFilter, SIGNAL(buttonClicked(QAbstractButton*)),
100  this, SLOT(on_update_airports_filter())
101  );
102 
103  //** Aiport Code Filter
104  QRadioButton *buttCode = new QRadioButton();
105  buttCode->setText("Code");
106  buttCode->setProperty("filter_column_idx", QVariant(CA_CODE));
107  buttCode->setChecked(true);
108  layoutAptTopBar->addWidget(buttCode);
109  buttonGroupFilter->addButton(buttCode, 0);
110 
111  //** Airport Name Filter
112  QRadioButton *buttName = new QRadioButton();
113  buttName->setText("Name");
114  buttName->setProperty("filter_column_idx", QVariant(CA_NAME));
115  layoutAptTopBar->addWidget(buttName);
116  buttonGroupFilter->addButton(buttName, 1);
117 
118  //** Find Airport Text
119  txtAirportsFilter = new QLineEdit();
120  layoutAptTopBar->addWidget(txtAirportsFilter);
121  txtAirportsFilter->setFixedWidth(100);
122  connect( txtAirportsFilter, SIGNAL(textChanged(QString)),
123  this, SLOT(on_update_airports_filter())
124  );
125 
126  layoutAptTopBar->addStretch(20);
127 
128 
129  QToolButton *buttonReloadCache = new QToolButton(this);
130  layoutAptTopBar->addWidget(buttonReloadCache);
131  buttonReloadCache->setText("Reload");
132  buttonReloadCache->setToolTip("Scan directories and reload cache");
133  buttonReloadCache->setIcon(QIcon(":/icon/load"));
134  buttonReloadCache->setAutoRaise(true);
135  buttonReloadCache->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
136  connect(buttonReloadCache, SIGNAL(clicked()), this, SLOT(on_reload_cache()) );
137 
138  QMenu *meniw = new QMenu();
139  buttonReloadCache->setMenu(meniw);
140  buttonReloadCache->setPopupMode(QToolButton::MenuButtonPopup);
141 
142  QAction *actView = meniw->addAction("View `airports.txt` cache file" );
143  connect(actView, SIGNAL(triggered()),
144  this, SLOT(on_view_airports_cache())
145  );
146  //==============================================================================
147  //== Airports/Runways Splitter
148  QSplitter *splitter = new QSplitter(this);
149  groupBoxAirport->addWidget(splitter);
150 
151 
152  //=== Airport Widget + Layout
153  QWidget *airportWidget = new QWidget();
154  splitter->addWidget(airportWidget);
155  QVBoxLayout *airportsLayout = new QVBoxLayout();
156  airportsLayout->setContentsMargins(0,0,0,0);
157  airportsLayout->setSpacing(0);
158  airportWidget->setLayout(airportsLayout);
159 
160  /* ======== NOTE ============
161  # The Airports tree is a treeView
162  ## with a model/proxt to enable filtersing
163  ## and the columns constants a CA_
164  # The Airport Info is a treeWidget
165  ## uses CI_ as the column constants
166  */
167 
168  //==============================================
169  //== Airport Models
170  model = new QStandardItemModel(this);
171  model->setColumnCount(2);
172  QStringList headerLabelsList;
173  headerLabelsList << tr("Code") << tr("Name") << "Dir";
174  model->setHorizontalHeaderLabels(headerLabelsList);
175 
176  proxyModel = new QSortFilterProxyModel(this);
177  proxyModel->setSourceModel(model);
178  proxyModel->setSortCaseSensitivity(Qt::CaseInsensitive);
179  proxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
180  proxyModel->setFilterKeyColumn( CA_NAME );
181 
182  //==============================================
183  //== TreeView aiports
184  treeAirports = new QTreeView(this);
185  airportsLayout->addWidget(treeAirports, 1, 0);
186  treeAirports->setModel(proxyModel);
187 
188  treeAirports->setUniformRowHeights(true);
189  treeAirports->setAlternatingRowColors(true);
190  treeAirports->setRootIsDecorated(false);
191  treeAirports->setSortingEnabled(true);
192  treeAirports->sortByColumn(CA_NAME, Qt::AscendingOrder);
193  treeAirports->setSelectionMode(QAbstractItemView::SingleSelection);
194  treeAirports->setSelectionBehavior(QAbstractItemView::SelectRows);
195  treeAirports->setEditTriggers(QAbstractItemView::NoEditTriggers);
196 
197  //* Headers and columns
198  treeAirports->header()->setStretchLastSection(true);
199  treeAirports->setColumnWidth(CA_CODE, 80);
200  treeAirports->setColumnWidth(CA_NAME, 50);
201  treeAirports->setColumnHidden(CA_DIR, true); // hide directory column
202 
203  connect( treeAirports->selectionModel(),
204  SIGNAL( currentChanged(QModelIndex,QModelIndex)),
205  this, SLOT( on_airport_tree_selected(QModelIndex, QModelIndex) )
206  );
207 
208  //================================
209  // StatusBar for Airports
210  statusBarAirports = new QStatusBar();
211  statusBarAirports->setSizeGripEnabled(false);
212  airportsLayout->addWidget(statusBarAirports);
213  statusBarAirports->showMessage("Idle");
214 
215  //= Open Airports Folder
216  QToolButton *buttonShowMetar = new QToolButton();
217  buttonShowMetar->setAutoRaise(true);
218  buttonShowMetar->setIcon(QIcon(":/icon/metar"));
219  buttonShowMetar->setText("Metar");
220  buttonShowMetar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
221  statusBarAirports->addPermanentWidget(buttonShowMetar);
222  connect(buttonShowMetar, SIGNAL(clicked()), this, SLOT(on_show_metar()));
223 
224 
225  //= Label Airports Folder - HIDDEN
226  labelAirportsFolder = new QLabel();
227  statusBarAirports->addPermanentWidget(labelAirportsFolder);
228  labelAirportsFolder->hide();
229 
230  //= Open Airports Folder
231  buttonOpenAirportsFolder = new QToolButton();
232  buttonOpenAirportsFolder->setAutoRaise(true);
233  buttonOpenAirportsFolder->setIcon(QIcon(":/icon/folder"));
234  statusBarAirports->addPermanentWidget(buttonOpenAirportsFolder);
235  connect(buttonOpenAirportsFolder, SIGNAL(clicked()), this, SLOT(on_open_airports_folder()));
236 
237  //========================================================
238  //** Airport Info Widget
239  QWidget *airportInfoWidget = new QWidget();
240  splitter->addWidget(airportInfoWidget);
241  QVBoxLayout *airportInfoLayout = new QVBoxLayout();
242  airportInfoLayout->setContentsMargins(0,0,0,0);
243  airportInfoLayout->setSpacing(0);
244  airportInfoWidget->setLayout(airportInfoLayout);
245 
246  //=========================================================
247  //* Airport Info TreeWidget
248  treeAptInfo = new QTreeWidget();
249  airportInfoLayout->addWidget(treeAptInfo, 3);
250  treeAptInfo->setAlternatingRowColors(true);
251  treeAptInfo->setRootIsDecorated(true);
252  treeAptInfo->setUniformRowHeights(true);
253  treeAptInfo->setExpandsOnDoubleClick(false);
254 
255  QTreeWidgetItem *headerItem = treeAptInfo->headerItem();
256  headerItem->setText(CI_NODE, tr(""));
257  headerItem->setText(CI_WIDTH, tr("Width"));
258  headerItem->setText(CI_LENGTH, tr("Length"));
259  headerItem->setText(CI_LAT, tr("Lat"));
260  headerItem->setText(CI_LON, tr("Lon"));
261  headerItem->setText(CI_HEADING, tr("Heading"));
262  headerItem->setText(CI_RUNWAYS, tr("R"));
263 
264 
265  treeAptInfo->setColumnHidden(CI_TYPE,true);
266  treeAptInfo->setColumnHidden(CI_LABEL,true);
267  treeAptInfo->setColumnHidden(CI_SETTING_KEY,true);
268  treeAptInfo->setColumnHidden(CI_WIDTH,true);
269  treeAptInfo->setColumnHidden(CI_LENGTH,true);
270  treeAptInfo->setColumnHidden(CI_HEADING,true);
271  treeAptInfo->setColumnHidden(CI_RUNWAYS, true);
272  treeAptInfo->setColumnHidden(CI_LAT, true);
273  treeAptInfo->setColumnHidden(CI_LON, true);
274 
275  treeAptInfo->setColumnWidth(CI_NODE, 120);
276  treeAptInfo->header()->setStretchLastSection(true);
277 
278  connect(treeAptInfo, SIGNAL(itemSelectionChanged()),
280  );
281  connect(treeAptInfo, SIGNAL(itemDoubleClicked(QTreeWidgetItem*,int)),
283  );
284 
285 
286  statusBarAirportInfo = new QStatusBar();
287  statusBarAirportInfo->setSizeGripEnabled(false);
288  airportInfoLayout->addWidget(statusBarAirportInfo);
289  statusBarAirportInfo->showMessage("");
290 
291 
292  splitter->setStretchFactor(0, 2);
293  splitter->setStretchFactor(1, 2);
294 
295 
296 
297  //========================================================================================================
298  //** Use Coordinates
299  //====================================================================
300 
301  /*groupBoxUseCoordinates = new XGroupVBox("Coordinates", this);
302  groupBoxUseCoordinates->setMaximumWidth(300);
303  tabWidget->addTab(groupBoxUseCoordinates, QIcon(":/icon/XXX"), "Start At Position");
304 
305  int space = 5;
306 
307  groupBoxUseCoordinates->xLayout->addSpacing(space);
308 
309  groupBoxUseCoordinates->addWidget(new QLabel(tr("Latitude (negative is south)")));
310  txtLat = new QLineEdit();
311  groupBoxUseCoordinates->addWidget(txtLat);
312  connect(txtLat, SIGNAL(textChanged(QString)), this, SLOT(on_coordinates_changed()));
313 
314  groupBoxUseCoordinates->addWidget(new QLabel(tr("Longtitude (negative is west)")));
315  txtLon = new QLineEdit();
316  groupBoxUseCoordinates->addWidget(txtLon);
317  connect(txtLon, SIGNAL(textChanged(QString)), this, SLOT(on_coordinates_changed()));
318 
319  groupBoxUseCoordinates->xLayout->addSpacing(space);
320  groupBoxUseCoordinates->addWidget(new QLabel(tr("Start at VOR")));
321  txtVOR = new QLineEdit();
322  groupBoxUseCoordinates->addWidget(txtVOR);
323  connect(txtVOR, SIGNAL(textChanged(QString)), this, SLOT(on_coordinates_changed()));
324 
325  groupBoxUseCoordinates->xLayout->addSpacing(space);
326  groupBoxUseCoordinates->addWidget(new QLabel(tr("Start at NDB")));
327  txtNDB = new QLineEdit();
328  groupBoxUseCoordinates->addWidget(txtNDB);
329  connect(txtNDB, SIGNAL(textChanged(QString)), this, SLOT(on_coordinates_changed()));
330 
331  groupBoxUseCoordinates->xLayout->addSpacing(space);
332  groupBoxUseCoordinates->addWidget(new QLabel(tr("Start at FIX")));
333  txtFIX = new QLineEdit();
334  groupBoxUseCoordinates->addWidget(txtFIX);
335  connect(txtFIX, SIGNAL(textChanged(QString)), this, SLOT(on_coordinates_changed()));
336 
337  groupBoxUseCoordinates->xLayout->addSpacing(space);
338  groupBoxUseCoordinates->addWidget(new QLabel(tr("Offset distance")));
339  txtOffset = new QLineEdit();
340  groupBoxUseCoordinates->addWidget(txtOffset);
341  connect(txtOffset, SIGNAL(textChanged(QString)), this, SLOT(on_coordinates_changed()));
342 
343  groupBoxUseCoordinates->xLayout->addSpacing(space);
344  groupBoxUseCoordinates->addWidget(new QLabel(tr("Altitude")));
345  txtAltitude = new QLineEdit();
346  groupBoxUseCoordinates->addWidget(txtAltitude);
347  connect(txtAltitude, SIGNAL(textChanged(QString)), this, SLOT(on_coordinates_changed()));
348 
349  groupBoxUseCoordinates->xLayout->addSpacing(space);
350  groupBoxUseCoordinates->addWidget(new QLabel(tr("Heading")));
351  txtHeading = new QLineEdit();
352  groupBoxUseCoordinates->addWidget(txtHeading);
353  connect(txtHeading, SIGNAL(textChanged(QString)), this, SLOT(on_coordinates_changed()));
354 
355  groupBoxUseCoordinates->xLayout->addSpacing(space);
356  groupBoxUseCoordinates->addWidget(new QLabel(tr("Roll")));
357  txtRoll = new QLineEdit();
358  groupBoxUseCoordinates->addWidget(txtRoll);
359 
360  groupBoxUseCoordinates->xLayout->addSpacing(space);
361  groupBoxUseCoordinates->addWidget(new QLabel(tr("Pitch")));
362  txtPitch = new QLineEdit();
363  groupBoxUseCoordinates->addWidget(txtPitch);
364 
365  groupBoxUseCoordinates->xLayout->addSpacing(space);
366  groupBoxUseCoordinates->addWidget(new QLabel(tr("Airspeed")));
367  txtAirspeed = new QLineEdit();
368  groupBoxUseCoordinates->addWidget(txtAirspeed);
369 
370 
371  groupBoxUseCoordinates->xLayout->addStretch(20);
372 
373 
374  connect(buttonGroupFilter, SIGNAL(buttonClicked(QAbstractButton*)),
375  this, SLOT(on_update_airports_filter())
376  );*/
377 
378 
379 
380 
381  //============================================================================
382  // Map Widget
383  //============================================================================
385  mapWidget->setMinimumWidth(400);
386  mainLayout->addWidget(mapWidget);
387  mapWidget->load_map("airport");
388  connect(mapWidget, SIGNAL(map_double_clicked(QString,QString, QString)), this, SLOT(on_map_double_clicked(QString, QString, QString)));
389 
390 
391  //============================================================================
392  //== Main Settings connection
393  connect(this, SIGNAL(setx(QString,bool,QString)), mainObject->X, SLOT(set_option(QString,bool,QString)) );
394  connect(this, SIGNAL(set_ena(QString,bool)), mainObject->X, SLOT(set_enabled(QString,bool)) );
395  connect(mainObject->X, SIGNAL(upx(QString,bool,QString)), this, SLOT(on_upx(QString,bool,QString)));
396  connect(mainObject, SIGNAL(on_debug_mode(bool)), this, SLOT(on_debug_mode()));
397 
398  on_debug_mode(); // shows hides some stuff
399 
400 // #ifdef ENABLE_APT_DAT_LOAD // this can no longer be 'safely' turned off
401  pAptDat = new loadAptDat(this); // class to do loading
402  ploadItem = &pAptDat->loadItem; // LOADITEM structure
403 // #endif // #ifdef ENABLE_APT_DAT_LOAD
404 
405 }
406 
408 {
409  if (pAptDat){
410  delete pAptDat; // stop thread is running, and free list
411  }
412 }
413 
414 //================================================================
415 //== Map Double Clicked
416 void AirportsWidget::on_map_double_clicked(QString lat, QString lon, QString heading)
417 {
418  // disable runway/parking - clear tree
419  emit set_ena("--runway=", false);
420  emit set_ena("--parking-id=", false);
421  emit set_ena("--airport=", false);
422 
423  /*treeAptInfo->selectionModel()->clear();*/
424 
425 
426  //- Set position
427  emit setx("--lat=", true, lat);
428  emit setx("--lon=", true, lon);
429  emit setx("--heading=", true, heading);
430  mapWidget->show_aircraft(mainObject->X->getx("--callsign="),
431  lat,
432  lon,
433  heading,
434  "0"
435  );
436 }
437 
438 
439 //==============================================
440 //== Initialize
442  static bool first_load_done = false;
443  if(first_load_done){
444  return;
445  }
446  QString file = mainObject->X->fgroot("/Airports/apt.dat");
447  if (QFile::exists(file)) {
448  // pass to thread to load
449  first_load_done = true;
450  } else {
451  file.append(".gz");
452  if (QFile::exists(file)) {
453  // pass to thread to load
454  first_load_done = true;
455  }
456  }
457 #ifdef ENABLE_APT_DAT_LOAD
458  if (first_load_done) {
459  // ploadItem->optionFlag |= lf_noFixName;
460  connect(pAptDat,SIGNAL(load_done()),this,SLOT(on_loadaptdat_done()));
461  pAptDat->loadOnThread(file); // start the loading
462  }
463 #endif // #ifdef ENABLE_APT_DAT_LOAD
464 
465  if (!QFile::exists(mainObject->data_file("airports.txt"))){
466  statusBarAirports->showMessage("No cached data. Click Import");
467  }else{
469  }
470  first_load_done = true;
471 }
472 
474 {
475  // first, check if the current apt.dat has been loaded
476  QString zf = mainObject->X->fgroot("/Airports/apt.dat");
477  if (!QFile::exists(zf)) {
478  zf.append(".gz"); // switch to 'gz' file
479  }
480  if (QFile::exists(zf) && !pAptDat->isFileLoaded(zf) ) {
481  connect(pAptDat,SIGNAL(load_done()),this,SLOT(on_loadaptdat_done()));
482  if ( pAptDat->loadOnThread(zf) == 0 ) { // start the thread loading
483  outLog("AirportWidget::on_loadaptdat_done() - started load "+zf);
484  return;
485  }
486  }
487  // appears it is (or is not valid, in which case nothing will change), so
488  // proceed to fill in Airport names
489  outLog("AirportWidget::on_loadaptdat_done()");
490  int max = model->rowCount();
491  int i;
492  QString icao, name;
493  QStandardItem *item;
494 
495  treeAirports->setUpdatesEnabled(false);
496  for (i = 0; i < max; i++) {
497  icao = model->item(i, CA_CODE)->text();
498  item = model->item(i, CA_NAME);
499  //name = pAptDat->findNameByICAO(icao,lf_FixName);
500  name = pAptDat->findNameByICAO(icao);
501  if (name.length())
502  item->setText(name);
503  }
504  treeAirports->setUpdatesEnabled(true);
505 }
506 
507 
508 //============================================================================
509 //== Load Airports Tree
510 //============================================================================
512 
513  //= Clear existing tree and inhibit updates till end
514  model->removeRows(0, model->rowCount());
515  treeAirports->setUpdatesEnabled(false);
516 
517  //= Airports Cache File
518  QFile dataFile(mainObject->data_file(("airports.txt")));
519  if (!dataFile.open(QIODevice::ReadOnly | QIODevice::Text)){
520  treeAirports->setUpdatesEnabled(true);
521  return;
522  }
523  QTextStream in(&dataFile);
524  QStringList dupes; // avoid adding any ICAO twice
525  // prepare for dropping the 'path'
526  // such a path should be per the current 'user' supplied paths
527  QString icao, name, path;
528  QString line = in.readLine();
529  int cnt;
530  //line = in.readLine(); // Why skip this line???
531  while(!line.isNull()){
532 
533  QStringList cols = line.split("\t");
534  cnt = cols.count();
535 
536  icao = cols.at(0); // get the ICAO
537  if (dupes.contains(icao)) {
538  line = in.readLine();
539  continue; // do NOT add twice
540  }
541  dupes += icao;
542  name = (cnt > 1 ? cols.at(1) : "");
543  path = (cnt > 2 ? cols.at(2) : "");
544 
545  QStandardItem *itemAirportCode = new QStandardItem();
546  itemAirportCode->setText(icao);
547 
548  QStandardItem *itemAirportName = new QStandardItem();
549  itemAirportName->setText(name);
550 
551  QStandardItem *itemAirportDir = new QStandardItem();
552  itemAirportDir->setText(path);
553 
554  QList<QStandardItem *> items;
555  items << itemAirportCode << itemAirportName << itemAirportDir;
556 
557  model->appendRow(items);
558  line = in.readLine();
559  }
560 
561  //= Update the status bar with the count
562  statusBarAirports->showMessage( QString("%1 airports").arg(model->rowCount()) );
563 
564  //= Restore previous airport from settings.. if found
565  QList<QStandardItem *> items = model->findItems( mainObject->X->getx("--airport=", "KSFO"), Qt::MatchExactly, CA_CODE);
566  if(items.count() > 0){
567  // restore selected node
568  QModelIndex srcIdx = model->indexFromItem(items[0]);
569  QModelIndex proxIdx = proxyModel->mapFromSource(srcIdx);
570  treeAirports->selectionModel()->select(proxIdx, QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows);
571  treeAirports->scrollTo(proxIdx, QAbstractItemView::PositionAtCenter);
572  treeAirports->selectionModel()->setCurrentIndex(proxIdx, QItemSelectionModel::Rows);
573 
574  //load_info_tree( model->item(srcIdx.row(), CA_DIR)->text(), model->item(srcIdx.row(), CA_CODE)->text() );
575  path = model->item(srcIdx.row(), CA_DIR)->text(); // preparing to use USER paths
576  labelAirportsFolder->setText(path);
577  buttonOpenAirportsFolder->setToolTip(labelAirportsFolder->text());
578  }
579  treeAirports->setUpdatesEnabled(true);
580 }
581 
582 
583 //==============================================================
584 //== Update Filters
586 
587  mainObject->settings->setValue("airports_button_filter", buttonGroupFilter->checkedId());
588  int filter_column_id = buttonGroupFilter->checkedButton()->property("filter_column_idx").toInt();
589  proxyModel->setFilterKeyColumn( filter_column_id );
590  proxyModel->setFilterFixedString( txtAirportsFilter->text() );
591  txtAirportsFilter->setFocus();
592 }
593 
594 
595 //==============================================================
596 //== Airport Clicked
597 void AirportsWidget::on_airport_tree_selected(QModelIndex currentIdx, QModelIndex previousIdx){
598  Q_UNUSED(previousIdx);
599 
600  txtAirportsFilter->setFocus();
601 
602  //= Clear the Info tree
603  treeAptInfo->model()->removeRows(0, treeAptInfo->model()->rowCount());
604  mapWidget->clear_map();
605 
606  //= No selection -eg a filter removing a selected node
607  if(!currentIdx.isValid()){
608  emit set_ena("--airport=", false);
609  emit set_ena("--runway=", false);
610  emit set_ena("--parking-id=", false);
611  return;
612  }
613 
614  //== We have an Airport..
615  //= Get the airport code forn source model
616  QModelIndex srcIndex = proxyModel->mapToSource(currentIdx);
617  QString airport_code = model->item(srcIndex.row(), CA_CODE)->text();
618  QString airport_dir = model->item(srcIndex.row(), CA_DIR)->text();
619 
620  emit setx("--airport=", true, airport_code);
621  mainObject->launcherWindow->on_upx("--airport=", true, airport_code); // Show airport in header
622 
623 
624  load_info_tree(airport_dir, airport_code);
625  mapWidget->zoom_to_airport(airport_code);
626 
627 }
628 
629 //==============================================================
630 // Load the Info Tree
631 //==============================================================
632 void AirportsWidget::load_info_tree(QString airport_dir, QString airport_code){
633 
634  QString count_label;
635  // prepare to use USER current scenery paths
636 #ifdef ENABLE_NEW_AIRPORT_PATH
637  if (airport_code.length() >= 3) {
638  QStringList paths = mainObject->X->getSceneryDirs();
639  int cnt, i;
640  cnt = paths.count();
641  if (cnt > 0) {
642  QString psep("/");
643  QString soup(psep);
644  soup.append(airport_code.at(0));
645  soup.append(psep);
646  soup.append(airport_code.at(1));
647  soup.append(psep);
648  soup.append(airport_code.at(2));
649  //soup.append(psep);
650  QString path;
651  QDir dir;
652  for (i = 0; i < cnt; i++) {
653  path = paths.at(i);
654  path.append(psep);
655  path.append("Airports");
656  path.append(soup);
657  if (dir.exists(path)) {
658  if (airport_dir != path) {
659  outLog("AirportsWidget::load_info_tree: from ["+airport_dir+"] to ["+path+"]");
660  airport_dir = path;
661  }
662  break;
663  }
664  }
665  }
666  }
667 #endif // ENABLE_NEW_AIRPORT_PATH
668 
669  //mapWidget->setUpdatesEnabled(false);
670 
671  //== Clear the existing airport
672  //mapWidget->clear_airport(airport_code);
673  //mapWidget->clear_map();
674  //treeAptInfo->setUpdatesEnabled(false);
675 
676 
677  //=== Load Tower
678  metarWidget->load_metar(airport_code);
679  load_tower_node(airport_dir, airport_code);
680  labelAirportsFolder->setText( airport_dir );
681  buttonOpenAirportsFolder->setToolTip(airport_dir);
682 
683  //=== Load Runways
684  int runways_count = load_runways_node(airport_dir, airport_code);
685  if(runways_count == 0){
686  count_label.append(tr("No runway"));
687  }else if(runways_count == 1){
688  count_label.append(tr("One runway"));
689  }else{
690  count_label.append(QString::number(runways_count)).append(" runways");
691  }
692 
693  count_label.append(" / ");
694 
695  //==== Load Stands
696  int stands_count = load_parking_node(airport_dir, airport_code);
697  if(stands_count == 0){
698  count_label.append(tr("No stands"));
699  }else if(stands_count == 1){
700  count_label.append(tr("One stand"));
701  }else{
702  count_label.append(QString::number(stands_count)).append(" stands");
703  }
704 
705  statusBarAirportInfo->showMessage(count_label);
706 
707 
708 
709  //==== Restore Runway node from settings
710  XOpt optRunway = mainObject->X->get_opt("--runway=");
711  if(optRunway.enabled){
712  QList<QTreeWidgetItem *> items = treeAptInfo->findItems(
713  optRunway.value,
714  Qt::MatchExactly | Qt::MatchRecursive,
715  CI_NODE);
716  if(items.size() > 0){
717  treeAptInfo->setCurrentItem(items[0]);
718  treeAptInfo->scrollToItem(items[0], QAbstractItemView::EnsureVisible);
719  return;
720  }
721  //return; //= dontbother with stand below as we found runway
722  }
723 
724  //= Restore Stand node from settings
725  XOpt optStand = mainObject->X->get_opt("--parking-id=");
726  if(optStand.enabled){
727  QList<QTreeWidgetItem *> items = treeAptInfo->findItems(
728  optStand.value,
729  Qt::MatchExactly | Qt::MatchRecursive,
730  CI_NODE);
731  if(items.size() > 0){
732  treeAptInfo->setCurrentItem(items[0]);
733  treeAptInfo->scrollToItem(items[0], QAbstractItemView::EnsureVisible);
734  return;
735  }
736  }
737 
738 
739  //= Were using --lat's enabled flag to scheckif positin is enabled terrible hack
740  XOpt latopt = mainObject->X->get_opt("--lat=");
741  if(latopt.enabled){
742  mapWidget->show_aircraft(mainObject->X->getx("--callsign="),
743  mainObject->X->getx("--lat="),
744  mainObject->X->getx("--lon="),
745  mainObject->X->getx("--heading="),
746  "0"
747  );
748  }
749 
750 
751 
752 }
753 
754 //==============================================================
755 // Load Runways
756 //==============================================================
757 int AirportsWidget::load_runways_node(QString airport_dir, QString airport_code){
758 
759  //= Create the Runways Node
760  QTreeWidgetItem *runwaysParent = new QTreeWidgetItem();
761  runwaysParent->setText(0, "Runways" );
762  runwaysParent->setIcon(0, QIcon(":/icon/folder"));
763  treeAptInfo->addTopLevelItem(runwaysParent);
764  treeAptInfo->setItemExpanded(runwaysParent, true);
765  treeAptInfo->setFirstItemColumnSpanned(runwaysParent, true);
766 
767 
768  //==============================================================
769  // Parse the <CODE>.threshold.xml file to get runways
770  //==============================================================
771  /*
772  <?xml version="1.0"?>
773  <PropertyList>
774  <runway>
775  <threshold>
776  <lon>0.044298885776989</lon>
777  <lat>51.505569223906</lat>
778  <rwy>10</rwy>
779  <hdg-deg>92.88</hdg-deg>
780  <displ-m>95</displ-m>
781  <stopw-m>55</stopw-m>
782  </threshold>
783  <threshold>
784  <lon>0.065996952433288</lon>
785  <lat>51.5048897753222</lat>
786  <rwy>28</rwy>
787  <hdg-deg>272.88</hdg-deg>
788  <displ-m>71</displ-m>
789  <stopw-m>90</stopw-m>
790  </threshold>
791  </runway>
792  </PropertyList>
793  */
794 
795  //* Get the contents of the file
796  QString threshold_file( airport_dir.append("/").append(airport_code).append(".threshold.xml") );
797  QFile fileXmlThrehsold(threshold_file);
798  fileXmlThrehsold.open(QIODevice::ReadOnly);
799 
800  //= Make file contents into a string from bytearray
801  QString xmlThresholdString = QString(fileXmlThrehsold.readAll()).toUtf8();
802 
803  //= Create domDocument - important dont pass string in QDomConstrucor(string) as ERRORS.. took hours DONT DO IT
804  QDomDocument dom;
805  dom.setContent(xmlThresholdString); //* AFTER dom has been created, then set the content from a string from the file
806 
807 
808  //==================================
809  //= Get <runway> nodes
810  QDomNodeList nodeRunways = dom.elementsByTagName("runway");
811 
812  if (nodeRunways.count() > 0){
813  for(int idxd =0; idxd < nodeRunways.count(); idxd++){
814 
815  // loops the <runway> nodes
816  QDomNode nodeRunway = nodeRunways.at(idxd);
817 
818  //== Add runway parent ie X - Y both ends
819  QTreeWidgetItem *rItem = new QTreeWidgetItem(runwaysParent);
820  rItem->setIcon(0, QIcon(":/icon/runways"));
821  rItem->setText(CI_RUNWAYS, "1");
822  rItem->setText(CI_NODE, nodeRunway.childNodes().at(0).firstChildElement("rwy").text().append(
823  " - ").append(
824  nodeRunway.childNodes().at(1).firstChildElement("rwy").text()
825  ));
826  //treeAptInfo->setItemExpanded(rItem, true);
827  treeAptInfo->setFirstItemColumnSpanned(rItem, true);
828 
829  //= Runway threshold 0
830  QTreeWidgetItem *tItem0 = new QTreeWidgetItem(rItem);
831  tItem0->setIcon(0, QIcon(":/icon/runway"));
832  tItem0->setText(CI_NODE, nodeRunway.childNodes().at(0).firstChildElement("rwy").text());
833  tItem0->setText(CI_LAT, nodeRunway.childNodes().at(0).firstChildElement("lat").text());
834  tItem0->setText(CI_LON, nodeRunway.childNodes().at(0).firstChildElement("lon").text());
835  tItem0->setText(CI_HEADING, nodeRunway.childNodes().at(0).firstChildElement("hdg-deg").text());
836  tItem0->setText(CI_TYPE, "runway");
837  tItem0->setText(CI_SETTING_KEY, QString(airport_code).append("runway").append(
838  nodeRunway.childNodes().at(0).firstChildElement("rwy").text()));
839 
840  //= Runway threshold 1
841  QTreeWidgetItem *tItem1 = new QTreeWidgetItem(rItem);
842  tItem1->setIcon(0, QIcon(":/icon/runway"));
843  tItem1->setText(CI_NODE, nodeRunway.childNodes().at(1).firstChildElement("rwy").text());
844  tItem1->setText(CI_LAT, nodeRunway.childNodes().at(1).firstChildElement("lat").text());
845  tItem1->setText(CI_LON, nodeRunway.childNodes().at(1).firstChildElement("lon").text());
846  tItem1->setText(CI_HEADING, nodeRunway.childNodes().at(1).firstChildElement("hdg-deg").text());
847  tItem1->setText(CI_TYPE, "runway");
848  tItem1->setText(CI_SETTING_KEY, QString(airport_code).append("runway").append(
849  nodeRunway.childNodes().at(1).firstChildElement("rwy").text()));
850 
851  mapWidget->add_runway( airport_code,
852  tItem0->text(CI_NODE),
853  tItem1->text(CI_NODE),
854  tItem0->text(CI_LAT), tItem0->text(CI_LON),
855  tItem1->text(CI_LAT), tItem1->text(CI_LON)
856  );
857 
858  }
859  }
860 
861 
862 
863 
864  return runwaysParent->childCount();
865 }
866 
867 //==============================================================
868 // Load Stands + Parking
869 //==============================================================
870 int AirportsWidget::load_parking_node(QString airport_dir, QString airport_code){
871 
872  //* Create the Parkings Node
873  QTreeWidgetItem *parkingParent = new QTreeWidgetItem();
874  parkingParent->setText(0, "Parking" );
875  parkingParent->setIcon(0, QIcon(":/icon/folder"));
876  treeAptInfo->addTopLevelItem(parkingParent);
877  treeAptInfo->setItemExpanded(parkingParent, true);
878 
879  //=======================================================================
880  // Parse the <groundnet/parking>.threshold.xml file for Parking Postiton
881  //=======================================================================
882  /*
883  <?xml version="1.0"?>
884  <groundnet>
885  <frequencies>
886  <AWOS>12807</AWOS>
887  <CLEARANCE>12197</CLEARANCE>
888  <GROUND>12190</GROUND>
889  <TOWER>12447</TOWER>
890  <APPROACH>13497</APPROACH>
891  </frequencies>
892  <parkingList>
893  <Parking index="0"
894  type="gate"
895  name="EGLL London Heathrow Ramp #11111"
896  number="1"
897  lat="N51 28.192"
898  lon="W00 27.892"
899  heading="56"
900  radius="54"
901  airlineCodes="" />
902  .... snipped ....
903  */
904 
905  //* Files in terrasync are named "groundnet.xml"; in scenery their "parking.xml" -- Why asks pete??
906  QString file_path(airport_dir.append("/").append(airport_code));
907  file_path.append( mainObject->X->terrasync_enabled() ? ".groundnet.xml" : ".parking.xml");
908 
909  //* Check parking file exists
910  if(QFile::exists(file_path)){
911 
912  //* Open file and read contents to string
913  QFile ppfile(file_path);
914  ppfile.open(QIODevice::ReadOnly);
915  QString xmlString = QString(ppfile.readAll()).toUtf8();
916 
917  //* Create domDocument - important - don't pass string in QDomConstrucor(string) as ERRORS.. took hours DONT DO IT
918  QDomDocument dom;
919  dom.setContent(xmlString); //* AFTER dom has been created, then set the content from a string from the file
920 
921 
922 
923  //===================================
924  //= Get Frequencies
925  QTreeWidgetItem *towerItem = treeAptInfo->findItems("tower", Qt::MatchExactly, CI_TYPE).at(0);
926  QDomNodeList nodeFreqs = dom.elementsByTagName("frequencies");
927 
928  for(int idxf =0; idxf < nodeFreqs.at(0).childNodes().count(); idxf++){
929  double freq = nodeFreqs.at(0).childNodes().at(idxf).firstChild().nodeValue().toDouble() / 100;
930  QTreeWidgetItem *freqItem = new QTreeWidgetItem(towerItem);
931  freqItem->setText(CI_NODE,
932  QString("%1 - %2").arg( nodeFreqs.at(0).childNodes().at(idxf).nodeName()
933  ).arg( QString::number(freq, 'f', 2)
934  ));
935 
936  }
937 
938 
939  //== Parking Positions
940  QStringList listParkingPositions;
941 
942  //= Get <Parking/> nodes and loop thru them and add to list (removing dupes)
943  QDomNodeList parkingNodes = dom.elementsByTagName("Parking");
944  if (parkingNodes.count() > 0){
945  for(int idxd =0; idxd < parkingNodes.count(); idxd++){
946 
947  QDomNode parkingNode = parkingNodes.at(idxd);
948  QDomNamedNodeMap attribs = parkingNode.attributes();
949  QString stand(attribs.namedItem("name").nodeValue());
950  stand.append(attribs.namedItem("number").nodeValue());
951 
952  //= Check it doesnt already exist - pete is confused as to multiple entries
953  if(!listParkingPositions.contains(stand)){
954  if(attribs.namedItem("type").nodeValue() == "gate"){
955 
956  //= Append position to eliminate dupes
957  if(!stand.contains(" ")){
958  listParkingPositions.append(stand);
959  QTreeWidgetItem *pItem = new QTreeWidgetItem(parkingParent);
960  pItem->setIcon(0, QIcon(":/icon/stand"));
961  pItem->setText(CI_NODE, stand);
962  pItem->setText(CI_TYPE, "stand");
963  pItem->setText(CI_LAT, Helpers::hmm_to_decimal(attribs.namedItem("lat").nodeValue()));
964  pItem->setText(CI_LON, Helpers::hmm_to_decimal(attribs.namedItem("lon").nodeValue()));
965  pItem->setText(CI_HEADING, attribs.namedItem("heading").nodeValue());
966  pItem->setText(CI_SETTING_KEY, QString(airport_code).append("stand").append(stand));
967  mapWidget->add_stand( airport_code,
968  stand,
969  pItem->text(CI_LAT),
970  pItem->text(CI_LON)
971  );
972  }
973  }
974  }
975  }
976 
977  }
978 
979 
980  } //= File Exists
981 
982  if(parkingParent->childCount() == 0){
983  QTreeWidgetItem *pItem = new QTreeWidgetItem(parkingParent);
984  pItem->setText(CI_NODE, "None");
985  return 0;
986  }
987  //* return the count
988  return parkingParent->childCount();
989 }
990 
991 //==============================================================
992 // Load Tower Node
993 //==============================================================
994 void AirportsWidget::load_tower_node(QString airport_dir, QString airport_code){
995 
996  //* Create the Parkings Node
997  QTreeWidgetItem *towerParent = new QTreeWidgetItem();
998  towerParent->setText(0, "No Tower" );
999  towerParent->setText(CI_TYPE, "tower");
1000  towerParent->setIcon(0, QIcon(":/icon/tower"));
1001  treeAptInfo->addTopLevelItem(towerParent);
1002  treeAptInfo->setItemExpanded(towerParent, false);
1003 
1004  //=======================================================================
1005  // Parse the ICAO.twr.xml file for Tower Postiton
1006  //=======================================================================
1007  /*
1008  <?xml version="1.0"?>
1009  <PropertyList>
1010  <tower>
1011  <twr>
1012  <lon>4.762789</lon>
1013  <lat>52.307064</lat>
1014  <elev-m>60.96</elev-m>
1015  </twr>
1016  </tower>
1017  </PropertyList>
1018  */
1019 
1020  //= Files in terrasync are named "groundnet.xml"; in scenery their "parking.xml" -- Why asks pete??
1021  QString file_path(airport_dir.append("/").append(airport_code).append(".twr.xml"));
1022 
1023  //= Check tower file exists
1024  if(QFile::exists(file_path)){
1025 
1026  //* Open file and read contents to string
1027  QFile ppfile(file_path);
1028  ppfile.open(QIODevice::ReadOnly);
1029  QString xmlString = QString(ppfile.readAll()).toUtf8();
1030 
1031  //= Create domDocument - important - don't pass string in QDomConstrucor(string) as ERRORS.. took hours DONT DO IT
1032  QDomDocument dom;
1033  dom.setContent(xmlString); //* AFTER dom has been created, then set the content from a string from the file
1034 
1035  //= Get <tower> nodes
1036  QDomNodeList towersNode = dom.elementsByTagName("tower");
1037 
1038  towerParent->setText(CI_LAT, towersNode.at(0).childNodes().at(0).firstChildElement("lat").text());
1039  towerParent->setText(CI_LON, towersNode.at(0).childNodes().at(0).firstChildElement("lon").text());
1040 
1041  mapWidget->add_tower(airport_code, towerParent->text(CI_LAT), towerParent->text(CI_LON));
1042  towerParent->setText(0, QString("%1 - Tower").arg(airport_code) );
1043 
1044 
1045  } /* File Exists */
1046 
1047  //* return the count
1048  return;
1049 }
1050 
1051 
1053 
1055  int resp = widget->exec();
1056  if(resp == QDialog::Rejected){
1057  return;
1058  }
1059 
1060  QProgressDialog progress(this);
1061  AirportsData::import(progress, mainObject);
1063 }
1064 
1065 
1066 
1067 //====================================================================
1068 // Current Selected Aiport
1069 //====================================================================
1070 
1072 
1073  if(treeAirports->selectionModel()->selectedIndexes().size() == 0){
1074  return "";
1075  }
1076  QModelIndex index = proxyModel->index(treeAirports->selectionModel()->selectedIndexes().at(0).row(), CA_CODE);
1077  QStandardItem *item = model->itemFromIndex(proxyModel->mapToSource(index));
1078  return item->text();
1079 }
1080 
1081 
1082 
1084 
1085  //* Validate Coordinates TODO - other stuff
1086  /*if(mainObject->X->getx("start_postition") == "1"){
1087  if(txtLat->text().trimmed().length() == 0){
1088  txtLat->setFocus();
1089  return QString("Need Latitude");
1090  }
1091  if(txtLon->text().trimmed().length() == 0){
1092  txtLon->setFocus();
1093  return QString("Need Longtitude");
1094  }*/
1095 
1096  //* Validate Airport
1097  /*}else{
1098  if (!treeAirports->selectionModel()->hasSelection()){
1099  return QString(tr("Airport: No Airport selected or check [x] Use Default;"));
1100  }
1101  }*/
1102 
1103 
1104  return QString("");
1105 
1106 }
1107 
1108 
1109 //==========================================================================
1110 /*void AirportsWidget::on_tab_changed(){
1111  emit setx("start_postition", true, QString::number(tabWidget->currentIndex()));
1112 }*/
1113 
1114 
1116 {
1117  //emit setx("--vor=", true, txtVOR->text());
1118  //emit setx("--ndb=", true, txtNDB->text());
1119  //emit setx("--fix=", true, txtFIX->text());
1120  //emit setx("--lat=", true, txtLat->text());
1121  //emit setx("--lon=", true, txtLon->text());
1122  //emit setx("--offset-distance=", true, txtOffset->text());
1123  //emit setx("--altitude=", true, txtAltitude->text());
1124  //emit setx("--heading=", true, txtHeading->text());
1125 
1126  /*mapWidget->show_aircraft(mainObject->X->getx("--callsign="),
1127  mainObject->X->getx("--lat="),
1128  mainObject->X->getx("--lon="),
1129  mainObject->X->getx("--heading="),
1130  "0"
1131  //mainObject->X->getx("--altitude=") --> this we will have later
1132  );*/
1133 }
1134 
1135 
1136 void AirportsWidget::on_upx(QString option, bool enabled, QString value)
1137 {
1138  Q_UNUSED(enabled);
1139  Q_UNUSED(value);
1140 
1141 
1142  //== This is a nasty hack where we have to move the aircraft if a new lat/lon/heading
1143  QStringList items;
1144  items << "--lat=" << "--lon=" << "--heading=";
1145 
1146  if(items.contains(option)){
1147 
1148  XOpt lat = mainObject->X->get_opt("--lat=");
1149  if(lat.enabled){ // Lat enabled is used to hold "custom postion" and not a runway or parking
1150  mapWidget->show_aircraft(mainObject->X->getx("--callsign="),
1151  mainObject->X->getx("--lat="),
1152  mainObject->X->getx("--lon="),
1153  mainObject->X->getx("--heading="),
1154  "0"
1155  );
1156  }
1157  }
1158 
1159 
1160 }
1161 
1162 
1164 {
1165 
1166 
1167  //= No Selection
1168  if(treeAptInfo->selectionModel()->hasSelection() == false){
1169  emit set_ena("--runway=", false);
1170  emit set_ena("--parking-id=", false);
1171  return;
1172  }
1173 
1174  QTreeWidgetItem *item = treeAptInfo->currentItem();
1175 
1176  //= Its a runway or stand
1177  if(item->text(CI_TYPE) == "runway" || item->text(CI_TYPE) == "stand"){
1178 
1179  if(item->text(CI_TYPE) == "runway"){
1180  emit setx("--runway=", true, item->text(CI_NODE));
1181  emit set_ena("--parking-id=", false);
1182  emit setx("--lat=", false, item->text(CI_LAT));
1183  emit setx("--lon=", false, item->text(CI_LON));
1184  emit setx("--heading=", false, item->text(CI_HEADING));
1185  mainObject->launcherWindow->on_upx("--runway=", true, item->text(CI_NODE)); // Show runway in header
1186 
1187  }else{ // its a stand
1188  emit set_ena("--runway=", false);
1189  emit setx("--parking-id=", true, item->text(CI_NODE));
1190  emit setx("--lat=", false, item->text(CI_LAT));
1191  emit setx("--lon=", false, item->text(CI_LON));
1192  emit setx("--heading=", false, item->text(CI_HEADING));
1193  mainObject->launcherWindow->on_upx("--parking-id=", true, item->text(CI_NODE)); // Show parking in header
1194  }
1195  mapWidget->show_aircraft(mainObject->X->getx("--callsign="),
1196  item->text(CI_LAT), item->text(CI_LON),
1197  item->text(CI_HEADING),
1198  "0");
1199  }
1200 
1201 }
1202 
1204 {
1205  Q_UNUSED(col_idx);
1206  QString typ = item->text(CI_TYPE);
1207  if (typ == "stand" || typ == "runway" || typ == "tower"){
1208  mapWidget->zoom_to_latlon(item->text(CI_LAT), item->text(CI_LON), 16);
1209  }
1210 }
1211 
1212 
1214 {
1215  if(labelAirportsFolder->text().length() == 0){
1216  return;
1217  }
1218  QUrl url( QString("file://%1").arg(labelAirportsFolder->text()) );
1219  QDesktopServices::openUrl(url);
1220 }
1221 
1222 
1224 {
1225  metarWidget->show();
1226 }
1227 
1229 {
1230  treeAirports->setColumnHidden(CA_DIR, this->mainObject->debug_mode == false);
1231 }
1232 
1234 {
1235  FileViewerWidget *fileViewer = new FileViewerWidget();
1236  fileViewer->setFile(mainObject->data_file("airports.txt"));
1237  fileViewer->setWindowState(Qt::WindowMaximized);
1238  fileViewer->show();
1239 
1240 }
QStringList getSceneryDirs()
void on_open_airports_folder()
A QGroupBox with a QVBoxLyout layout.
Definition: xgroupboxes.h:19
int load_parking_node(QString airport_dir, QString airport_code)
int load_runways_node(QString airport_dir, QString airport_code)
QSortFilterProxyModel * proxyModel
void show_aircraft(QString callsign, QString lat, QString lon, QString heading, QString altitude)
void on_airport_info_double_clicked(QTreeWidgetItem *, int)
void add_tower(QString apt, QString lat, QString lon)
MainObject * mainObject
QTreeWidget * treeAptInfo
void zoom_to_latlon(QString lat, QString lon, int zoom)
QString value
Definition: xopt.h:19
The MainObject is an extended QObject, and the main "controller" for FGx.
Definition: mainobject.h:66
QTreeView * treeAirports
void load_metar(QString apt)
Definition: metarwidget.cpp:39
void set_ena(QString option, bool enabled)
void on_update_airports_filter()
void on_view_airports_cache()
QString current_airport()
Show a files contents, raw and pretty.
AirportsWidget(MainObject *mOb, QWidget *parent=0)
OpenLayerWidget * mapWidget
void setx(QString option, bool enabled, QString value)
QVBoxLayout * xLayout
Definition: xgroupboxes.h:26
bool debug_mode
Definition: mainobject.h:75
QLabel * labelAirportsFolder
void add_runway(QString apt, QString rwy1, QString rwy2, QString lat1, QString lon1, QString lat2, QString lon2)
static bool import(QProgressDialog &progress, MainObject *mainObject)
QButtonGroup * buttonGroupFilter
Definition: xopt.h:14
void load_tower_node(QString airport_dir, QString airport_code)
QString data_file(QString file_name)
Path to a data file eg data_file("airports.txt")
Definition: mainobject.cpp:438
void load_map(QString map_type)
QStatusBar * statusBarAirports
XGroupVBox * groupBoxAirport
void on_coordinates_changed()
void setFile(QString file_name)
Loads file and sets labels.
void on_map_double_clicked(QString lat, QString lon, QString heading)
void addWidget(QWidget *w)
Definition: xgroupboxes.cpp:21
void on_upx(QString option, bool enabled, QString value)
XSettingsModel * X
Definition: mainobject.h:86
void on_upx(QString option, bool enabled, QString value)
QStandardItemModel * model
void on_airport_tree_selected(QModelIndex currentIdx, QModelIndex previousIdx)
QStatusBar * statusBarAirportInfo
LauncherWindow * launcherWindow
Definition: mainobject.h:89
void add_stand(QString apt, QString name, QString lat, QString lon)
void on_airport_info_selection_changed()
void load_info_tree(QString airport_dir, QString airport_code)
void zoom_to_airport(QString apt)
loadAptDat * pAptDat
QToolButton * buttonOpenAirportsFolder
bool terrasync_enabled()
Sert terrasync enabled/disabled.
XSettings * settings
Definition: mainobject.h:85
XOpt get_opt(QString option)
void addLayout(QBoxLayout *lay)
Definition: xgroupboxes.cpp:27
PLOADITEM ploadItem
QString getx(QString option)
QLineEdit * txtAirportsFilter
bool enabled
Definition: xopt.h:20
MetarWidget * metarWidget