Fork me on GitHub
2.15.20
FGx
A cross-platform launcher for FlightGear
aircraftwidget.cpp
Go to the documentation of this file.
1 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-
2 // FGx FlightGear Launcher // aircraftwidget.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 "app_config.h"
11 
12 #include <QProcess>
13 #include <QByteArray>
14 #include <QString>
15 #include <QStringList>
16 #include <QFile>
17 
18 #include <QXmlQuery>
19 #include <QDomDocument>
20 
21 // @TODO - qt5 dont use this
22 #include <QDesktopServices>
23 #include <QFileDialog>
24 
25 #include <QVBoxLayout>
26 #include <QHBoxLayout>
27 #include <QGroupBox>
28 #include <QSplitter>
29 #include <QProgressDialog>
30 
31 #include <QToolBar>
32 #include <QToolButton>
33 #include <QAbstractButton>
34 #include <QButtonGroup>
35 
36 #include <QAction>
37 #include <QLabel>
38 #include <QCheckBox>
39 #include <QTabWidget>
40 
41 #include <QHeaderView>
42 #include <QAbstractItemView>
43 #include <QPixmap>
44 #include <QDoubleValidator>
45 
46 
48 #include "aircraft/aircraftdata.h"
49 #include "utilities/utilities.h"
50 #include "utilities/messagebox.h"
51 
53 
54 
56  QWidget(parent)
57 {
58 
59 
60  mainObject = mOb;
61 
62  //========================================================
63  //= Models
64  model = new QStandardItemModel(this);
65  QStringList hLabels;
66  hLabels << "Dir" << "Aero" << "Description" << "FDM" << "Authors" << "XML" << "FilePath" << "FilterDir" << "Filter" << "BASE";
67  //model->setColumnCount(hLabels.length());
68  model->setHorizontalHeaderLabels(hLabels);
69 
70  proxyModel = new AircraftProxyModel(); //QSortFilterProxyModel();
71  proxyModel->setSourceModel(model);
72  proxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
73  proxyModel->setFilterKeyColumn(C_FILTER);
74  proxyModel->setSortCaseSensitivity(Qt::CaseInsensitive);
75 
76  //= Custom Dir button stuff
77  buttGroupShowDirs = new QButtonGroup(this);
78  buttGroupShowDirs->setExclusive(false);
79  connect(buttGroupShowDirs, SIGNAL(buttonClicked(QAbstractButton*)),
80  this, SLOT(on_toggle_directory())
81  );
82 
83  actGroupDeleteCustomDirs = new QActionGroup(this);
84  actGroupDeleteCustomDirs->setExclusive(false);
85  connect(actGroupDeleteCustomDirs, SIGNAL(triggered(QAction*)),
86  this, SLOT(on_remove_custom_dir(QAction*))
87  );
88 
89 
90 
91  //=======================================================
92  //* Main Layout
93  QVBoxLayout *mainLayout = new QVBoxLayout();
94  setLayout(mainLayout);
95  mainLayout->setSpacing(0);
96  mainLayout->setContentsMargins(0,0,0,0);
97 
98  splitter = new QSplitter(this);
99  mainLayout->addWidget(splitter);
100 
101  //===============================================================================
102  //** Left
103  QWidget *leftWidget = new QWidget();
104  splitter->addWidget(leftWidget);
105  splitter->setContentsMargins(10,10,10,10);
106  QVBoxLayout *treeLayout = new QVBoxLayout();
107  leftWidget->setLayout(treeLayout);
108  treeLayout->setContentsMargins(0,0,0,0);
109  treeLayout->setSpacing(0);
110 
111  //=======================================================
112  //= Top Toolbar
113  QHBoxLayout *topBar = new QHBoxLayout();
114  topBar->setSpacing(5);
115  treeLayout->addLayout(topBar);
116 
117  //---------------------------------------
118  //= Filter Toolbar
119  ToolBarGroup *grpFilter = new ToolBarGroup();
120  topBar->addWidget(grpFilter);
121  grpFilter->setTitle("Filter");
122 
123  //= Clear filter button
124  QToolButton * buttClearFilter = new QToolButton();
125  buttClearFilter->setText("CKR >");
126  buttClearFilter->setFixedWidth(20);
127  buttClearFilter->setIcon(QIcon(":/icon/clear_filter"));
128  buttClearFilter->setAutoRaise(true);
129  buttClearFilter->setToolButtonStyle(Qt::ToolButtonIconOnly);
130  grpFilter->addWidget(buttClearFilter);
131  connect(buttClearFilter, SIGNAL(clicked()), this, SLOT(on_clear_filter()) );
132 
133  //= Filter Text
134  txtFilter = new QLineEdit();
135  txtFilter->setFixedWidth(100);
136  grpFilter->addWidget(txtFilter);
137  connect(txtFilter, SIGNAL(textChanged(const QString)), this, SLOT(on_filter_text_changed(const QString)));
138 
139 
140  //---------------------------------------
141  //= Custom Directories
142  grpCustomDirs = new ToolBarGroup();
143  topBar->addWidget(grpCustomDirs);
144  grpCustomDirs->setTitle("Directories");
145 
146  //= Show Base button
147  buttShowBase = new QToolButton();
148  //buttShowBase->setProperty("dir", mainObject->X->aircraft_path() ); ?? WE DO THIS AT LOAD_AIRCRAFT IN CASE CHANGED
149  buttShowBase->setProperty("base", "1" );
150  buttShowBase->setToolTip( mainObject->X->aircraft_path());
151  buttShowBase->setText( "Base Package" );
152  buttShowBase->setIcon(QIcon(":/icon/base_folder"));
153  buttShowBase->setCheckable(true);
154  buttShowBase->setChecked(true);
155  buttShowBase->setAutoRaise(true);
156  buttShowBase->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
158  buttGroupShowDirs->addButton(buttShowBase);
159 
160  //= Show Base button
161  QToolButton * buttAddCustomDir = new QToolButton();
162  buttAddCustomDir->setText("Add");
163  buttAddCustomDir->setIcon(QIcon(":/icon/folder_add"));
164  buttAddCustomDir->setAutoRaise(true);
165  buttAddCustomDir->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
166  grpCustomDirs->addWidget(buttAddCustomDir);
167  connect(buttAddCustomDir, SIGNAL(clicked()), this, SLOT(on_add_custom_dir()));
168 
169  topBar->addStretch(20);
170 
171  //---------------------------------------
172  //= Refresh Action
173  ToolBarGroup *grpActions = new ToolBarGroup();
174  topBar->addWidget(grpActions);
175  grpActions->setTitle("Actions");
176 
177  //== Reload cache
178  QToolButton *actionReloadCacheDb = new QToolButton(this);
179  actionReloadCacheDb->setText("Reload");
180  actionReloadCacheDb->setIcon(QIcon(":/icon/load"));
181  actionReloadCacheDb->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
182  actionReloadCacheDb->setAutoRaise(true);
183  grpActions->addWidget(actionReloadCacheDb);
184  connect(actionReloadCacheDb, SIGNAL(clicked()), this, SLOT(on_reload_cache()) );
185 
186  QMenu *menuReload = new QMenu();
187  actionReloadCacheDb->setMenu(menuReload);
188  actionReloadCacheDb->setPopupMode(QToolButton::MenuButtonPopup);
189 
190  QAction *actView = menuReload->addAction("View `aircraft.txt` cache file" );
191  connect(actView, SIGNAL(triggered()),
192  this, SLOT(on_view_aircraft_cache())
193  );
194 
195 
196  //=======================================================
197  //= Treeview
198  treeView = new QTreeView(this);
199  treeLayout->addWidget(treeView);
200  treeView->setModel(proxyModel);
201 
202  treeView->setRootIsDecorated(false);
203  treeView->setUniformRowHeights(true);
204  treeView->setSortingEnabled(true);
205  treeView->setSelectionMode(QAbstractItemView::SingleSelection);
206  treeView->setSelectionBehavior(QAbstractItemView::SelectRows);
207 
208  treeView->header()->setStretchLastSection(true);
209  treeView->setColumnWidth(C_DIR, 60);
210  treeView->setColumnWidth(C_FDM, 60);
211  treeView->setColumnWidth(C_DESCRIPTION, 200);
212  this->on_debug_mode(); // debug mode shows/hides some columns
213  connect( treeView->selectionModel(),
214  SIGNAL( selectionChanged(const QItemSelection &, const QItemSelection & ) ),
215  SLOT( on_tree_selection_changed() )
216  );
217 
218 
219  //=================================
220  //= Status Bar
221  statusBar = new QStatusBar();
222  statusBar->setSizeGripEnabled(false);
223  treeLayout->addWidget(statusBar);
224 
225 
226 
227  //== View nested Checkbox
228  /*checkViewNested = new QCheckBox();
229  checkViewNested->setText("View folders");
230  statusBarTree->addPermanentWidget(checkViewNested);
231  connect(checkViewNested, SIGNAL(clicked()), this, SLOT(load_tree()));*/
232 
233 
234 
235 
236  //================================================================================================
237  //= Right
238  //================================================================================================
239 
240  QGroupBox *grpAero = new QGroupBox();
241  splitter->addWidget(grpAero);
242  grpAero->setDisabled(false);
243  grpAero->setMinimumWidth(300);
244  //grpAero->setTitle(tr("Preview, Radio, Fuel"));
245 
246 
247  QVBoxLayout *aeroLayout = new QVBoxLayout();
248  grpAero->setLayout(aeroLayout);
249 
250  QHBoxLayout *layAeroTopBar = new QHBoxLayout();
251  aeroLayout->addLayout(layAeroTopBar);
252 
253  lblAero = new QLabel();
254  lblAero->setStyleSheet("font-size: 20pt; font-weight: bold;");
255  layAeroTopBar->addWidget(lblAero, 10);
256 
257  buttOpenAeroDir = new QToolButton();
258  buttOpenAeroDir->setToolTip("Browse model files");
259  buttOpenAeroDir->setAutoRaise(true);
260  buttOpenAeroDir->setIcon(QIcon(":/icon/folder_open"));
261  buttOpenAeroDir->setToolButtonStyle(Qt::ToolButtonIconOnly);
262  buttOpenAeroDir->setDisabled(true);
263  layAeroTopBar->addWidget(buttOpenAeroDir, 0);
264  connect(buttOpenAeroDir, SIGNAL(clicked()),
265  this, SLOT(on_open_aircraft_path())
266  );
267 
268  lblAeroDescription = new QLabel();
269  aeroLayout->addWidget(lblAeroDescription);
270 
271  lblAeroXml = new QLabel();
272  aeroLayout->addWidget(lblAeroXml);
273 
274  //**********************************************8
275  //** Aero Panel
276  QGroupBox *grpAeroPanel = new QGroupBox();
277  grpAeroPanel->setStyleSheet("background-image: url(:/artwork/background-gray-tabbar); border-top: 0px;");
278  aeroLayout->addWidget(grpAeroPanel);
279 
280 
281  QVBoxLayout *aeroPanelLayout = new QVBoxLayout();
282  grpAeroPanel->setLayout(aeroPanelLayout);
283 
284  QHBoxLayout *imgBox = new QHBoxLayout();
285  aeroPanelLayout->addLayout(imgBox);
286 
287  aeroImageLabel = new QLabel(this);
288  aeroImageLabel->setFixedWidth(171);
289  aeroImageLabel->setFixedHeight(128);
290  imgBox->addWidget(aeroImageLabel);
291 
292 
293  //******************************************************8
294  //** Tab Widgets
295  QTabWidget *aeroTabs = new QTabWidget();
296  aeroLayout->addWidget(aeroTabs, 120);
297 
298  QWidget *aeroControlWidget = new QWidget();
299  QWidget *fuelWidget = new QWidget();
300  aeroTabs->addTab(aeroControlWidget, tr("Radio"));
301  aeroTabs->addTab(fuelWidget, tr("Fuel"));
302 
303  //** Fuel Widget
304  QGridLayout *layoutFuelPane = new QGridLayout();
305  fuelWidget->setLayout(layoutFuelPane);
306  int rowFuel = 1;
307 
308  // Enable fuel freeze
309  rowFuel++;
310  checkBoxFuelFreeze = new QCheckBox(this);
311  checkBoxFuelFreeze->setText("Enable fuel freeze");
312  layoutFuelPane->addWidget(checkBoxFuelFreeze, 0, 1, 1, Qt::AlignLeft);
313  connect(checkBoxFuelFreeze, SIGNAL(clicked()), this, SLOT(on_enable_fuel_freeze_clicked()));
314 
315  //* Tank 1
316  rowFuel++;
317  layoutFuelPane->addWidget(new QLabel(tr("Tank 1")), rowFuel, 0, 1, 1, Qt::AlignRight);
318  txtTank1 = new QLineEdit();
319  txtTank1->setValidator(new QDoubleValidator(0, 200, 2, this));
320  layoutFuelPane->addWidget(txtTank1,rowFuel, 1, 1, 1);
321  connect(txtTank1, SIGNAL(textChanged(QString)), this, SLOT(on_fuel_changed()));
322 
323  //* Tank 2
324  rowFuel++;
325  layoutFuelPane->addWidget(new QLabel(tr("Tank 2")), rowFuel, 0, 1, 1, Qt::AlignRight);
326  txtTank2 = new QLineEdit();
327  txtTank2->setValidator(new QDoubleValidator(0, 200, 2, this));
328  layoutFuelPane->addWidget(txtTank2,rowFuel, 1, 1, 1);
329  connect(txtTank2, SIGNAL(textChanged(QString)), this, SLOT(on_fuel_changed()));
330 
331  //* Tank 3
332  rowFuel++;
333  layoutFuelPane->addWidget(new QLabel(tr("Tank 3")), rowFuel, 0, 1, 1, Qt::AlignRight);
334  txtTank3 = new QLineEdit();
335  txtTank3->setValidator(new QDoubleValidator(0, 200, 2, this));
336  layoutFuelPane->addWidget(txtTank3, rowFuel, 1, 1, 1);
337  connect(txtTank3, SIGNAL(textChanged(QString)), this, SLOT(on_fuel_changed()));
338 
339  layoutFuelPane->setRowStretch(rowFuel + 1, 20); // stretch end
340 
341 
342  //** Aero Control Widget
343  QGridLayout *layoutAeroPane = new QGridLayout();
344  aeroControlWidget->setLayout(layoutAeroPane);
345  int row = 1;
346 
347  //* Navs
348  layoutAeroPane->addWidget(new QLabel(tr("NAV1")), row, 0, 1, 1, Qt::AlignRight);
349  txtNav1 = new QLineEdit();
350  txtNav1->setValidator(new QDoubleValidator(0, 200, 2, this));
351  layoutAeroPane->addWidget(txtNav1,row, 1, 1, 1);
352  connect(txtNav1, SIGNAL(textChanged(QString)), this, SLOT(on_navs_changed()));
353 
354  row++;
355  layoutAeroPane->addWidget(new QLabel(tr("NAV2")), row, 0, 1, 1, Qt::AlignRight);
356  txtNav2 = new QLineEdit();
357  txtNav2->setValidator(new QDoubleValidator(0, 200, 2, this));
358  layoutAeroPane->addWidget(txtNav2,row, 1, 1, 1);
359  connect(txtNav2, SIGNAL(textChanged(QString)), this, SLOT(on_navs_changed()));
360 
361  //= ADF
362  row++;
363  layoutAeroPane->addWidget(new QLabel(tr("ADF1")), row, 0, 1, 1, Qt::AlignRight);
364  txtAdf1 = new QLineEdit();
365  txtAdf1->setValidator(new QDoubleValidator(0, 200,0, this));
366  layoutAeroPane->addWidget(txtAdf1, row, 1, 1, 1);
367  connect(txtAdf1, SIGNAL(textChanged(QString)), this, SLOT(on_navs_changed()));
368 
369  row++;
370  layoutAeroPane->addWidget(new QLabel(tr("ADF2")), row, 0, 1, 1, Qt::AlignRight);
371  txtAdf2 = new QLineEdit();
372  txtAdf2->setValidator(new QDoubleValidator(0, 200,0, this));
373  layoutAeroPane->addWidget(txtAdf2, row, 1, 1, 1);
374  connect(txtAdf2, SIGNAL(textChanged(QString)), this, SLOT(on_navs_changed()));
375 
376  //= Comms
377  row++;
378  layoutAeroPane->addWidget(new QLabel(tr("COM1")), row, 0, 1, 1, Qt::AlignRight);
379  txtCom1 = new QLineEdit();
380  txtCom1->setValidator(new QDoubleValidator(0, 200, 2, this));
381  layoutAeroPane->addWidget(txtCom1,row, 1, 1, 1);
382  connect(txtCom1, SIGNAL(textChanged(QString)), this, SLOT(on_navs_changed()));
383 
384  row++;
385  layoutAeroPane->addWidget(new QLabel(tr("COM2")), row, 0, 1, 1, Qt::AlignRight);
386  txtCom2 = new QLineEdit();
387  txtCom2->setValidator(new QDoubleValidator(0, 200, 2, this));
388  layoutAeroPane->addWidget(txtCom2,row, 1, 1, 1);
389  connect(txtCom2, SIGNAL(textChanged(QString)), this, SLOT(on_navs_changed()));
390 
391 
392  layoutAeroPane->setRowStretch(row + 1, 20); // stretch end
393 
394  //==================
395  //== Setup
396 
397  splitter->setCollapsible(0, false);
398  splitter->setCollapsible(1, false);
399  splitter->setStretchFactor(0, 50);
400  splitter->setStretchFactor(1, 10);
401  splitter->setProperty("settings_namespace", "aircraft_widget_splitter");
403  connect(splitter, SIGNAL(splitterMoved(int,int)), this, SLOT(on_splitter_moved()));
404 
406 
407  //== Main Settings connection
408  connect(this, SIGNAL(setx(QString,bool,QString)), mainObject->X, SLOT(set_option(QString,bool,QString)) );
409  connect(mainObject->X, SIGNAL(upx(QString,bool,QString)), this, SLOT(on_upx(QString,bool,QString)));
410  connect(mainObject, SIGNAL(on_debug_mode(bool)), this, SLOT(on_debug_mode()));
411 
413 
414 }
417 }
418 
420  txtFilter->setText("");
421  txtFilter->setFocus();
422 }
423 
425  proxyModel->setFilterFixedString(s);
426 }
427 
428 //==========================================================================1
429 // Aircraft Selected
430 //==========================================================================
432 
433  if(treeView->selectionModel()->hasSelection() == false){
434  outLog("on_tree_selection_changed: no selected item");
435  lblAero->setText("-");
436  lblAeroDescription->setText("-");
437  lblAeroXml->setText("");
438  this->buttOpenAeroDir->setDisabled(true);
439  this->buttOpenAeroDir->setIcon(QIcon(":/icon/folder_open"));
440  emit setx("--aircraft=", false, "");
441  return;
442  }
443 
444  lblAero->setText( model->itemFromIndex(
445  proxyModel->mapToSource(treeView->selectionModel()->selectedIndexes().at(C_AERO))
446  )->text());
447  lblAeroDescription->setText( model->itemFromIndex(
448  proxyModel->mapToSource(treeView->selectionModel()->selectedIndexes().at(C_DESCRIPTION))
449  )->text());
450 
451 
452  QString xmlFile = model->itemFromIndex(
453  proxyModel->mapToSource(treeView->selectionModel()->selectedIndexes().at(C_FILE_PATH))
454  )->text();
455  lblAeroXml->setText(xmlFile);
456 
457  int is_base = model->itemFromIndex(
458  proxyModel->mapToSource(treeView->selectionModel()->selectedIndexes().at(C_BASE))
459  )->text().toInt();
460  this->buttOpenAeroDir->setDisabled(false);
461  if( is_base == 1 ){
462  this->buttOpenAeroDir->setIcon(QIcon(":/icon/base_folder"));
463  }else{
464  this->buttOpenAeroDir->setIcon(QIcon(":/icon/custom_folder"));
465  }
466 
467  QModelIndex midx = treeView->selectionModel()->selectedIndexes().at(C_DIR);
468  QStandardItem *item = model->itemFromIndex( proxyModel->mapToSource(midx) );
469 
470  //= Get the thumbnail image
471  QString thumb_file = QString("%1/%2/thumbnail.jpg").arg(mainObject->X->aircraft_path(), item->text());
472  if(QFile::exists(thumb_file)){
473  QPixmap aeroImage(thumb_file);
474  if(!aeroImage.isNull()){
475  //outLog("on_tree_selection_changed: Loaded thumb "+thumb_file);
476  aeroImageLabel->setText("");
477  aeroImageLabel->setPixmap(aeroImage);
478 
479  } else{
480  //outLog("on_tree_selection_changed: NO thumb load "+thumb_file);
481  aeroImageLabel->clear();
482  aeroImageLabel->setText("No Image");
483  }
484  }else{
485  aeroImageLabel->setText("No Image");
486  }
487 
488  emit setx("--aircraft=", true, selected_aircraft());
489  mainObject->launcherWindow->on_upx("--aircraft=", true, selected_aircraft()); // Show aircraft in header
490 }
491 
492 
493 //==============================
494 //== Select an aircraft in tree
495 void AircraftWidget::select_node(QString aero){
496  if(aero.length() == 0){
497  return;
498  }
499  /*
500  QList<QTreeWidgetItem*> items = treeWidget->findItems(aero, Qt::MatchExactly | Qt::MatchRecursive, C_AERO);
501  if(items.length() > 0){
502  treeWidget->setCurrentItem(items[0]);
503  treeWidget->scrollToItem(items[0], QAbstractItemView::PositionAtCenter);
504 
505  }*/
506 }
507 
508 //==============================
509 //== return selected Aircraft
511 
512  QModelIndex midx = treeView->selectionModel()->selectedIndexes().at(C_AERO);
513  QStandardItem *item = model->itemFromIndex( proxyModel->mapToSource(midx) );
514  return item->text();
515 }
516 
517 //=============================================================
518 // Validate
520  //if(groupUseAircraft->checkedId() == 1 && !treeWidget->currentItem()){
521  // return QString("Aircraft: No aircraft selected or check [x] Use default");
522  // outLog("FGx reports: AircraftWidget::validate() No aircraft selected (maybe no list), and [x] use default not selected. ***");
523  //}
524  return QString("");
525 }
526 
527 
528 //=============================================================
529 // Rescan aircraft cache
531 
532  model->removeRows(0, model->rowCount());
533  statusBar->showMessage("Reloading cache");
534 
535  QProgressDialog progress(this);
536  QSize size(320,100);
537  progress.resize(size);
538  progress.setWindowIcon(QIcon(":/icon/load"));
539 
540  AircraftData::import(progress, mainObject);
541  load_aircraft();
542 }
543 
544 /* @brief Load Custom Aircraft Paths */
546 
547  QList<QStandardItem*> row;
548 
549  // Get paths as lsit from settings
550  QStringList custom_dirs = this->mainObject->settings->value("custom_aircraft_dirs").toStringList();
551  for(int i = 0; i < custom_dirs.size(); i++){
552 
553  // get the xml-sets in dir, and recus eg might be a single aircraft or a dir of aircraft
554  QFileInfoList xmlSets = AircraftData::get_xml_set_files(custom_dirs.at(i), true);
555  //qDebug() << xmlSets;
556 
557  for(int fi = 0; fi < xmlSets.length(); fi++){
558 
559  // get data from the model file
560  ModelInfo mi = AircraftData::read_model_xml(xmlSets.at(fi).absoluteFilePath());
561 
562  // Add model row
563  row = this->create_model_row();
564  row.at(C_DIR)->setText(mi.dir);
565  row.at(C_DIR)->setIcon(QIcon(":/icon/custom_folder"));
566 
567  row.at(C_AERO)->setText(mi.aero);
568  row.at(C_AERO)->setIcon(QIcon(":/icon/aircraft"));
569  QFont f = row.at(C_AERO)->font();
570  f.setBold(true);
571  row.at(C_AERO)->setFont(f);
572 
573  row.at(C_DESCRIPTION)->setText(mi.description);
574  row.at(C_FDM)->setText(mi.fdm);
575  row.at(C_AUTHOR)->setText(mi.authors);
576  row.at(C_XML_FILE)->setText(mi.xml_file);
577  row.at(C_FILE_PATH)->setText(mi.file_path);
578  row.at(C_FILTER_PATH)->setText(custom_dirs.at(i));
579  row.at(C_BASE)->setText("0");
580 
581  QString filter_str = mi.aero; // filter is the aero+description
582  filter_str.append( mi.description );
583  row.at(C_FILTER)->setText( filter_str );
584  }
585  }
586 }
587 
588 //=============================================================
589 /* @brief Load/reload the model */
591 
592  buttShowBase->setToolTip( mainObject->X->aircraft_path());
593  buttShowBase->setProperty("dir", mainObject->X->aircraft_path());
594 
595  int c =0;
596 
597  QList<QStandardItem*> row;
598 
599  model->removeRows(0, model->rowCount());
600 
601  this->load_custom_aircraft();
602 
603  //=== Load Base Package
604  QFile dataFile(mainObject->data_file(("aircraft.txt")));
605  if (!dataFile.open(QIODevice::ReadOnly | QIODevice::Text)){
606  //TODO - catch error
607  return;
608  }
609  QTextStream in(&dataFile);
610  QString line = in.readLine();
611  c = 0;
612  while(!line.isNull()){
613 
614  QStringList cols = line.split("\t");
615  if (cols.size() <= C_FILTER_PATH) {
616  //TODO - warn discarding line
617  line = in.readLine();
618  continue;
619  }
620 
621  // Add model row
622  row = this->create_model_row();
623  row.at(C_DIR)->setText(cols.at(C_DIR));
624  row.at(C_DIR)->setIcon(QIcon(":/icon/base_folder"));
625 
626  row.at(C_AERO)->setText(cols.at(C_AERO));
627  row.at(C_AERO)->setIcon(QIcon(":/icon/aircraft"));
628  QFont f = row.at(C_AERO)->font();
629  f.setBold(true);
630  row.at(C_AERO)->setFont(f);
631 
632  row.at(C_DESCRIPTION)->setText(cols.at(C_DESCRIPTION));
633  row.at(C_FDM)->setText(cols.at(C_FDM));
634  row.at(C_AUTHOR)->setText(cols.at(C_AUTHOR));
635  row.at(C_XML_FILE)->setText(cols.at(C_XML_FILE));
636  row.at(C_FILE_PATH)->setText(cols.at(C_FILE_PATH));
637  row.at(C_FILTER_PATH)->setText(cols.at(C_FILTER_PATH));
638  //row.at(C_FILTER_PATH)->setText(mainObject->X->aircraft_path());
639 
640  QString filter_str = cols.at(C_AERO);
641  filter_str.append(cols.at(C_DESCRIPTION) );
642  row.at(C_FILTER)->setText( filter_str );
643  row.at(C_BASE)->setText("1");
644  c++;
645  line = in.readLine();
646  }
647 
648  //treeView->sortByColumn(C_DIR, Qt::AscendingOrder);
649  treeView->sortByColumn(C_AERO, Qt::AscendingOrder);
650 
651  treeView->resizeColumnToContents(C_DIR);
652  treeView->resizeColumnToContents(C_AERO);
653  treeView->resizeColumnToContents(C_FDM);
654  //treeView->resizeColumnToContents(C_DIR);
655 
656  select_node(mainObject->X->getx("--aircraft="));
657  QString str = QString("%1 aircraft").arg(this->model->rowCount());
658  statusBar->showMessage(str);
659  outLog("*** FGx: AircraftWidget::load_tree: with " + str);
660 }
661 
662 QList<QStandardItem*> AircraftWidget::create_model_row(){
663  QList<QStandardItem*> lst;
664  for(int i = 0; i < this->model->columnCount(); i++){
665  lst.append( new QStandardItem() );
666  }
667  model->appendRow(lst);
668  return lst;
669 }
670 
671 //=============================================================
672 // Initialize
674 
675  static bool first_load_done = false;
676  if(first_load_done){
677  return;
678  }
679  if (!QFile::exists(mainObject->data_file("aircraft.txt"))){
680  statusBar->showMessage("*** No cached data. Use set paths and reload");
681  }else{
682  load_aircraft();
683  }
684  first_load_done = true;
685 }
686 
687 
688 
689 
691 {
692  emit setx("--nav1=", true, txtNav1->text());
693  emit setx("--nav2=", true, txtNav2->text());
694  emit setx("--adf1=", true, txtAdf1->text());
695  emit setx("--adf2=", true, txtAdf2->text());
696  emit setx("--com1=", true, txtCom1->text());
697  emit setx("--com2=", true, txtCom2->text());
698 
699 }
700 
702  emit setx("--enable-fuel-freeze", checkBoxFuelFreeze->isChecked(), "");
703 }
704 
706 {
707  emit setx("--prop:/consumables/fuels/tank[1]/level-gal=", true, txtTank1->text());
708  emit setx("--prop:/consumables/fuels/tank[2]/level-gal=", true, txtTank2->text());
709  emit setx("--prop:/consumables/fuels/tank[3]/level-gal=", true, txtTank3->text());
710 
711 }
712 
713 
714 
715 //=====================================================
716 void AircraftWidget::on_upx( QString option, bool enabled, QString value)
717 {
718  Q_UNUSED(enabled);
719  //= NOTE: The --aircraft=. --runway, etc is detected as the tree loads from cache
720 
721  if(option == "--aircraft"){
722  //= see tree load
723  select_node(value);
724 
725  }else if(option == "--fg-aircraft="){
726  //txtAircraftPath->setText(value);
727 
728  //== tab radio
729  }else if(option == "--nav1="){
730  txtNav1->setText(value);
731 
732  }else if(option == "--nav2="){
733  txtNav2->setText(value);
734 
735 
736  }else if(option == "--adf1="){
737  txtAdf1->setText(value);
738 
739  }else if(option == "--adf2="){
740  txtAdf2->setText(value);
741 
742 
743  }else if(option == "--com1="){
744  txtCom1->setText(value);
745 
746  }else if(option == "--com2="){
747  txtCom2->setText(value);
748 
749 
750  //=== tab fuel
751 
752  }else if(option == "use_default_fuel"){
753  checkBoxUseDefaultFuel->setChecked(enabled);
754 
755  }else if(option == "--enable-fuel-freeze"){
756  checkBoxFuelFreeze->setChecked(enabled);
757 
758  }else if(option == "--prop:/consumables/fuels/tank[1]/level-gal="){
759  txtTank1->setText(value);
760 
761  }else if(option == "--prop:/consumables/fuels/tank[2]/level-gal="){
762  txtTank2->setText(value);
763 
764  }else if(option == "--prop:/consumables/fuels/tank[3]/level-gal="){
765  txtTank3->setText(value);
766  }
767 }
768 
769 //=====================================================================
770 // Custom aircraft Dir Stuff
771 //=====================================================================
772 // switches a directories visiibility
774 
775 
776  for(int i = 0; i < buttGroupShowDirs->buttons().length(); i++){
777  QString dir = buttGroupShowDirs->buttons().at(i)->property("dir").toString();
778  // qDebug() << "d=" << dir;
779  this->proxyModel->show_dir(dir, buttGroupShowDirs->buttons().at(i)->isChecked());
780  }
781 }
782 
783 
784 
785 // HELP. .this function crashed for some reason..
787 {
788  qDebug() << "--------on_remove_custom_dir()";
789 
790  QString dir = act->property("dir").toString();
791 
792  //return;
793  QStringList custom_dirs = this->mainObject->settings->value("custom_aircraft_dirs").toStringList();
794  int idx = custom_dirs.indexOf(dir);
795  qDebug() << dir << "==" << idx;
796  if( idx == -1) {
797  qDebug() << "arrgggggghhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh";
798  return;
799  }
800  custom_dirs.removeAt(idx);
801  qDebug() << "removed dir " << idx << custom_dirs;
802  this->mainObject->settings->setValue("custom_aircraft_dirs", custom_dirs);
803  this->mainObject->settings->sync();
804  qDebug() << "saved " << custom_dirs;
805  this->load_custom_dir_buttons();
806  qDebug() << " ALL DONE ";
807 }
808 
810 {
811 
812  QString sel_dir = QFileDialog::getExistingDirectory(this, tr("Select an Aircraft directory"),
813  "", QFileDialog::ShowDirsOnly);
814  if(sel_dir.length() == 0){
815  return;
816  }
817  QString sto_dir = QDir::fromNativeSeparators(sel_dir);
818  QStringList custom_dirs = this->mainObject->settings->value("custom_aircraft_dirs").toStringList();
819  if(custom_dirs.indexOf(sto_dir) == -1){
820  custom_dirs.append(sto_dir);
821  }
822  this->mainObject->settings->setValue("custom_aircraft_dirs", custom_dirs);
823  this->mainObject->settings->sync();
824  this->load_custom_dir_buttons();
825 }
826 
828 {
829  //qDebug() << "---load_custom_dir_buttons" << actGroupDeleteCustomDirs->actions().length() << "=" << buttGroupShowDirs->buttons().length() << "=" << lstCustomDirButtons.length();
830 
831  // Delete all the deletes from actinGroup
832  QList<QAction*> actions = actGroupDeleteCustomDirs->actions();
833  for(int i = 0; i < actions.length(); i++){
834  actGroupDeleteCustomDirs->removeAction(actions.at(i));
835  }
836 
837  // Loop buttons and remove from containers then delete
838  while(!lstCustomDirButtons.isEmpty() ){
839  qDebug() << "nuked button" ;
841  buttGroupShowDirs->removeButton(lstCustomDirButtons.at(0));
842  delete lstCustomDirButtons.takeFirst();
843  }
844  //qDebug() << " after nuke " << actGroupDeleteCustomDirs->actions().length() << "=" << buttGroupShowDirs->buttons().length() << "=" << lstCustomDirButtons.length();
845 
846  QStringList custom_dirs = this->mainObject->settings->value("custom_aircraft_dirs").toStringList();
847  for(int i=0; i < custom_dirs.size(); i++){
848 
849  QFileInfo dinfo(custom_dirs.at(i));
850 
851  QToolButton * buttDir = new QToolButton();
852  grpCustomDirs->bottomLayout->insertWidget(grpCustomDirs->bottomLayout->count() - 1, buttDir);
853  buttGroupShowDirs->addButton(buttDir);
854  lstCustomDirButtons.append(buttDir);
855  //qDebug() << "Add button" << dinfo.absoluteFilePath();
856  buttDir->setProperty("dir", QDir::toNativeSeparators(dinfo.absoluteFilePath()));
857  buttDir->setToolTip( QDir::toNativeSeparators( custom_dirs.at(i) ) );
858  buttDir->setText(dinfo.baseName());
859  buttDir->setIcon(QIcon(":/icon/custom_folder"));
860  buttDir->setCheckable(true);
861  buttDir->setChecked(true);
862  buttDir->setAutoRaise(true);
863  buttDir->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
864 
865  // qDebug() << "pre menu =" << dinfo.absoluteFilePath();
866  QMenu *meniw = new QMenu();
867  buttDir->setMenu(meniw);
868  buttDir->setPopupMode(QToolButton::MenuButtonPopup); //grhhhh.. vs Qt::ToolButtonTextBesideIcon
869 
870  /// qDebug() << "pre action =" << dinfo.absoluteFilePath();
871  // remove action
872  QAction *act = meniw->addAction("Remove");
873  act->setIcon(QIcon(":/icon/bin"));
874  act->setProperty("dir", dinfo.absoluteFilePath());
875  meniw->addAction(act);
876  // qDebug() << "post action =" << dinfo.absoluteFilePath();
877  actGroupDeleteCustomDirs->addAction(act);
878  qDebug() << " psot group =" << dinfo.absoluteFilePath();
879 
880 
881  }
882  qDebug() << " Done loading";
883  this->on_toggle_directory();
884 }
885 
887 {
888  if(lblAeroXml->text().length() == 0){
889  return;
890  }
891  QFileInfo fi(lblAeroXml->text());
892  QUrl url(QString("file://%1").arg(fi.dir().absolutePath()));
893  QDesktopServices::openUrl(url);
894 }
896 {
897  FileViewerWidget *fileViewer = new FileViewerWidget();
898  fileViewer->setFile(mainObject->data_file("aircraft.txt"));
899  fileViewer->setWindowState(Qt::WindowMaximized);
900  fileViewer->show();
901 
902 }
903 
905  bool hidden = !this->mainObject->debug_mode;
906  treeView->setColumnHidden(C_XML_FILE, hidden);
907  treeView->setColumnHidden(C_FILE_PATH, hidden);
908  treeView->setColumnHidden(C_FILTER_PATH, hidden);
909  treeView->setColumnHidden(C_BASE, hidden);
910  //treeView->setColumnHidden(C_AUTHOR, true);
911  treeView->setColumnHidden(C_FILTER, hidden);
912 }
QLineEdit * txtCom2
void on_filter_text_changed(const QString)
MainObject * mainObject
ToolBarGroup * grpCustomDirs
void setTitle(QString)
QActionGroup * actGroupDeleteCustomDirs
void on_remove_custom_dir(QAction *)
QLineEdit * txtTank3
void on_toggle_directory()
The MainObject is an extended QObject, and the main "controller" for FGx.
Definition: mainobject.h:66
QList< QStandardItem * > create_model_row()
static ModelInfo read_model_xml(QString dir)
void on_enable_fuel_freeze_clicked()
QToolButton * buttShowBase
QLabel * aeroImageLabel
void on_upx(QString option, bool enabled, QString value)
QString fdm
Definition: modelinfo.h:16
QLabel * lblAeroXml
void load_custom_dir_buttons()
QLineEdit * txtNav2
QSplitter * splitter
QString aero
Definition: modelinfo.h:13
Show a files contents, raw and pretty.
void select_node(QString aero)
void saveSplitter(QSplitter *splitter)
Saves a splitters dimensions.
Definition: xsettings.cpp:65
void removeWidget(QWidget *)
QString xml_file
Definition: modelinfo.h:14
void addWidget(QWidget *)
bool debug_mode
Definition: mainobject.h:75
QLineEdit * txtCom1
void on_tree_selection_changed()
QCheckBox * checkBoxUseDefaultFuel
AircraftWidget(MainObject *mOb, QWidget *parent=0)
QString data_file(QString file_name)
Path to a data file eg data_file("airports.txt")
Definition: mainobject.cpp:438
QHBoxLayout * bottomLayout
Definition: toolbargroup.h:16
QLabel * lblAeroDescription
void restoreSplitter(QSplitter *splitter)
Restores a splitters dimensions.
Definition: xsettings.cpp:76
void load_custom_aircraft()
void setx(QString option, bool enabled, QString value)
QToolButton * buttOpenAeroDir
QString aircraft_path()
The path to the /Aircraft directory.
void setFile(QString file_name)
Loads file and sets labels.
void on_upx(QString option, bool enabled, QString value)
XSettingsModel * X
Definition: mainobject.h:86
QString file_path
Definition: modelinfo.h:19
AircraftProxyModel * proxyModel
void show_dir(QString dir, bool show)
QLineEdit * txtTank1
QCheckBox * checkBoxFuelFreeze
void on_view_aircraft_cache()
QStandardItemModel * model
LauncherWindow * launcherWindow
Definition: mainobject.h:89
QString selected_aircraft()
QList< QToolButton * > lstCustomDirButtons
QLineEdit * txtTank2
QString dir
Definition: modelinfo.h:15
QLineEdit * txtAdf2
QLabel * lblAero
QLineEdit * txtNav1
QTreeView * treeView
QString description
Definition: modelinfo.h:18
QButtonGroup * buttGroupShowDirs
QLineEdit * txtAdf1
QStatusBar * statusBar
static QFileInfoList get_xml_set_files(QString dir, bool recus)
QLineEdit * txtFilter
XSettings * settings
Definition: mainobject.h:85
void on_open_aircraft_path()
static bool import(QProgressDialog &progress, MainObject *mainObject)
QString authors
Definition: modelinfo.h:17
QString getx(QString option)