Fork me on GitHub
2.15.20
FGx
A cross-platform launcher for FlightGear
launcherwindow.cpp
Go to the documentation of this file.
1 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-
2 // FGx FlightGear Launcher // launcherwindow.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 #include <QUrl>
10 #include <QCoreApplication>
11 #include <QtCore/QTimer>
12 #include <QtCore/QProcess>
13 #include <QWhatsThis>
14 
15 
16 #include <QApplication>
17 #include <QVBoxLayout>
18 #include <QHeaderView>
19 #include <QDesktopServices>
20 #include <QMenuBar>
21 #include <QMenu>
22 #include <QAction>
23 #include <QStyleFactory>
24 #include <QMessageBox>
25 #include <QToolBar>
26 #include <QFileDialog>
27 
28 #include "xwidgets/xgroupboxes.h"
29 
31 #include "utilities/utilities.h"
32 #include "utilities/messagebox.h"
33 
35 
36 /*! \class LauncherWindow
37  * \brief The LauncherWindow is raised and controlled by MainObject
38  *
39  * At Present its created upon application launch as a hidden/show window
40 */
42  : QWidget(parent)
43 {
44 
45  initializing = true;
46  mainObject = mob;
47  setAccessibleName("launcherWindow");
48 
49  setProperty("settings_namespace", QVariant("launcher_window"));
51 
52  setWindowTitle(QCoreApplication::applicationName());
53  setWindowIcon(QIcon(":/icon/favicon"));
54 
55 
56  //====================================================
57  //== Outer Layout
58  //====================================================
59  QVBoxLayout *outerContainer = new QVBoxLayout();
60  outerContainer->setContentsMargins(0, 0, 0, 0);
61  outerContainer->setSpacing(0);
62  setLayout(outerContainer);
63 
64 
65  //== Application Menu
66 
68  outerContainer->addWidget(menuWidget, 0);
69 
70 
71  //== Message Label
72 
74  outerContainer->addWidget(headerWidget,0);
75 
76 
77  QVBoxLayout *mainLayout = new QVBoxLayout();
78  mainLayout->setContentsMargins(10, 0, 10, 10);
79  outerContainer->addLayout(mainLayout);
80 
81 
82  //====================================================
83  //** Main TabWidget with Widgets
84  //====================================================
85  tabWidget = new QTabWidget(this);
86  tabWidget->setObjectName("launcher_tabs");
87  mainLayout->addWidget(tabWidget);
88  connect(tabWidget, SIGNAL(currentChanged(int)), this, SLOT(on_tab_changed(int)));
89 
90 
91  //* Core Settings
93  tabWidget->addTab(coreSettingsWidget, tr("Core Settings"));
94 
95  //* Aircraft Widget
97  tabWidget->addTab(aircraftWidget, tr("Aircraft"));
98 
99  //** Position Tab
101  tabWidget->addTab(airportsWidget, tr("Position"));
102 
103  //* Time / Weather Widget
105  tabWidget->addTab(timeWeatherWidget, tr("Time and Weather"));
106 
107  //* Rendering Widget
109  tabWidget->addTab(renderingWidget, tr("Rendering"));
110 
111 
112  //* Network Tab
114  tabWidget->addTab( networkWidget, tr("Network"));
115 
116 
117  //* Expert Options
119  tabWidget->addTab( expertOptionsWidget, tr("Expert Options"));
120 
121 
122  mainLayout->addSpacing(10);
123  mainLayout->setAlignment( Qt::AlignTop );
124 
125 
126 
127  //========================================================================================
128  //**Bottom Bar
129  //========================================================================================
130 
131  //* Show bottom bar
132  QHBoxLayout *bottomActionLayout = new QHBoxLayout();
133  bottomActionLayout->setAlignment( Qt::AlignTop );
134  mainLayout->addLayout(bottomActionLayout);
135 
136  XGroupHBox *toolBox = new XGroupHBox(tr("Profiles"));
137  bottomActionLayout->addWidget(toolBox);
138 
139  //toolBox->setStyleSheet("XGroupHBox::title { color: #000000; background-color: yellow }");
140 
141  //= Load Settings
142  QToolButton *buttonLoadSettings = new QToolButton(this);
143  buttonLoadSettings->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
144  buttonLoadSettings->setText("Load");
145  buttonLoadSettings->setAutoRaise(true);
146  buttonLoadSettings->setIcon(QIcon(":/icon/load"));
147  buttonLoadSettings->setStyleSheet("padding: 0px;");
148  toolBox->addWidget(buttonLoadSettings);
149  connect(buttonLoadSettings, SIGNAL(clicked()),
150  this, SLOT(load_profile())
151  );
152 
153  //= Save Settings
154  QToolButton *buttonSaveSettings = new QToolButton(this);
155  buttonSaveSettings->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
156  buttonSaveSettings->setText("Save");
157  buttonSaveSettings->setAutoRaise(true);
158  buttonSaveSettings->setIcon(QIcon(":/icon/save"));
159  buttonSaveSettings->setStyleSheet("padding: 0px;");
160  toolBox->addWidget(buttonSaveSettings);
161  connect(buttonSaveSettings, SIGNAL(clicked()),
162  this, SLOT(save_profile())
163  );
164 
165  //= Reset Settings
166  QToolButton *buttonResetSettings = new QToolButton(this);
167  buttonResetSettings->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
168  buttonResetSettings->setText("Reset");
169  buttonResetSettings->setAutoRaise(true);
170  buttonResetSettings->setIcon(QIcon(":/icon/reset"));
171  buttonResetSettings->setStyleSheet("padding: 0px;");
172  toolBox->addWidget(buttonResetSettings);
173  connect(buttonResetSettings, SIGNAL(clicked()),
174  this, SLOT(reset_profile())
175  );
176  bottomActionLayout->addStretch(20);
177 
178 
179 
180  bottomActionLayout->addStretch(100);
181 
182  //=============================================================
183  //== Start Stop ==
184  //=============================================================
185 
186 
187  //= TerraSync
188  exeTerraSync = new ExeControls("TerraSync");
189  bottomActionLayout->addWidget(exeTerraSync);
190  connect(exeTerraSync->buttonStart, SIGNAL(clicked()),
191  this, SLOT(on_start_terrasync_clicked())
192  );
193 
194  connect(mainObject->processTerraSync, SIGNAL(running(bool)), exeTerraSync, SLOT(set_running(bool)));
195  connect(exeTerraSync, SIGNAL(stop()), mainObject->processTerraSync, SLOT(stop()));
196 
197  //= FlightGear
198  exeFgfs = new ExeControls("FlightGear (fgfs)");
199  bottomActionLayout->addWidget(exeFgfs);
200  connect( exeFgfs->buttonStart, SIGNAL(clicked()),
201  this, SLOT(on_start_fgfs_clicked())
202  );
203  connect(mainObject->processFgFs, SIGNAL(running(bool)), exeFgfs, SLOT(set_running(bool)));
204  connect(exeFgfs, SIGNAL(stop()), mainObject->processFgFs, SLOT(stop()));
205 
206  //= All
207  exeAll = new ExeControls("FlightGear");
208  //exeAll->setStyleSheet("QGroupBox::title { color: #ffffff; background-color: #007eff }");
209  bottomActionLayout->addWidget(exeAll);
210  connect( exeAll->buttonStart, SIGNAL(clicked()),
211  this, SLOT(on_start_all_clicked())
212  );
213  connect(mainObject->processFgFs, SIGNAL(running(bool)), exeAll, SLOT(set_running(bool)));
214  connect(exeAll, SIGNAL(stop()), mainObject, SLOT(stop_all()) );
215 
216  on_debug_mode(); //= Show hide exe widgets
217 
218  //====================================================================================
219  //* Problem: Qt Has no "Show event" for a "widget", so we need to present Widgets first
220  //** and then initialise. This is achieved with a timer that triggers in a moment
221 
222  // TODO - disable widget till sane in initialize()
223  //centralWidget()->setDisabled(true);
224 
225  initializing = false;
226  QTimer::singleShot(300, this, SLOT(initialize()));
227 
228 
229  connect(this, SIGNAL(setx(QString,bool,QString)), mainObject->X, SLOT(set_option(QString,bool,QString)) );
230  connect(mainObject->X, SIGNAL(upx(QString,bool,QString)), this, SLOT(on_upx(QString,bool,QString)));
231  connect(mainObject, SIGNAL(on_debug_mode(bool)), this, SLOT(on_debug_mode()));
232 
233 }
234 
236 {
237 }
238 
239 
240 //=======================================================================================================================
241 // initialize and Setup
242 //=======================================================================================================================
244 
245  //= retorelast tab
246  tabWidget->setCurrentIndex( mainObject->settings->value("launcher_last_tab", 0).toInt() );
247 
248  //= First load the profiles
249 
250  QSettings firstsettings;
251  QString previous = mainObject->X->getLastUsed();
252  int done = 0;
253  while (!firstsettings.value("firststartup").toBool()) {
254  // stay here UNTIL the FIRST SAVE has been done
255  if (done == 0) { // first time - set a kind, gentle message
256  previous = "Welcome to FGx. You need to save this Settings Profile first. Choose a writable location in next dialog and click \"Save\".";
257  outLog("*** Looks like first startup without profile, reading default values. ***");
259  }
260  QMessageBox::warning(this, tr("FGx First Startup - Settings Reset"),previous,QMessageBox::Ok);
261  done++;
262  if ( mainObject->X->save_profile() ) {
263  firstsettings.setValue("firststartup", "true");
264  firstsettings.sync();
265 
266  } else { // did NOT write a profile - get quite INSISTANT ;=()
267  previous.sprintf("Try %d! You MUST save this Settings Profile first. Choose a writable location in next dialog and click \"Ok\" ONLY.",
268  (done + 1));
269  }
270  // reload lists after setting default init values
273  }
274 
275  // This we do everytime, solves a lot of problems loading the first saved profile
276  previous = mainObject->X->getLastUsed();
277  mainObject->X->load_last_profile(previous);
278  QFileInfo fi(previous);
279  QString name = fi.fileName();
280  header_show_message("Last used profile loaded: "+name);
281 
282  //= check paths are sane
283  if(!mainObject->X->paths_sane()){
284  //mainObject->show_setup_wizard();
285  }
286 
287  //* Paths are sane so we can initialize;
291 }
292 
293 //=======================================================================================================================
294 // Start Commands
295 //=======================================================================================================================
296 
297 //= Start All
299  if(!validate()){
300  return;
301  }
302  //save_settings();
304 }
305 
306 //= Start FgFs
308  qDebug() << "pre validate";
309  if(!validate()){
310  return;
311  }
312  qDebug() << "save";
313  //save_settings();
315 }
316 
317 //= Start Terrasync
319  if(!validate()){
320  return;
321  }
322  //save_settings();
324 }
325 
326 
327 
328 //================================================================================
329 // Save Settings
330 //================================================================================
332 {
333  mainObject->settings->sync();
334  // get lastused profile name
335  QString previous = mainObject->X->getLastUsed();
336  previous = util_getBaseName(previous);
337  headerWidget->showMessage("Settings saved to "+previous);
338  outLog("FGx: LauncherWindow widget says: settings saved to "+previous);
339 
340 }
341 
342 //================================================================================
343 // Load Profile
344 //================================================================================
346 {
347  QString message("Profile load abandoned");
348  if (mainObject->X->load_profile()) {
349  // get lastused profile name
350  QString previous = mainObject->X->getLastUsed();
351  previous = util_getBaseName(previous);
352  message = "Profile loaded from "+previous;
353  }
354  headerWidget->showMessage(message);
355  reset_profile(); // resets the profile, gives emitting back, reload cache
356 
357 }
358 
359 //================================================================================
360 // Save Profile
361 //================================================================================
363 {
364  QString message("Profile save abandoned");
365  if (mainObject->X->save_profile()) {
366  // get lastused profile name
367  QString previous = mainObject->X->getLastUsed();
368  previous = util_getBaseName(previous);
369  message = "Profile saved to "+previous;
370  }
371  headerWidget->showMessage(message);
372 }
373 
374 
375 //================================================================================
376 // Reset Profile
377 //================================================================================
379 {
380  QString message("Reset to loaded profile.");
381  QString previous = mainObject->X->getLastUsed();
382  mainObject->X->load_last_profile(previous);
383  headerWidget->showMessage(message);
384  airportsWidget->on_reload_cache(); // Reload the aircraft and airport lists
385 }
386 
387 
388 //==============================================
389 //== View Buttons
391  if(!validate()){
392  return;
393  }
394  save_settings();
395 }
396 
397 
398 //=======================================================================================================================
399 //* Validate
400 //=======================================================================================================================
402 
403  QString v;
404 
406  if(v != ""){
407  tabWidget->setCurrentIndex( tabWidget->indexOf(coreSettingsWidget));
409  return false;
410  }
411 
412  v = aircraftWidget->validate();
413  if(v != ""){
414  tabWidget->setCurrentIndex( tabWidget->indexOf(aircraftWidget));
416  return false;
417  }
418  outLog("*** FGx reports: Aircraft settings ok. ***");
419 
420  v = airportsWidget->validate();
421  if(v != ""){
422  tabWidget->setCurrentIndex( tabWidget->indexOf(airportsWidget));
424  return false;
425  }
426  outLog("*** FGx reports: Airport settings ok. ***");
427 
428  v = networkWidget->validate();
429  if(v != ""){
430  tabWidget->setCurrentIndex( tabWidget->indexOf(networkWidget));
432  return false;
433  }
435  if(v != ""){
436  tabWidget->setCurrentIndex( tabWidget->indexOf(timeWeatherWidget));
438  return false;
439  }
440  outLog("*** FGx reports: Network settings ok. ***");
441 
442  outLog("*** FGx reports: ALL SETTINGS VALID. ***");
443  return true;
444 }
445 
446 
447 //=======================================================================================================================
448 //* Message Event
449 //=======================================================================================================================
450 
452 
453 {
454  headerWidget->showMessage(message);
455 }
456 
457 
458 //=======================================================================================================================
459 //* Misc Events
460 //=======================================================================================================================
461 void LauncherWindow::moveEvent(QMoveEvent *ev){
462  Q_UNUSED(ev);
463  this->mainObject->settings->saveWindow(this);
464 }
465 
466 //= window close
467 void LauncherWindow::closeEvent(QCloseEvent *event){
468 
469  QMessageBox msgBox;
470  msgBox.setText("Profile and Settings:");
471  msgBox.setInformativeText("Closing application: Do you want to save your changes?");
472  msgBox.setStandardButtons(QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel);
473  msgBox.setDefaultButton(QMessageBox::Save);
474  int ret = msgBox.exec();
475 
476  switch (ret) {
477  case QMessageBox::Save:
479  save_settings();
480  mainObject->settings->sync();
481  event->accept();
482  break;
483  case QMessageBox::Discard:
484  event->accept();
485  break;
486  case QMessageBox::Cancel:
487  event->ignore();
488  break;
489  default:
491  save_settings();
492  mainObject->settings->sync();
493  event->accept();
494  break;
495  }
496 
497  mainObject->on_quit();
498 
499 
500 }
501 
502 
503 //=== Tab Changes
505  if(initializing){
506  return;
507  }
508 
509  /* if(tab_idx == tabWidget->indexOf(airportsWidget)){
510  airportsWidget->treeWidgetAirportInfo->update();
511  airportsWidget->mapWidget->update();
512  } */
513 
514  if(tab_idx == tabWidget->indexOf(this->expertOptionsWidget)){
515  //on_command_preview();
516  }else{
517  //= we dont want to restore to output preview cos it validates and will throw popup
518  mainObject->settings->setValue("launcher_last_tab", tabWidget->currentIndex());
519  }
520 
521  // deal with focus in events
522  if(tab_idx == tabWidget->indexOf(this->aircraftWidget)) {
523  this->aircraftWidget->txtFilter->setFocus();
524  }
525 }
526 
527 
528 
529 
530 
531 //============================================
532 //= Set Widgets on Debug Mode
534 {
535  exeFgfs->setVisible(mainObject->debug_mode == true);
536  exeTerraSync->setVisible(mainObject->debug_mode == true);
537  exeAll->setVisible(mainObject->debug_mode == false);
538 }
539 
540 
541 
542 //============================================
543 //= Update Settings
544 void LauncherWindow::on_upx(QString option, bool enabled, QString value)
545 {
546  Q_UNUSED(enabled);
547  Q_UNUSED(value);
548 
549  if(option == "--callsign=" ){
550  headerWidget->setCallsign( value );
551  }
552 
553  QStringList keys;
554  keys << "--callsign=" << "--aircraft=" << "--airport=" << "--runway=" << "--parking-id=";
555  if(keys.contains(option)){
556  QString header = QString("<font color=#ff0000>%1</font> : <b>%2</b>"
557  ).arg( mainObject->X->getx("--callsign=")
558  ).arg( mainObject->X->getx("--aircraft=")
559  );
560  XOpt apt = mainObject->X->get_opt("--airport=");
561  if(apt.enabled){
562  header.append(" @ ").append(apt.value);
563 
564  XOpt rwy = mainObject->X->get_opt("--runway=");
565  if(rwy.enabled){
566  header.append(" RWY ").append(rwy.value);
567  }else{
568  XOpt stand = mainObject->X->get_opt("--parking-id=");
569  if(stand.enabled){
570  header.append(" Stand: ").append(stand.value);
571  }
572  }
573  }
574 
575  headerWidget->setHeader( header );
576 
577 
578  }
579 
580 
581 }
582 
583 
ExpertOptionsWidget * expertOptionsWidget
QString validate()
void setx(QString option, bool enabled, QString value)
QTabWidget * tabWidget
bool paths_sane()
Checks whether the executablem FG_ROOT paths are sane.
void setHeader(QString text)
NetworkWidget * networkWidget
void header_show_message(QString message)
XProcess * processFgFs
Definition: mainobject.h:97
QString value
Definition: xopt.h:19
void moveEvent(QMoveEvent *ev)
The MainObject is an extended QObject, and the main "controller" for FGx.
Definition: mainobject.h:66
bool load_profile()
Opens Profile Dialog for loading a .ini File.
AircraftWidget * aircraftWidget
LauncherWindow(MainObject *mob, QWidget *parent=0)
void on_start_fgfs_clicked()
void on_start_terrasync_clicked()
Aircraft panel with a left/right splitter, model/proxy/tree vs selected.
void saveWindow(QWidget *widget)
Saves a window's size and position.
Definition: xsettings.cpp:90
HeaderWidget * headerWidget
QPushButton * buttonLoadSettings
XGroupHBox * toolBox
XProcess * processTerraSync
Definition: mainobject.h:98
void on_start_all_clicked()
void on_tab_changed(int)
bool debug_mode
Definition: mainobject.h:75
QPushButton * buttonResetSettings
void restoreWindow(QWidget *widget)
Restores a size window position.
Definition: xsettings.cpp:101
MenuWidget * menuWidget
Definition: xopt.h:14
void on_quit()
Definition: mainobject.cpp:329
A QGroupBox with a QHBoxLyout layout.
Definition: xgroupboxes.h:39
RenderingWidget * renderingWidget
QPushButton * buttonSaveSettings
QToolButton * buttonStart
Definition: execontrols.h:28
ExeControls * exeAll
void load_last_profile(QString profile)
Opens last used profile.
void closeEvent(QCloseEvent *event)
void read_default_ini()
Read Values from ini.
void on_upx(QString option, bool enabled, QString value)
QString getLastUsed()
XSettingsModel * X
Definition: mainobject.h:86
void setCallsign(QString text)
TimeWeatherWidget * timeWeatherWidget
bool save_profile()
Opens Profile Dialog for loading a .ini File.
void start_all()
Definition: mainobject.cpp:284
LauncherWindow * launcherWindow
Definition: mainobject.h:89
void addWidget(QWidget *w)
Definition: xgroupboxes.cpp:45
void start_fgfs()
Definition: mainobject.cpp:309
AirportsWidget * airportsWidget
void showMessage(QString message, int timeout)
ExeControls * exeTerraSync
QLineEdit * txtFilter
The HeaderWidget is the top part of the LauncherWindow and contains the info and a normally hidden me...
Definition: headerwidget.h:23
CoreSettingsWidget * coreSettingsWidget
XSettings * settings
Definition: mainobject.h:85
void start_terrasync()
Definition: mainobject.cpp:316
XOpt get_opt(QString option)
ExeControls * exeFgfs
QString getx(QString option)
MainObject * mainObject
bool enabled
Definition: xopt.h:20
The MenuWidget is the top part of the LauncherWindow.
Definition: menuwidget.h:29