NCL Composer  0.1.5
 All Classes Functions Variables Pages
ComposerMainWindow.cpp
1 /* Copyright (c) 2011 Telemidia/PUC-Rio.
2  * All rights reserved. This program and the accompanying materials
3  * are made available under the terms of the Eclipse Public License v1.0
4  * which accompanies this distribution, and is available at
5  * http://www.eclipse.org/legal/epl-v10.html
6  *
7  * Contributors:
8  * Telemidia/PUC-Rio - initial API and implementation
9  */
10 #include "ComposerMainWindow.h"
11 #include "ui_ComposerMainWindow.h"
12 
13 #include <QPixmap>
14 #include <QCloseEvent>
15 #include <QDialogButtonBox>
16 #include <QToolBar>
17 #include <QToolButton>
18 #include <QApplication>
19 
20 #include <QRegExp>
21 
22 #include <QDesktopServices>
23 
24 #include "GeneralPreferences.h"
25 
26 #include "NewProjectWizard.h"
27 
28 #ifdef USE_MDI
29 #include <QMdiArea>
30 #endif
31 
32 // #define SHOW_PROFILES
33 namespace composer {
34 namespace gui {
35 
36 const int autoSaveInterval = 1 * 60 * 1000; //ms
37 
39  : QMainWindow(parent),
40  ui(new Ui::ComposerMainWindow),
41  allDocksMutex(QMutex::Recursive),
42  localGingaProcess(this)
43 {
44  ui->setupUi(this);
45 
46  // Local Ginga Run
47  connect(&localGingaProcess, SIGNAL(finished(int)),
48  this, SLOT(runHasFinished()));
49 
50  // Remote Ginga Run
51 #ifdef WITH_LIBSSH2
52  runRemoteGingaVMAction.moveToThread(&runRemoteGingaVMThread);
53 
54  connect(&runRemoteGingaVMThread, SIGNAL(started()),
55  &runRemoteGingaVMAction, SLOT(runCurrentProject()));
56 
57  connect(&runRemoteGingaVMAction, SIGNAL(finished()),
58  &runRemoteGingaVMThread, SLOT(quit()));
59 
60  connect(&runRemoteGingaVMThread, SIGNAL(finished()),
61  this, SLOT(runHasFinished()));
62 
63  connect(&runRemoteGingaVMThread, SIGNAL(terminated()),
64  this, SLOT(runHasFinished()));
65 #endif
66 
67 }
68 
69 void ComposerMainWindow::init(const QApplication &app)
70 {
71  /* The following code could be in another function */
72  QPixmap mPix(":/mainwindow/nclcomposer-splash");
73  QSplashScreen splash(mPix);
74  splash.setMask(mPix.mask());
75  splash.showMessage(tr("Loading NCL Composer..."), Qt::AlignRight, Qt::gray);
76 
77  //splash.blockSignals(true);
78  splash.show();
79  app.processEvents();
80 
81  splash.showMessage(tr("Starting GUI..."), Qt::AlignRight, Qt::gray);
82 
83  initGUI();
84  app.processEvents();
85 
86  splash.showMessage(tr("Starting Modules and Plugins..."), Qt::AlignRight,
87  Qt::gray);
88  initModules();
89  app.processEvents();
90 
91 #ifdef WITH_LIBSSH2
92  SimpleSSHClient::init(); // Initializes the libssh2 library
93 #endif
94 
95  autoSaveTimer = new QTimer(this);
96  connect(autoSaveTimer, SIGNAL(timeout()),
97  this, SLOT(autoSaveCurrentProjects()));
98 
99  autoSaveTimer->start(autoSaveInterval);
100 
101  splash.showMessage(tr("Reloading last session..."), Qt::AlignRight,
102  Qt::gray);
103  readSettings();
104  app.processEvents();
105 
106  splash.finish(this);
107  connect(&app, SIGNAL(focusChanged(QWidget *, QWidget *)),
108  this, SLOT(focusChanged(QWidget *, QWidget *)),
109  Qt::DirectConnection);
110 
111  show();
112 }
113 
114 ComposerMainWindow::~ComposerMainWindow()
115 {
116  delete ui;
117  delete menu_Perspective;
118 #ifdef WITH_LIBSSH2
120 #endif
121 }
122 
123 void ComposerMainWindow::initModules()
124 {
125  PluginControl *pgControl = PluginControl::getInstance();
126  LanguageControl *lgControl = LanguageControl::getInstance();
127  ProjectControl *projectControl = ProjectControl::getInstance();
128 
129  connect(pgControl,SIGNAL(notifyError(QString)),
130  SLOT(errorDialog(QString)));
131 
132  connect(pgControl,SIGNAL(addPluginWidgetToWindow(IPluginFactory*,
133  IPlugin*, Project*, int)),
134  SLOT(addPluginWidget(IPluginFactory*, IPlugin*, Project*, int)));
135 
136  connect(lgControl,SIGNAL(notifyError(QString)),
137  SLOT(errorDialog(QString)));
138 
139  connect(projectControl, SIGNAL(notifyError(QString)),
140  SLOT(errorDialog(QString)));
141 
142  connect(projectControl,SIGNAL(projectAlreadyOpen(QString)),
143  SLOT(onOpenProjectTab(QString)));
144 
145  connect(projectControl, SIGNAL(startOpenProject(QString)),
146  this, SLOT(startOpenProject(QString)));
147 
148  connect(projectControl, SIGNAL(endOpenProject(QString)), this,
149  SLOT(endOpenProject(QString)));
150 
151  connect(projectControl,SIGNAL(endOpenProject(QString)),
152  SLOT(addToRecentProjects(QString)));
153 
154  //connect(projectControl, SIGNAL(endOpenProject(QString)),
155  // welcomeWidget, SLOT(addToRecentProjects(QString)));
156 
157  connect(welcomeWidget, SIGNAL(userPressedRecentProject(QString)),
158  this, SLOT(userPressedRecentProject(QString)));
159 
160  connect(projectControl,SIGNAL(projectAlreadyOpen(QString)),
161  SLOT(onOpenProjectTab(QString)));
162 
163  connect(projectControl, SIGNAL(dirtyProject(QString, bool)),
164  this, SLOT(setProjectDirty(QString, bool)));
165 
166  readExtensions();
167 }
168 
169 void ComposerMainWindow::readExtensions()
170 {
171  GlobalSettings settings;
172 
173  settings.beginGroup("extensions");
174  extensions_paths.clear();
175 
176  //Remember: The dafault paths are been added in main.cpp
177  if (settings.contains("path"))
178  extensions_paths << settings.value("path").toStringList();
179 
180  extensions_paths.removeDuplicates(); // Remove duplicate paths
181 
182  // add all the paths to LibraryPath, i.e., plugins are allowed to install
183  // dll dependencies in the extensions path.
184  for(int i = 0; i < extensions_paths.size(); i++)
185  {
186  qDebug() << "Adding library " << extensions_paths.at(i);
187  QApplication::addLibraryPath(extensions_paths.at(i) + "/");
188  }
189 
190  // foreach path where extensions can be installed, try to load profiles.
191  for(int i = 0; i < extensions_paths.size(); i++)
192  {
193  LanguageControl::getInstance()->loadProfiles(extensions_paths.at(i));
194  }
195 
196  // foreach path where extensions can be installed, try to load plugins.
197  for(int i = 0; i < extensions_paths.size(); i++)
198  {
199  PluginControl::getInstance()->loadPlugins(extensions_paths.at(i));
200  }
201  settings.endGroup();
202 
203  preferences->addPreferencePage(new GeneralPreferences());
204 
205  /* Load the preferences page */
206  preferences->addPreferencePage(new RunGingaConfig());
207 
208  // preferences->addPreferencePage(new ImportBasePreferences());
209 
210  /* Load PreferencesPages from Plugins */
211  QList<IPluginFactory*> list =
212  PluginControl::getInstance()->getLoadedPlugins();
213 
214  IPluginFactory *currentFactory;
215  foreach(currentFactory, list)
216  {
217  preferences->addPreferencePage(currentFactory);
218  }
219 }
220 
221 QString ComposerMainWindow::promptChooseExtDirectory()
222 {
223  QMessageBox mBox;
224 
225  mBox.setText(tr("The Extension Directory is not set"));
226  mBox.setInformativeText(tr("Do you want to try the default"
227  "directory (%1)?").arg(QDir::homePath()));
228  mBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
229  mBox.setDefaultButton(QMessageBox::Yes);
230  mBox.setIcon(QMessageBox::Question);
231  if (mBox.exec() == QMessageBox::No)
232  {
233  QString dirName = QFileDialog::getExistingDirectory(this,
234  tr("Select Directory"),
235  getLastFileDialogPath(),
236  QFileDialog::ShowDirsOnly);
237  return dirName;
238  } else {
239  return "";
240  }
241 }
242 
243 void ComposerMainWindow::readSettings()
244 {
245  GlobalSettings settings;
246 
247  settings.beginGroup("mainwindow");
248  restoreGeometry(settings.value("geometry").toByteArray());
249  restoreState(settings.value("windowState").toByteArray());
250  settings.endGroup();
251 
252  QApplication::processEvents();
253 
254  settings.beginGroup("openfiles");
255  QStringList openfiles = settings.value("openfiles").toStringList();
256  settings.endGroup();
257 
258  openProjects(openfiles);
259 }
260 
261 void ComposerMainWindow::openProjects(const QStringList &projects)
262 {
263  qDebug() << "Openning files:" << projects;
264  for(int i = 0; i < projects.size(); i++)
265  {
266  QString src = projects.at(i);
267 #ifdef WIN32
268  src = src.replace(QDir::separator(), "/");
269 #endif
270 
271  QFile file(src);
272  bool openCurrentFile = true;
273 
274  if(!file.exists())
275  {
276  int resp =
277  QMessageBox::question(this,
278  tr("File does not exists anymore."),
279  tr("The File %1 does not exists, but "
280  "the last time you have closed NCL"
281  " Composer this files was open. "
282  "Do you want to create this file "
283  "again?").arg(src),
284  QMessageBox::Yes | QMessageBox::No,
285  QMessageBox::No);
286 
287  if(resp != QMessageBox::Yes) openCurrentFile = false;
288  }
289 
290  if (openCurrentFile)
291  {
293 
294  ProjectControl::getInstance()->launchProject(src);
295  }
296  }
297 
298  /* Update Recent Projects on Menu */
299  GlobalSettings settings;
300  QStringList recentProjects = settings.value("recentprojects").toStringList();
301  updateRecentProjectsMenu(recentProjects);
302  welcomeWidget->updateRecentProjects(recentProjects);
303 }
304 
305 void ComposerMainWindow::initGUI()
306 {
307 #ifndef Q_WS_MAC
308  setWindowIcon(QIcon(":/mainwindow/icon"));
309 #endif
310  setWindowTitle(tr("NCL Composer"));
311  tabProjects = new QTabWidget(0);
312 
313  ui->frame->layout()->addWidget(tabProjects);
314 
315  // tabProjects->setMovable(true);
316  tabProjects->setTabsClosable(true);
317 
318  /* tbLanguageDropList = new QToolButton(this);
319  tbLanguageDropList->setIcon(QIcon(":/mainwindow/language"));
320  tbLanguageDropList->setToolTip(tr("Change your current language"));
321  tbLanguageDropList->setPopupMode(QToolButton::InstantPopup); */
322 
323  tbPerspectiveDropList = new QToolButton(this);
324  tbPerspectiveDropList->setIcon(QIcon(":/mainwindow/perspective"));
325  tbPerspectiveDropList->setToolTip(tr("Change your current perspective"));
326  tbPerspectiveDropList->setPopupMode(QToolButton::InstantPopup);
327 
328  connect( tabProjects, SIGNAL(tabCloseRequested(int)),
329  this, SLOT(tabClosed(int)), Qt::DirectConnection);
330 
331  connect(tabProjects, SIGNAL(currentChanged(int)),
332  this, SLOT(currentTabChanged(int)));
333 
334 // createStatusBar();
335  createActions();
336  createMenus();
337 // createLanguageMenu();
338  createAboutPlugins();
339 
340  preferences = new PreferencesDialog(this);
341  perspectiveManager = new PerspectiveManager(this);
342  pluginDetailsDialog = new PluginDetailsDialog(aboutPluginsDialog);
343 
344  connect(ui->action_RunNCL, SIGNAL(triggered()), this, SLOT(runNCL()));
345  connect(ui->action_StopNCL, SIGNAL(triggered()), this, SLOT(stopNCL()));
346 
347  ui->action_RunNCL->setEnabled(true);
348 
349 // UNDO/REDO
350  // connect(ui->action_Undo, SIGNAL(triggered()), this, SLOT(undo()));
351  // connect(ui->action_Redo, SIGNAL(triggered()), this, SLOT(redo()));
352 
353  welcomeWidget = new WelcomeWidget(this);
354  tabProjects->addTab(welcomeWidget, tr("Welcome"));
355  tabProjects->setTabIcon(0, QIcon());
356 
357  connect(welcomeWidget, SIGNAL(userPressedOpenProject()),
358  this, SLOT(openProject()));
359 
360  connect(welcomeWidget, SIGNAL(userPressedNewProject()),
361  this, SLOT(launchProjectWizard()));
362 
363  connect(welcomeWidget, SIGNAL(userPressedSeeInstalledPlugins()),
364  this, SLOT(aboutPlugins()));
365 
366 
367  //Task Progress Bar
368 
369 #ifdef WITH_LIBSSH2
370  taskProgressBar = new QProgressDialog(this);
371  taskProgressBar->setWindowTitle(tr("Copy content to Ginga VM."));
372  taskProgressBar->setModal(true);
373 
374  // start taskProgressBar
375  connect(&runRemoteGingaVMAction, SIGNAL(startTask()),
376  taskProgressBar, SLOT(show()));
377 
378  connect(&runRemoteGingaVMAction, SIGNAL(taskDescription(QString)),
379  taskProgressBar, SLOT(setLabelText(QString)));
380 
381  connect(&runRemoteGingaVMAction, SIGNAL(taskMaximumValue(int)),
382  taskProgressBar, SLOT(setMaximum(int)));
383 
384  connect(&runRemoteGingaVMAction, SIGNAL(taskValue(int)),
385  taskProgressBar, SLOT(setValue(int)));
386 
387  connect(&runRemoteGingaVMAction, SIGNAL(copyFinished()),
388  taskProgressBar, SLOT(hide()));
389 
390  connect(&runRemoteGingaVMAction, SIGNAL(finished()),
391  taskProgressBar, SLOT(hide()));
392 
393  connect(taskProgressBar, SIGNAL(canceled()),
394  &runRemoteGingaVMAction, SLOT(stopExecution()),
395  Qt::DirectConnection);
396 
397  disconnect(taskProgressBar, SIGNAL(canceled()),
398  taskProgressBar, SLOT(cancel()));
399 
400  connect(&runRemoteGingaVMAction, SIGNAL(finished()),
401  taskProgressBar, SLOT(hide()));
402 
403 // This shows the taskBar inside the toolBar. In the future, this can
404 // taskProgressBarAction = ui->toolBar->insertWidget(ui->action_Save,
405 // taskProgressBar);
406 // taskProgressBarAction->setVisible(false);
407 #endif
408 
409 }
410 
411 void ComposerMainWindow::keyPressEvent(QKeyEvent *event)
412 {
413  if(event->modifiers() == Qt::ControlModifier && event->key() == Qt::Key_Z)
414  {
415  undo();
416  event->accept();
417  }
418  else if(event->modifiers() == Qt::ControlModifier &&
419  event->key() == Qt::Key_Y)
420  {
421  redo();
422  event->accept();
423  }
424 }
425 
427  Project *project, int n)
428 {
429  QMainWindow *w;
430  QString location = project->getLocation();
431  QString projectId = project->getAttribute("id");
432 
433 #ifdef USE_MDI
434  QMdiArea *mdiArea;
435 #endif
436  if (projectsWidgets.contains(location))
437  {
438  w = projectsWidgets[location];
439 #ifdef USE_MDI
440  mdiArea = (QMdiArea *)w->centralWidget();
441  mdiArea->setBackground(QBrush(QColor("#FFFFFF")));
442 #endif
443  } else {
444  w = new QMainWindow(tabProjects);
445 #ifdef USE_MDI
446  mdiArea = new QMdiArea;
447  mdiArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
448  mdiArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
449  w->setCentralWidget(mdiArea);
450 #else
451  w->setDockNestingEnabled(true);
452  w->setTabPosition(Qt::AllDockWidgetAreas, QTabWidget::West);
453 #endif
454  int index = tabProjects->addTab(w, projectId);
455  updateTabWithProject(index, location);
456  projectsWidgets[location] = w;
457  }
458  QWidget *pW = plugin->getWidget();
459 
460 #ifdef USE_MDI
461  mdiArea->addSubWindow(pW);
462  pW->setWindowModified(true);
463  pW->setWindowTitle(projectId + " - " + fac->name());
464  pW->show();
465  pW->setObjectName(fac->id());
466 #else
467  ClickableQDockWidget *dock = new ClickableQDockWidget(fac->name());
468  dock->setProperty("project", location);
469 
470  dock->setAllowedAreas(Qt::AllDockWidgetAreas);
471  dock->setFeatures(QDockWidget::AllDockWidgetFeatures);
472 
473  connect(dock, SIGNAL(clicked()), pW, SLOT(setFocus()));
474  pW->setFocusPolicy(Qt::StrongFocus);
475 
476  QFrame *borderFrame = new QFrame();
477  borderFrame->setFrameShape(QFrame::NoFrame);
478  borderFrame->setFrameShadow(QFrame::Plain);
479 
480  QVBoxLayout *layoutBorderFrame = new QVBoxLayout();
481  layoutBorderFrame->setMargin(0);
482  layoutBorderFrame->addWidget(pW);
483  borderFrame->setLayout(layoutBorderFrame);
484 
485  dock->setWidget(borderFrame);
486  dock->setObjectName(fac->id());
487 
488  dock->setMinimumSize(0, 0);
489  tabProjects->setCurrentWidget(w);
490 
491  if(firstDock.contains(location)) {
492  w->tabifyDockWidget(firstDock[location], dock);
493  }
494  else
495  {
496  w->addDockWidget(Qt::LeftDockWidgetArea, dock);
497  firstDock[location] = dock;
498  }
499 
500  QFrame *titleBar = new QFrame();
501  titleBar->setContentsMargins(0,0,0,0);
502 
503  QLabel *titleLabel = new QLabel(fac->name());
504  titleLabel->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Minimum);
505 
506  QHBoxLayout *layout = new QHBoxLayout(titleBar);
507  layout->setMargin(0);
508  layout->setSpacing(0);
509 
510  layout->addWidget(titleLabel);
511 
512  titleBar->setStyleSheet(" ");
513 
514  dock->setTitleBarWidget(titleBar);
515  allDocksMutex.lock();
516  allDocks.insert(0, dock);
517  allDocksMutex.unlock();
518 
519  QPushButton *refresh = new QPushButton(titleBar);
520  refresh->setIcon(QIcon(":/mainwindow/refreshplugin"));
521  refresh->setToolTip(tr("Reload View Model"));
522  addButtonToDockTitleBar(titleBar, refresh);
523  connect(refresh, SIGNAL(pressed()), plugin, SLOT(updateFromModel()));
524 
525  QPushButton *hide = new QPushButton(titleBar);
526  connect(hide, SIGNAL(pressed()), dock, SLOT(close()));
527  hide->setIcon(QIcon(":/mainwindow/closeplugin"));
528  hide->setToolTip(tr("Hide View"));
529 
530  addButtonToDockTitleBar(titleBar, hide);
531 
532  // dock->installEventFilter(this);
533  updateDockStyle(dock, false);
534 #endif
535 }
536 
537 void ComposerMainWindow::updateDockStyle(QDockWidget *dock, bool selected)
538 {
539  qWarning() << "ComposerMainWindows::updateDockStyle ( " << dock << selected << ")";
540 
541  QList <QTabBar*> tabBars = this->findChildren <QTabBar *>();
542 
543  // \todo We can improve this foreach
544  foreach (QTabBar *tabBar, tabBars)
545  {
546  for(int index = 0; index < tabBar->count(); index++)
547  {
548  QVariant tmp = tabBar->tabData(index);
549  QDockWidget * dockWidget = reinterpret_cast<QDockWidget *>(tmp.toULongLong());
550  if(dockWidget == dock)
551  {
552  if(!tabBar->property("activePlugin").isValid())
553  {
554  tabBar->setProperty("activePlugin", "false");
555  tabBar->setStyleSheet(styleSheet());
556  }
557 
558  bool activePlugin = tabBar->property("activePlugin").toBool();
559  if(selected)
560  {
561  if(!activePlugin)
562  {
563  tabBar->setProperty("activePlugin", "true");
564  tabBar->setStyleSheet(styleSheet());
565  }
566  }
567  else
568  {
569  if(activePlugin)
570  {
571  tabBar->setProperty("activePlugin", "false");
572  tabBar->setStyleSheet(styleSheet());
573  }
574  }
575  }
576  }
577  }
578 
579  QFrame *titleBar = (QFrame*) dock->titleBarWidget();
580  if(!titleBar->property("activePluginTitleBar").isValid())
581  {
582  titleBar->setProperty("activePluginTitleBar", "false");
583  dock->setProperty("activePluginBorder", "false");
584  dock->setStyleSheet(styleSheet());
585  }
586 
587  bool activePluginTitleBar = titleBar->property("activePluginTitleBar").toBool();
588  if(!selected)
589  {
590  if(activePluginTitleBar)
591  {
592  titleBar->setProperty("activePluginTitleBar", "false");
593  dock->setProperty("activePluginBorder", "false");
594  dock->setStyleSheet(styleSheet());
595  }
596  }
597  else
598  {
599  if(!activePluginTitleBar)
600  {
601  titleBar->setProperty("activePluginTitleBar", "true");
602  dock->setProperty("activePluginBorder", "true");
603  dock->setStyleSheet(styleSheet());
604  }
605  }
606 }
607 
608 void ComposerMainWindow::addButtonToDockTitleBar(QFrame *titleBar,
609  QPushButton *button)
610 {
611  button->setIconSize(QSize(18, 18));
612 
613  titleBar->layout()->addWidget(button);
614 }
615 
616 void ComposerMainWindow::tabClosed(int index)
617 {
618  if(index == 0)
619  return; // Do nothing
620 
621  QString location = tabProjects->tabToolTip(index);
622  Project *project = ProjectControl::getInstance()->getOpenProject(location);
623  qDebug() << location << project;
624  if(project != NULL && project->isDirty())
625  {
626  int ret = QMessageBox::warning(this, project->getAttribute("id"),
627  tr("The project has been modified.\n"
628  "Do you want to save your changes?"),
629  QMessageBox::Yes | QMessageBox::Default,
630  QMessageBox::No,
631  QMessageBox::Cancel|QMessageBox::Escape);
632  if (ret == QMessageBox::Yes)
634  else if (ret == QMessageBox::Cancel)
635  return;
636  }
637 
638  ProjectControl::getInstance()->closeProject(location);
639 
640  //Remove temporary file
641  removeTemporaryFile(location);
642 
643  if(projectsWidgets.contains(location))
644  {
645  QMainWindow *w = projectsWidgets[location];
646 
647  allDocksMutex.lock();
648  QList <QDockWidget*> newAllDocks;
649  //Remove from allDocks
650  for( int i = 0; i < allDocks.size(); i++)
651  {
652  if(allDocks.at(i)->property("project") == location)
653  {
654  // It will not be part of the new allDock widget!
655  // allDocks.removeAt(i);
656  }
657  else
658  newAllDocks.push_back(allDocks.at(i));
659  }
660  allDocks = newAllDocks;
661  allDocksMutex.unlock();
662 
663  projectsWidgets.remove(location);
664  firstDock.remove(location);
665 
666  // Delete QMainWindow
667  if (w)
668  {
669  w->close();
670  w->deleteLater();
671  }
672  }
673  qWarning() << "ComposerMainWindow::tabClosed ends";
674 }
675 
676 void ComposerMainWindow::closeCurrentTab()
677 {
678  if(tabProjects->currentIndex())
679  {
680  int currentIndex = tabProjects->currentIndex();
681  tabClosed(currentIndex);
682  }
683 }
684 void ComposerMainWindow::closeAllFiles()
685 {
686  while(tabProjects->count() > 1)
687  {
688  tabClosed(1);
689  tabProjects->removeTab(1);
690  }
691 }
692 
694 {
695  if (!projectsWidgets.contains(location)) return;
696  QMainWindow *w = projectsWidgets[location];
697  tabProjects->setCurrentWidget(w);
698 }
699 
700 void ComposerMainWindow::createMenus()
701 {
702 #ifdef Q_WS_MAC
703  ui->menubar->setNativeMenuBar(true);
704 #endif
705 
706  ui->menu_Edit->addAction(editPreferencesAct);
707 
708  menuBar()->addSeparator();
709 
710  connect( ui->menu_Window, SIGNAL(aboutToShow()),
711  this, SLOT(updateViewMenu()));
712 
713  connect(ui->action_CloseProject, SIGNAL(triggered()),
714  this, SLOT(closeCurrentTab()));
715 
716  connect(ui->action_CloseAll, SIGNAL(triggered()),
717  this, SLOT(closeAllFiles()));
718 
719  connect( ui->action_Save, SIGNAL(triggered()),
720  this, SLOT(saveCurrentProject()));
721 
722  connect( ui->action_SaveAs, SIGNAL(triggered()),
723  this, SLOT(saveAsCurrentProject()));
724 
725  connect ( ui->action_NewProject, SIGNAL(triggered()),
726  this, SLOT(launchProjectWizard()));
727 
728  /* menu_Language = new QMenu(0);
729  tbLanguageDropList->setMenu(menu_Language);
730  ui->toolBar->addWidget(tbLanguageDropList);*/
731 
732  menu_Perspective = new QMenu(0);
733  // assing menu_Perspective to tbPerspectiveDropList
734  tbPerspectiveDropList->setMenu(menu_Perspective);
735  ui->toolBar->addWidget(tbPerspectiveDropList);
736 
737  // tabProjects->setCornerWidget(tbPerspectiveDropList, Qt::TopRightCorner);
738  tabProjects->setCornerWidget(ui->toolBar, Qt::TopRightCorner);
739  // tabProjects->setCornerWidget(ui->menu_Window, Qt::TopLeftCorner);
740 
741 // updateMenuLanguages();
742  updateMenuPerspectives();
743 }
744 
745 void ComposerMainWindow::createAboutPlugins()
746 {
747  aboutPluginsDialog = new QDialog(this);
748  aboutPluginsDialog->setWindowTitle(tr("Installed Plugins"));
749 
750 #ifdef SHOW_PROFILES
751  profilesExt = new QListWidget(aboutPluginsDialog);
752  profilesExt->setAlternatingRowColors(true);
753 #endif
754 
755  /* This should be a new Widget and change some code for there */
756  pluginsExt = new QTreeWidget(aboutPluginsDialog);
757  pluginsExt->setAlternatingRowColors(true);
758 
759  connect(pluginsExt, SIGNAL(itemSelectionChanged()),
760  this, SLOT(selectedAboutCurrentPluginFactory()));
761 
762  QStringList header;
763  header << tr("Name") << tr("Load") << tr("Version") << tr("Vendor");
764  pluginsExt->setHeaderLabels(header);
765 
766  QDialogButtonBox *bOk = new QDialogButtonBox(QDialogButtonBox::Ok |
767  QDialogButtonBox::Close,
768  Qt::Horizontal,
769  aboutPluginsDialog);
770 
771  detailsButton = bOk->button(QDialogButtonBox::Ok);
772  detailsButton->setText(tr("Details"));
773  detailsButton->setIcon(QIcon());
774  detailsButton->setEnabled(false);
775 
776  connect(bOk, SIGNAL(rejected()), aboutPluginsDialog, SLOT(close()));
777 
778  connect( detailsButton, SIGNAL(pressed()), this, SLOT(showPluginDetails()) );
779 
780  QGridLayout *gLayout = new QGridLayout(aboutPluginsDialog);
781  gLayout->addWidget(new QLabel(tr("The <b>Composer</b> is an IDE for"
782  " Declarative Multimedia languages."),
783  aboutPluginsDialog));
784 
785 #ifdef SHOW_PROFILES
786  gLayout->addWidget(new QLabel(tr("<b>Installed Language Profiles</b>"),
787  aboutPluginsDialog));
788  gLayout->addWidget(profilesExt);
789 #endif
790  gLayout->addWidget(new QLabel(tr("<b>Installed Plug-ins</b>")));
791  gLayout->addWidget(pluginsExt);
792  gLayout->addWidget(bOk);
793  aboutPluginsDialog->setLayout(gLayout);
794 
795  aboutPluginsDialog->setModal(true);
796 
797  connect(aboutPluginsDialog, SIGNAL(finished(int)),
798  this, SLOT(saveLoadPluginData(int)));
799 }
800 
801 void ComposerMainWindow::about()
802 {
803  AboutDialog dialog(this);
804  dialog.exec();
805 }
806 
807 void ComposerMainWindow::aboutPlugins()
808 {
809  QList<IPluginFactory*>::iterator it;
810  QList<IPluginFactory*> pList = PluginControl::getInstance()->
811  getLoadedPlugins();
812  pluginsExt->clear();
813 
814  //search for categories
815  QTreeWidgetItem *treeWidgetItem;
816  QMap <QString, QTreeWidgetItem*> categories;
817  for (it = pList.begin(); it != pList.end(); it++) {
818  IPluginFactory *pF = *it;
819  QString category = pF->category();
820  if(!categories.contains(category)){
821  treeWidgetItem = new QTreeWidgetItem(pluginsExt);
822  categories.insert(category, treeWidgetItem);
823  treeWidgetItem->setText(0, category);
824  treeWidgetItem->setTextColor(0, QColor("#0000FF"));
825  }
826  }
827 
828  treeWidgetItem2plFactory.clear();
829  for (it = pList.begin(); it != pList.end(); it++) {
830  IPluginFactory *pF = *it;
831  treeWidgetItem = new QTreeWidgetItem(categories.value(pF->category()));
832  treeWidgetItem2plFactory.insert(treeWidgetItem, pF);
833 
834  treeWidgetItem->setText(0, pF->name());
835 
836  // Set checked (or not) based on the settings
837  GlobalSettings settings;
838  settings.beginGroup("loadPlugins");
839  if(!settings.contains(pF->id()) || settings.value(pF->id()).toBool())
840  treeWidgetItem->setCheckState(1, Qt::Checked);
841  else
842  treeWidgetItem->setCheckState(1, Qt::Unchecked);
843 
844  settings.endGroup();
845  treeWidgetItem->setText(2, pF->version());
846  treeWidgetItem->setText(3, pF->vendor());
847  }
848 
849  pluginsExt->expandAll();
850 
851  pluginsExt->setColumnWidth(0, 150);
852  pluginsExt->resizeColumnToContents(1);
853  pluginsExt->resizeColumnToContents(2);
854  pluginsExt->resizeColumnToContents(3);
855 
856  /* PROFILE LANGUAGE */
857 #ifdef SHOW_PROFILES
858  QList<ILanguageProfile*>::iterator itL;
859  QList<ILanguageProfile*> lList = LanguageControl::getInstance()->
860  getLoadedProfiles();
861  profilesExt->clear();
862 
863  for(itL = lList.begin(); itL != lList.end(); itL++)
864  {
865  ILanguageProfile *lg = *itL;
866  profilesExt->addItem(new QListWidgetItem(lg->getProfileName()));
867  }
868 #endif
869 
870  detailsButton->setEnabled(false);
871  aboutPluginsDialog->show();
872 }
873 
874 void ComposerMainWindow::errorDialog(QString message)
875 {
876  //QMessageBox::warning(this,tr("Error!"),message);
877  qWarning() << message;
878 }
879 
880 void ComposerMainWindow::createActions() {
881 
882  connect(ui->action_About, SIGNAL(triggered()), this, SLOT(about()));
883 
884  connect( ui->action_AboutPlugins, SIGNAL(triggered()),
885  this, SLOT(aboutPlugins()));
886 
887  fullScreenViewAct = new QAction(tr("&FullScreen"),this);
888  fullScreenViewAct->setShortcut(tr("F11"));
889 
890  connect(fullScreenViewAct,SIGNAL(triggered()),this,
891  SLOT(showCurrentWidgetFullScreen()));
892 
893  editPreferencesAct = new QAction(tr("&Preferences"), this);
894  editPreferencesAct->setStatusTip(tr("Edit preferences"));
895  connect (editPreferencesAct, SIGNAL(triggered()), this,
896  SLOT(showEditPreferencesDialog()));
897 
898  connect(ui->action_Preferences, SIGNAL(triggered()),
899  this, SLOT(showEditPreferencesDialog()));
900 
901  connect(ui->action_Exit, SIGNAL(triggered()), this, SLOT(close()));
902  saveCurrentPluginsLayoutAct = new QAction(tr("Save current perspective..."),
903  this);
904 
905  connect( saveCurrentPluginsLayoutAct, SIGNAL(triggered()),
906  this, SLOT(saveCurrentGeometryAsPerspective()));
907 
908  restorePluginsLayoutAct = new QAction(tr("Restore a perspective"), this);
909  connect(restorePluginsLayoutAct, SIGNAL(triggered()),
910  this, SLOT(restorePerspective()));
911 
912  QWidget* spacer = new QWidget();
913  spacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
914 
915  //Add a separator to the toolbar. All actions after preferences (including
916  // it will be aligned in the bottom.
917  ui->toolBar->insertWidget(ui->action_Preferences, spacer);
918 
919  connect (ui->action_OpenProject, SIGNAL(triggered()),
920  this, SLOT(openProject()));
921 
922  connect (ui->action_ImportFromExistingNCL, SIGNAL(triggered()),
923  this, SLOT(importFromDocument()));
924 
925  connect (ui->action_GoToClubeNCLWebsite, SIGNAL(triggered()),
926  this, SLOT(gotoNCLClubWebsite()));
927 
928  connect (ui->action_Help, SIGNAL(triggered()), this, SLOT(showHelp()));
929 }
930 
931 void ComposerMainWindow::createStatusBar()
932 {
933  statusBar()->showMessage(tr("Ready"));
934 }
935 
936 void ComposerMainWindow::showCurrentWidgetFullScreen()
937 {
938  tabProjects->addAction(fullScreenViewAct);
939 
940  if(!tabProjects->isFullScreen())
941  {
942  tabProjects->setWindowFlags(Qt::Window);
943  tabProjects->showFullScreen();
944  }
945  else
946  {
947  tabProjects->setParent(ui->frame, Qt::Widget);
948  tabProjects->show();
949  }
950 }
951 
952 void ComposerMainWindow::updateViewMenu()
953 {
954  ui->menu_Window->clear();
955 
956  ui->menu_Window->addAction(fullScreenViewAct);
957 
958  ui->menu_Window->addSeparator();
959 
960  //Update menu Views.
961  ui->menu_Views->clear();
962  ui->menu_Window->addMenu(ui->menu_Views);
963  if(tabProjects->count()) //see if there is any open document
964  {
965  QString location = tabProjects->tabToolTip(tabProjects->currentIndex());
966 
967  for(int i = 0; i < allDocks.size(); i++)
968  {
969  if(allDocks.at(i)->property("project").toString() == location)
970  ui->menu_Views->addAction(allDocks.at(i)->toggleViewAction());
971  }
972  }
973 
974  if(ui->menu_Views->isEmpty())
975  ui->menu_Views->setEnabled(false);
976  else
977  ui->menu_Views->setEnabled(true);
978 
979  ui->menu_Window->addSeparator();
980  ui->menu_Window->addAction(saveCurrentPluginsLayoutAct);
981  ui->menu_Window->addAction(restorePluginsLayoutAct);
982 
983 }
984 
985 void ComposerMainWindow::closeEvent(QCloseEvent *event)
986 {
987 
989  for(int index = 1; index < tabProjects->count(); index++)
990  {
991  QString location = tabProjects->tabToolTip(index);
992  Project *project = ProjectControl::getInstance()->getOpenProject(location);
993 
994  qDebug() << location << project;
995  if(project != NULL && project->isDirty())
996  {
997  tabProjects->setCurrentIndex(index);
998  int ret = QMessageBox::warning(this, project->getAttribute("id"),
999  tr("The project %1 has been modified.\n"
1000  "Do you want to save your changes?").
1001  arg(location),
1002  QMessageBox::Yes | QMessageBox::Default,
1003  QMessageBox::No,
1004  QMessageBox::Cancel|QMessageBox::Escape);
1005  if (ret == QMessageBox::Yes)
1007  else if (ret == QMessageBox::Cancel)
1008  {
1009  event->ignore();
1010  return;
1011  }
1012  }
1013  }
1014 
1015  GlobalSettings settings;
1016  settings.beginGroup("extensions");
1017  settings.setValue("path", extensions_paths);
1018  settings.endGroup();
1019 
1020  settings.beginGroup("mainwindow");
1021  settings.setValue("geometry", saveGeometry());
1022  settings.setValue("windowState", saveState());
1023  settings.endGroup();
1024 
1025  QStringList openfiles;
1026  QString key;
1027  foreach (key, projectsWidgets.keys())
1028  openfiles << key;
1029 
1030  settings.beginGroup("openfiles");
1031  if(openfiles.size())
1032  {
1033  settings.setValue("openfiles", openfiles);
1034  }
1035  else {
1036  /* If there aren't any openfile, remove this settings, otherwise it will
1037  try to load the current path */
1038  settings.remove("openfiles");
1039  }
1040  settings.endGroup();
1041  settings.sync();
1042  cleanUp();
1043 
1044  qApp->quit(); // close the application
1045 }
1046 
1047 void ComposerMainWindow::cleanUp()
1048 {
1049  LanguageControl::releaseInstance();
1050  ProjectControl::releaseInstance();
1051  PluginControl::releaseInstance();
1052 }
1053 
1054 void ComposerMainWindow::showEditPreferencesDialog()
1055 {
1056  preferences->show();
1057 }
1058 
1059 void ComposerMainWindow::startOpenProject(QString project)
1060 {
1061  (void) project;
1062 
1063  this->setCursor(QCursor(Qt::WaitCursor));
1064  update();
1065 }
1066 
1067 void ComposerMainWindow::endOpenProject(QString project)
1068 {
1069  this->setCursor(QCursor(Qt::ArrowCursor));
1070 
1071  GlobalSettings settings;
1072 
1073  if(settings.contains("default_perspective"))
1074  {
1075  QString defaultPerspective =
1076  settings.value("default_perspective").toString();
1077 
1078  // Ok! There is a default perspective, so use it
1079  restorePerspective(defaultPerspective);
1080 
1081  update();
1082  }
1083  else
1084  {
1085  // There is no a default perspective, so let use the system default.
1086  QMainWindow *window = projectsWidgets[project];
1087  QList <QDockWidget *> docks = window->findChildren <QDockWidget* >(QRegExp("br.*"));
1088  QMap <QString, QDockWidget*> dockByPluginId;
1089  QList <QDockWidget *> leftDocks, rightDocks, bottomDocks;
1090  for(int i = 0; i < docks.size(); i++)
1091  {
1092  dockByPluginId[docks[i]->objectName()] = docks[i];
1093  if(docks[i]->objectName() == "br.puc-rio.telemidia.OutlineView" ||
1094  docks[i]->objectName() == "br.puc-rio.telemidia.PropertiesView")
1095  {
1096  leftDocks.append(docks[i]);
1097  }
1098  else if(docks[i]->objectName() == "br.puc-rio.telemidia.DebugConsole" ||
1099  docks[i]->objectName() == "br.ufma.deinf.laws.validator")
1100  {
1101  bottomDocks.append(docks[i]);
1102  }
1103  else
1104  rightDocks.append(docks[i]);
1105  }
1106 
1107  for(int i = leftDocks.size()-1; i >= 0; i--)
1108  {
1109  leftDocks[i]->widget()->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
1110  leftDocks[i]->widget()->setMinimumWidth(200);
1111  // leftDocks[i]->widget()->setMaximumWidth(400);
1112  if(!i)
1113  window->addDockWidget(Qt::LeftDockWidgetArea, leftDocks[i]);
1114  else
1115  window->addDockWidget(Qt::LeftDockWidgetArea, leftDocks[i], Qt::Vertical);
1116 
1117  window->adjustSize();
1118  }
1119 
1120  for(int i = 0; i < rightDocks.size(); i++)
1121  {
1122  rightDocks[i]->widget()->setSizePolicy(QSizePolicy::Expanding,
1123  QSizePolicy::Expanding);
1124 
1125  if(!i)
1126  window->addDockWidget(Qt::RightDockWidgetArea, rightDocks[i]);
1127  else
1128  window->tabifyDockWidget(rightDocks[0], rightDocks[i]);
1129  }
1130 
1131  for(int i = 0; i < bottomDocks.size(); i++)
1132  {
1133  bottomDocks[i]->widget()->setSizePolicy(QSizePolicy::MinimumExpanding,
1134  QSizePolicy::MinimumExpanding);
1135  bottomDocks[i]->widget()->setMaximumHeight(200);
1136  bottomDocks[i]->widget()->setMinimumHeight(100);
1137  if(!i)
1138  window->addDockWidget(Qt::RightDockWidgetArea, bottomDocks[i], Qt::Vertical);
1139  else
1140  window->tabifyDockWidget(bottomDocks[0], bottomDocks[i]);
1141  }
1142  }
1143 
1144  this->updateGeometry();
1145 }
1146 
1148 {
1149  int index = tabProjects->currentIndex();
1150  bool saveAlsoNCLDocument = true;
1151 
1152  if(index != 0)
1153  {
1154  QString location = tabProjects->tabToolTip(index);
1155  Project *project = ProjectControl::getInstance()->getOpenProject(location);
1156 
1157  PluginControl::getInstance()->savePluginsData(project);
1158  ProjectControl::getInstance()->saveProject(location);
1159  ui->action_Save->setEnabled(false);
1160 
1161  if(saveAlsoNCLDocument)
1162  {
1163  QString nclfilepath = location.mid(0, location.lastIndexOf(".")) + ".ncl";
1164  QFile file(nclfilepath);
1165  if(file.open(QFile::WriteOnly | QIODevice::Truncate))
1166  {
1167  // Write FILE!!
1168  if(project->getChildren().size())
1169  file.write(project->getChildren().at(0)->toString(0, false).toAscii());
1170 
1171  file.close();
1172  }
1173  }
1174  }
1175  else
1176  {
1177  QMessageBox box(QMessageBox::Warning,
1178  tr("Information"),
1179  tr("There aren't a project to be saved."),
1180  QMessageBox::Ok
1181  );
1182  box.exec();
1183  }
1184 }
1185 
1187 {
1188  int index = tabProjects->currentIndex();
1189  bool saveAlsoNCLDocument = true;
1190 
1191  if(index != 0)
1192  {
1193  QString location = tabProjects->tabToolTip(index);
1194 
1195  QString destFileName = QFileDialog::getSaveFileName(
1196  this,
1197  tr("Save as NCL Composer Project"),
1198  getLastFileDialogPath(),
1199  tr("NCL Composer Projects (*.cpr)") );
1200 
1201  if(!destFileName.isNull() && !destFileName.isEmpty())
1202  {
1203  updateLastFileDialogPath(destFileName);
1204 
1205  if(!destFileName.endsWith(".cpr"))
1206  destFileName = destFileName + ".cpr";
1207 
1208  /* Move the location of the current project to destFileName */
1209  ProjectControl::getInstance()->moveProject(location, destFileName);
1210 
1211  /* Get the project */
1212  Project *project =
1213  ProjectControl::getInstance()->getOpenProject(destFileName);
1214 
1215  PluginControl::getInstance()->savePluginsData(project);
1216  ProjectControl::getInstance()->saveProject(destFileName);
1217 
1218  /* Update Tab Text and Index */
1219  updateTabWithProject(index, destFileName);
1220 
1221  ui->action_Save->setEnabled(false);
1222 
1223  if(saveAlsoNCLDocument)
1224  {
1225  QString nclfilepath =
1226  location.mid(0, destFileName.lastIndexOf(".")) + ".ncl";
1227 
1228  QFile file(nclfilepath);
1229  if(file.open(QFile::WriteOnly | QIODevice::Truncate))
1230  {
1231  // Write FILE!!
1232  if(project->getChildren().size())
1233  file.write(project->getChildren().at(0)->toString(0, false).toAscii());
1234 
1235  file.close();
1236  }
1237  }
1238 
1239  addToRecentProjects(destFileName);
1240  }
1241  }
1242  else
1243  {
1244  QMessageBox box(QMessageBox::Warning,
1245  tr("Information"),
1246  tr("There aren't a project to be saved."),
1247  QMessageBox::Ok
1248  );
1249  box.exec();
1250  }
1251 }
1252 
1253 void ComposerMainWindow::saveCurrentGeometryAsPerspective()
1254 {
1255  if(tabProjects->count()) // If there is a document open
1256  {
1257  perspectiveManager->setBehavior(PERSPEC_SAVE);
1258  if(perspectiveManager->exec())
1259  {
1260  savePerspective(perspectiveManager->getSelectedName());
1261  saveDefaultPerspective(perspectiveManager->getDefaultPerspective());
1262  }
1263  }
1264  else
1265  {
1266  QMessageBox box(QMessageBox::Warning,
1267  tr("Information"),
1268  tr("There aren't a layout open to be saved."),
1269  QMessageBox::Ok
1270  );
1271  box.exec();
1272  }
1273  /* Update the elements in MENU PERSPECTIVE*/
1274  updateMenuPerspectives();
1275 }
1276 
1277 void ComposerMainWindow::restorePerspective()
1278 {
1279  perspectiveManager->setBehavior(PERSPEC_LOAD);
1280  if(perspectiveManager->exec())
1281  {
1282  restorePerspective(perspectiveManager->getSelectedName());
1283  }
1284 
1285  /* Update the elements in MENU PERSPECTIVE*/
1286  updateMenuPerspectives();
1287 }
1288 
1289 void ComposerMainWindow::savePerspective(QString layoutName)
1290 {
1291  if(tabProjects->count()) //see if there is any open document
1292  {
1293  QString location = tabProjects->tabToolTip(tabProjects->currentIndex());
1294 
1295  QMainWindow *window = projectsWidgets[location];
1296  QSettings settings(QSettings::IniFormat,
1297  QSettings::UserScope,
1298  "telemidia",
1299  "composer");
1300 
1301  settings.beginGroup("pluginslayout");
1302  settings.setValue(layoutName, window->saveState(0));
1303  settings.endGroup();
1304  }
1305 }
1306 
1307 void ComposerMainWindow::saveDefaultPerspective(QString defaultPerspectiveName)
1308 {
1309  GlobalSettings settings;
1310  settings.setValue("default_perspective", defaultPerspectiveName);
1311 }
1312 
1313 void ComposerMainWindow::restorePerspective(QString layoutName)
1314 {
1315  if(tabProjects->count()) //see if there is any open project
1316  {
1317  QString location = tabProjects->tabToolTip(
1318  tabProjects->currentIndex());
1319 
1320  QMainWindow *window = projectsWidgets[location];
1321  GlobalSettings settings;
1322  settings.beginGroup("pluginslayout");
1323 #ifndef USE_MDI
1324  window->restoreState(settings.value(layoutName).toByteArray());
1325 #endif
1326  settings.endGroup();
1327  }
1328 }
1329 
1330 void ComposerMainWindow::runNCL()
1331 {
1332  // check if there is other instance already running
1333  if(localGingaProcess.state() == QProcess::Running
1334 #ifdef WITH_LIBSSH2
1335  || runRemoteGingaVMThread.isRunning()
1336 #endif
1337  )
1338  {
1339  QMessageBox::StandardButton reply;
1340  reply = QMessageBox::warning(NULL, tr("Warning!"),
1341  tr("You already have an NCL application "
1342  "running. Please, stop it before you start "
1343  "a new one."),
1344  QMessageBox::Ok);
1345  return;
1346  }
1347 
1348  ui->action_RunNCL->setEnabled(false);
1349 
1350  // There is no other instance running, so let's run
1351  bool runRemote = false;
1352  GlobalSettings settings;
1353  settings.beginGroup("runginga");
1354  if(settings.contains("run_remote") && settings.value("run_remote").toBool())
1355  runRemote = true;
1356  else
1357  runRemote = false;
1358  settings.endGroup();
1359 
1360  if(runRemote)
1361  runOnRemoteGingaVM();
1362  else
1363  runOnLocalGinga();
1364 
1365  ui->action_StopNCL->setEnabled(true);
1366 }
1367 
1368 void ComposerMainWindow::runOnLocalGinga()
1369 {
1370  GlobalSettings settings;
1371  QString command, args;
1372  settings.beginGroup("runginga");
1373  command = settings.value("local_ginga_cmd").toString();
1374  args = settings.value("local_ginga_args").toString();
1375  settings.endGroup();
1376 
1377  // TODO: Ask to Save current project before send it to Ginga VM.
1378  QStringList args_list;
1379  QString location = tabProjects->tabToolTip(tabProjects->currentIndex());
1380 
1381  if(location.isEmpty())
1382  {
1383  QMessageBox::StandardButton reply;
1384  reply = QMessageBox::warning(this, tr("Warning!"),
1385  tr("There aren't a current NCL project."),
1386  QMessageBox::Ok);
1387  return;
1388  }
1389 
1390  Project *project = ProjectControl::getInstance()->getOpenProject(location);
1391  QString nclpath = location.mid(0, location.lastIndexOf("/")) + "/tmp.ncl";
1392  qDebug() << "Running NCL File: " << nclpath;
1393 
1394  QFile file(nclpath);
1395  if(file.open(QFile::WriteOnly | QIODevice::Truncate))
1396  {
1397  /* Write FILE!! */
1398  if(project->getChildren().size())
1399  file.write(project->getChildren().at(0)->toString(0, false).toAscii());
1400 
1401  file.close();
1402 
1403  /* PARAMETERS */
1404  //\todo Other parameters
1405  args.replace("${nclpath}", nclpath);
1406  args_list << args.split("\n");
1407  /* RUNNING GINGA */
1408  localGingaProcess.start(command, args_list);
1409  QByteArray result = localGingaProcess.readAll();
1410  }
1411  else
1412  {
1413  qWarning() << "Error trying to running NCL. Could not create : "
1414  << nclpath << " !";
1415  }
1416 }
1417 
1418 void ComposerMainWindow::runOnRemoteGingaVM()
1419 {
1420 #ifdef WITH_LIBSSH2
1421  int currentTab = tabProjects->currentIndex();
1422  if(currentTab != 0)
1423  {
1424  //Disable a future Run (while the current one does not finish)!!
1425  ui->action_RunNCL->setEnabled(false);
1426 
1427  QString location = tabProjects->tabToolTip(currentTab);
1428  Project *currentProject = ProjectControl::getInstance()->
1429  getOpenProject(location);
1430 
1431  if(currentProject->isDirty())
1432  {
1433  /*QMessageBox::StandardButton reply;
1434  reply = QMessageBox::warning(this, tr("Warning!"),
1435  tr("Your document is not saved. "
1436  "Do you want to save it now?"),
1437  QMessageBox::Yes, QMessageBox::No);*/
1438 
1439  int reply;
1440  reply = QMessageBox::warning(NULL, tr("Warning!"),
1441  tr("Your document is not saved."
1442  "Do you want to save it now?"),
1443  QMessageBox::Yes, QMessageBox::No);
1444 
1445  if(reply == QMessageBox::Yes)
1446  {
1447  // save the current project before send it to Ginga VM
1449  }
1450  }
1451 
1452  runRemoteGingaVMAction.setCurrentProject(currentProject);
1453 
1454  runRemoteGingaVMThread.start();
1455  }
1456  else
1457  {
1458  // There aren't a current project.
1459  QMessageBox::StandardButton reply;
1460  reply = QMessageBox::warning(NULL, tr("Warning!"),
1461  tr("There aren't a current NCL project."),
1462  QMessageBox::Ok);
1463  }
1464 
1465 #else
1466  QMessageBox::StandardButton reply;
1467  reply = QMessageBox::warning(NULL, tr("Warning!"),
1468  tr("Your NCL Composer was not build with Remote "
1469  "Run support."),
1470  QMessageBox::Ok);
1471 #endif
1472 }
1473 
1474 void ComposerMainWindow::stopNCL()
1475 {
1476  if(localGingaProcess.state() == QProcess::Running)
1477  localGingaProcess.close();
1478 
1479 #ifdef WITH_LIBSSH2
1480  if(runRemoteGingaVMThread.isRunning())
1481  stopRemoteGingaVMAction.stopRunningApplication();
1482 #endif
1483 
1484  updateRunActions();
1485 }
1486 
1487 bool ComposerMainWindow::isRunningNCL()
1488 {
1489  // check if there is other instance already running
1490  if(localGingaProcess.state() == QProcess::Running
1491 #ifdef WITH_LIBSSH2
1492  || runRemoteGingaVMThread.isRunning()
1493 #endif
1494  )
1495  {
1496  return true;
1497  }
1498  return false;
1499 }
1500 
1501 void ComposerMainWindow::updateRunActions()
1502 {
1503  if(isRunningNCL())
1504  {
1505  ui->action_RunNCL->setEnabled(false);
1506  ui->action_StopNCL->setEnabled(true);
1507  }
1508  else
1509  {
1510  ui->action_RunNCL->setEnabled(true);
1511  ui->action_StopNCL->setEnabled(false);
1512  }
1513 }
1514 
1515 void ComposerMainWindow::runHasFinished()
1516 {
1517  qDebug() << "ComposerMainWindow::runHasFinished()";
1518  updateRunActions();
1519 }
1520 
1521 void ComposerMainWindow::launchProjectWizard()
1522 {
1523  NewProjectWizard wizard (this);
1524  wizard.setModal(true);
1525  wizard.exec();
1526 
1527  if(wizard.result() == QWizard::Accepted)
1528  {
1529  QString filename = wizard.getProjectFullPath();
1530 
1531  filename.replace("\\", "/"); //Force the use of "/"
1532 
1533  if( !filename.isNull() && !filename.isEmpty())
1534  {
1535 
1536  updateLastFileDialogPath(filename);
1537 
1538  if(!filename.endsWith(".cpr"))
1539  filename = filename + QString(".cpr");
1540 
1541  QFileInfo info(filename);
1542  // If the file already exist ask the user if it want to overwrite it
1543  if(info.exists())
1544  {
1545  if(QMessageBox::question(this, tr("File already exists!"),
1546  tr("The file \"%1\" already exists. Do you want overwrite it?").arg(filename),
1547  QMessageBox::Yes|QMessageBox::No, QMessageBox::No) == QMessageBox::No)
1548  return; // Do not overwrite!
1549 
1550  QFile::remove(filename); // Remove the OLD file (only if the user accept it)
1551  }
1552 
1553  // We dont need to check this, when creating a new project
1554  // checkTemporaryFileLastModified(filename);
1555 
1556 
1557  if(ProjectControl::getInstance()->launchProject(filename))
1558  {
1559  // After launch the project we will insert NCL, HEAD and BODY elements
1560  // by default
1561  Project *project = ProjectControl::getInstance()
1562  ->getOpenProject(filename);
1563 
1564  addDefaultStructureToProject( project,
1565  wizard.shouldCopyDefaultConnBase(),
1566  wizard.shouldCreateADefaultRegion());
1567  }
1568  else
1569  {
1570  // \todo a report to this problem (we should track the error message).
1571  }
1572  }
1573  }
1574 }
1575 
1576 void ComposerMainWindow::addDefaultStructureToProject(Project *project,
1577  bool shouldCopyDefaultConnBase,
1578  bool shouldCreateADefaultRegion,
1579  bool save)
1580 {
1581  const QString defaultNCLID = "myNCLDocID";
1582  const QString defaultBodyID = "myBodyID";
1583  const QString defaultConnBaseID = "connBaseId";
1584  const QString defaultRegionBaseID = "regionBase0";
1585  const QString defaultRegionID = "region0";
1586 
1587  QMap <QString, QString> nclAttrs, headAttrs, bodyAttrs;
1588  nclAttrs.insert("id", defaultNCLID);
1589  nclAttrs.insert("xmlns", "http://www.ncl.org.br/NCL3.0/EDTVProfile");
1590 
1591  Entity *nclEntity;
1592  MessageControl *msgControl = PluginControl::getInstance()
1593  ->getMessageControl(project);
1594  msgControl->anonymousAddEntity("ncl", project->getUniqueId(), nclAttrs);
1595 
1596  nclEntity = project->getEntitiesbyType("ncl").first();
1597 
1598  if(nclEntity != NULL)
1599  {
1600  QString nclEntityId = nclEntity->getUniqueId();
1601  msgControl->anonymousAddEntity("head", nclEntityId, headAttrs);
1602 
1603  bodyAttrs.insert("id", defaultBodyID);
1604  msgControl->anonymousAddEntity("body", nclEntityId, bodyAttrs);
1605  }
1606 
1607  // Copy the default connector
1608  if(shouldCopyDefaultConnBase)
1609  {
1610  GlobalSettings settings;
1611  settings.beginGroup("importBases");
1612  QString defaultConnBase =
1613  settings.value("default_conn_base").toString();
1614  settings.endGroup();
1615 
1616  qDebug() << "[GUI] DefaultConnBase " << defaultConnBase;
1617 
1618  QFileInfo defaultConnBaseInfo(defaultConnBase);
1619  if(defaultConnBaseInfo.exists())
1620  {
1621  QString filename = project->getLocation();
1622  QString newConnBase = filename. mid(0, filename.lastIndexOf("/")+1) +
1623  defaultConnBaseInfo.fileName();
1624 
1625  qDebug() << "[GUI] Copy " << defaultConnBase << " to "
1626  << newConnBase;
1627 
1628  //remove the file if it already exists
1629  if(QFile::exists(newConnBase))
1630  {
1631  QFile::remove(newConnBase);
1632  }
1633 
1634  //copy the defaultConnBase to the project dir
1635  if(QFile::copy(defaultConnBase, newConnBase))
1636  {
1637  //If everything is OK we import the new defaultConnBase to NCL
1638  // document.
1639 
1640  QMap <QString, QString> connBaseAttrs, importBaseAttrs;
1641  connBaseAttrs.insert("id", defaultConnBaseID);
1642  importBaseAttrs.insert("alias", "conn");
1643  importBaseAttrs.insert("documentURI",
1644  defaultConnBaseInfo.fileName());
1645 
1646  //add connectorBase element
1647  Entity *head = project->getEntitiesbyType("head").at(0);
1648  msgControl->anonymousAddEntity("connectorBase",
1649  head->getUniqueId(),
1650  connBaseAttrs);
1651 
1652  //add importBase element
1653  Entity *connectorBase =
1654  project->getEntitiesbyType("connectorBase").at(0);
1655  msgControl->anonymousAddEntity("importBase",
1656  connectorBase->getUniqueId(),
1657  importBaseAttrs);
1658  }
1659  else //error
1660  {
1661  QMessageBox::warning(this, tr("Error!"),
1662  tr("There was an error copying the default"
1663  "Connector Base. You will need to add a "
1664  "Connector Base by hand in your NCL "
1665  "code."),
1666  tr("Ok"));
1667  }
1668  }
1669  else //error
1670  {
1671  QMessageBox::warning(this, tr("Error!"),
1672  tr("The default Connector Base %1 does not "
1673  "exists").arg(defaultConnBase),
1674  tr("Ok"));
1675  }
1676  }
1677 
1678  if(shouldCreateADefaultRegion)
1679  {
1680  QMap <QString, QString> regionBaseAttrs, regionAttrs;
1681  QList<Entity*> regionBases = project->getEntitiesbyType("regionBase");
1682 
1683  // There is no regionBase, so lets create one
1684  if(!regionBases.size())
1685  {
1686  regionBaseAttrs.insert("id", defaultRegionBaseID);
1687  Entity *head = project->getEntitiesbyType("head").at(0);
1688  msgControl->anonymousAddEntity("regionBase",
1689  head->getUniqueId(),
1690  regionBaseAttrs);
1691  }
1692 
1693  //Now, its time to add the region itself
1694  Entity *regionBase = project->getEntitiesbyType("regionBase").at(0);
1695  regionAttrs.insert("id", defaultRegionID);
1696  regionAttrs.insert("top", "0");
1697  regionAttrs.insert("left", "0");
1698  regionAttrs.insert("width", "100%");
1699  regionAttrs.insert("height", "100%");
1700  regionAttrs.insert("zIndex", "1");
1701  msgControl->anonymousAddEntity("region",
1702  regionBase->getUniqueId(),
1703  regionAttrs);
1704  }
1705 
1706  if(shouldCreateADefaultRegion)
1707  {
1708 
1709  }
1710 
1711  if(save)
1712  saveCurrentProject(); //Save the just created basic file!
1713 }
1714 
1716 {
1717  QString filename = QFileDialog::getOpenFileName(this,
1718  tr("Open NCL Composer Project"),
1719  getLastFileDialogPath(),
1720  tr("NCL Composer Projects (*.cpr)"));
1721  if(filename != "")
1722  {
1723 #ifdef WIN32
1724  filename = filename.replace("\\", "/");
1725 #endif
1726 
1728 
1729  ProjectControl::getInstance()->launchProject(filename);
1730 
1731  updateLastFileDialogPath(filename);
1732  }
1733 }
1734 
1736 {
1737  QFileInfo temporaryFileInfo(filename + "~");
1738  QFileInfo fileInfo(filename);
1739 
1740  if(temporaryFileInfo.exists() &&
1741  temporaryFileInfo.lastModified() > fileInfo.lastModified())
1742  {
1743  bool replace = QMessageBox::question(this,
1744  tr("Temporary file is newer."),
1745  tr("There is a temporary file related to %1 that is"
1746  " newer. Do you want replace the %1 file with "
1747  " this temporary one?").arg(filename),
1748  QMessageBox::Yes | QMessageBox::No,
1749  QMessageBox::No);
1750 
1751  if(replace)
1752  {
1753  QFile file (filename + "~");
1754  if(!file.copy(filename))
1755  {
1756  QFile oldfile (filename);
1757  oldfile.remove();
1758  file.copy(filename);
1759  }
1760  }
1761  }
1762 }
1763 
1765 {
1766  QFile file(location + "~");
1767  return file.remove();
1768 }
1769 
1770 void ComposerMainWindow::updateLastFileDialogPath(QString filepath)
1771 {
1772  Utilities::updateLastFileDialogPath(filepath);
1773 }
1774 
1775 QString ComposerMainWindow::getLastFileDialogPath()
1776 {
1777  return Utilities::getLastFileDialogPath();
1778 }
1779 
1780 void ComposerMainWindow::importFromDocument()
1781 {
1782  QString docFilename = QFileDialog::getOpenFileName(
1783  this,
1784  tr("Choose the NCL file to be imported"),
1785  getLastFileDialogPath(),
1786  tr("NCL Documents (*.ncl)") );
1787 
1788  if(docFilename != "")
1789  {
1790  updateLastFileDialogPath(docFilename);
1791 
1792  QString projFilename = QFileDialog::getSaveFileName(
1793  this,
1794  tr("Choose the NCL Composer Project where the NCL document must be "
1795  "imported"),
1796  getLastFileDialogPath(),
1797  tr("NCL Composer Projects (*.cpr)") );
1798 
1799  //Create the file
1800  QFile f(projFilename);
1801  f.open(QIODevice::ReadWrite);
1802  f.close();
1803 
1804  if(projFilename != "")
1805  {
1806 #ifdef WIN32
1807  projFilename = projFilename.replace(QDir::separator(), "/");
1808 #endif
1809  ProjectControl::getInstance()->importFromDocument(docFilename,
1810  projFilename);
1811 
1812  updateLastFileDialogPath(projFilename);
1813  }
1814  }
1815 }
1816 
1817 void ComposerMainWindow::addToRecentProjects(QString projectUrl)
1818 {
1819  GlobalSettings settings;
1820  QStringList recentProjects = settings.value("recentProjects").toStringList();
1821 
1822  recentProjects.push_front(projectUrl);
1823  recentProjects.removeDuplicates();
1824 
1825  //MAXIMUM SIZE
1826  while(recentProjects.size() > this->maximumRecentProjectsSize)
1827  recentProjects.pop_back();
1828 
1829  settings.setValue("recentProjects", recentProjects);
1830 
1831  updateRecentProjectsMenu(recentProjects);
1832  welcomeWidget->updateRecentProjects(recentProjects);
1833 }
1834 
1835 void ComposerMainWindow::updateRecentProjectsMenu(QStringList &recentProjects)
1836 {
1837  ui->menu_Recent_Files->clear();
1838  if(recentProjects.size() == 0 )
1839  {
1840  QAction *act = ui->menu_Recent_Files->addAction(tr("empty"));
1841  act->setEnabled(false);
1842  }
1843  else /* There are at least one element in the recentProject list */
1844  {
1845  for(int i = 0; i < recentProjects.size(); i++)
1846  {
1847  QAction *act = ui->menu_Recent_Files->addAction(
1848  recentProjects.at(i));
1849  act->setData(recentProjects.at(i));
1850  connect(act, SIGNAL(triggered()), this, SLOT(userPressedRecentProject()));
1851  }
1852 
1853  ui->menu_Recent_Files->addSeparator();
1854  QAction *clearRecentProjects =
1855  ui->menu_Recent_Files->addAction(tr("Clear Recent Projects"));
1856 
1857  connect(clearRecentProjects, SIGNAL(triggered()),
1858  this, SLOT(clearRecentProjects()));
1859 
1860  }
1861 }
1862 
1863 void ComposerMainWindow::userPressedRecentProject(QString src)
1864 {
1865 #ifdef WIN32
1866  src = src.replace(QDir::separator(), "/");
1867 #endif
1868 
1869  QFile file(src);
1870  bool openCurrentFile = true, recreateFile = false;
1871  if(!file.exists())
1872  {
1873  int resp =
1874  QMessageBox::question(this,
1875  tr("File does not exists anymore."),
1876  tr("The File %1 does not exists anymore. "
1877  "Do you want to create this file "
1878  "again?").arg(src),
1879  QMessageBox::Yes | QMessageBox::No,
1880  QMessageBox::No);
1881 
1882  if(resp != QMessageBox::Yes)
1883  openCurrentFile = false;
1884  else
1885  recreateFile = true;
1886  }
1887 
1888  if(openCurrentFile)
1889  {
1891 
1892  ProjectControl::getInstance()->launchProject(src);
1893  if(recreateFile)
1894  {
1895  // Create the directory structure if it does not exist anymore
1896 
1897  QDir dir;
1898  bool ok = dir.mkpath(QFileInfo(src).absolutePath()); //this function creates the path, with all its necessary parents;
1899 
1900  if(!ok)
1901  {
1902  //error message, could not create the required directory structure!
1903  QMessageBox::critical(this, tr("Error!"), tr("Error creating directory structure"));
1904  return;
1905  }
1906 
1907  // \todo Ask for the import or not of the defaultConnBase.
1908  addDefaultStructureToProject(
1909  ProjectControl::getInstance()->getOpenProject(src),
1910  false,
1911  false,
1912  true);
1913  }
1914  }
1915 }
1916 
1917 void ComposerMainWindow::userPressedRecentProject()
1918 {
1919  QAction *action = qobject_cast<QAction *> (QObject::sender());
1920 
1921  QString src = action->data().toString();
1922 
1923  userPressedRecentProject(src);
1924 }
1925 
1926 void ComposerMainWindow::clearRecentProjects(void)
1927 {
1928  GlobalSettings settings;
1929 
1930  settings.remove("recentProjects");
1931  QStringList empty;
1932  updateRecentProjectsMenu(empty);
1933  welcomeWidget->updateRecentProjects(empty);
1934 }
1935 
1936 void ComposerMainWindow::selectedAboutCurrentPluginFactory()
1937 {
1938  QList<QTreeWidgetItem*> selectedPlugins = pluginsExt->selectedItems();
1939  if(selectedPlugins.size())
1940  {
1941  if(treeWidgetItem2plFactory.value(selectedPlugins.at(0)) != NULL)
1942  {
1943  pluginDetailsDialog->setCurrentPlugin(
1944  treeWidgetItem2plFactory.value(selectedPlugins.at(0)));
1945  detailsButton->setEnabled(true);
1946  }
1947  else
1948  detailsButton->setEnabled(false);
1949  }
1950 }
1951 
1952 void ComposerMainWindow::showPluginDetails()
1953 {
1954  pluginDetailsDialog->show();
1955 }
1956 
1957 void ComposerMainWindow::restorePerspectiveFromMenu()
1958 {
1959  QAction *action = qobject_cast<QAction*>(QObject::sender());
1960  restorePerspective(action->data().toString());
1961 }
1962 
1963 void ComposerMainWindow::updateMenuPerspectives()
1964 {
1965  GlobalSettings settings;
1966  settings.beginGroup("pluginslayout");
1967  QStringList keys = settings.allKeys();
1968  settings.endGroup();
1969 
1970  menu_Perspective->clear();
1971 
1972  for(int i = 0; i < keys.size(); i++)
1973  {
1974  QAction *act = menu_Perspective->addAction(keys.at(i),
1975  this,
1976  SLOT(restorePerspectiveFromMenu()));
1977  act->setData(keys[i]);
1978  }
1979 
1980  // Add Option to save current Perspective
1981  menu_Perspective->addSeparator();
1982  menu_Perspective->addAction(saveCurrentPluginsLayoutAct);
1983 }
1984 
1985 void ComposerMainWindow::updateMenuLanguages()
1986 {
1987  QStringList languages;
1988  languages << tr("English") << tr("Portugues (Brasil)");
1989 
1990  for(int i = 0; i < languages.size(); i++)
1991  {
1992  QAction *act = menu_Language->addAction(languages.at(i),
1993  this,
1994  SLOT(changeLanguageFromMenu()));
1995  act->setData(languages[i]);
1996  }
1997 }
1998 
1999 void ComposerMainWindow::currentTabChanged(int n)
2000 {
2001  if(n)
2002  {
2003  tbPerspectiveDropList->setEnabled(true);
2004  saveCurrentPluginsLayoutAct->setEnabled(true);
2005  restorePluginsLayoutAct->setEnabled(true);
2006  ui->action_CloseProject->setEnabled(true);
2007  ui->action_Save->setEnabled(true);
2008  ui->action_SaveAs->setEnabled(true);
2009 
2010  // \todo: This should check if there is already running application
2011  updateRunActions();
2012  }
2013  else
2014  {
2015  tbPerspectiveDropList->setEnabled(false);
2016  saveCurrentPluginsLayoutAct->setEnabled(false);
2017  restorePluginsLayoutAct->setEnabled(false);
2018  ui->action_CloseProject->setEnabled(false);
2019  ui->action_Save->setEnabled(false);
2020  ui->action_SaveAs->setEnabled(false);
2021  ui->action_RunNCL->setEnabled(false);
2022  ui->action_StopNCL->setEnabled(false);
2023  }
2024 }
2025 
2026 void ComposerMainWindow::focusChanged(QWidget *old, QWidget *now)
2027 {
2028  if(now == NULL)
2029  return; // Do nothing!!
2030 
2031  if(qApp->activeModalWidget() != NULL)
2032  return; // Do nothing!! (Wait for the popup to end)
2033 
2034  // qDebug() << "Locking allDocksMutex 1";
2035  allDocksMutex.lock();
2036  for(int i = 0; i < allDocks.size(); i++)
2037  {
2038  // if(old != NULL && allDocks.at(i)->isAncestorOf(old))
2039  updateDockStyle(allDocks.at(i), false);
2040  }
2041  allDocksMutex.unlock();
2042  // qDebug() << "Unlocked allDocksMutex 1";
2043 
2044  // qDebug() << "Locking allDocksMutex 2";
2045  allDocksMutex.lock();
2046 
2047  if(now != NULL)
2048  {
2049  for(int i = 0 ; i < allDocks.size(); i++)
2050  {
2051  bool isAncestor = false;
2052  QWidget *child = now;
2053 // qDebug() << "Start" << i << allDocks.size();
2054  while (child && child != this)
2055  {
2056 // qDebug() << "child pointer" << child;
2057 // qDebug() << child->metaObject()->className();
2058  if (child == allDocks.at(i))
2059  {
2060  isAncestor = true;
2061  break;
2062  }
2063  child = child->parentWidget();
2064  }
2065 // qDebug() << "End";
2066 
2067  if(isAncestor)
2068  updateDockStyle(allDocks.at(i), true);
2069  }
2070  }
2071  allDocksMutex.unlock();
2072 // qDebug() << "Unlocked allDocksMutex 2";
2073 }
2074 
2075 void ComposerMainWindow::setProjectDirty(QString location, bool isDirty)
2076 {
2077  QMainWindow *window = projectsWidgets[location];
2078  QString projectId =
2079  ProjectControl::getInstance()->
2080  getOpenProject(location)->getAttribute("id");
2081 
2082  int index = tabProjects->indexOf(window);
2083 
2084  ui->action_Save->setEnabled(true);
2085 
2086  if(index >= 0) {
2087  if(isDirty)
2088  tabProjects->setTabText(index, QString("*")+projectId);
2089  else
2090  tabProjects->setTabText(index, projectId);
2091  }
2092 }
2093 
2094 void ComposerMainWindow::undo()
2095 {
2096  int index = tabProjects->currentIndex();
2097 
2098  if(index != -1)
2099  {
2100  QString location = tabProjects->tabToolTip(index);
2101  Project *project = ProjectControl::getInstance()->getOpenProject(location);
2102  MessageControl *msgControl =
2103  PluginControl::getInstance()->getMessageControl(project);
2104  msgControl->undo();
2105  }
2106 }
2107 
2108 void ComposerMainWindow::redo()
2109 {
2110  int index = tabProjects->currentIndex();
2111 
2112  if(index != -1)
2113  {
2114  QString location = tabProjects->tabToolTip(index);
2115  Project *project = ProjectControl::getInstance()->getOpenProject(location);
2116  MessageControl *msgControl =
2117  PluginControl::getInstance()->getMessageControl(project);
2118  msgControl->redo();
2119  }
2120 
2121 }
2122 
2123 void ComposerMainWindow::gotoNCLClubWebsite()
2124 {
2125  QDesktopServices::openUrl(QUrl("http://club.ncl.org.br"));
2126 }
2127 
2129 {
2130  composerHelpWidget.show();
2131  return true;
2132 
2133  // Old implementation based on Assistant
2134  /*if (!proc)
2135  proc = new QProcess();
2136 
2137  if (proc->state() != QProcess::Running)
2138  {
2139  QString app = QLibraryInfo::location(QLibraryInfo::BinariesPath) +
2140  QDir::separator();
2141 #if !defined(Q_OS_MAC)
2142  app += QLatin1String("assistant");
2143 #else
2144  app += QLatin1String("Assistant.app/Contents/MacOS/Assistant");
2145 #endif
2146 
2147  QStringList args;
2148 // args << QLatin1String("-collectionFile")
2149 // << QLatin1String("help/composerhelp.qhc")
2150 // << QLatin1String("-enableRemoteControl");
2151 
2152  proc->start(app, args);
2153 
2154  if (!proc->waitForStarted()) {
2155  QMessageBox::critical(0, QObject::tr("Simple Text Viewer"),
2156  QObject::tr("Unable to launch Qt Assistant (%1)").arg(app));
2157  return false;
2158  }
2159  }
2160  return true; */
2161 }
2162 
2163 void ComposerMainWindow::autoSaveCurrentProjects()
2164 {
2165  for(int i = 1; i < tabProjects->count(); i++)
2166  {
2167  QString location = tabProjects->tabToolTip(i);
2168  Project *project = ProjectControl::getInstance()->getOpenProject(location);
2169  if(project->isDirty())
2170  {
2171  PluginControl::getInstance()->savePluginsData(project);
2172  ProjectControl::getInstance()->saveTemporaryProject(location);
2173  }
2174  }
2175 }
2176 
2177 // we create the menu entries dynamically, dependant on the existing translations
2178 void ComposerMainWindow::createLanguageMenu(void)
2179 {
2180  QActionGroup* langGroup = new QActionGroup(menu_Language);
2181  langGroup->setExclusive(true);
2182 
2183  connect(langGroup, SIGNAL(triggered(QAction *)), this, SLOT(slotLanguageChanged(QAction *)));
2184 
2185  // format systems language
2186  QString defaultLocale = QLocale::system().name(); // e.g. "de_DE"
2187  defaultLocale.truncate(defaultLocale.lastIndexOf('_')); // e.g. "de"
2188 
2189  m_langPath = QApplication::applicationDirPath();
2190  m_langPath.append("/languages");
2191  QDir dir(m_langPath);
2192  QStringList fileNames = dir.entryList(QStringList("composer_*.qm"));
2193 
2194  qDebug() << fileNames;
2195  for (int i = 0; i < fileNames.size(); ++i)
2196  {
2197  // get locale extracted by filename
2198  QString locale;
2199  locale = fileNames[i]; // "TranslationExample_de.qm"
2200  locale.truncate(locale.lastIndexOf('.')); // "TranslationExample_de"
2201  locale.remove(0, locale.indexOf('_') + 1); // "de"
2202 
2203  QString lang = QLocale::languageToString(QLocale(locale).language());
2204  QIcon ico(QString("%1/%2.png").arg(m_langPath).arg(locale));
2205 
2206  QAction *action = new QAction(ico, lang, this);
2207  action->setCheckable(true);
2208  action->setData(locale);
2209 
2210 // ui->menu_Language->addAction(action);
2211  menu_Language->addAction(action);
2212  langGroup->addAction(action);
2213 
2214  // set default translators and language checked
2215  if (defaultLocale == locale)
2216  {
2217  action->setChecked(true);
2218  }
2219  }
2220 }
2221 
2222 // Called every time, when a menu entry of the language menu is called
2224 {
2225  if(0 != action)
2226  {
2227  // load the language dependant on the action content
2228  loadLanguage(action->data().toString());
2229  setWindowIcon(action->icon());
2230  }
2231 }
2232 
2233 void ComposerMainWindow::switchTranslator(QTranslator& translator,
2234  const QString& filename)
2235 {
2236  // remove the old translator
2237  qApp->removeTranslator(&translator);
2238 
2239  // load the new translator
2240  if(translator.load(filename))
2241  qApp->installTranslator(&translator);
2242 }
2243 
2244 void ComposerMainWindow::loadLanguage(const QString& rLanguage)
2245 {
2246  qDebug() << rLanguage;
2247  if(m_currLang != rLanguage)
2248  {
2249  m_currLang = rLanguage;
2250  QLocale locale = QLocale(m_currLang);
2251  QLocale::setDefault(locale);
2252  QString languageName = QLocale::languageToString(locale.language());
2253  switchTranslator(m_translator,
2254  m_langPath + "/" + QString("composer_%1.qm").arg(rLanguage));
2255  switchTranslator(m_translatorQt, QString("qt_%1.qm").arg(rLanguage));
2256 
2257 // ui->statusBar->showMessage(tr("Current Language changed to %1").arg(languageName));
2258  }
2259 }
2260 
2262 {
2263  if(0 != event)
2264  {
2265  switch(event->type())
2266  {
2267  // this event is send if a translator is loaded
2268  case QEvent::LanguageChange:
2269  ui->retranslateUi(this);
2270  break;
2271  // this event is send, if the system, language changes
2272  case QEvent::LocaleChange:
2273  {
2274  QString locale = QLocale::system().name();
2275  locale.truncate(locale.lastIndexOf('_'));
2276  loadLanguage(locale);
2277  }
2278  break;
2279  default:
2280  break;
2281  }
2282  }
2283 
2284  QMainWindow::changeEvent(event);
2285 }
2286 
2287 void ComposerMainWindow::updateTabWithProject(int index, QString newLocation)
2288 {
2289  QString oldLocation = tabProjects->tabToolTip(index);
2290 
2291  if(oldLocation == newLocation) return; /* do nothing */
2292 
2293  /* Already had a project in this tab */
2294  if(!oldLocation.isNull() && !oldLocation.isEmpty())
2295  {
2296  // Update projectsWidgets
2297  if(projectsWidgets.contains(oldLocation))
2298  {
2299  projectsWidgets.insert(newLocation, projectsWidgets.value(oldLocation));
2300  projectsWidgets.remove(oldLocation);
2301  }
2302 
2303  //update firstDock
2304  if(firstDock.contains(oldLocation))
2305  {
2306  firstDock.insert(newLocation, firstDock.value(oldLocation));
2307  firstDock.remove(oldLocation);
2308 
2309  };
2310  }
2311 
2312  tabProjects->setTabToolTip(index, newLocation);
2313  Project *project = ProjectControl::getInstance()->getOpenProject(newLocation);
2314  if(project != NULL)
2315  {
2316  QString projectId = project->getAttribute("id");
2317  tabProjects->setTabText(index, projectId);
2318  }
2319 }
2320 
2322 {
2323  GlobalSettings settings;
2324  settings.beginGroup("loadPlugins");
2325  QTreeWidgetItem *item;
2326  qDebug() << treeWidgetItem2plFactory.keys();
2327  foreach(item, treeWidgetItem2plFactory.keys())
2328  {
2329  if(item->checkState(1))
2330  {
2331  settings.setValue(treeWidgetItem2plFactory.value(item)->id(), true);
2332  }
2333  else
2334  {
2335  qDebug() << treeWidgetItem2plFactory.value(item) << "2";
2336  settings.setValue(treeWidgetItem2plFactory.value(item)->id(), false);
2337  }
2338  }
2339  settings.endGroup();
2340 }
2341 
2342 void ComposerMainWindow::on_actionReport_Bug_triggered()
2343 {
2344  QDesktopServices::openUrl(QUrl("http://composer.telemidia.puc-rio.br/en/contact"));
2345 }
2346 
2347 } } //end namespace