BuildmLearn Toolkit  2.0.4
BuildmLearn Toolkit is an easy-to-use program that helps users make mobile apps without any knowledge of application development.
 All Classes Functions Enumerations Groups Pages
formmain.cpp
1 /*
2  Copyright (c) 2012, BuildmLearn Contributors listed at http://buildmlearn.org/people/
3  All rights reserved.
4 
5  Redistribution and use in source and binary forms, with or without
6  modification, are permitted provided that the following conditions are met:
7 
8  * Redistributions of source code must retain the above copyright notice, this
9  list of conditions and the following disclaimer.
10 
11  * Redistributions in binary form must reproduce the above copyright notice,
12  this list of conditions and the following disclaimer in the documentation
13  and/or other materials provided with the distribution.
14 
15  * Neither the name of the BuildmLearn nor the names of its
16  contributors may be used to endorse or promote products derived from
17  this software without specific prior written permission.
18 
19  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27  OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30 
31 #include "gui/formmain.h"
32 
33 #include "definitions/definitions.h"
34 #include "gui/formupdate.h"
35 #include "gui/formabout.h"
36 #include "gui/formsettings.h"
37 #include "gui/systemtrayicon.h"
38 #include "gui/formhelp.h"
39 #include "gui/formsimulator.h"
40 #include "gui/formnewproject.h"
41 #include "gui/custommessagebox.h"
42 #include "gui/formuploadbundle.h"
43 #include "miscellaneous/iconfactory.h"
44 #include "core/templatesimulator.h"
45 #include "core/templatefactory.h"
46 #include "core/templateentrypoint.h"
47 #include "core/templateeditor.h"
48 #include "core/templategenerator.h"
49 #include "templates/quiz/quizentrypoint.h"
50 
51 #include <QStackedWidget>
52 #include <QMessageBox>
53 #include <QFileDialog>
54 #include <QInputDialog>
55 #include <QHBoxLayout>
56 #include <QVBoxLayout>
57 #include <QDesktopWidget>
58 #include <QLayoutItem>
59 #include <QProgressBar>
60 #include <QScrollArea>
61 
62 
63 FormMain::FormMain(QWidget *parent)
64  : QMainWindow(parent),
65  m_statusProgress(new QProgressBar(this)),
66  m_statusLabel(new QLabel(this)),
67  m_centralArea(new QScrollArea(this)),
68  m_centralLayout(new QVBoxLayout(m_centralArea)),
69  m_firstTimeShow(true),
70  m_ui(new Ui::FormMain),
71  m_simulatorWindow(NULL) {
72  m_ui->setupUi(this);
73 
74  m_normalTitle = APP_LONG_NAME;
75  m_unsavedTitle = m_normalTitle + " *";
76 
77  m_statusProgress->setFixedHeight(m_ui->m_statusBar->sizeHint().height());
78 
79  // Addd necessary widgets to status.
80  m_ui->m_statusBar->addWidget(m_statusProgress);
81  m_ui->m_statusBar->addWidget(m_statusLabel, 1);
82  m_statusLabel->setVisible(false);
83  m_statusProgress->setVisible(false);
84 
85  setWindowTitle(m_normalTitle);
86 
87  // Disable "maximize" button.
88  setWindowFlags(windowFlags() & ~Qt::WindowMaximizeButtonHint);
89 
90  m_centralArea->setFrameStyle(QFrame::NoFrame);
91 
92  setCentralWidget(m_centralArea);
93  setupSimulatorWindow();
94  setupActionShortcuts();
95  setupIcons();
96  setupTrayMenu();
97  setupToolbar();
98  loadSizeAndPosition();
99  createConnections();
100 
101  //#if !defined(DEBUG)
102 #if defined(DISABLE_STORE)
103  m_ui->m_actionUploadApplicationToStore->setVisible(false);
104 #else
105  if (!qApp->settings()->value(APP_CFG_GEN, "enable_store", true).toBool()) {
106  m_ui->m_actionUploadApplicationToStore->setVisible(false);
107  }
108 #endif
109 
110 #if defined(DISABLE_APK_GENERATION)
111  m_ui->m_actionGenerateMobileApplication->setVisible(false);
112 #else
113  if (!qApp->settings()->value(APP_CFG_GEN, "enable_apk_generation", true).toBool()) {
114  m_ui->m_actionGenerateMobileApplication->setVisible(false);
115  }
116 #endif
117  //#endif
118 
119  // Make sure simulator window is displayed.
120  m_ui->m_actionViewSimulatorWindow->setChecked(m_simulatorWindow->isVisibleOnStartup());
121  m_ui->m_actionStickSimulatorWindow->setChecked(m_simulatorWindow->isSticked());
122 }
123 
124 FormMain::~FormMain() {
125  delete m_ui;
126 
127  qDebug("Destroying FormMain instance.");
128 }
129 
130 QList<QAction*> FormMain::allActions() {
131  QList<QAction*> actions;
132 
133  actions.append(m_ui->m_actionCheckForUpdates);
134  actions.append(m_ui->m_actionGenerateMobileApplication);
135  actions.append(m_ui->m_actionUploadApplicationToStore);
136  actions.append(m_ui->m_actionLoadProject);
137  actions.append(m_ui->m_actionNewProject);
138  actions.append(m_ui->m_actionSaveProject);
139  actions.append(m_ui->m_actionSaveProjectAs);
140  actions.append(m_ui->m_actionSimulatorRun);
141  actions.append(m_ui->m_actionSimulatorStop);
142  actions.append(m_ui->m_actionSimulatorGoBack);
143  actions.append(m_ui->m_actionViewSimulatorWindow);
144  actions.append(m_ui->m_actionStickSimulatorWindow);
145  actions.append(m_ui->m_actionQuit);
146  actions.append( m_ui->m_actionSettings);
147  actions.append(m_ui->m_actionHelp);
148 
149  return actions;
150 }
151 
152 void FormMain::setupSimulatorWindow() {
153  m_simulatorWindow = new FormSimulator(this);
154 }
155 
156 void FormMain::createConnections() {
157  // General connections.
158  connect(qApp, SIGNAL(aboutToQuit()), this, SLOT(onAboutToQuit()));
159  connect(m_ui->m_actionQuit, SIGNAL(triggered()), this, SLOT(close()));
160  connect(m_ui->m_actionCheckForUpdates, SIGNAL(triggered()), this, SLOT(showUpdates()));
161  connect(m_ui->m_actionAboutToolkit, SIGNAL(triggered()), this, SLOT(showAbout()));
162  connect(m_ui->m_actionSettings, SIGNAL(triggered()), this, SLOT(showSettings()));
163  connect(m_ui->m_actionHelp, SIGNAL(triggered()), this, SLOT(showHelp()));
164 
165  // View connections.
166  connect(m_ui->m_actionViewSimulatorWindow, SIGNAL(toggled(bool)), this, SLOT(switchSimulatorWindow(bool)));
167  connect(m_ui->m_actionStickSimulatorWindow, SIGNAL(toggled(bool)), m_simulatorWindow, SLOT(setIsSticked(bool)));
168 
169  // Extra simulator connections.
170  connect(m_simulatorWindow, SIGNAL(closed()), this, SLOT(onSimulatorWindowClosed()));
171  connect(m_simulatorWindow, SIGNAL(stopEnableChanged(bool)), m_ui->m_actionSimulatorStop, SLOT(setEnabled(bool)));
172  connect(m_ui->m_actionSimulatorStop, SIGNAL(triggered()), m_simulatorWindow->m_ui->m_btnStopSimulation, SLOT(click()));
173  connect(m_ui->m_actionSimulatorRun, SIGNAL(triggered()), this, SLOT(startSimulation()));
174  connect(m_ui->m_actionSimulatorGoBack, SIGNAL(triggered()), this, SLOT(takeSimulationOneStepBack()));
175 
176  // Project connections.
177  connect(m_ui->m_actionNewProject, SIGNAL(triggered()), this ,SLOT(openNewProjectDialog()));
178  connect(m_ui->m_actionSaveProject, SIGNAL(triggered()), this ,SLOT(openSaveProjectDialog()));
179  connect(m_ui->m_actionSaveProjectAs, SIGNAL(triggered()), this, SLOT(openSaveProjectAsDialog()));
180  connect(m_ui->m_actionLoadProject, SIGNAL(triggered()), this ,SLOT(openLoadProjectDialog()));
181  connect(m_ui->m_actionOpenOutputDirectory, SIGNAL(triggered()), this, SLOT(openOutputDirectory()));
182 
183  // Template system connections.
184  connect(qApp->templateManager(), SIGNAL(newTemplateCoreCreated(TemplateCore*)), this, SLOT(setTemplateCore(TemplateCore*)));
185  connect(qApp, SIGNAL(externalApplicationsRechecked()), this, SLOT(onExternalApplicationsChanged()));
186  connect(m_ui->m_actionGenerateMobileApplication, SIGNAL(triggered()), this, SLOT(generateMobileApplication()));
187  connect(m_ui->m_actionUploadApplicationToStore, SIGNAL(triggered()), this, SLOT(uploadMobileApplicationToStore()));
188  connect(qApp->templateManager()->generator(), SIGNAL(generationStarted()), this, SLOT(onGenerationStarted()));
189  connect(qApp->templateManager()->generator(), SIGNAL(generationFinished(TemplateCore::GenerationResult,QString)),
190  this, SLOT(onGenerationDone(TemplateCore::GenerationResult,QString)));
191  connect(qApp->templateManager()->generator(), SIGNAL(generationProgress(int,QString)), this, SLOT(onGenerationProgress(int,QString)));
192 }
193 
194 void FormMain::setupActionShortcuts() {
195  m_ui->m_actionGenerateMobileApplication->setShortcut(QKeySequence("Ctrl+G", QKeySequence::PortableText));
196  m_ui->m_actionLoadProject->setShortcut(QKeySequence("Ctrl+L", QKeySequence::PortableText));
197  m_ui->m_actionNewProject->setShortcut(QKeySequence("Ctrl+N", QKeySequence::PortableText));
198  m_ui->m_actionSaveProject->setShortcut(QKeySequence("Ctrl+S", QKeySequence::PortableText));
199  m_ui->m_actionSaveProjectAs->setShortcut(QKeySequence("Ctrl+Shift+S", QKeySequence::PortableText));
200  m_ui->m_actionQuit->setShortcut(QKeySequence("Ctrl+Q", QKeySequence::PortableText));
201  m_ui->m_actionSettings->setShortcut(QKeySequence("Ctrl+T", QKeySequence::PortableText));
202  m_ui->m_actionHelp->setShortcut(QKeySequence("F1", QKeySequence::PortableText));
203  m_ui->m_actionOpenOutputDirectory->setShortcut(QKeySequence("Ctrl+D", QKeySequence::PortableText));
204 }
205 
206 void FormMain::setupIcons() {
207  IconFactory *factory = IconFactory::instance();
208 
209  m_ui->m_actionSettings->setIcon(factory->fromTheme("application-settings"));
210  m_ui->m_actionQuit->setIcon(factory->fromTheme("application-exit"));
211  m_ui->m_actionAboutToolkit->setIcon(factory->fromTheme("application-about"));
212  m_ui->m_actionCheckForUpdates->setIcon(factory->fromTheme("check-for-updates"));
213  m_ui->m_actionHelp->setIcon(factory->fromTheme("dialog-question"));
214  m_ui->m_actionNewProject->setIcon(factory->fromTheme("project-new"));
215  m_ui->m_actionSaveProject->setIcon(factory->fromTheme("project-save"));
216  m_ui->m_actionSaveProjectAs->setIcon(factory->fromTheme("project-save-as"));
217  m_ui->m_actionLoadProject->setIcon(factory->fromTheme("project-load"));
218  m_ui->m_actionUploadApplicationToStore->setIcon(factory->fromTheme("project-upload"));
219  m_ui->m_actionGenerateMobileApplication->setIcon(factory->fromTheme("project-generate"));
220  m_ui->m_menuSimulatorWindow->setIcon(factory->fromTheme("view-simulator"));
221  m_ui->m_actionStickSimulatorWindow->setIcon(factory->fromTheme("simulation-stick"));
222  m_ui->m_actionViewSimulatorWindow->setIcon(factory->fromTheme("view-simulator"));
223  m_ui->m_actionSimulatorRun->setIcon(factory->fromTheme("simulation-run"));
224  m_ui->m_actionSimulatorStop->setIcon(factory->fromTheme("simulation-stop"));
225  m_ui->m_actionSimulatorGoBack->setIcon(factory->fromTheme("simulation-back"));
226  m_ui->m_actionOpenOutputDirectory->setIcon(factory->fromTheme("view-output"));
227 }
228 
229 void FormMain::setupToolbar() {
230  m_ui->m_toolBar->setWindowTitle(tr("Main toolbar"));
231 
232  m_ui->m_toolBar->addAction(m_ui->m_actionNewProject);
233  m_ui->m_toolBar->addAction(m_ui->m_actionLoadProject);
234  m_ui->m_toolBar->addAction(m_ui->m_actionSaveProject);
235  m_ui->m_toolBar->addAction(m_ui->m_actionSaveProjectAs);
236  m_ui->m_toolBar->addSeparator();
237  m_ui->m_toolBar->addAction(m_ui->m_actionSimulatorRun);
238  m_ui->m_toolBar->addAction(m_ui->m_actionSimulatorStop);
239  m_ui->m_toolBar->addAction(m_ui->m_actionSimulatorGoBack);
240  m_ui->m_toolBar->addAction(m_ui->m_actionGenerateMobileApplication);
241  m_ui->m_toolBar->addAction(m_ui->m_actionUploadApplicationToStore);
242  m_ui->m_toolBar->addAction(m_ui->m_actionHelp);
243 }
244 
245 void FormMain::setupTrayMenu() {
247 #if defined(Q_OS_WIN)
248  m_trayMenu = new TrayIconMenu(APP_NAME, this);
249 #else
250  m_trayMenu = new QMenu(APP_NAME, this);
251 #endif
252 
253  // Add needed items to the menu.
254  m_trayMenu->addAction(m_ui->m_actionCheckForUpdates);
255  m_trayMenu->addSeparator();
256  m_trayMenu->addAction(m_ui->m_actionQuit);
257 
258  qDebug("Creating tray icon menu.");
259  }
260 }
261 
262 void FormMain::loadSizeAndPosition() {
263  QRect screen = qApp->desktop()->screenGeometry();
264  QRect windows = rect();
265  Settings *settings = qApp->settings();
266 
267  windows.setWidth(windows.width() + m_simulatorWindow->width());
268 
269  // Reload main window size & position.
270  resize(settings->value(APP_CFG_GUI, "window_size", size()).toSize());
271  move(settings->value(APP_CFG_GUI, "window_position", screen.center() - windows.center()).toPoint());
272 
273  // Load visual state of simulator window.
274  m_simulatorWindow->loadState();
275 }
276 
277 void FormMain::saveSizeAndPosition() {
278  Settings *settings = qApp->settings();
279 
280  settings->setValue(APP_CFG_GUI, "window_position", pos());
281  settings->setValue(APP_CFG_GUI, "window_size", size());
282 
283  // Save visual state of simulator window.
284  m_simulatorWindow->saveState();
285 }
286 
287 void FormMain::quit()
288 {
289 
290 }
291 
292 void FormMain::startSimulation() {
293  showSimulator();
294  QTimer::singleShot(0, m_simulatorWindow, SLOT(startSimulation()));
295 }
296 
297 void FormMain::takeSimulationOneStepBack() {
298  showSimulator();
299  QTimer::singleShot(0, m_simulatorWindow, SLOT(goBack()));
300 }
301 
302 void FormMain::onCanGenerateChanged(bool can_generate, const QString &informative_text) {
303  if (can_generate) {
304  // Editor of active template can generate applications.
305  if (!qApp->externalApplicationChecked()) {
306  qApp->recheckExternalApplications(false);
307  }
308 
309  if (!qApp->externalApplicationsReady()) {
310  m_ui->m_actionGenerateMobileApplication->setEnabled(false);
311  m_ui->m_actionGenerateMobileApplication->setToolTip(qApp->externalApplicationsStatus());
312  }
313  else {
314  // All external generators are set, template is ready, we can generate.
315  m_ui->m_actionGenerateMobileApplication->setEnabled(true);
316  m_ui->m_actionGenerateMobileApplication->setToolTip(tr("Generate mobile application"));
317  }
318 
319  m_ui->m_actionUploadApplicationToStore->setEnabled(true);
320  m_ui->m_actionUploadApplicationToStore->setToolTip(tr("Upload mobile application to store"));
321  m_ui->m_actionSimulatorRun->setEnabled(true);
322  m_ui->m_actionSimulatorRun->setToolTip(tr("Start new simulation"));
323  }
324  else {
325  // Editor of active template cannot generate applications.
326  m_ui->m_actionUploadApplicationToStore->setEnabled(false);
327  m_ui->m_actionUploadApplicationToStore->setToolTip(informative_text);
328  m_ui->m_actionGenerateMobileApplication->setEnabled(can_generate);
329  m_ui->m_actionGenerateMobileApplication->setToolTip(qApp->externalApplicationsStatus());
330  m_ui->m_actionSimulatorRun->setEnabled(can_generate);
331  m_ui->m_actionSimulatorRun->setToolTip(informative_text);
332  }
333 }
334 
335 void FormMain::onExternalApplicationsChanged() {
336  if (qApp->templateManager()->activeCore() != NULL) {
337  TemplateEditor *active_editor = qApp->templateManager()->activeCore()->editor();
338 
339  onCanGenerateChanged(active_editor->canGenerateApplications(),
340  active_editor->generationStatusDescription());
341  }
342  else {
343  // There is no active template, thus no simulations can be started
344  // but still update generator buttons.
345  onCanGenerateChanged(false, QString());
346  }
347 }
348 
349 void FormMain::onEditorChanged() {
350  setWindowTitle(m_unsavedTitle);
351 
352  TemplateCore *current_core = static_cast<TemplateEditor*>(sender())->core();
353 
354  if (current_core->assignedFile().isEmpty()) {
355  // Template which was already saved or is loaded
356  // from XML bundle file has changed its state
357  // and is now unsaved.
358  m_ui->m_actionSaveProjectAs->setEnabled(true);
359  m_ui->m_actionSaveProject->setEnabled(true);
360  }
361  else {
362  // Template from new project has changed.
363  m_ui->m_actionSaveProjectAs->setEnabled(true);
364  m_ui->m_actionSaveProject->setEnabled(true);
365  }
366 }
367 
368 void FormMain::onGenerationProgress(int percentage_completed, const QString &message) {
369  qApp->processEvents();
370 
371  m_statusLabel->setText(message);
372  m_statusLabel->setVisible(true);
373  m_statusProgress->setValue(percentage_completed);
374  m_statusProgress->setVisible(true);
375 }
376 
377 void FormMain::onGenerationStarted() {
378  qApp->processEvents();
379 
380  m_ui->m_actionGenerateMobileApplication->setEnabled(false);
381 }
382 
383 void FormMain::onGenerationDone(TemplateCore::GenerationResult result_code, const QString &output_file) {
384  qApp->processEvents();
385 
386  m_generatedApplicationPath = output_file;
387 
388  if (qApp->templateManager()->activeCore() != NULL) {
389  m_ui->m_actionGenerateMobileApplication->setEnabled(qApp->templateManager()->activeCore()->editor()->canGenerateApplications());
390  }
391  else {
392  m_ui->m_actionGenerateMobileApplication->setEnabled(false);
393  }
394 
395  m_statusLabel->clear();
396  m_statusLabel->setVisible(false);
397  m_statusProgress->setValue(0);
398  m_statusProgress->setVisible(false);
399 
400  // TODO: Print information about result.
401  switch (result_code) {
402  case TemplateCore::Success: {
403  CustomMessageBox msg_box(this);
404 
405  // Initialize message box properties.
406  msg_box.setWindowTitle(tr("Mobile application generated"));
407 #if defined(Q_OS_WIN32)
408  msg_box.setText(tr("Mobile application was successfully generated."));
409 
410  QPushButton *btn_open_folder = msg_box.addButton(tr("Open output folder"),
411  QMessageBox::DestructiveRole);
412  connect(btn_open_folder, SIGNAL(clicked()), this, SLOT(openOutputDirectory()));
413 #else
414  msg_box.setText(tr("Mobile application was successfully generated and is placed in "
415  "output directory \"%1\"").arg(QDir::toNativeSeparators(qApp->templateManager()->outputDirectory())));
416 #endif
417  msg_box.setIcon(QMessageBox::Information);
418  msg_box.setStandardButtons(QMessageBox::Ok);
419 
420  // Setup button box icons.
421 #if defined(Q_OS_OS2)
422  QDialogButtonBox *button_box = msg_box.findChild<QDialogButtonBox*>();
423  CustomMessageBox::iconify(button_box);
424 #endif
425 
426  msg_box.exec();
427  break;
428  }
429  case TemplateCore::Aborted:
430  // Supress abortion state because this is not critical state.
431  break;
432 
433  default:
434  CustomMessageBox::show(this, QMessageBox::Critical, tr("Mobile application not generated"),
435  tr("Application was NOT generated successfully."));
436  break;
437  }
438 }
439 
440 void FormMain::openOutputDirectory() {
441 #if defined(Q_OS_WIN32)
442  // Open explorer window with target path.
443  QProcess::startDetached("explorer", QStringList() /*<< "/root,"*/ << QDir::toNativeSeparators(qApp->templateManager()->outputDirectory()));
444 #else
445  // TODO: Better handling here and add action icon.
446  CustomMessageBox::show(this, QMessageBox::Warning, tr("Cannot open directory"),
447  tr("Output directory cannot be opened, output directory is \"%1\".").arg(QDir::toNativeSeparators(qApp->templateManager()->outputDirectory())));
448 #endif
449 }
450 
451 void FormMain::setTemplateCore(TemplateCore *core) {
452  setWindowTitle(m_normalTitle);
453 
454  // Set editor widget as central widget of main window
455  // and setup simulator stuff.
456  TemplateEditor *editor = core->editor();
457  TemplateSimulator *simulator = core->simulator();
458 
459  // Clear previous editor if any.
460  while (m_centralLayout->count() > 0) {
461  QLayoutItem *item = m_centralLayout->itemAt(0);
462 
463  item->widget()->deleteLater();
464  m_centralLayout->removeItem(item);
465 
466  delete item;
467  }
468 
469  // Set editor part.
470  m_centralLayout->layout()->addWidget(editor);
471  editor->setParent(m_centralArea);
472 
473  connect(editor, SIGNAL(changed()), this, SLOT(onEditorChanged()));
474  connect(editor, SIGNAL(canGenerateChanged(bool,QString)), this, SLOT(onCanGenerateChanged(bool,QString)));
475  connect(simulator, SIGNAL(canGoBackChanged(bool)), m_ui->m_actionSimulatorGoBack, SLOT(setEnabled(bool)));
476 
477  // Set simulator part.
478  m_simulatorWindow->setActiveSimulation(simulator);
479 
480  // Now, new template editor is set and simulator is set. Launch the template.
481  core->launch();
482 }
483 
484 void FormMain::onAboutToQuit() {
485  // Save all necessary things before application exits.
486  saveSizeAndPosition();
487 }
488 
489 void FormMain::onSimulatorWindowClosed() {
490  m_ui->m_actionViewSimulatorWindow->setChecked(false);
491 }
492 
493 void FormMain::switchSimulatorWindow(bool show) {
494  if (show) {
495  m_simulatorWindow->show();
496  }
497  else {
498  m_simulatorWindow->close();
499  }
500 }
501 
502 void FormMain::showSimulator() {
503  if (!m_ui->m_actionViewSimulatorWindow->isChecked()) {
504  m_ui->m_actionViewSimulatorWindow->setChecked(true);
505  }
506 }
507 
508 void FormMain::showSettings() {
509  QPointer<FormSettings> form_pointer = new FormSettings(this);
510  form_pointer.data()->exec();
511  delete form_pointer.data();
512 }
513 
514 void FormMain::showAbout() {
515  QPointer<FormAbout> form_about = new FormAbout(this);
516  form_about.data()->exec();
517  delete form_about.data();
518 }
519 
520 void FormMain::showUpdates() {
521  QPointer<FormUpdate> form_update = new FormUpdate(this);
522  form_update.data()->exec();
523  delete form_update.data();
524 }
525 
526 void FormMain::showHelp(bool enable_do_not_show_again_option) {
527  QPointer<FormHelp> form_help = new FormHelp(enable_do_not_show_again_option, this);
528  form_help.data()->exec();
529  delete form_help.data();
530 }
531 
532 void FormMain::showUpdatesAfterBubbleClick() {
533  display();
534  showUpdates();
535 }
536 
537 void FormMain::switchVisibility(bool force_hide) {
538  if (force_hide || isVisible()) {
540  hide();
541  m_simulatorWindow->hide();
542  }
543  else {
544  // Window gets minimized in single-window mode.
545  showMinimized();
546  }
547  }
548  else {
549  display();
550 
552  m_simulatorWindow->show();
553  }
554  }
555 }
556 
558  QMainWindow::show();
559 
560  if (m_firstTimeShow) {
561  m_firstTimeShow = false;
562 
563  if (qApp->settings()->value(APP_CFG_GUI, "show_help_startup", true).toBool()) {
564  showHelp(true);
565  }
566  }
567 }
568 
570  // Make sure window is not minimized.
571  setWindowState(windowState() & ~Qt::WindowMinimized);
572 
573  // Display the window and make sure it is raised on top.
574  show();
575  activateWindow();
576  raise();
577 
578  // Raise alert event. Check the documentation for more info on this.
579  Application::alert(this);
580 }
581 
582 void FormMain::openSaveProjectDialog() {
583  if (qApp->templateManager()->activeCore()->assignedFile().isEmpty()) {
584  // This project was not saved/loaded before, se we need to use "Save as..."
585  // feature.
586  openSaveProjectAsDialog();
587  }
588  else {
589  if (qApp->templateManager()->saveCurrentProject()) {
590  // Everything saved OK.
591  m_ui->m_actionSaveProject->setEnabled(false);
592  setWindowTitle(m_normalTitle);
593  }
594  else {
595  // TODO:
596  }
597  }
598 }
599 
600 void FormMain::openSaveProjectAsDialog() {
601  QString selected_file = QFileDialog::getSaveFileName(this,
602  tr("Select destination file for the project"),
603  qApp->templateManager()->activeCore()->assignedFile(),
604  tr("BuildmLearn Toolkit projects (*.buildmlearn)"),
605  0);
606 
607  if (!selected_file.isEmpty()) {
608  if (qApp->templateManager()->saveCurrentProjectAs(selected_file)) {
609  // Everything saved OK.
610  m_ui->m_actionSaveProject->setEnabled(false);
611  setWindowTitle(m_normalTitle);
612  }
613  else {
614  // TODO:
615  }
616  }
617 }
618 
619 void FormMain::openLoadProjectDialog() {
620  if (!saveUnsavedProject()) {
621  return;
622  }
623 
624  QString selected_file = QFileDialog::getOpenFileName(this,
625  tr("Select destination file for the project"),
626  QDir::homePath(),
627  tr("BuildmLearn Toolkit projects (*.buildmlearn)"),
628  0);
629 
630  if (selected_file.isEmpty()) {
631  return;
632  }
633 
634  if (qApp->templateManager()->loadProject(selected_file)) {
635  m_ui->m_actionSaveProjectAs->setEnabled(true);
636  m_ui->m_actionSaveProject->setEnabled(false);
637  }
638 }
639 
641  if (!saveUnsavedProject()) {
642  return;
643  }
644 
645  QPointer<FormNewProject> form_new_project = new FormNewProject(qApp->templateManager(), this);
646  TemplateEntryPoint *entry_point = form_new_project.data()->startNewTemplate();
647 
648  delete form_new_project.data();
649 
650  if (entry_point != NULL) {
651  // User selected proper template to start with.
652  // Load the template.
653  qApp->templateManager()->startNewProject(entry_point);
654  }
655 }
656 
658  if (qApp->templateManager()->activeCore() != NULL) {
659  qApp->templateManager()->generator()->generateMobileApplication(qApp->templateManager()->activeCore());
660  }
661  else {
662  QMessageBox::warning(this,
663  tr("Cannot generate application"),
664  tr("No project is opened, thus, cannot generate application."));
665  }
666 }
667 
669  QPointer<FormUploadBundle> form_pointer = new FormUploadBundle(this);
670  form_pointer.data()->exec();
671 
672  if (form_pointer.data()->uploadStatus() == StoreFactory::Success) {
673  // Successfully uploaded, show message.
674  CustomMessageBox::show(this, QMessageBox::Information,
675  tr("Application uploaded"),
676  tr("Your application was successfully submitted. It would be reviewed and published to the BuildmLearn Store. You would receive email notification regarding this."));
677  }
678 
679  delete form_pointer.data();
680 }
681 
683  if (qApp->templateManager()->activeCore() != NULL) {
684  if (qApp->templateManager()->activeCore()->editor()->isDirty()) {
685  QMessageBox::StandardButton decision = CustomMessageBox::show(this,
686  QMessageBox::Warning,
687  tr("Unsaved work"),
688  tr("There is unsaved project. You might want to save your current project, unless you do not mind losing your unsaved work."),
689  tr("Do you want to save your unsaved project before proceeding?"), QString(),
690  QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel,
691  QMessageBox::Yes);
692 
693  switch (decision) {
694  case QMessageBox::Yes:
695  openSaveProjectDialog();
696  return true;
697 
698  case QMessageBox::No:
699  return true;
700 
701  case QMessageBox::Cancel:
702  default:
703  return false;
704  }
705  }
706  }
707 
708  return true;
709 }
710 
711 void FormMain::closeEvent(QCloseEvent *e) {
712  if (!qApp->isClosing()) {
713  if (!saveUnsavedProject()) {
714  e->ignore();
715  return;
716  }
717  }
718 
720  qApp->trayIcon()->hide();
721  }
722 
723  e->accept();
724  qApp->quit();
725 }
726 
727 void FormMain::moveEvent(QMoveEvent *e) {
728  e->accept();
729  emit moved();
730 }
731 
732 void FormMain::resizeEvent(QResizeEvent *e) {
733  e->accept();
734  emit resized();
735 }
void setActiveSimulation(TemplateSimulator *simulation)
Sets new active simulation widget.
Dialog for showing update details.
Definition: formupdate.h:51
void generateMobileApplication()
Generates mobile APK application from currently active project.
Definition: formmain.cpp:657
void switchVisibility(bool force_hide=false)
Switches visibility of main window.
Definition: formmain.cpp:537
void moved()
Emitted when window is moved.
virtual QString generationStatusDescription()
Access to description of current state.
Separate window which contains active simulator.
Definition: formsimulator.h:19
virtual TemplateEditor * editor() const
Access to editor widget of the template.
Definition: templatecore.h:84
Form for displaying and editting settings.
Definition: formsettings.h:52
Main application window.
Definition: formmain.h:53
bool isVisibleOnStartup() const
Indicates whether simulator window should be shown when application launches.
Definition: formsimulator.h:45
void show()
Displays simulator window.
bool isSticked() const
Indicates whether simulator window is sticked to main window or not.
Definition: formsimulator.h:39
virtual TemplateSimulator * simulator() const
Access to simulator widget of the template.
Definition: templatecore.h:90
static void iconify(QDialogButtonBox *button_box)
Performs icon replacements for given button box.
void resizeEvent(QResizeEvent *e)
Executed when window is resized.
Definition: formmain.cpp:732
void moveEvent(QMoveEvent *e)
Executed when window is moved.
Definition: formmain.cpp:727
void uploadMobileApplicationToStore()
Displays dialog for uploading applications to store.
Definition: formmain.cpp:668
Represents the editor of the template.
void openNewProjectDialog()
Opens "New project" dialog.
Definition: formmain.cpp:640
Form for uploading applications to BuildmLearn Store.
void resized()
Emitted when window is resized.
virtual bool canGenerateApplications()
Specifies if template can generate applications or not.
void setValue(const QString &section, const QString &key, const QVariant &value)
Sets new value into settings.
Definition: settings.h:74
Custom message boxes.
virtual void launch()
Called after this template is fully loaded in toolkit.
void show()
Displays window.
Definition: formmain.cpp:557
Icon theme manipulator and provider.
Definition: iconfactory.h:47
void display()
Displays the window.
Definition: formmain.cpp:569
Application-wide settings mechanism.
Definition: settings.h:40
bool saveUnsavedProject()
Performs necessary steps to save active project if there is unsaved work.
Definition: formmain.cpp:682
static bool isSystemTrayAvailable()
Indicates whether tray icon is supported.
static QMessageBox::StandardButton show(QWidget *parent, QMessageBox::Icon icon, const QString &title, const QString &text, const QString &informative_text=QString(), const QString &detailed_text=QString(), QMessageBox::StandardButtons buttons=QMessageBox::Ok, QMessageBox::StandardButton default_button=QMessageBox::Ok)
Displays custom message box.
Form for displaying "about" information.
Definition: formabout.h:46
The entry point for a template.
QString assignedFile() const
Access to assigned XML "bundle" file.
FormMain(QWidget *parent=0)
Constructor.
Definition: formmain.cpp:63
QVariant value(const QString &section, const QString &key, const QVariant &default_value=QVariant())
Getter/setter for settings values.
Definition: settings.h:64
Dialog for creating new projects.
void closeEvent(QCloseEvent *e)
Executed when main application window is closed.
Definition: formmain.cpp:711
QList< QAction * > allActions()
Access to all actions provided by this window.
Definition: formmain.cpp:130
Form for displaying application help.
Definition: formhelp.h:46
void loadState()
Loads size & position for the window from settings.
The core class container for single template.
Definition: templatecore.h:43
GenerationResult
Possible results of generation of bundle data.
Definition: templatecore.h:48
void saveState()
Saves size & position for the window into settings.
QIcon fromTheme(const QString &name)
Returns icon from active theme.
Definition: iconfactory.h:58
static IconFactory * instance()
Singleton getter.
Definition: iconfactory.cpp:48
Base widget which represents simulator of the template.