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 #include <QTime>
21 #include <QMenu>
22 #include <QPrinter>
23 #include <QTimer>
24 #include <QScrollArea>
25 #include <QPainter>
26 #include <QPrintDialog>
27 #include <QToolButton>
28 #include <QToolBar>
29 #include <QSpinBox>
30 #include <QBoxLayout>
31 #include <QMenuBar>
32 #include <QMessageBox>
33 #include <QTextEdit>
34 #include <QTextBlock>
35
36 #include <QMdiArea>
37 #include "udav_wnd.h"
38 #include "mgl2/qmathgl.h"
39 #include "plot_pnl.h"
40 #include "anim_dlg.h"
41 #include "style_dlg.h"
42 #include "newcmd_dlg.h"
43 #include "subplot_dlg.h"
44 #undef sprintf
45 extern bool mglAutoSave;
46 extern bool mglHighlight;
47 extern bool mglDotsRefr;
48 extern mglParse parser;
49 int animDelay=500;
50 void raisePanel(QWidget *w);
51 //-----------------------------------------------------------------------------
PlotPanel(QWidget * parent)52 PlotPanel::PlotPanel(QWidget *parent) : QWidget(parent)
53 {
54 gifOn = jpgOn = false;
55 animDialog = new AnimParam(this); animPos = -1;
56 stlDialog = new StyleDialog(this);
57 newCmdDlg = new NewCmdDialog(this);
58 subplotDlg = new SubplotDialog(this);
59 printer = new QPrinter; curPos = subId = -1;
60 timer = new QTimer(this);
61 connect(timer, SIGNAL(timeout()), this, SLOT(next()));
62 connect(animDialog, SIGNAL(putText(const QString &)), this, SLOT(animText(const QString &)));
63 connect(newCmdDlg, SIGNAL(result(const QString&, bool)), this, SLOT(putCmd(const QString&)));
64 connect(subplotDlg, SIGNAL(result(const QString&)), this, SLOT(insCmd(const QString&)));
65
66 menu = new QMenu(_("Graphics"),this);
67 popup = new QMenu(this);
68 mgl = new QMathGL(this);
69 draw = new mglDrawScript(parser.Self());
70 mgl_set_flag(mgl->getGraph(),1,MGL_SHOW_POS); mgl->setDraw(draw);
71 connect(mgl,SIGNAL(askStyle(int)),this,SLOT(setStyle(int)));
72 connect(mgl,SIGNAL(objChanged(int)),this,SLOT(setCurPos(int)));
73
74 QBoxLayout *v = new QVBoxLayout(this); toolTop(v);
75 QBoxLayout *h = new QHBoxLayout(); v->addLayout(h); toolLeft(h);
76 mgl->setPopup(popup);
77
78 sv = new QScrollArea(this); h->addWidget(sv); sv->setWidget(mgl);
79 emit giveFocus();
80 }
81 //-----------------------------------------------------------------------------
~PlotPanel()82 PlotPanel::~PlotPanel() { delete printer; }
83 //-----------------------------------------------------------------------------
setStyle(int id)84 void PlotPanel::setStyle(int id)
85 { if(stlDialog->exec()) mgl->setStyle(id, stlDialog->getStyle()); }
86 //-----------------------------------------------------------------------------
setSubId(int id)87 void PlotPanel::setSubId(int id) { subId = id; }
88 //-----------------------------------------------------------------------------
animText(const QString & txt)89 void PlotPanel::animText(const QString &txt) { animPutText(txt); }
90 //-----------------------------------------------------------------------------
setCurPos(int pos)91 void PlotPanel::setCurPos(int pos)
92 {
93 if(!mglHighlight) pos = -1;
94 if(curPos!=pos) { curPos = pos; execute(); }
95 }
96 //-----------------------------------------------------------------------------
stop()97 void PlotPanel::stop() { parser.Stop(); mgl->stop(); }
98 //-----------------------------------------------------------------------------
execute()99 void PlotPanel::execute()
100 {
101 if(mglAutoSave) save();
102 mgl->setDotsPreview(mglDotsRefr);
103 raisePanel(this);
104 objId = subId = -1;
105 emit clearWarn();
106 QTime t; t.start();
107 mgl_set_facenum(mgl->getGraph(),0);
108 draw->text=textMGL->toPlainText();
109 draw->line=curPos;
110 mgl->update();
111 setStatus(QString(_("Drawing time %1 ms")).arg(t.elapsed()*1e-3));
112 emit giveFocus();
113 }
114 //-----------------------------------------------------------------------------
pressF9()115 void PlotPanel::pressF9()
116 {
117 int l=animParam.length(), i;
118 wchar_t *str = new wchar_t[l+2];
119 animPos = 0; curPos = -1;
120 QString cur = animParam.section('\n',animPos,animPos);
121 for(i=0;i<l;i++) str[i] = (cur[i]).unicode();
122 str[i] = 0;
123 parser.AddParam(0,str);
124 delete []str;
125
126 QTime t; t.start();
127 parser.RestoreOnce();
128 draw->text=textMGL->toPlainText();
129 draw->line=curPos; mgl->update();
130 setStatus(QString(_("Drawing time %1 ms")).arg(t.elapsed()*1e-3));
131 emit giveFocus();
132 }
133 //-----------------------------------------------------------------------------
animStart(bool st)134 void PlotPanel::animStart(bool st)
135 {
136 if(!st)
137 { timer->stop(); if(gifOn) mgl_close_gif(mgl->getGraph()); return; }
138 if(animParam.isEmpty())
139 {
140 if(animDialog->exec())
141 {
142 animParam = animDialog->getResult();
143 gifOn = animDialog->gifOn;
144 jpgOn = animDialog->jpgOn;
145 }
146 else return;
147 }
148 timer->start(animDelay);
149 if(gifOn)
150 {
151 mglGraph gr(mgl->getGraph());
152 gr.StartGIF("", animDelay);
153 gr.ResetFrames();
154 }
155 raisePanel(this);
156 }
157 //-----------------------------------------------------------------------------
nextSlide()158 void PlotPanel::nextSlide()
159 {
160 animSwitch(false);
161 next();
162 emit giveFocus();
163 }
164 //-----------------------------------------------------------------------------
next()165 void PlotPanel::next()
166 {
167 if(animParam.isEmpty())
168 {
169 if(animDialog->exec())
170 {
171 animParam = animDialog->getResult();
172 gifOn = animDialog->gifOn;
173 jpgOn = animDialog->jpgOn;
174 }
175 else return;
176 }
177 int l=animParam.length(), n=animParam.count('\n') + (animParam[l-1]=='\n' ? 0:1), i;
178 wchar_t *str = new wchar_t[l+2];
179 animPos = (animPos+1)%n;
180 QString cur = animParam.section('\n',animPos,animPos);
181 for(i=0;i<l;i++) str[i] = (cur[i]).unicode();
182 str[i] = 0;
183 parser.AddParam(0,str);
184 delete []str;
185 mglGraph gr(mgl->getGraph());
186 if(gr.GetNumFrame() >= n) execute();
187 else
188 {
189 gr.NewFrame(); execute(); gr.EndFrame();
190 if(jpgOn) gr.WriteFrame();
191 QString s; s.asprintf(_("%d - %d of %d"),gr.GetNumFrame(),animPos,n);
192 setStatus(QString(_("Frame %1 of %2")).arg(animPos).arg(n));
193 }
194 }
195 //-----------------------------------------------------------------------------
prevSlide()196 void PlotPanel::prevSlide()
197 {
198 if(animParam.isEmpty())
199 {
200 if(animDialog->exec())
201 {
202 animParam = animDialog->getResult();
203 gifOn = animDialog->gifOn;
204 jpgOn = animDialog->jpgOn;
205 }
206 else return;
207 }
208 animSwitch(false);
209 int l=animParam.length(), n=animParam.count('\n') + (animParam[l-1]=='\n' ? 0:1), i;
210 wchar_t *str = new wchar_t[l+2];
211 animPos = (animPos-1+n)%n;
212 QString cur = animParam.section('\n',animPos,animPos);
213 for(i=0;i<l;i++) str[i] = (cur[i]).unicode();
214 str[i] = 0;
215 parser.AddParam(0,str);
216 delete []str;
217 execute();
218 emit giveFocus();
219 }
220 //-----------------------------------------------------------------------------
animSetup()221 void PlotPanel::animSetup()
222 {
223 if(animDialog->exec())
224 {
225 animParam = animDialog->getResult();
226 gifOn = animDialog->gifOn;
227 jpgOn = animDialog->jpgOn;
228 animPos = -1;
229 }
230 }
231 //-----------------------------------------------------------------------------
adjust()232 void PlotPanel::adjust()
233 {
234 mgl->setSize(sv->width()-5, sv->height()-5);
235 raisePanel(this); emit giveFocus();
236 }
237 //-----------------------------------------------------------------------------
setMGLFont(const QString & path)238 void PlotPanel::setMGLFont(const QString &path) { mgl->setMGLFont(path); }
239 //-----------------------------------------------------------------------------
animParseText(const QString & txt)240 void PlotPanel::animParseText(const QString &txt)
241 {
242 int i, n = txt.count('\n')+1;
243 double a1=0,a2=0,da=0;
244 QString s, all;
245 for(i=0;i<n;i++)
246 {
247 s = txt.section('\n',i,i);
248 if(s[0]=='#' && s[1]=='#' && s[2]=='a' && s[3].isSpace())
249 all = all + s.mid(4) + "\n";
250 if(s[0]=='#' && s[1]=='#' && s[2]=='c' && s[3].isSpace())
251 {
252 s = s.mid(4);
253 a1 = s.section(' ',0,0).toDouble();
254 a2 = s.section(' ',1,1).toDouble();
255 da = s.section(' ',2,2).toDouble();
256 animDialog->setResult(a1,a2,da);
257 }
258 }
259 if(!all.isEmpty())
260 {
261 animDialog->setResult(all);
262 animParam = all;
263 }
264 else if(a1!=a2 && da!=0)
265 {
266 for(double a=a1;a<=a2;a+=da) all = all + QString::number(a)+"\n";
267 animParam = all;
268 }
269 }
270 //-----------------------------------------------------------------------------
271 //#include "xpm/wire.xpm"
272 #include "xpm/text.xpm"
273 #include "xpm/line.xpm"
274 #include "xpm/curve.xpm"
275 #include "xpm/mark_o.xpm"
276 #include "xpm/mark_s.xpm"
277 #include "xpm/mark_a.xpm"
278 #include "xpm/mark_d.xpm"
279 #include "xpm/arc.xpm"
280 #include "xpm/polygon.xpm"
281 #include "xpm/box.xpm"
282 //-----------------------------------------------------------------------------
toolTop(QBoxLayout * v)283 void PlotPanel::toolTop(QBoxLayout *v)
284 {
285 QAction *a, *aa;
286 QMenu *o=menu, *oo;
287 QToolBar *t = new QToolBar(this); v->addWidget(t); t->setMovable(false);
288
289 // graphics menu
290 a = new QAction(QPixmap(":/png/alpha.png"), _("Alpha"), this);
291 a->setShortcut(Qt::CTRL+Qt::Key_T); a->setCheckable(true);
292 connect(a, SIGNAL(toggled(bool)), mgl, SLOT(setAlpha(bool)));
293 connect(mgl, SIGNAL(alphaChanged(bool)), a, SLOT(setChecked(bool)));
294 a->setToolTip(_("Switch on/off transparency for the graphics (Ctrl+T)."));
295 o->addAction(a); t->addAction(a);
296
297 a = new QAction(QPixmap(":/png/weather-clear.png"), _("Light"), this);
298 a->setShortcut(Qt::CTRL+Qt::Key_L); a->setCheckable(true);
299 connect(a, SIGNAL(toggled(bool)), mgl, SLOT(setLight(bool)));
300 connect(mgl, SIGNAL(lightChanged(bool)), a, SLOT(setChecked(bool)));
301 a->setToolTip(_("Switch on/off lightning for the graphics (Ctrl+L)."));
302 o->addAction(a); t->addAction(a);
303
304 a = new QAction(QPixmap(":/png/view-grid.png"), _("Grid"), this);
305 a->setShortcut(Qt::CTRL+Qt::Key_G); a->setCheckable(true);
306 connect(a, SIGNAL(toggled(bool)), mgl, SLOT(setGrid(bool)));
307 a->setToolTip(_("Switch on/off grid of absolute coordinates (Ctrl+G)."));
308 o->addAction(a); t->addAction(a);
309
310 a = new QAction(QPixmap(":/png/transform-move.png"), _("Rotate by mouse"), this);
311 a->setCheckable(true);
312 connect(a, SIGNAL(toggled(bool)), mgl, SLOT(setRotate(bool)));
313 connect(mgl, SIGNAL(rotateChanged(bool)), a, SLOT(setChecked(bool)));
314 a->setToolTip(_("Switch on/off mouse handling of the graphics\n(rotation, shifting, zooming and perspective)."));
315 t->addAction(a);
316
317 /* a = new QAction(QPixmap(":/png/zoom-fit-best.png"), _("Zoom by mouse"), this);
318 a->setCheckable(true);
319 connect(a, SIGNAL(toggled(bool)), mgl, SLOT(setZoom(bool)));
320 connect(mgl, SIGNAL(zoomChanged(bool)), a, SLOT(setChecked(bool)));
321 a->setToolTip(_("Switch on/off mouse zoom of selected region."));
322 t->addAction(a);*/
323
324 o->addSeparator();
325 a = new QAction(QPixmap(":/png/zoom-original.png"), _("Restore"), this);
326 connect(a, SIGNAL(triggered()), mgl, SLOT(restore()));
327 a->setToolTip(_("Restore default graphics rotation, zoom and perspective (Ctrl+Space)."));
328 a->setShortcut(Qt::CTRL+Qt::Key_Space);
329 o->addAction(a); popup->addAction(a); t->addAction(a);
330
331 a = new QAction(QPixmap(":/png/view-refresh.png"), _("Redraw"), this);
332 connect(a, SIGNAL(triggered()), this, SLOT(execute()));
333 a->setToolTip(_("Execute script and redraw graphics (F5)."));
334 a->setShortcut(Qt::Key_F5);
335 o->addAction(a); popup->addAction(a); t->addAction(a);
336
337 a = new QAction(QPixmap(":/png/view-fullscreen.png"), _("Adjust size"), this);
338 connect(a, SIGNAL(triggered()), this, SLOT(adjust()));
339 a->setToolTip(_("Change canvas size to fill whole region (F6)."));
340 a->setShortcut(Qt::Key_F6); o->addAction(a);
341
342 a = new QAction(QPixmap(":/png/document-revert.png"), _("Reload"), this);
343 connect(a, SIGNAL(triggered()), this, SLOT(pressF9()));
344 a->setToolTip(_("Restore status for 'once' command and reload data (F9)."));
345 a->setShortcut(Qt::Key_F9); o->addAction(a); popup->addAction(a);
346
347 a = new QAction(QPixmap(":/png/process-stop.png"), _("Stop"), this);
348 connect(a, SIGNAL(triggered()), this, SLOT(stop()));
349 a->setToolTip(_("Stop script execution (F7)."));
350 a->setShortcut(Qt::Key_F7); o->addAction(a); t->addAction(a);
351
352 a = new QAction(QPixmap(":/png/edit-copy.png"), _("Copy plot"), this);
353 connect(a, SIGNAL(triggered()), mgl, SLOT(copy()));
354 a->setToolTip(_("Copy graphics to clipboard (Ctrl+Shift+G)."));
355 a->setShortcut(Qt::CTRL+Qt::SHIFT+Qt::Key_G);
356 o->addAction(a); popup->addAction(a); t->addAction(a);
357
358 a = new QAction(QPixmap(":/png/edit-copy.png"), _("Copy click coor."), this);
359 connect(a, SIGNAL(triggered()), mgl, SLOT(copyClickCoor()));
360 a->setToolTip(_("Copy coordinates of last mouse click to clipboard."));
361 o->addAction(a); popup->addAction(a);
362
363 // l->addStretch(1);
364 {
365 oo = new QMenu(_("Primitives ..."),this);
366 aa=a = new QAction(QPixmap(line_xpm), _("Add line"), this);
367 connect(a, SIGNAL(triggered()), mgl, SLOT(addLine()));
368 connect(mgl, SIGNAL(usePrimChanged(bool)), a, SLOT(setVisible(bool)));
369 a->setToolTip(_("Add line which properties can be changed later by mouse."));
370 oo->addAction(a);
371
372 a = new QAction(QPixmap(arc_xpm), _("Add arc"), this);
373 connect(a, SIGNAL(triggered()), mgl, SLOT(addArc()));
374 connect(mgl, SIGNAL(usePrimChanged(bool)), a, SLOT(setVisible(bool)));
375 a->setToolTip(_("Add arc which properties can be changed later by mouse."));
376 oo->addAction(a);
377
378 a = new QAction(QPixmap(curve_xpm), _("Add curve"), this);
379 connect(a, SIGNAL(triggered()), mgl, SLOT(addCurve()));
380 connect(mgl, SIGNAL(usePrimChanged(bool)), a, SLOT(setVisible(bool)));
381 a->setToolTip(_("Add curve which properties can be changed later by mouse."));
382 oo->addAction(a);
383
384 a = new QAction(QPixmap(mark_s_xpm), _("Add rect"), this);
385 connect(a, SIGNAL(triggered()), mgl, SLOT(addRect()));
386 connect(mgl, SIGNAL(usePrimChanged(bool)), a, SLOT(setVisible(bool)));
387 a->setToolTip(_("Add rectangle which properties can be changed later by mouse."));
388 oo->addAction(a);
389
390 a = new QAction(QPixmap(mark_d_xpm), _("Add rhombus"), this);
391 connect(a, SIGNAL(triggered()), mgl, SLOT(addRhomb()));
392 connect(mgl, SIGNAL(usePrimChanged(bool)), a, SLOT(setVisible(bool)));
393 a->setToolTip(_("Add rhombus which properties can be changed later by mouse."));
394 oo->addAction(a);
395
396 a = new QAction(QPixmap(mark_o_xpm), _("Add ellipse"), this);
397 connect(a, SIGNAL(triggered()), mgl, SLOT(addEllipse()));
398 connect(mgl, SIGNAL(usePrimChanged(bool)), a, SLOT(setVisible(bool)));
399 a->setToolTip(_("Add ellipse which properties can be changed later by mouse."));
400 oo->addAction(a);
401
402 a = new QAction(QPixmap(polygon_xpm), _("Add polygon"), this);
403 connect(a, SIGNAL(triggered()), mgl, SLOT(addPolygon()));
404 connect(mgl, SIGNAL(usePrimChanged(bool)), a, SLOT(setVisible(bool)));
405 a->setToolTip(_("Add ellipse which properties can be changed later by mouse."));
406 oo->addAction(a);
407
408 a = new QAction(QPixmap(mark_a_xpm), _("Add mark"), this);
409 connect(a, SIGNAL(triggered()), mgl, SLOT(addMark()));
410 connect(mgl, SIGNAL(usePrimChanged(bool)), a, SLOT(setVisible(bool)));
411 a->setToolTip(_("Add marker which properties can be changed later by mouse."));
412 oo->addAction(a);
413
414 a = new QAction(QPixmap(text_xpm), _("Add text"), this);
415 connect(a, SIGNAL(triggered()), mgl, SLOT(addText()));
416 connect(mgl, SIGNAL(usePrimChanged(bool)), a, SLOT(setVisible(bool)));
417 a->setToolTip(_("Add text which properties can be changed later by mouse."));
418 oo->addAction(a);
419
420 QToolButton *bb = new QToolButton(this);
421 bb->setDefaultAction(aa); bb->setMenu(oo);
422 bb->setPopupMode(QToolButton::MenuButtonPopup);
423 t->addWidget(bb);
424 }
425
426 a = new QAction(QPixmap(":/png/edit-delete.png"), _("Delete selected"), this);
427 connect(a, SIGNAL(triggered()), this, SLOT(deleteSelected()));
428 a->setToolTip(_("Delete selected plot."));
429 o->addAction(a); popup->addAction(a); t->addAction(a);
430
431 a = new QAction(QPixmap(":/png/layer-visible-off.png"), _("Hide selected"), this);
432 connect(a, SIGNAL(triggered()), this, SLOT(hideSelected()));
433 a->setToolTip(_("Hide selected plots."));
434 o->addAction(a); popup->addAction(a); t->addAction(a);
435
436 const MainWindow *mw=findMain(this);
437 if(mw) t->addAction(mw->ahide);
438
439 a = new QAction(QPixmap(":/png/format-indent-more.png"), _("New command"), this);
440 connect(a, SIGNAL(triggered()), newCmdDlg, SLOT(show()));
441 a->setToolTip(_("Show dialog for new command or edit arguments of existed one."));
442 o->addAction(a); popup->addAction(a); t->addAction(a);
443
444 a = new QAction(QPixmap(box_xpm), _("New inplot"), this);
445 connect(a, SIGNAL(triggered()), subplotDlg, SLOT(show()));
446 a->setToolTip(_("Show dialog for new inplot and put it into the script."));
447 o->addAction(a); popup->addAction(a); t->addAction(a);
448
449 a = new QAction(QPixmap(":/png/object-order-lower.png"), _("Move plot up"), this);
450 connect(a, SIGNAL(triggered()), this, SLOT(movePlotUp()));
451 a->setToolTip(_("Move selected plot up to previous subplot."));
452 o->addAction(a); popup->addAction(a); t->addAction(a);
453
454 a = new QAction(QPixmap(":/png/object-order-raise.png"), _("Move plot down"), this);
455 connect(a, SIGNAL(triggered()), this, SLOT(movePlotDown()));
456 a->setToolTip(_("Move selected plot down to next subplot."));
457 o->addAction(a); popup->addAction(a); t->addAction(a);
458
459
460 o->addMenu(oo); //t->addSeparator();
461
462 tet = new QSpinBox(this); tet->setWrapping(true);
463 t->addWidget(tet); tet->setRange(-180, 180); tet->setSingleStep(10);
464 connect(tet, SIGNAL(valueChanged(int)), mgl, SLOT(setTet(int)));
465 connect(mgl, SIGNAL(tetChanged(int)), tet, SLOT(setValue(int)));
466 tet->setToolTip(_("Set value of \\theta angle.\nYou can use keys (Shift+Meta+Up or Shift+Meta+Down)."));
467
468 phi = new QSpinBox(this); phi->setWrapping(true);
469 t->addWidget(phi); phi->setRange(-180, 180); phi->setSingleStep(10);
470 connect(phi, SIGNAL(valueChanged(int)), mgl, SLOT(setPhi(int)));
471 connect(mgl, SIGNAL(phiChanged(int)), phi, SLOT(setValue(int)));
472 phi->setToolTip(_("Set value of \\phi angle.\nYou can use keys (Shift+Meta+Left or Shift+Meta+Right)."));
473
474 oo = new QMenu(_("Export as 2D ..."),this);
475 oo->addAction(_("PNG"), mgl, SLOT(exportPNG()),Qt::ALT+Qt::Key_P);
476 oo->addAction(_("solid PNG"), mgl, SLOT(exportPNGs()),Qt::ALT+Qt::Key_F);
477 oo->addAction(_("JPEG"), mgl, SLOT(exportJPG()),Qt::ALT+Qt::Key_J);
478 oo->addAction(_("bitmap EPS"), mgl, SLOT(exportBPS()));
479 oo->addAction(_("vector EPS"), mgl, SLOT(exportEPS()),Qt::ALT+Qt::Key_E);
480 oo->addAction(_("SVG"), mgl, SLOT(exportSVG()),Qt::ALT+Qt::Key_S);
481 oo->addAction(_("LaTeX"), mgl, SLOT(exportTEX()),Qt::ALT+Qt::Key_L);
482
483 o->addMenu(oo); popup->addMenu(oo);
484 oo = new QMenu(_("Export as 3D ..."),this);
485 oo->addAction(_("MGLD"), mgl, SLOT(exportMGLD()),Qt::ALT+Qt::Key_M);
486 oo->addAction(_("PRC"), mgl, SLOT(exportPRC()),Qt::ALT+Qt::Key_D);
487 oo->addAction(_("OBJ"), mgl, SLOT(exportOBJ()),Qt::ALT+Qt::Key_O);
488 oo->addAction(_("STL"), mgl, SLOT(exportSTL()));
489 oo->addAction(_("XYZ"), mgl, SLOT(exportXYZ()));
490 // oo->addAction(_("X3D"), QMGL, SLOT(exportX3D()),Qt::ALT+Qt::Key_X); // TODO: Add later
491 o->addMenu(oo); popup->addMenu(oo);
492 }
493 //-----------------------------------------------------------------------------
toolLeft(QBoxLayout * h)494 void PlotPanel::toolLeft(QBoxLayout *h)
495 {
496 QAction *a;
497 QMenu *o=menu, *oo;
498 QToolBar *t = new QToolBar(this); h->addWidget(t); t->setMovable(false);
499 t->setAllowedAreas(Qt::LeftToolBarArea); t->setOrientation(Qt::Vertical);
500
501 // zooming menu
502 oo = o->addMenu(_("Zoom/move"));
503 a = new QAction(QPixmap(":/png/arrow-left.png"), _("Move left"), this);
504 connect(a, SIGNAL(triggered()), mgl, SLOT(shiftLeft()));
505 a->setShortcut(Qt::ALT+Qt::Key_Left);
506 a->setToolTip(_("Move graphics left by 1/3 of its width."));
507 oo->addAction(a); t->addAction(a);
508
509 a = new QAction(QPixmap(":/png/arrow-up.png"), _("Move up"), this);
510 connect(a, SIGNAL(triggered()), mgl, SLOT(shiftUp()));
511 a->setShortcut(Qt::ALT+Qt::Key_Up);
512 a->setToolTip(_("Move graphics up by 1/3 of its height."));
513 oo->addAction(a); t->addAction(a);
514
515 a = new QAction(QPixmap(":/png/zoom-in.png"), _("Zoom in"), this);
516 connect(a, SIGNAL(triggered()), mgl, SLOT(zoomIn()));
517 a->setShortcut(Qt::ALT+Qt::Key_Equal);
518 a->setToolTip(_("Zoom in graphics."));
519 oo->addAction(a); t->addAction(a);
520
521 a = new QAction(QPixmap(":/png/zoom-out.png"), _("Zoom out"), this);
522 connect(a, SIGNAL(triggered()), mgl, SLOT(zoomOut()));
523 a->setShortcut(Qt::ALT+Qt::Key_Minus);
524 a->setToolTip(_("Zoom out graphics."));
525 oo->addAction(a); t->addAction(a);
526
527 a = new QAction(QPixmap(":/png/arrow-down.png"), _("Move down"), this);
528 connect(a, SIGNAL(triggered()), mgl, SLOT(shiftDown()));
529 a->setShortcut(Qt::ALT+Qt::Key_Down);
530 a->setToolTip(_("Move graphics down 1/3 of its height."));
531 oo->addAction(a); t->addAction(a);
532
533 a = new QAction(QPixmap(":/png/arrow-right.png"), _("Move right"), this);
534 connect(a, SIGNAL(triggered()), mgl, SLOT(shiftRight()));
535 a->setShortcut(Qt::ALT+Qt::Key_Right);
536 a->setToolTip(_("Move graphics right by 1/3 of its width."));
537 oo->addAction(a); t->addAction(a);
538
539 // rotate menu
540 oo = o->addMenu(_("Rotate"));
541 a = new QAction(QPixmap(":/png/object-rotate-up.png"), _("Rotate up"), this);
542 a->setShortcut(Qt::SHIFT+Qt::META+Qt::Key_Up);
543 connect(a, SIGNAL(triggered()), tet, SLOT(stepUp())); oo->addAction(a);
544 a->setToolTip(_("Increase \\theta angle by 10 degrees."));
545 a = new QAction(QPixmap(":/png/object-rotate-down.png"), _("Rotate down"), this);
546 a->setShortcut(Qt::SHIFT+Qt::META+Qt::Key_Down);
547 connect(a, SIGNAL(triggered()), tet, SLOT(stepDown())); oo->addAction(a);
548 a->setToolTip(_("Decrease \\theta angle by 10 degrees."));
549 a = new QAction(QPixmap(":/png/object-rotate-left.png"), _("Rotate left"), this);
550 a->setShortcut(Qt::SHIFT+Qt::META+Qt::Key_Right);
551 connect(a, SIGNAL(triggered()), phi, SLOT(stepUp())); oo->addAction(a);
552 a->setToolTip(_("Increase \\phi angle by 10 degrees."));
553 a = new QAction(QPixmap(":/png/object-rotate-right.png"), _("Rotate right"), this);
554 a->setShortcut(Qt::SHIFT+Qt::META+Qt::Key_Left);
555 connect(a, SIGNAL(triggered()), phi, SLOT(stepDown())); oo->addAction(a);
556 a->setToolTip(_("Decrease \\phi angle by 10 degrees."));
557
558 // animation menu
559 oo = o->addMenu(_("Animation"));
560 a = new QAction(QPixmap(":/png/media-seek-forward.png"), _("Next slide"), this);
561 connect(a, SIGNAL(triggered()), this, SLOT(nextSlide()));
562 a->setShortcut(Qt::CTRL+Qt::Key_Period);
563 a->setToolTip(_("Show next slide (Ctrl+.)."));
564 oo->addAction(a); t->addAction(a);
565
566 a = new QAction(QPixmap(":/png/media-playback-start.png"), _("Slideshow"), this);
567 a->setCheckable(true);
568 connect(a, SIGNAL(toggled(bool)), this, SLOT(animStart(bool)));
569 connect(this, SIGNAL(animSwitch(bool)),a,SLOT(setChecked(bool)));
570 a->setToolTip(_("Run slideshow (Ctrl+F5). If no parameter specified\nthen the dialog with slideshow options will appear."));
571 a->setShortcut(Qt::CTRL+Qt::Key_F5); oo->addAction(a); t->addAction(a);
572
573 oo->addAction(_("Setup show"), this, SLOT(animSetup()), Qt::CTRL+Qt::Key_W);
574
575 a = new QAction(QPixmap(":/png/media-seek-backward.png"), _("Prev slide"), this);
576 connect(a, SIGNAL(triggered()), this, SLOT(prevSlide()));
577 a->setShortcut(Qt::CTRL+Qt::Key_Comma);
578 a->setToolTip(_("Show previous slide (Ctrl+,)."));
579 oo->addAction(a); t->addAction(a);
580 }
581 //-----------------------------------------------------------------------------
getFit()582 QString PlotPanel::getFit() { return QString(mgl_get_fit(mgl->getGraph())); }
583 //-----------------------------------------------------------------------------
deleteSelected()584 void PlotPanel::deleteSelected()
585 {
586 if(curPos>=0)
587 {
588 textMGL->moveCursor(QTextCursor::Start);
589 for(int i=0;i<curPos;i++) textMGL->moveCursor(QTextCursor::NextBlock);
590 QTextCursor tc= textMGL->textCursor();
591 tc.select(QTextCursor::LineUnderCursor);
592 tc.removeSelectedText();
593 tc.deleteChar();
594 curPos = -1; execute();
595 }
596 else emit setStatus("No selection.");
597 }
598 //-----------------------------------------------------------------------------
hideSelected()599 void PlotPanel::hideSelected()
600 {
601 if(curPos>=0)
602 {
603 textMGL->moveCursor(QTextCursor::Start);
604 for(int i=0;i<curPos;i++) textMGL->moveCursor(QTextCursor::NextBlock);
605 textMGL->insertPlainText("#h ");
606 curPos = -1; execute();
607 }
608 else emit setStatus("No selection.");
609 }
610 //-----------------------------------------------------------------------------
putCmd(const QString & cmd)611 void PlotPanel::putCmd(const QString &cmd)
612 {
613 textMGL->moveCursor(QTextCursor::Start);
614 if(curPos>=0) for(int i=0;i<curPos;i++)
615 textMGL->moveCursor(QTextCursor::NextBlock);
616 textMGL->insertPlainText(cmd+"\n");
617 curPos = -1; execute();
618 }
619 //-----------------------------------------------------------------------------
insCmd(const QString & cmd)620 void PlotPanel::insCmd(const QString &cmd)
621 {
622 textMGL->moveCursor(QTextCursor::EndOfBlock);
623 textMGL->insertPlainText("\n"+cmd);
624 curPos = -1; execute();
625 }
626 //-----------------------------------------------------------------------------
movePlotUp()627 void PlotPanel::movePlotUp()
628 {
629 if(curPos>0)
630 {
631 QTextCursor tc = textMGL->textCursor();
632 tc.movePosition(QTextCursor::Start);
633 tc.movePosition(QTextCursor::NextBlock,QTextCursor::MoveAnchor,curPos);
634 tc.select(QTextCursor::BlockUnderCursor);
635 QString s = tc.selectedText();
636 tc.deleteChar();
637 bool ins=true;
638
639 while(tc.movePosition(QTextCursor::PreviousBlock))
640 {
641 QString q = tc.block().text();
642 if(q.startsWith("subplot ") || q.startsWith("inplot ") || q.startsWith("multiplot ") || q.startsWith("gridplot ") || q.startsWith("columnplot ") || q.startsWith("stickplot "))
643 {
644 tc.movePosition(QTextCursor::EndOfBlock);
645 tc.insertText(s); ins=false; break;
646 }
647 }
648 if(ins)
649 {
650 tc.movePosition(QTextCursor::Start); tc.insertText(s+"\n");
651 tc.movePosition(QTextCursor::Start); tc.deleteChar();
652 }
653 curPos = tc.block().blockNumber(); execute();
654 }
655 else if(curPos<0) emit setStatus("No selection.");
656 }
657 //-----------------------------------------------------------------------------
movePlotDown()658 void PlotPanel::movePlotDown()
659 {
660 if(curPos>=0)
661 {
662 QTextCursor tc = textMGL->textCursor();
663 tc.movePosition(QTextCursor::Start);
664 tc.movePosition(QTextCursor::NextBlock,QTextCursor::MoveAnchor,curPos);
665 tc.select(QTextCursor::BlockUnderCursor);
666 QString s = tc.selectedText();
667 if(curPos==0) s = "\n"+s;
668 tc.deleteChar();
669 bool ins=true;
670
671 while(tc.movePosition(QTextCursor::NextBlock))
672 {
673 QString q = tc.block().text();
674 if(q.startsWith("subplot ") || q.startsWith("inplot ") || q.startsWith("multiplot ") || q.startsWith("gridplot ") || q.startsWith("columnplot ") || q.startsWith("stickplot "))
675 {
676 tc.movePosition(QTextCursor::EndOfBlock);
677 tc.insertText(s); ins=false; break;
678 }
679 }
680 if(ins) { tc.movePosition(QTextCursor::End); tc.insertText(s); }
681 curPos = tc.block().blockNumber(); execute();
682 }
683 else emit setStatus("No selection.");
684 }
685 //-----------------------------------------------------------------------------
686
687