kame.cpp
1 /***************************************************************************
2  Copyright (C) 2002-2015 Kentaro Kitagawa
3  kitagawa@phys.s.u-tokyo.ac.jp
4 
5  This program is free software; you can redistribute it and/or
6  modify it under the terms of the GNU Library General Public
7  License as published by the Free Software Foundation; either
8  version 2 of the License, or (at your option) any later version.
9 
10  You should have received a copy of the GNU Library General
11  Public License and a list of authors along with this program;
12  see the files COPYING and AUTHORS.
13 ***************************************************************************/
14 #include "xrubysupport.h"
15 #include <QTimer>
16 #include <QAction>
17 #include <QMenu>
18 #include <QMenuBar>
19 #include <QDesktopWidget>
20 #include <QApplication>
21 #include <QDockWidget>
22 #include <QCloseEvent>
23 #include <QMdiArea>
24 #include <QMdiSubWindow>
25 #include <QMainWindow>
26 #include <QMessageBox>
27 #include <QFileDialog>
28 #ifdef WITH_KDE
29  #include <kstandarddirs.h>
30 #else
31  #include <QStandardPaths>
32 #endif
33 
34 #include "kame.h"
35 #include "xsignal.h"
36 #include "xscheduler.h"
37 #include "measure.h"
38 #include "interface.h"
39 #include "xrubywriter.h"
40 #include "xdotwriter.h"
41 #include "xrubythreadconnector.h"
42 #include "ui_rubythreadtool.h"
43 #include "ui_caltableform.h"
44 #include "ui_recordreaderform.h"
45 #include "ui_nodebrowserform.h"
46 #include "ui_interfacetool.h"
47 #include "ui_graphtool.h"
48 #include "ui_drivertool.h"
49 #include "ui_scalarentrytool.h"
50 #include "icon.h"
51 #include "messagebox.h"
52 
53 QWidget *g_pFrmMain = 0L;
54 static XMessageBox *s_pMessageBox = 0L;
55 
56 FrmKameMain::FrmKameMain()
57  :QMainWindow(NULL) {
58  resize(QSize(
59  std::min(1280, QApplication::desktop()->width()),
60  height()).expandedTo(sizeHint()) );
61 
62  setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
63 
64  show();
65 
66  g_pFrmMain = this;
67 
68  createActions();
69  createMenus();
70 
71  //Central MDI area.
72  m_pMdiCentral = new QMdiArea( this );
73  setCentralWidget( m_pMdiCentral );
74  m_pMdiCentral->setViewMode(QMdiArea::TabbedView);
75  m_pMdiCentral->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
76 
77 // setDockOptions(QMainWindow::ForceTabbedDocks | QMainWindow::VerticalTabs);
78  //Left MDI area.
79  QDockWidget* dock = new QDockWidget(i18n("KAME Toolbox West"), this);
80  dock->setFeatures(QDockWidget::DockWidgetFloatable);
81  dock->setWindowIcon(*g_pIconDriver);
82  m_pMdiLeft = new QMdiArea( this );
83  m_pMdiLeft->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
84  m_pMdiLeft->setViewMode(QMdiArea::TabbedView);
85  m_pMdiLeft->setTabPosition(QTabWidget::West);
86  dock->setWidget(m_pMdiLeft);
87  addDockWidget(Qt::LeftDockWidgetArea, dock);
88 
89  //Right MDI area.
90  dock = new QDockWidget(i18n("KAME Toolbox East"), this);
91  dock->setFeatures(QDockWidget::DockWidgetFloatable);
92  dock->setWindowIcon(*g_pIconInterface);
93  m_pMdiRight= new QMdiArea( this );
94  m_pMdiRight->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
95  m_pMdiRight->setViewMode(QMdiArea::TabbedView);
96  m_pMdiRight->setTabPosition(QTabWidget::East);
97  dock->setWidget(m_pMdiRight);
98  addDockWidget(Qt::RightDockWidgetArea, dock);
99 
100  g_signalBuffer.reset(new XSignalBuffer());
101 
102  m_pFrmDriver = new FrmDriver(this);
103  m_pFrmDriver->setWindowIcon(*g_pIconDriver);
104  QMdiSubWindow* swnd = addDockableWindow(m_pMdiLeft, m_pFrmDriver, false);
105 
106  m_pFrmGraphList = new FrmGraphList(this);
107  m_pFrmGraphList->setWindowIcon(*g_pIconGraph);
108  addDockableWindow(m_pMdiLeft, m_pFrmGraphList, false);
109 
110  m_pFrmCalTable = new FrmCalTable(this);
111  m_pFrmCalTable->setWindowIcon( *g_pIconRoverT);
112  addDockableWindow(m_pMdiLeft, m_pFrmCalTable, false);
113 
114  m_pFrmNodeBrowser = new FrmNodeBrowser(this);
115  m_pFrmNodeBrowser->setWindowIcon(QApplication::style()->standardIcon(QStyle::SP_FileDialogContentsView));
116  addDockableWindow(m_pMdiLeft, m_pFrmNodeBrowser, false);
117 
118  m_pMdiLeft->activatePreviousSubWindow();
119  m_pMdiLeft->activatePreviousSubWindow();
120  m_pMdiLeft->activatePreviousSubWindow();
121 
122  m_pFrmInterface = new FrmInterface(this);
123  m_pFrmInterface ->setWindowIcon(*g_pIconInterface);
124  swnd = addDockableWindow(m_pMdiRight, m_pFrmInterface, false);
125 
126  m_pFrmScalarEntry = new FrmEntry(this);
127  m_pFrmScalarEntry->setWindowIcon(*g_pIconScalar);
128  addDockableWindow(m_pMdiRight, m_pFrmScalarEntry, false);
129 
130  m_pFrmRecordReader = new FrmRecordReader(this);
131  m_pFrmRecordReader->setWindowIcon(*g_pIconReader);
132  addDockableWindow(m_pMdiRight, m_pFrmRecordReader, false);
133 
134  m_pMdiRight->activatePreviousSubWindow();
135  m_pMdiRight->activatePreviousSubWindow();
136 
137  s_pMessageBox = new XMessageBox(this);
138  m_pViewMenu->addSeparator();
139  QAction *act = new QAction( *g_pIconInfo, XMessageBox::form()->windowTitle(), this);
140  connect(act, SIGNAL(triggered()), XMessageBox::form(), SLOT(showNormal()));
141  m_pViewMenu->addAction(act);
142 
143  resize(QSize(std::min(1280, width()), 560));
144 
145  // The root for all nodes.
146  m_measure = XNode::createOrphan<XMeasure>("Measurement", false);
147 
148  // signals and slots connections
149  connect( m_pFileCloseAction, SIGNAL( triggered() ), this, SLOT( fileCloseAction_activated() ) );
150  connect( m_pFileExitAction, SIGNAL( triggered() ), this, SLOT( fileExitAction_activated() ) );
151  connect( m_pFileOpenAction, SIGNAL( triggered() ), this, SLOT( fileOpenAction_activated() ) );
152  connect( m_pFileSaveAction, SIGNAL( triggered() ), this, SLOT( fileSaveAction_activated() ) );
153  connect( m_pHelpAboutAction, SIGNAL( triggered() ), this, SLOT( helpAboutAction_activated() ) );
154  connect( m_pHelpContentsAction, SIGNAL( triggered() ), this, SLOT( helpContentsAction_activated() ) );
155  connect( m_pHelpIndexAction, SIGNAL( triggered() ), this, SLOT( helpIndexAction_activated() ) );
156 // connect( m_pMesRunAction, SIGNAL( triggered() ), this, SLOT( mesRunAction_activated() ) );
157  connect( m_pMesStopAction, SIGNAL( triggered() ), this, SLOT( mesStopAction_activated() ) );
158  connect( m_pScriptRunAction, SIGNAL( triggered() ), this, SLOT( scriptRunAction_activated() ) );
159  connect( m_pScriptLineShellAction, SIGNAL( triggered() ), this, SLOT( scriptLineShellAction_activated() ) );
160  connect( m_pScriptDotSaveAction, SIGNAL( triggered() ), this, SLOT( scriptDotSaveAction_activated() ) );
161  connect( m_pFileLogAction, SIGNAL( toggled(bool) ), this, SLOT( fileLogAction_toggled(bool) ) );
162 
163  connect(qApp, SIGNAL(aboutToQuit()), this, SLOT(aboutToQuit()));
164  connect(qApp, SIGNAL( lastWindowClosed() ), qApp, SLOT( quit() ) );
165 
166  m_pTimer = new QTimer(this);
167  connect(m_pTimer, SIGNAL (timeout() ), this, SLOT(processSignals()));
168  m_pTimer->start(0);
169 
170  scriptLineShellAction_activated();
171 }
172 
173 struct MySubWindow : public QMdiSubWindow {
174  void closeEvent(QCloseEvent *e) {
175  e->ignore();
176  }
177 };
178 QMdiSubWindow *
179 FrmKameMain::addDockableWindow(QMdiArea *area, QWidget *widget, bool closable) {
180  QMdiSubWindow *wnd;
181  if(closable) {
182  wnd = new QMdiSubWindow();
183  wnd->setAttribute(Qt::WA_DeleteOnClose);
184  }
185  else {
186  wnd = new MySubWindow(); //delegated class, which ignores closing events.
187  QAction *act = new QAction(widget->windowIcon(), widget->windowTitle(), this);
188  connect(act, SIGNAL(triggered()), wnd, SLOT(showMaximized()));
189  m_pViewMenu->addAction(act);
190  }
191  wnd->setWidget(widget);
192  area->addSubWindow(wnd);
193  wnd->setWindowIcon(widget->windowIcon());
194  wnd->setWindowTitle(widget->windowTitle());
195  wnd->showMaximized();
196  return wnd;
197 }
198 
199 FrmKameMain::~FrmKameMain() {
200  m_pTimer->stop();
201 // while( !g_signalBuffer->synchronize()) {}
202  m_measure.reset();
203  g_signalBuffer.reset();
204  delete s_pMessageBox; s_pMessageBox = 0L;
205 }
206 
207 void
208 FrmKameMain::aboutToQuit() {
209 }
210 
211 void
212 FrmKameMain::createActions() {
213  // actions
214  m_pFileOpenAction = new QAction( this );
215 // fileOpenAction->setIcon( QIconSet( *IconKame48x48 ) );
216  m_pFileOpenAction->setIcon(QApplication::style()->standardIcon(QStyle::SP_DirOpenIcon));
217  m_pFileSaveAction = new QAction( this );
218  m_pFileSaveAction->setEnabled( true );
219  m_pFileSaveAction->setIcon(QApplication::style()->standardIcon(QStyle::SP_DialogSaveButton));
220  m_pFileCloseAction = new QAction( this );
221  m_pFileCloseAction->setEnabled( true );
222 // fileCloseAction->setIcon( QIconSet( *IconClose48x48 ) );
223  m_pFileCloseAction->setIcon(QApplication::style()->standardIcon(QStyle::SP_DirClosedIcon));
224  m_pFileExitAction = new QAction( this );
225 // fileExitAction->setIcon( QIconSet( *IconStop48x48 ) );
226  m_pFileExitAction->setIcon(QApplication::style()->standardIcon(QStyle::SP_DialogCloseButton));
227  m_pHelpContentsAction = new QAction( this );
228  m_pHelpIndexAction = new QAction( this );
229  m_pHelpAboutAction = new QAction( this );
230  m_pHelpAboutAction->setIcon(QApplication::style()->standardIcon(QStyle::SP_DialogHelpButton));
231  m_pFileLogAction = new QAction( this );
232  m_pFileLogAction->setCheckable( true );
233  m_pFileLogAction->setChecked( g_bLogDbgPrint );
234  m_pFileLogAction->setIcon(QApplication::style()->standardIcon(QStyle::SP_DriveCDIcon));
235 // m_pMesRunAction = new QAction( this, "mesRunAction" );
236 // m_pMesRunAction->setEnabled( TRUE );
237  // m_pMesRunAction->setIcon( QIconSet( *g_pIconDriver) );
238  m_pMesStopAction = new QAction( this );
239  m_pMesStopAction->setEnabled( true );
240  m_pMesStopAction->setIcon( QIcon( *g_pIconStop) );
241  m_pScriptRunAction = new QAction( this );
242  m_pScriptRunAction->setEnabled( true );
243  m_pScriptRunAction->setIcon( QIcon( *g_pIconScript) );
244  m_pScriptLineShellAction = new QAction( this );
245  m_pScriptLineShellAction->setEnabled( true );
246  m_pScriptLineShellAction->setIcon(QApplication::style()->standardIcon(QStyle::SP_FileDialogDetailedView));
247  m_pScriptDotSaveAction = new QAction( this );
248  m_pScriptDotSaveAction->setEnabled( true );
249  m_pScriptDotSaveAction->setIcon(QApplication::style()->standardIcon(QStyle::SP_DialogSaveButton));
250 
251  m_pFileOpenAction->setText( i18n( "&Open..." ) );
252  m_pFileOpenAction->setShortcut( i18n( "Ctrl+O" ) );
253  m_pFileSaveAction->setText( tr( "&Save..." ) );
254  m_pFileSaveAction->setShortcut( i18n( "Ctrl+S" ) );
255  m_pFileExitAction->setText( i18n( "E&xit" ) );
256  m_pHelpContentsAction->setText( i18n( "&Contents..." ) );
257  m_pHelpIndexAction->setText( i18n( "&Index..." ) );
258  m_pHelpAboutAction->setText( i18n( "&About" ) );
259  m_pFileLogAction->setText( i18n( "&Log Debugging Info" ) );
260  m_pMesStopAction->setText( i18n( "&Stop" ) );
261  m_pScriptRunAction->setText( i18n( "&Run..." ) );
262  m_pScriptLineShellAction->setText( i18n( "&New Line Shell" ) );
263  m_pScriptDotSaveAction->setText( i18n( "&Graphviz Save .dot..." ) );
264  m_pFileCloseAction->setText( i18n( "&Close" ) );
265 }
266 void
267 FrmKameMain::createMenus() {
268 
269  // menubar
270  m_pFileMenu = menuBar()->addMenu(i18n( "&File" ) );
271  m_pFileMenu->addAction(m_pFileOpenAction);
272  m_pFileMenu->addAction(m_pFileSaveAction);
273  m_pFileMenu->addAction(m_pFileCloseAction);
274  m_pFileMenu->addSeparator();
275  m_pFileMenu->addAction(m_pFileLogAction);
276  m_pFileMenu->addSeparator();
277  m_pFileMenu->addAction(m_pFileExitAction);
278 
279  m_pMeasureMenu = menuBar()->addMenu(i18n( "&Measure" ));
280  m_pMeasureMenu->addAction(m_pMesStopAction);
281 
282  m_pScriptMenu = menuBar()->addMenu( i18n( "&Script" ) );
283  m_pScriptMenu->addAction(m_pScriptRunAction);
284  m_pScriptMenu->addAction(m_pScriptLineShellAction);
285  m_pScriptMenu->addSeparator();
286  m_pScriptMenu->addAction(m_pScriptDotSaveAction);
287 
288  m_pViewMenu = menuBar()->addMenu(i18n( "&View" ) );
289 
290  m_pHelpMenu = menuBar()->addMenu(i18n( "&Help" ) );
291  m_pHelpMenu->addAction(m_pHelpContentsAction);
292  m_pHelpMenu->addAction(m_pHelpIndexAction );
293  m_pHelpMenu->addSeparator();
294  m_pHelpMenu->addAction(m_pHelpAboutAction);
295 }
296 
297 void
298 FrmKameMain::processSignals() {
299  bool idle = g_signalBuffer->synchronize();
300  if(idle) {
301  msecsleep(5);
302  #ifdef HAVE_LIBGCCPP
303  static XTime last = XTime::now();
304  if(XTime::now() - last > 3) {
305  GC_gcollect();
306  last = XTime::now();
307  }
308  #endif
309  }
310  msecsleep(0);
311 }
312 
313 void
314 FrmKameMain::closeEvent( QCloseEvent* ce ) {
315  bool opened = false;
316  {
317  Snapshot shot( *m_measure->interfaces());
318  if(shot.size()) {
319  const XNode::NodeList &list(*shot.list());
320  for(auto it = list.begin(); it != list.end(); it++) {
321  auto intf = dynamic_pointer_cast<XInterface>( *it);
322  if(intf->isOpened()) opened = true;
323  }
324  }
325  }
326  if(opened) {
327  QMessageBox::warning( this, "KAME", i18n("Stop running first.") );
328  ce->ignore();
329  }
330  else {
331  ce->accept();
332  printf("quit\n");
333  m_conMeasRubyThread.reset();
334  m_measure->terminate();
335 
336  m_measure.reset();
337  }
338 }
339 
340 void FrmKameMain::fileCloseAction_activated() {
341  m_conMeasRubyThread.reset();
342  m_measure->terminate();
343 }
344 
345 
346 void FrmKameMain::fileExitAction_activated() {
347  close();
348 }
349 
350 void FrmKameMain::fileOpenAction_activated() {
351  QString filename = QFileDialog::getOpenFileName (
352  this, i18n("Open Measurement File"), "",
353  "KAME2 Measurement files (*.kam);;"
354  "KAME1 Measurement files (*.mes);;"
355  "All files (*.*);;"
356  );
357  openMes(filename);
358 }
359 
360 
361 void FrmKameMain::fileSaveAction_activated() {
362  QString filter = "KAME2 Measurement files (*.kam)";
363 #if QT_VERSION < QT_VERSION_CHECK(5,0,0)
364  QString filename = QFileDialog::getSaveFileName (
365  this, i18n("Save Measurement File"), "", filter);
366 #else
367  //old qt cannot make native dialog in this mode.
368  QFileDialog dialog(this);
369  dialog.setWindowTitle(i18n("Save Measurement File"));
370  dialog.setViewMode(QFileDialog::Detail);
371  dialog.setNameFilter(filter);
372  dialog.setConfirmOverwrite(true);
373  dialog.setDefaultSuffix("kam");
374  dialog.setAcceptMode(QFileDialog::AcceptSave);
375  if( !dialog.exec())
376  return;
377  QString filename = dialog.selectedFiles().at(0);
378 #endif
379  if( !filename.isEmpty()) {
380  std::ofstream ofs(filename.toLocal8Bit().data(), std::ios::out);
381  if(ofs.good()) {
382  XRubyWriter writer(m_measure, ofs);
383  writer.write();
384  }
385  }
386 }
387 
388 
389 void FrmKameMain::helpAboutAction_activated() {
390  QMessageBox::about( this,
391  i18n("K's Adaptive Measurement Engine."), "KAME");
392 }
393 
394 void FrmKameMain::helpContentsAction_activated() {
395 }
396 
397 
398 void FrmKameMain::helpIndexAction_activated() {
399 }
400 
401 /*
402  void FrmKameMain::mesRunAction_activated()
403  {
404  m_pMesRunAction->setEnabled(false);
405  m_pMesStopAction->setEnabled(true);
406  m_pFileCloseAction->setEnabled(false);
407  m_pFileExitAction->setEnabled(false);
408  m_measure->start();
409  }
410 */
411 
412 void FrmKameMain::mesStopAction_activated() {
413  m_measure->stop();
414 /*
415  * m_pMesRunAction->setEnabled(true);
416  m_pMesStopAction->setEnabled(false);
417  m_pFileCloseAction->setEnabled(true);
418  m_pFileExitAction->setEnabled(true);
419 */
420 }
421 
422 int
423 FrmKameMain::openMes(const XString &filename) {
424  if( !filename.empty()) {
425  runNewScript("Open Measurement", filename );
426 // while(rbthread->isAlive()) {
427 // KApplication::kApplication()->processEvents();
428 // g_signalBuffer->synchronize();
429 // }
430 // closeWindow(view);
431  return 0;
432  }
433  return -1;
434 }
435 
436 shared_ptr<XRubyThread>
437 FrmKameMain::runNewScript(const XString &label, const XString &filename) {
438  shared_ptr<XRubyThread> rbthread = m_measure->ruby()->
439  create<XRubyThread>(label.c_str(), true, filename );
440  FrmRubyThread* form = new FrmRubyThread(this);
441  m_conRubyThreadList.push_back(xqcon_create<XRubyThreadConnector>(
442  rbthread, form, m_measure->ruby()));
443  addDockableWindow(m_pMdiCentral, form, true);
444 
445  // erase unused xqcon_ptr
446  for(auto it = m_conRubyThreadList.begin(); it != m_conRubyThreadList.end(); ) {
447  if((*it)->isAlive()) {
448  it++;
449  }
450  else {
451  it = m_conRubyThreadList.erase(it);
452  }
453  }
454  return rbthread;
455 }
456 void FrmKameMain::scriptRunAction_activated() {
457  QString filename = QFileDialog::getOpenFileName (
458  this, "",
459  i18n("Open Script File"),
460  "KAME Script files (*.seq);;"
461  "Ruby Script files (*.rb)"
462  );
463  if( !filename.isEmpty()) {
464  static unsigned int thread_no = 1;
465  runNewScript(formatString("Thread%d", thread_no), filename );
466  thread_no++;
467  }
468 }
469 
470 #define RUBYLINESHELL_FILE "rubylineshell.rb"
471 
472 void FrmKameMain::scriptLineShellAction_activated() {
473  QString filename =
474 #ifdef WITH_KDE
475  KStandardDirs::locate("appdata", RUBYLINESHELL_FILE);
476 #else
477  QStandardPaths::locate(QStandardPaths::DataLocation, RUBYLINESHELL_FILE);
478  if(filename.isEmpty()) {
479  //for macosx/win
480  QDir dir(QApplication::applicationDirPath());
481 #if defined __MACOSX__ || defined __APPLE__
482  //For macosx application bundle.
483  dir.cdUp();
484 #endif
485  QString path = RUBYLINESHELL_DIR RUBYLINESHELL_FILE;
486  dir.filePath(path);
487  if(dir.exists())
488  filename = dir.absoluteFilePath(path);
489  }
490 #endif
491  if(filename.isEmpty()) {
492  g_statusPrinter->printError("No KAME ruby support file installed.");
493  }
494  else {
495  static unsigned int int_no = 1;
496  runNewScript(formatString("Line Shell%d", int_no), filename );
497  int_no++;
498  }
499 }
500 
501 void FrmKameMain::scriptDotSaveAction_activated() {
502  QString filename = QFileDialog::getSaveFileName (
503  this,
504  i18n("Save Graphviz dot File"), "",
505  "Graphviz dot files (*.dot);;"
506  "All files (*.*)"
507  );
508  if( !filename.isEmpty()) {
509  std::ofstream ofs(filename.toLocal8Bit().data(), std::ios::out);
510  if(ofs.good()) {
511  XDotWriter writer(m_measure, ofs);
512  writer.write();
513  }
514  }
515 }
516 
517 void FrmKameMain::fileLogAction_toggled( bool var) {
518  g_bLogDbgPrint = var;
519 }
520 

Generated for KAME4 by  doxygen 1.8.3