1 /***************************************************************************
2 * Copyright (C) 2008 by Alexey Balakin *
3 * mathgl.abalakin@gmail.com *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
20 #ifdef WIN32
21 #include <io.h>
22 #include <direct.h>
23 #else
24 #include <unistd.h>
25 #endif
26 #include <QMenuBar>
27 #include <QMessageBox>
28 #include <QApplication>
29 #include <QSettings>
30 #include <QSplitter>
31 #include <QFileDialog>
32 #include <QStatusBar>
33 #include <QDockWidget>
34 #include <QCloseEvent>
35 #include <QTextCodec>
36 #include <QTranslator>
37 #include <QMimeData>
38 #include <QUrl>
39 #include <QFileInfo>
40 //-----------------------------------------------------------------------------
41 #include <mgl2/qmathgl.h>
42 #include "udav_wnd.h"
43 #include "text_pnl.h"
44 #include "plot_pnl.h"
45 #include "prop_dlg.h"
46 #include "qmglsyntax.h"
47 //-----------------------------------------------------------------------------
48 extern bool mglAutoExecute;
49 PropDialog *propDlg=0;
50 int MainWindow::num_wnd=0;
51 QStringList recentFiles;
52 int MaxRecentFiles=5;
53 bool editPosBottom = false;
54 bool mglAutoSave = false;
55 bool mglHighlight = true;
56 bool mglDotsRefr = true;
57 // bool mglAutoPure = true;
58 bool mglCompleter = true;
59 bool loadInNewWnd = false;
60 bool mglWheelZoom = false;
61 QString pathHelp;
62 extern mglParse parser;
63 extern QColor mglColorScheme[10];
64 extern QString defFontFamily;
65 extern int defFontSize;
66 extern QString pathFont;
67 extern int defWidth, defHeight;
68 //-----------------------------------------------------------------------------
69 QWidget *createCalcDlg(QWidget *p, QTextEdit *e);
70 QDialog *createArgsDlg(QWidget *p);
71 QWidget *createMemPanel(QWidget *p);
72 QWidget *createHlpPanel(QWidget *p);
73 void showHelpMGL(QWidget *hlp, QString s);
addDataPanel(QWidget * p,QWidget * w,QString name)74 void addDataPanel(QWidget *p, QWidget *w, QString name)
75 {
76 MainWindow *wnd = dynamic_cast<MainWindow *>(p);
77 if(wnd) wnd->addPanel(w, name);
78 }
79 //-----------------------------------------------------------------------------
80 #ifndef UDAV_DIR
81 #ifdef WIN32
82 #define UDAV_DIR ""
83 #else
84 #define UDAV_DIR "/usr/local/share/udav/"
85 #endif
86 #endif
87 //-----------------------------------------------------------------------------
88 int mgl_cmd_cmp(const void *a, const void *b);
89 void udavLoadDefCommands();
90 void udavShowHint(QWidget *);
91 void mgl_ask_qt(const wchar_t *quest, wchar_t *res);
92 //-----------------------------------------------------------------------------
main(int argc,char ** argv)93 int main(int argc, char **argv)
94 {
95 QString lang="";
96 QSettings settings("udav","UDAV");
97 settings.setPath(QSettings::IniFormat, QSettings::UserScope, "UDAV");
98 settings.beginGroup("/UDAV");
99 pathHelp = settings.value("/helpPath", MGL_DOC_DIR).toString();
100 pathFont = settings.value("/userFont", "").toString();
101 lang = settings.value("/udavLang", "").toString();
102
103 const char *loc="";
104 if(lang=="en") loc = "C.UTF8";
105 #if WIN32
106 if(lang=="ru") loc = "ru_RU.cp1251";
107 #else
108 if(lang=="ru") loc = "ru_RU.utf8";
109 #endif
110 if(lang=="es") { loc = "es_ES.utf8"; lang="en"; } // TODO remove lang="en"; then Spanish translation is ready !
111 mgl_textdomain(argv?argv[0]:NULL,loc);
112
113 bool showHint = settings.value("/showHint", true).toBool();
114 mglCompleter = settings.value("/completer", true).toBool();
115 settings.endGroup();
116
117 mgl_suppress_warn(true);
118 QCoreApplication::setAttribute(Qt::AA_X11InitThreads);
119 #ifdef WIN32
120 QCoreApplication::addLibraryPath("c:/plugins/");
121 QCoreApplication::addLibraryPath(QFileInfo(QString::fromLocal8Bit(argv[0])).absolutePath().append("/plugins/"));
122 #endif
123 mgl_ask_func = mgl_ask_qt;
124 QApplication a(argc, argv);
125 QTranslator translator;
126 //QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));
127 #if defined(WIN32)
128 if(pathHelp.isEmpty()) pathHelp = a.applicationDirPath()+"\\";
129 #else
130 if(pathHelp.isEmpty()) pathHelp=MGL_DOC_DIR;
131 #endif
132
133 if(!lang.isEmpty())
134 {
135 if(!translator.load("udav_"+lang, UDAV_DIR))
136 translator.load("udav_"+lang, pathHelp);
137 a.installTranslator(&translator);
138 }
139
140 udavLoadDefCommands();
141 parser.AllowSetSize(true);
142 MainWindow *mw = new MainWindow();
143 if(argc>1)
144 {
145 QTextCodec *codec = QTextCodec::codecForLocale();
146 mw->load(codec->toUnicode(argv[1]), true);
147 }
148 mw->show();
149 mw->edit->edit->setFocus();
150 a.connect(&a, SIGNAL(lastWindowClosed()), &a, SLOT(quit()));
151 if(showHint) udavShowHint(mw);
152 return a.exec();
153 }
154 //-----------------------------------------------------------------------------
155 //
156 // mgl addon
157 //
158 //-----------------------------------------------------------------------------
udavLoadDefCommands()159 void udavLoadDefCommands() {} //{ udavAddCommands(udav_base_cmd); }
160 //-----------------------------------------------------------------------------
161 //
162 // Class MainWindow
163 //
164 //-----------------------------------------------------------------------------
MainWindow(QWidget * wp)165 MainWindow::MainWindow(QWidget *wp) : QMainWindow(wp)
166 {
167 QAction *a;
168 setWindowTitle(_("untitled - UDAV"));
169 setAttribute(Qt::WA_DeleteOnClose);
170
171 split = new QSplitter(this);
172 ltab = new QTabWidget(split);
173 ltab->setMovable(true); ltab->setTabPosition(QTabWidget::South);
174 // ltab->setTabsClosable(true);
175 rtab = new QTabWidget(split);
176 rtab->setMovable(true); rtab->setTabPosition(QTabWidget::South);
177
178 messWnd = new QDockWidget(_("Messages and warnings"),this);
179 mess = new QTextEdit(this); messWnd->setWidget(mess);
180 messWnd->setAllowedAreas(Qt::TopDockWidgetArea | Qt::BottomDockWidgetArea);
181 addDockWidget(Qt::BottomDockWidgetArea, messWnd);
182 messWnd->resize(size().width(), 0); new MessSyntax(mess);
183 // connect(mess,SIGNAL(cursorPositionChanged()),this,SLOT(messClicked()));
184 connect(mess,SIGNAL(selectionChanged()),this,SLOT(messClicked()));
185
186 hideWnd = new QDockWidget(_("Hidden plots"),this);
187 hidden = new TextEdit(this); hideWnd->setWidget(hidden);
188 hideWnd->setAllowedAreas(Qt::TopDockWidgetArea | Qt::BottomDockWidgetArea);
189 addDockWidget(Qt::BottomDockWidgetArea, hideWnd);
190 hideWnd->resize(size().width(), 0); hidden->setReadOnly(true);
191 connect(hidden,SIGNAL(selectionChanged()),this,SLOT(hiddenClicked())); // TODO
192 // connect(hidden,SIGNAL(cursorPositionChanged()),this,SLOT(hiddenClicked()));
193
194 calcWnd = new QDockWidget(_("Calculator"),this);
195
196 aload = a = new QAction(QPixmap(":/png/document-open.png"), _("Open file"), this);
197 connect(a, SIGNAL(triggered()), this, SLOT(choose()));
198 a->setToolTip(_("Open and execute/show script or data from file (Ctrl+O).\nYou may switch off automatic exection in UDAV properties."));
199 a->setShortcut(Qt::CTRL+Qt::Key_O);
200
201 asave = a = new QAction(QPixmap(":/png/document-save.png"), _("Save script"), this);
202 connect(a, SIGNAL(triggered()), this, SLOT(save()));
203 a->setToolTip(_("Save script to a file (Ctrl+S)"));
204 a->setShortcut(Qt::CTRL+Qt::Key_S);
205
206 acalc = a = new QAction(QPixmap(":/png/accessories-calculator.png"), _("Calculator"), this);
207 a->setShortcut(Qt::Key_F4); a->setCheckable(true);
208 connect(a, SIGNAL(toggled(bool)), calcWnd, SLOT(setVisible(bool)));
209 connect(calcWnd, SIGNAL(visibilityChanged(bool)), a, SLOT(setChecked(bool)));
210 a->setToolTip(_("Show calculator which evaluate and help to type textual formulas.\nTextual formulas may contain data variables too."));
211 a->setChecked(false); calcWnd->setVisible(false);
212
213 ainfo = a = new QAction(_("Show info"), this);
214 a->setShortcut(Qt::Key_F2); a->setCheckable(true);
215 connect(a, SIGNAL(toggled(bool)), messWnd, SLOT(setVisible(bool)));
216 connect(messWnd, SIGNAL(visibilityChanged(bool)), a, SLOT(setChecked(bool)));
217 a->setChecked(false); messWnd->setVisible(false);
218
219 ahide = a = new QAction(QPixmap(":/png/layer-visible-on.png"), _("Show hidden plots"), this);
220 a->setShortcut(Qt::Key_F8); a->setCheckable(true);
221 connect(a, SIGNAL(toggled(bool)), hideWnd, SLOT(setVisible(bool)));
222 connect(hideWnd, SIGNAL(visibilityChanged(bool)), a, SLOT(setChecked(bool)));
223 a->setChecked(false); hideWnd->setVisible(false);
224
225 graph = new PlotPanel(this);
226 rtab->addTab(graph,QPixmap(":/png/office-chart-line.png"),_("Canvas"));
227 // connect(info,SIGNAL(addPanel(QWidget*)),this,SLOT(addPanel(QWidget*)));
228 info = createMemPanel(this);
229 rtab->addTab(info,QPixmap(":/png/system-file-manager.png"),_("Info"));
230 hlp = createHlpPanel(this);
231 rtab->addTab(hlp,QPixmap(":/png/help-contents.png"),_("Help"));
232 edit = new TextPanel(this); edit->graph = graph;
233 graph->textMGL = edit->edit;
234 connect(graph->mgl,SIGNAL(showWarn(QString)),mess,SLOT(setText(QString)));
235 connect(graph->mgl,SIGNAL(showWarn(QString)),edit->edit,SLOT(setErrMessage(QString)));
236 connect(graph,SIGNAL(clearWarn()),mess,SLOT(clear()));
237 ltab->addTab(edit,QPixmap(":/png/text-plain.png"),_("Script"));
238
239 calcWnd->setWidget(createCalcDlg(this, edit->edit));
240 calcWnd->setAllowedAreas(Qt::TopDockWidgetArea | Qt::BottomDockWidgetArea);
241 addDockWidget(Qt::BottomDockWidgetArea, calcWnd);
242 calcWnd->resize(size().width(), 200);
243
244 makeMenu();
245 setCentralWidget(split);
246 setWindowIcon(QIcon(":/udav.png"));
247 readSettings();
248 if(!propDlg) propDlg = new PropDialog;
249
250 connect(graph, SIGNAL(save()), this, SLOT(save()));
251 connect(graph, SIGNAL(setStatus(const QString &)), this, SLOT(setStatus(const QString &)));
252 connect(graph, SIGNAL(animPutText(const QString &)), edit, SLOT(animPutText(const QString &)));
253 connect(graph,SIGNAL(giveFocus()),edit->edit,SLOT(setFocus()));
254 connect(graph->mgl, SIGNAL(objChanged(int)), edit, SLOT(setCursorPosition(int)));
255 // connect(graph->mgl, SIGNAL(posChanged(QString)), statusBar(), SLOT(showMessage(QString)));
256 connect(graph->mgl, SIGNAL(refreshData()), this, SLOT(refresh()));
257 connect(graph->mgl, SIGNAL(refreshData()), edit, SLOT(refreshData()));
258 connect(graph->mgl,SIGNAL(doubleClick(int)),edit,SLOT(newCmd(int)));
259
260 connect(edit->edit,SIGNAL(textChanged()),this,SLOT(updateHidden()));
261 connect(mess, SIGNAL(textChanged()), this, SLOT(warnChanged()));
262 connect(propDlg, SIGNAL(sizeChanged(int,int)), graph->mgl, SLOT(imgSize(int,int)));
263 connect(edit->edit,SIGNAL(textChanged()), this, SLOT(setAsterix()));
264 connect(edit->edit, SIGNAL(cursorPositionChanged()), this, SLOT(editPosChanged()));
265 connect(edit,SIGNAL(setCurrentFile(QString)),this,SLOT(setCurrentFile(QString)));
266 connect(edit,SIGNAL(setStatus(QString)),this,SLOT(setStatus(QString)));
267
268 setStatus(_("Ready"));
269 num_wnd++;
270 edit->setAcceptDrops(false); // for disabling default action by 'edit'
271 setAcceptDrops(true);
272 }
273 //-----------------------------------------------------------------------------
makeMenu()274 void MainWindow::makeMenu()
275 {
276 QAction *a;
277 QMenu *o;
278
279 // file menu
280 {
281 o = menuBar()->addMenu(_("File"));
282 a = new QAction(QPixmap(":/png/document-new.png"), _("New script"), this);
283 connect(a, SIGNAL(triggered()), this, SLOT(newDoc()));
284 a->setToolTip(_("Create new empty script window (Ctrl+N)."));
285 a->setShortcut(Qt::CTRL+Qt::Key_N); o->addAction(a);
286
287 o->addAction(aload);
288 o->addAction(asave);
289
290 a = new QAction(_("Save as ..."), this);
291 connect(a, SIGNAL(triggered()), this, SLOT(saveAs()));
292 o->addAction(a);
293
294 o->addSeparator();
295 o->addAction(_("Print script"), edit, SLOT(printText()));
296 a = new QAction(QPixmap(":/png/document-print.png"), _("Print graphics"), this);
297 connect(a, SIGNAL(triggered()), graph->mgl, SLOT(print()));
298 a->setToolTip(_("Open printer dialog and print graphics (Ctrl+P)"));
299 a->setShortcut(Qt::CTRL+Qt::Key_P); o->addAction(a);
300 o->addSeparator();
301 fileMenu = o->addMenu(_("Recent files"));
302 o->addSeparator();
303 o->addAction(_("Quit"), qApp, SLOT(closeAllWindows()));
304 }
305
306 menuBar()->addMenu(edit->menu);
307 menuBar()->addMenu(graph->menu);
308
309 // settings menu
310 {
311 o = menuBar()->addMenu(_("Settings"));
312 a = new QAction(QPixmap(":/png/preferences-system.png"), _("Properties"), this);
313 connect(a, SIGNAL(triggered()), this, SLOT(properties()));
314 a->setToolTip(_("Show dialog for UDAV properties.")); o->addAction(a);
315 o->addAction(_("Set arguments"), createArgsDlg(this), SLOT(exec()));
316
317 o->addAction(acalc);
318 o->addAction(ainfo);
319 o->addAction(ahide);
320 }
321
322 menuBar()->addSeparator();
323 o = menuBar()->addMenu(_("Help"));
324 a = new QAction(QPixmap(":/png/help-contents.png"), _("MGL help"), this);
325 connect(a, SIGNAL(triggered()), this, SLOT(showHelp()));
326 a->setToolTip(_("Show help on MGL commands (F1)."));
327 a->setShortcut(Qt::Key_F1); o->addAction(a);
328 a = new QAction(QPixmap(":/png/help-faq.png"), _("Hints"), this);
329 connect(a, SIGNAL(triggered()), this, SLOT(showHint()));
330 a->setToolTip(_("Show hints of MGL usage.")); o->addAction(a);
331 o->addAction(_("About"), this, SLOT(about()));
332 o->addAction(_("About Qt"), this, SLOT(aboutQt()));
333 }
334 //-----------------------------------------------------------------------------
closeEvent(QCloseEvent * ce)335 void MainWindow::closeEvent(QCloseEvent* ce)
336 {
337 bool ok=true;
338 writeSettings();
339 if(edit->isModified())
340 switch(QMessageBox::information(this, _("UDAV"),
341 _("Do you want to save the changes to the document?"),
342 QMessageBox::Yes, QMessageBox::No, QMessageBox::Cancel))
343 {
344 case QMessageBox::Yes: save(); break;
345 case QMessageBox::No: break;
346 default: ok=false; break;
347 }
348 if(ok)
349 {
350 num_wnd--;
351 ce->accept();
352 if(num_wnd==0) QApplication::quit();
353 }
354 else ce->ignore();
355 }
356 //-----------------------------------------------------------------------------
dropEvent(QDropEvent * de)357 void MainWindow::dropEvent(QDropEvent * de)
358 {
359 // Linux Qt send "text/plain" mime data in drop event
360 // Windows version send "text/uri-list"
361 QTextCodec *codec = QTextCodec::codecForLocale();
362 QString filename;
363 if ( de->mimeData()->hasFormat("text/plain") )
364 {
365 // Under linux just convert the text from the local encodig to Qt's unicode
366 filename = codec->toUnicode(de->mimeData()->data("text/plain"));
367 if (filename.indexOf("file:") == 0)
368 load(filename.remove("file://").trimmed(), false);
369 }else
370 if ( de->mimeData()->hasUrls() )
371 {
372 // Under win - parse the dropped data and find the path to local file
373 QList<QUrl> UrlList;
374 QFileInfo finfo;
375 UrlList = de->mimeData()->urls();
376 if ( UrlList.size() > 0) // if at least one QUrl is present in list
377 {
378 filename = UrlList[0].toLocalFile(); // convert first QUrl to local path
379 finfo.setFile( filename );
380 if ( finfo.isFile() )
381 {
382 load(filename, false);
383 }
384 }
385 }
386 }
387 //-----------------------------------------------------------------------------
dragEnterEvent(QDragEnterEvent * event)388 void MainWindow::dragEnterEvent(QDragEnterEvent *event)
389 {
390 QTextCodec *codec = QTextCodec::codecForLocale();
391 QString filename = codec->toUnicode(event->mimeData()->data("text/plain"));
392 /*if ( event->provides("text/plain") )
393 {
394 QTextCodec *codec = QTextCodec::codecForLocale();
395 QString instring = codec->toUnicode(event->mimeData()->data("text/plain"));
396 if ( instring.indexOf("file://") >= 0)
397 {
398 event->acceptProposedAction();
399 setStatus(instring);
400 }
401 }
402 else */
403 if(event->mimeData()->hasUrls())
404 {
405 QList<QUrl> UrlList;
406 QFileInfo finfo;
407 UrlList = event->mimeData()->urls();
408 if ( UrlList.size() > 0) // if at least one QUrl is present in list
409 {
410 filename = UrlList[0].toLocalFile(); // convert first QUrl to local path
411 finfo.setFile(filename);
412 if ( finfo.isFile() )
413 {
414 event->acceptProposedAction();
415 setStatus(filename);
416 }
417 }
418 }
419 }
420 //-----------------------------------------------------------------------------
showHelp()421 void MainWindow::showHelp()
422 {
423 QString s = edit->selection(), dlm(" #;:\t");
424 int i, n = s.length();
425 for(i=0;i<n;i++) if(dlm.contains(s[i])) break;
426 s.truncate(i);
427 // s = s.section(' ',0);
428 showHelpMGL(hlp,s);
429 }
430 //-----------------------------------------------------------------------------
431 int mgl_cmd_cmp(const void *a, const void *b);
editPosChanged()432 void MainWindow::editPosChanged()
433 {
434 QString text = edit->selection(), dlm(" #;:\t");
435 int n = text.length(), i;
436 for(i=0;i<n;i++) if(dlm.contains(text[i])) break;
437 text.truncate(i);
438
439 QByteArray qxtext = text.toLatin1();
440 const char *ctext = qxtext.constData();
441 const char *desc = parser.CmdDesc(ctext);
442 const char *form = parser.CmdFormat(ctext);
443 if(form) setStatus(QString(desc)+": "+QString(form));
444 else setStatus(_("Not recognized"));
445 }
446 //-----------------------------------------------------------------------------
setEditPos(bool bottom)447 void MainWindow::setEditPos(bool bottom)
448 { split->setOrientation(bottom ? Qt::Vertical : Qt::Horizontal); }
449 //-----------------------------------------------------------------------------
properties()450 void MainWindow::properties() { propDlg->exec(); }
451 //-----------------------------------------------------------------------------
about()452 void MainWindow::about()
453 {
454 QString s = "<a href='http://mathgl.sourceforge.net/doc_en/UDAV-overview.html'>UDAV</a> v. 2."+QString::number(MGL_VER2)+
455 _("<br>(c) Alexey Balakin, 2007-present<br><br><a href='http://www.gnu.org/copyleft/gpl.html'>License is GPL v.2 or later.</a>");
456 QMessageBox::about(this, _("UDAV - about"), s);
457 }
458 //-----------------------------------------------------------------------------
aboutQt()459 void MainWindow::aboutQt()
460 { QMessageBox::aboutQt(this, _("About Qt")); }
461 //-----------------------------------------------------------------------------
writeSettings()462 void MainWindow::writeSettings()
463 {
464 QSettings settings("udav","UDAV");
465 settings.setPath(QSettings::IniFormat, QSettings::UserScope, "UDAV");
466 settings.beginGroup("/UDAV");
467 settings.setValue("/animDelay", animDelay);
468 settings.setValue("/geometry/size", size());
469 // settings.setValue("/geometry/dock", messWnd->size());
470 settings.setValue("/geometry/split_e/w1", split->sizes().at(0));
471 settings.setValue("/geometry/split_e/w2", split->sizes().at(1));
472
473 settings.setValue("/recentFiles", recentFiles);
474 settings.setValue("/recentFilesMax", MaxRecentFiles);
475 settings.setValue("/helpPath", pathHelp);
476 settings.setValue("/userFont", pathFont);
477 settings.setValue("/colComment",mglColorScheme[0].name());
478 settings.setValue("/colString", mglColorScheme[1].name());
479 settings.setValue("/colKeyword",mglColorScheme[2].name());
480 settings.setValue("/colOption", mglColorScheme[3].name());
481 settings.setValue("/colSuffix", mglColorScheme[4].name());
482 settings.setValue("/colNumber", mglColorScheme[5].name());
483 settings.setValue("/colACKeyword", mglColorScheme[6].name());
484 settings.setValue("/colFCKeyword", mglColorScheme[7].name());
485 settings.setValue("/colReserved", mglColorScheme[8].name());
486 settings.setValue("/colCurrLine", mglColorScheme[9].name());
487 settings.setValue("/autoExec", mglAutoExecute);
488 settings.setValue("/autoSave", mglAutoSave);
489 settings.setValue("/highlight", mglHighlight);
490 settings.setValue("/dotsRefresh", mglDotsRefr);
491 // settings.setValue("/autoPure", mglAutoPure);
492 settings.setValue("/editAtTop", editPosBottom);
493 settings.setValue("/fontFamily", defFontFamily);
494 settings.setValue("/fontSize", defFontSize);
495 settings.setValue("/loadInNewWnd", loadInNewWnd);
496 settings.setValue("/completer", mglCompleter);
497 settings.setValue("/wheelZoom", mglWheelZoom);
498 settings.endGroup();
499 }
500 //-----------------------------------------------------------------------------
readSettings()501 void MainWindow::readSettings()
502 {
503 QSettings settings("udav","UDAV");
504 settings.setPath(QSettings::IniFormat, QSettings::UserScope, "UDAV");
505 settings.beginGroup("/UDAV");
506 pathHelp = settings.value("/helpPath", MGL_DOC_DIR).toString();
507 if(pathHelp.isEmpty()) pathHelp=MGL_DOC_DIR;
508 MaxRecentFiles = settings.value("/recentFilesMax", 5).toInt();
509 animDelay = settings.value("/animDelay", 500).toInt();
510 resize(settings.value("/geometry/size", QSize(880,720)).toSize());
511 QList<int> le;
512 le.append(settings.value("/geometry/split_e/w1", 230).toInt());
513 le.append(settings.value("/geometry/split_e/w2", 604).toInt());
514 split->setSizes(le);
515
516 pathFont = settings.value("/userFont", "").toString();
517 mglColorScheme[0] = QColor(settings.value("/colComment","#007F00").toString());
518 mglColorScheme[1] = QColor(settings.value("/colString", "#FF0000").toString());
519 mglColorScheme[2] = QColor(settings.value("/colKeyword","#00007F").toString());
520 mglColorScheme[3] = QColor(settings.value("/colOption", "#7F0000").toString());
521 mglColorScheme[4] = QColor(settings.value("/colSuffix", "#7F0000").toString());
522 mglColorScheme[5] = QColor(settings.value("/colNumber", "#0000FF").toString());
523 mglColorScheme[6] = QColor(settings.value("/colACKeyword","#7F007F").toString());
524 mglColorScheme[7] = QColor(settings.value("/colFCKeyword","#007F7F").toString());
525 mglColorScheme[8] = QColor(settings.value("/colReserved", "#0000FF").toString());
526 mglColorScheme[9] = QColor(settings.value("/colCurrLine", "#FFFFCC").toString());
527 mglAutoSave = settings.value("/autoSave", false).toBool();
528 mglHighlight = settings.value("/highlight", true).toBool();
529 // mglAutoPure = settings.value("/autoPure", true).toBool();
530 mglAutoExecute = settings.value("/autoExec", true).toBool();
531 editPosBottom = settings.value("/editAtTop", false).toBool();
532 mglCompleter = settings.value("/completer", true).toBool();
533 mglWheelZoom = settings.value("/wheelZoom", false).toBool();
534 loadInNewWnd = settings.value("/loadInNewWnd", false).toBool();
535 mglDotsRefr = settings.value("/dotsRefresh", true).toBool();
536 defFontFamily = settings.value("/fontFamily", "Georgia").toString();
537 defFontSize = settings.value("/fontSize", 10).toInt();
538 edit->setEditorFont(); setEditPos(editPosBottom);
539 graph->setMGLFont(pathFont);
540 graph->mgl->enableWheel = mglWheelZoom;
541
542 defWidth = settings.value("/defWidth", 640).toInt();
543 defHeight = settings.value("/defHeight", 480).toInt();
544 graph->mgl->setSize(defWidth, defHeight);
545
546 recentFiles = settings.value("/recentFiles").toStringList();
547 settings.endGroup();
548 updateRecentFileItems();
549 }
550 //-----------------------------------------------------------------------------
setStatus(const QString & txt)551 void MainWindow::setStatus(const QString &txt)
552 { statusBar()->showMessage(txt, 5000); }
553 //-----------------------------------------------------------------------------
setCurrentFile(const QString & fileName)554 void MainWindow::setCurrentFile(const QString &fileName)
555 {
556 filename = fileName;
557 mgl_set_plotid(graph->mgl->getGraph(), fileName.toLocal8Bit().constData());
558 edit->setModified(false);
559 if(filename.isEmpty())
560 setWindowTitle(_("untitled - UDAV"));
561 else
562 {
563 setWindowTitle(QFileInfo(filename).fileName()+" - UDAV");
564 int i = recentFiles.indexOf(filename);
565 if(i>=0) recentFiles.removeAt(i);
566 recentFiles.push_front(filename);
567 updateRecentFileItems();
568 if(chdir(qPrintable(QFileInfo(filename).path())))
569 QMessageBox::warning(this, _("UDAV - save current"),
570 _("Couldn't change to folder ")+QFileInfo(filename).path());
571 }
572 }
573 //-----------------------------------------------------------------------------
openRecentFile()574 void MainWindow::openRecentFile()
575 {
576 QAction *a = qobject_cast<QAction *>(sender());
577 if(!a) return;
578 if(edit->isModified())
579 switch(QMessageBox::information(this, _("UDAV - save current"),
580 _("Do you want to save the changes to the document?"),
581 QMessageBox::Yes, QMessageBox::No, QMessageBox::Cancel))
582 {
583 case QMessageBox::Yes: save(); break;
584 case QMessageBox::No: break;
585 default: return;
586 }
587 QString fn = recentFiles[a->data().toInt()];
588 if(!fn.isEmpty()) load(fn);
589 }
590 //-----------------------------------------------------------------------------
updateRecentFileItems()591 void MainWindow::updateRecentFileItems()
592 {
593 foreach(QWidget *w, QApplication::topLevelWidgets())
594 {
595 MainWindow *wnd = qobject_cast<MainWindow *>(w);
596 if(wnd) wnd->updateRecent();
597 }
598 }
599 //-----------------------------------------------------------------------------
updateRecent()600 void MainWindow::updateRecent()
601 {
602 QAction *a;
603 fileMenu->clear(); qApp->processEvents();
604 for(int i=0; i<recentFiles.size() && i<MaxRecentFiles; i++)
605 {
606 QString text="&"+QString::number(i+1)+" "+QFileInfo(recentFiles[i]).fileName();
607 a = fileMenu->addAction(text, this, SLOT(openRecentFile()));
608 a->setData(i);
609 }
610 }
611 //-----------------------------------------------------------------------------
newDoc()612 void MainWindow::newDoc()
613 {
614 MainWindow *ed = new MainWindow;
615 ed->show(); ed->activateWindow();
616 }
617 //-----------------------------------------------------------------------------
choose()618 void MainWindow::choose()
619 {
620 if(edit->isModified())
621 switch(QMessageBox::information(this, _("UDAV - save current"),
622 _("Do you want to save the changes to the document?"),
623 QMessageBox::Yes, QMessageBox::No, QMessageBox::Cancel))
624 {
625 case QMessageBox::Yes: save(); break;
626 case QMessageBox::No: break;
627 default: return;
628 }
629 QSettings settings("udav","UDAV");
630 settings.setPath(QSettings::IniFormat, QSettings::UserScope, "UDAV");
631 settings.beginGroup("/UDAV");
632 QString fn = QFileDialog::getOpenFileName(this,
633 _("UDAV - Open file"),
634 settings.value("/filePath", MGL_DOC_DIR).toString(),
635 _("MGL scripts (*.mgl)\nHDF5 files (*.hdf *.h5)\nText files (*.txt)\nData files (*.dat)\nAll files (*.*)"));
636 settings.endGroup();
637 if(!fn.isEmpty()) load(fn);
638 else setStatus(_("Loading aborted"));
639 }
640 //-----------------------------------------------------------------------------
load(const QString & fileName,bool noNewWnd)641 void MainWindow::load(const QString &fileName, bool noNewWnd)
642 {
643 // save current path
644 QFileInfo fi(fileName); filename = fileName;
645 QSettings settings("udav","UDAV");
646 settings.setPath(QSettings::IniFormat, QSettings::UserScope, "UDAV");
647 settings.beginGroup("/UDAV");
648 settings.setValue("/filePath", fi.absolutePath());
649 settings.endGroup();
650 // open new window if it is required
651 if(loadInNewWnd && !noNewWnd)
652 {
653 MainWindow *mw = new MainWindow;
654 mw->edit->load(fileName);
655 mw->show(); //ed->activateWindow();
656 }
657 else edit->load(fileName);
658 }
659 //-----------------------------------------------------------------------------
save()660 void MainWindow::save()
661 {
662 if(filename.isEmpty()) saveAs();
663 else edit->save(filename);
664 }
665 //-----------------------------------------------------------------------------
saveAs()666 void MainWindow::saveAs()
667 {
668 QString fn;
669 fn = QFileDialog::getSaveFileName(this, _("UDAV - save file"), "",
670 _("MGL scripts (*.mgl)\nHDF5 files (*.hdf *.h5)\nAll files (*.*)"));
671 if(fn.isEmpty())
672 { setStatus(_("Saving aborted")); return; }
673 else
674 {
675 int nn=fn.length();
676 if(fn[nn-4]!='.' && fn[nn-3]!='.') fn = fn + ".mgl";
677 filename = fn; save();
678 }
679 }
680 //-----------------------------------------------------------------------------
setAsterix()681 void MainWindow::setAsterix()
682 {
683 if(edit->isModified())
684 {
685 if(filename.isEmpty())
686 setWindowTitle(_("untitled* - UDAV"));
687 else
688 setWindowTitle(QFileInfo(filename).fileName()+"* - UDAV");
689 }
690 else
691 {
692 if(filename.isEmpty())
693 setWindowTitle(_("untitled - UDAV"));
694 else
695 setWindowTitle(QFileInfo(filename).fileName()+" - UDAV");
696 }
697 }
698 //-----------------------------------------------------------------------------
updateDataItems()699 void updateDataItems()
700 {
701 foreach (QWidget *w, QApplication::topLevelWidgets())
702 if(w->inherits("MainWindow")) ((MainWindow *)w)->refresh();
703 }
704 //-----------------------------------------------------------------------------
addPanel(QWidget * w,QString name)705 void MainWindow::addPanel(QWidget *w, QString name)
706 {
707 ltab->addTab(w,QPixmap(":/png/text-csv.png"),name);
708 ltab->setCurrentWidget(w);
709 }
710 //-----------------------------------------------------------------------------
findMain(QWidget * wnd)711 MGL_LOCAL_PURE MainWindow *findMain(QWidget *wnd)
712 {
713 MainWindow *mw=0;
714 QObject *w=wnd;
715
716 while(w && !mw)
717 {
718 mw = dynamic_cast<MainWindow *>(w);
719 w = w->parent();
720 }
721 return mw;
722 }
723 //-----------------------------------------------------------------------------
raisePanel(QWidget * w)724 void raisePanel(QWidget *w)
725 {
726 MainWindow *mw=findMain(w);
727 if(mw) mw->rtab->setCurrentWidget(w);
728 }
729 //-----------------------------------------------------------------------------
updateHidden()730 void MainWindow::updateHidden()
731 {
732 QTextCursor tc = edit->edit->textCursor();
733 long pos = tc.position(), i=0;
734 hidden->clear();
735 tc.movePosition(QTextCursor::Start);
736 do {
737 i++;
738 if(tc.block().text().startsWith("#h "))
739 hidden->append("Line "+QString::number(i)+QString::fromWCharArray(L" \u2192 ")+tc.block().text().mid(3)+"\n");
740 } while(tc.movePosition(QTextCursor::NextBlock));
741 tc.setPosition(pos);
742 }
743 //-----------------------------------------------------------------------------
hiddenClicked()744 void MainWindow::hiddenClicked()
745 {
746 QString q = hidden->textCursor().block().text();
747 if(q.contains("Line "))
748 {
749 int n = q.section(' ',1,1).toInt()-1;
750 edit->edit->moveCursor(QTextCursor::Start);
751 for(int i=0;i<n;i++) edit->edit->moveCursor(QTextCursor::NextBlock);
752 edit->edit->textCursor().deleteChar();
753 edit->edit->textCursor().deleteChar();
754 edit->edit->textCursor().deleteChar();
755 }
756 graph->execute();
757 }
758 //-----------------------------------------------------------------------------
messClicked()759 void MainWindow::messClicked()
760 {
761 QString q = mess->textCursor().block().text();
762 if(q.contains("in line "))
763 {
764 int n = q.section(' ',-1).toInt()-1; if(n<0) return;
765 edit->moveCursor(QTextCursor::Start);
766 for(int i=0;i<n;i++) edit->moveCursor(QTextCursor::NextBlock);
767 }
768 edit->setFocus();
769 }
770 //-----------------------------------------------------------------------------
warnChanged()771 void MainWindow::warnChanged()
772 {
773 if(mess->toPlainText().isEmpty())
774 { messWnd->hide(); ainfo->setChecked(false); }
775 else
776 { messWnd->show(); ainfo->setChecked(true); }
777 }
778 //-----------------------------------------------------------------------------
779