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