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 <QTableWidget>
21 #include <QLabel>
22 #include <QAction>
23 #include <QLayout>
24 #include <QMenuBar>
25 #include <QLineEdit>
26 #include <QMenu>
27 #include <QClipboard>
28 #include <QStatusBar>
29 #include <QFileDialog>
30 #include <QPushButton>
31 #include <QApplication>
32 #include <QInputDialog>
33 #include <QToolButton>
34 #include <QSpinBox>
35 #include <QComboBox>
36 #include <QCheckBox>
37 #include <QMessageBox>
38 #include <mgl2/mgl.h>
39 //-----------------------------------------------------------------------------
40 #include "dat_pnl.h"
41 #include "info_dlg.h"
42 #include "xpm/table.xpm"
43 #undef sprintf // fix libintl bug of defining sprintf
44 //-----------------------------------------------------------------------------
45 extern mglParse parser;
46 void updateDataItems();
47 void addDataPanel(QWidget *wnd, QWidget *w, QString name);
deleteDat(void * o)48 void deleteDat(void *o) { if(o) delete ((DatPanel *)o); }
refreshData(QWidget * w)49 void refreshData(QWidget *w) { ((DatPanel *)w)->refresh(); }
50 //-----------------------------------------------------------------------------
newDataWnd(InfoDialog * inf,QWidget * wnd,mglDataA * v)51 QWidget *newDataWnd(InfoDialog *inf, QWidget *wnd, mglDataA *v)
52 {
53 DatPanel *t = new DatPanel(inf);
54 if(v) t->setVar(v);
55 addDataPanel(wnd,t,t->dataName());
56 return t;
57 }
58 //-----------------------------------------------------------------------------
DatPanel(InfoDialog * inf,QWidget * parent)59 DatPanel::DatPanel(InfoDialog *inf, QWidget *parent) : QWidget(parent)
60 {
61 setAttribute(Qt::WA_DeleteOnClose);
62 kz = nx = ny = nz = 0; var = 0;
63 ready = false; infoDlg = inf;
64 QBoxLayout *v,*h,*m;
65
66 menu = new QMenu(_("Data"),this);
67 v = new QVBoxLayout(this);
68 h = new QHBoxLayout(); v->addLayout(h); toolTop(h);
69 h = new QHBoxLayout(); v->addLayout(h);
70 m = new QVBoxLayout(); h->addLayout(m); toolLeft(m);
71 tab = new QTableWidget(this); h->addWidget(tab);
72 connect(tab, SIGNAL(cellChanged(int,int)), this, SLOT(putValue(int, int)));
73
74 setWindowIcon(QPixmap(table_xpm));
75 }
76 //-----------------------------------------------------------------------------
~DatPanel()77 DatPanel::~DatPanel() { if(var && var->o==this) var->o = 0; }
78 //-----------------------------------------------------------------------------
refresh()79 void DatPanel::refresh()
80 {
81 bool rc = false;
82 if(!var) return;
83 infoDlg->allowRefresh=false;
84 if(nx!=var->GetNx()) { nx = var->GetNx(); tab->setColumnCount(nx); rc=true; }
85 if(ny!=var->GetNy()) { ny = var->GetNy(); tab->setRowCount(ny); rc=true; }
86 if(kz>=var->GetNz()) { kz = 0; emit sliceChanged(0); }
87 if(nz!=var->GetNz()) { nz = var->GetNz(); emit nzChanged(nz); }
88 id = QString(var->GetColumnId());
89 if(nz==1 && ny>1 && !id.isEmpty())
90 {
91 QStringList head;
92 QString s;
93 for(int i=0;i<ny;i++)
94 {
95 s = QString("%1").arg(i);
96 if(id[i]>='a' && id[i]<='z') s=s+" ("+id[i]+")";
97 head<<s;
98 }
99 tab->setHorizontalHeaderLabels(head);
100 }
101 QString s,d;
102 if(rc)
103 {
104 QStringList sh,sv;
105 for(long i=0;i<nx;i++) sh<<QString::number(i);
106 tab->setHorizontalHeaderLabels(sh);
107 for(long i=0;i<ny;i++) sv<<QString::number(i);
108 tab->setVerticalHeaderLabels(sv);
109 for(long i=0;i<nx;i++) for(long j=0;j<ny;j++)
110 tab->setItem(j,i,new QTableWidgetItem);
111 }
112 mglDataC *cc = dynamic_cast<mglDataC*>(var);
113 if(cc) for(long i=0;i<nx;i++) for(long j=0;j<ny;j++)
114 {
115 dual f = cc->a[i+nx*(j+ny*kz)];
116 if(mgl_isnan(f)) s = "nan";
117 else if(mgl_isbad(f)) s="inf";
118 else if(imag(f)>0) s.asprintf("%.15g+%.15gi",real(f),imag(f));
119 else if(imag(f)<0) s.asprintf("%.15g-%.15gi",real(f),-imag(f));
120 else s.asprintf("%15g",real(f));
121 tab->item(j,i)->setText(s);
122 }
123 else for(long i=0;i<nx;i++) for(long j=0;j<ny;j++)
124 {
125 double f = var->v(i,j,kz);
126 if(mgl_isnan(f)) s = "nan";
127 else if(mgl_isbad(f)) s=f>0?"inf":"-inf";
128 else s.asprintf("%.15g",f);
129 tab->item(j,i)->setText(s);
130 }
131 infoDlg->allowRefresh=true; infoDlg->refresh();
132 const wchar_t *vs = var->Name();
133 long m=wcslen(vs);
134 QChar *ss = new QChar[m+1];
135 for(long i=0;i<m;i++) ss[i] = vs[i];
136 s = QString(ss, m); delete []ss;
137 d.asprintf("%d * %d * %d", nx, ny, nz);
138 ready = true;
139 }
140 //-----------------------------------------------------------------------------
setVar(mglDataA * v)141 void DatPanel::setVar(mglDataA *v)
142 {
143 ready = false;
144 if(var) var->o = 0;
145 var = v; infoDlg->setVar(v);
146 nx = ny = nz = kz = 0;
147 if(v)
148 {
149 QString s = QString::fromWCharArray(v->Name());
150 v->o = this; v->func = deleteDat;
151 refresh();
152 setWindowTitle(s + _(" - UDAV variable"));
153 infoDlg->setWindowTitle(s + _(" - UDAV preview"));
154 }
155 else
156 { tab->setColumnCount(0); tab->setRowCount(0); emit nzChanged(nz); }
157 emit sliceChanged(0);
158 }
159 //-----------------------------------------------------------------------------
setSlice(int k)160 void DatPanel::setSlice(int k)
161 {
162 if(k>=nz) k=nz-1;
163 if(k<0) k=0;
164 if(k!=kz)
165 {
166 infoDlg->setSlice(k);
167 emit sliceChanged(k);
168 kz = k; refresh();
169 }
170 }
171 //-----------------------------------------------------------------------------
mgl_str2dual(const char * s)172 dual mgl_str2dual(const char *s)
173 {
174 setlocale(LC_NUMERIC, "C");
175 double re=0,im=0; size_t ll=strlen(s);
176 while(s[ll]<=' ') ll--;
177 if(*s=='(') sscanf(s,"(%lg,%lg)",&re,&im);
178 else if(*s=='i') { re=0; im=atof(s+1); }
179 else if(*s=='[') sscanf(s,"[%lg,%lg]",&re,&im);
180 else if(*s=='{') sscanf(s,"{%lg,%lg}",&re,&im);
181 else if(s[ll]=='i')
182 {
183 double a,b;
184 int s1=sscanf(s,"%lg+%lgi",&re,&im);
185 int s2=sscanf(s,"%lg-%lgi",&a,&b);
186 if(s1<2)
187 {
188 if(s2==2) { re=a; im=-b; }
189 else { im=atof(s); re=0; }
190 }
191 }
192 else
193 {
194 double a,b;
195 int s1=sscanf(s,"%lg+i%lg",&re,&im);
196 int s2=sscanf(s,"%lg-i%lg",&a,&b);
197 if(s1<2)
198 {
199 if(s2==2) { re=a; im=-b; }
200 else { re=atof(s); im=0; }
201 }
202 }
203 setlocale(LC_NUMERIC, "");
204 return dual(re,im);
205 }
206 //-----------------------------------------------------------------------------
putValue(int r,int c)207 void DatPanel::putValue(int r, int c)
208 {
209 if(!var || r<0 || c<0 || r>=ny || c>=nx || !ready) return;
210 QString s = tab->item(r,c)->text().toLower();
211 mreal f;
212 dual g;
213 if(s=="nan") f=NAN;
214 else if(s=="inf") f=INFINITY;
215 else if(s=="-inf") f=-INFINITY;
216 else
217 { g = mgl_str2dual(s.toLocal8Bit().constData()); f = real(g); }
218 mglDataC *cc = dynamic_cast<mglDataC*>(var);
219 if(cc)
220 {
221 if(g!=cc->a[c+nx*(r+ny*kz)])
222 {
223 if(mgl_isnan(g)) s="nan";
224 else if(mgl_isbad(g)) s="inf";
225 else if(imag(g)>0) s.asprintf("%g+%gi",real(g),imag(g));
226 else if(imag(g)<0) s.asprintf("%g-%gi",real(g),-imag(g));
227 else s.asprintf("%g",real(g));
228 tab->item(r,c)->setText(s);
229 }
230 cc->a[c+nx*(r+ny*kz)] = g;
231 }
232 else
233 {
234 if(f!=var->v(c,r,kz))
235 {
236 if(mgl_isnan(f)) s="nan";
237 else if(mgl_isbad(f)) s=f>0?"inf":"-inf";
238 else s.asprintf("%g", f);
239 tab->item(r,c)->setText(s);
240 }
241 var->set_v(f,c,r,kz);
242 }
243 infoDlg->refresh();
244 }
245 //-----------------------------------------------------------------------------
save()246 void DatPanel::save()
247 {
248 QString fn = QFileDialog::getSaveFileName(this, _("UDAV - Save/export data"), "",
249 _("Data files (*.dat)\nHDF5 files (*.h5 *.hdf)\nPNG files (*.png)\nAll files (*.*)"));
250 if(fn.isEmpty()) return;
251 QString ext = fn.section(".",-1);
252 if(ext=="png")
253 {
254 bool ok;
255 QString s = QInputDialog::getText(this, _("UDAV - Export to PNG"), _("Enter color scheme"), QLineEdit::Normal, MGL_DEF_SCH, &ok);
256 if(ok) var->Export(fn.toLocal8Bit().constData(), s.toLocal8Bit().constData());
257 }
258 else if(ext=="h5" || ext=="hdf")
259 {
260 bool ok;
261 QString s = QInputDialog::getText(this, _("UDAV - Save to HDF"), _("Enter data name"), QLineEdit::Normal, QString::fromWCharArray(var->Name()), &ok);
262 if(ok) var->SaveHDF(fn.toLocal8Bit().constData(), s.toLocal8Bit().constData());
263 }
264 else var->Save(fn.toLocal8Bit().constData());
265 }
266 //-----------------------------------------------------------------------------
load()267 void DatPanel::load()
268 {
269 mglData *d = dynamic_cast<mglData *>(var); if(!d) return;
270 QString fn = QFileDialog::getOpenFileName(this, _("UDAV - Load data"), "",
271 _("Data files (*.dat)\nHDF5 files (*.h5 *.hdf)\nPNG files (*.png)\nAll files (*.*)"));
272 if(fn.isEmpty()) return;
273 QString ext = fn.section(".",-1);
274 if(ext=="png")
275 {
276 bool ok;
277 QString s = QInputDialog::getText(this, _("UDAV - Import PNG"), _("Enter color scheme"), QLineEdit::Normal, MGL_DEF_SCH, &ok);
278 if(ok) d->Import(fn.toLocal8Bit().constData(), s.toLocal8Bit().constData());
279 }
280 else if(ext=="h5" || ext=="hdf")
281 {
282 bool ok;
283 QString s = QInputDialog::getText(this, _("UDAV - Read from HDF"), _("Enter data name"), QLineEdit::Normal, QString::fromWCharArray(var->Name()), &ok);
284 if(ok) d->ReadHDF(fn.toLocal8Bit().constData(), s.toLocal8Bit().constData());
285 }
286 else d->Read(fn.toLocal8Bit().constData());
287 refresh();
288 }
289 //-----------------------------------------------------------------------------
copy()290 void DatPanel::copy()
291 {
292 QTableWidgetSelectionRange ts = tab->selectedRanges().first();
293 QString res;
294 for(long j=ts.topRow();j<=ts.bottomRow();j++)
295 {
296 for(long i=ts.leftColumn();i<=ts.rightColumn();i++)
297 {
298 res = res + tab->item(j,i)->text();
299 if(i<ts.rightColumn()) res = res + "\t";
300 }
301 res = res + "\n";
302 }
303 QApplication::clipboard()->setText(res, QClipboard::Clipboard);
304 }
305 //-----------------------------------------------------------------------------
paste()306 void DatPanel::paste()
307 {
308 QString txt = QApplication::clipboard()->text(QClipboard::Clipboard);
309 QString s, t;
310 int r = tab->currentRow(), c = tab->currentColumn(), i, j;
311 for(i=0;i<ny-r;i++)
312 {
313 s = txt.section('\n',i,i,QString::SectionSkipEmpty);
314 if(s.isEmpty()) break;
315 for(j=0;j<nx-c;j++)
316 {
317 t = s.section('\t',j,j,QString::SectionSkipEmpty);
318 if(t.isEmpty()) { j=nx; continue; }
319 var->set_v(t.toDouble(),j+c,i+r,kz);
320 }
321 }
322 refresh();
323 }
324 //-----------------------------------------------------------------------------
plot()325 void DatPanel::plot() // TODO: plot dialog
326 {
327
328 }
329 //-----------------------------------------------------------------------------
list()330 void DatPanel::list() // TODO: in which script insert ???
331 {
332 /* if(nx*ny+ny > 1020)
333 { QMessageBox::warning(this, _("UDAV - To list conversion"), _("Too many numbers (>1000) on slice"), QMessageBox::Ok, 0, 0); return; }
334 if(nz > 1)
335 QMessageBox::information(this, _("UDAV - To list conversion"), _("Only current slice will be inserted"), QMessageBox::Ok, 0, 0);
336 QString res = "list\t", s;
337 for(long j=0;j<ny;j++)
338 {
339 for(long i=0;i<nx;i++)
340 {
341 s.asprintf("%g\t",d->a[i+nx*(j+kz*ny)]);
342 res += s;
343 }
344 if(j<ny-1) res = res + "|\t";
345 }*/
346 }
347 //-----------------------------------------------------------------------------
inrange()348 void DatPanel::inrange()
349 {
350 QString v1("-1"), v2("1"), dir("x");
351 if(sizesDialog(_("UDAV - Fill data"), _("Enter range for data and direction of filling"), _("From"), _("To"), _("Direction"), v1, v2, dir))
352 {
353 mglData *d = dynamic_cast<mglData *>(var);
354 if(d) d->Fill(v1.toDouble(), v2.toDouble(), dir[0].toLatin1());
355 mglDataC *dc = dynamic_cast<mglDataC *>(var);
356 if(dc) dc->Fill(v1.toDouble(), v2.toDouble(), dir[0].toLatin1());
357 mglDataV *dv = dynamic_cast<mglDataV *>(var);
358 if(dv) dv->Fill(v1.toDouble(), v2.toDouble(), dir[0].toLatin1());
359 refresh();
360 }
361 }
362 //-----------------------------------------------------------------------------
norm()363 void DatPanel::norm()
364 {
365 QString v1("0"), v2("1"), how;
366 if(sizesDialog(_("UDAV - Normalize data"), _("Enter range for final data"), _("From"), _("To"), _("Symmetrical?"), v1, v2, how))
367 {
368 mglData *d = dynamic_cast<mglData *>(var);
369 if(d) d->Norm(v1.toDouble(), v2.toDouble(), (how=="on" || how.contains('s')));
370 refresh();
371 }
372 }
373 //-----------------------------------------------------------------------------
normsl()374 void DatPanel::normsl()
375 {
376 QString v1("0"), v2("1"), dir("z");
377 if(sizesDialog(_("UDAV - Normalize by slice"), _("Enter range for final data"), _("From"), _("To"), _("Direction"), v1, v2, dir))
378 {
379 mglData *d = dynamic_cast<mglData *>(var);
380 if(d) d->NormSl(v1.toDouble(), v2.toDouble(), dir[0].toLatin1());
381 refresh();
382 }
383 }
384 //-----------------------------------------------------------------------------
create()385 void DatPanel::create()
386 {
387 QString mx, my("1"), mz("1");
388 if(sizesDialog(_("UDAV - Clear data"), _("Enter new data sizes"), _("X-size"), _("Y-size"), _("Z-size"), mx, my, mz))
389 {
390 mglData *d = dynamic_cast<mglData *>(var);
391 if(d) d->Create(mx.toInt(), my.toInt(), mz.toInt());
392 mglDataC *c = dynamic_cast<mglDataC *>(var);
393 if(c) c->Create(mx.toInt(), my.toInt(), mz.toInt());
394 refresh(); updateDataItems();
395 }
396 }
397 //-----------------------------------------------------------------------------
reSize()398 void DatPanel::reSize()
399 {
400 QString mx, my, mz;
401 mx.asprintf("%d",nx); my.asprintf("%d",ny); mz.asprintf("%d",nz);
402 if(sizesDialog(_("UDAV - Resize data"), _("Enter new data sizes"), _("X-size"), _("Y-size"), _("Z-size"), mx, my, mz))
403 {
404 mglData *d = dynamic_cast<mglData *>(var);
405 if(d) d->Set(d->Resize(mx.toInt(), my.toInt(), mz.toInt()));
406 refresh(); updateDataItems();
407 }
408 }
409 //-----------------------------------------------------------------------------
squize()410 void DatPanel::squize()
411 {
412 QString mx("1"), my("1"), mz("1");
413 if(sizesDialog(_("UDAV - Squeeze data"), _("Enter step of saved points. For example, '1' save all, '2' save each 2nd point, '3' save each 3rd and so on."), _("X-direction"), _("Y-direction"), _("Z-direction"), mx, my, mz))
414 {
415 mglData *d = dynamic_cast<mglData *>(var);
416 if(d) d->Squeeze(mx.toInt(), my.toInt(), mz.toInt());
417 refresh(); updateDataItems();
418 }
419 }
420 //-----------------------------------------------------------------------------
crop()421 void DatPanel::crop()
422 {
423 QString n1("1"), n2("1"), dir;
424 if(sizesDialog(_("UDAV - Crop data"), _("Enter range of saved date."), _("From"), _("To"), _("Direction"), n1, n2, dir))
425 {
426 mglData *d = dynamic_cast<mglData *>(var);
427 if(d) d->Squeeze(n1.toInt(), n2.toInt(), dir[0].toLatin1());
428 refresh(); updateDataItems();
429 }
430 }
431 //-----------------------------------------------------------------------------
rearrange()432 void DatPanel::rearrange()
433 {
434 QString mx, my, mz;
435 mx.asprintf("%d",nx); my.asprintf("%d",ny); mz.asprintf("%d",nz);
436 if(sizesDialog(_("UDAV - Rearrange data"), _("Enter new data sizes"), _("X-size"), _("Y-size"), _("Z-size"), mx, my, mz))
437 {
438 mglData *d = dynamic_cast<mglData *>(var);
439 if(d) d->Rearrange(mx.toInt(), my.toInt(), mz.toInt());
440 refresh(); updateDataItems();
441 }
442 }
443 //-----------------------------------------------------------------------------
hist()444 void DatPanel::hist()
445 {
446 QLabel *l;
447 QLineEdit *id, *v1, *v2;
448 QSpinBox *nm;
449 QPushButton *b;
450 QDialog *d = new QDialog(this); d->setWindowTitle(_("UDAV - Make histogram"));
451 QGridLayout *g = new QGridLayout(d);
452 l = new QLabel(_("From"), d); g->addWidget(l,0,0);
453 l = new QLabel(_("To"), d); g->addWidget(l,0,1);
454 v1 = new QLineEdit(d); g->addWidget(v1,1,0);
455 v2 = new QLineEdit(d); g->addWidget(v2,1,1);
456 l = new QLabel(_("Number of points"), d); g->addWidget(l,2,0);
457 l = new QLabel(_("Put in variable"), d); g->addWidget(l,2,1);
458 nm = new QSpinBox(d); nm->setRange(2,8192); g->addWidget(nm,3,0);
459 id = new QLineEdit(d); nm->setSingleStep(10); g->addWidget(id,3,1);
460 b = new QPushButton(_("Cancel"), d); g->addWidget(b,4,0);
461 connect(b, SIGNAL(clicked()), d, SLOT(reject()));
462 b = new QPushButton(_("OK"), d); g->addWidget(b,4,1);
463 connect(b, SIGNAL(clicked()), d, SLOT(accept())); b->setDefault(true);
464 // now execute dialog and get values
465 bool res = d->exec();
466 if(res && !v1->text().isEmpty() && !v2->text().isEmpty() && !id->text().isEmpty())
467 {
468 mglData *vv = dynamic_cast<mglData*>(parser.AddVar(id->text().toLocal8Bit().constData()));
469 if(vv) vv->Set(mgl_data_hist(var, nm->value(), v1->text().toDouble(), v2->text().toDouble(),0));
470 updateDataItems();
471 }
472 }
473 //-----------------------------------------------------------------------------
first()474 void DatPanel::first() { setSlice(0); }
475 //-----------------------------------------------------------------------------
last()476 void DatPanel::last() { setSlice(nz-1); }
477 //-----------------------------------------------------------------------------
next()478 void DatPanel::next() { setSlice(kz+1); }
479 //-----------------------------------------------------------------------------
prev()480 void DatPanel::prev() { setSlice(kz-1); }
481 //-----------------------------------------------------------------------------
gosl()482 void DatPanel::gosl()
483 {
484 bool ok;
485 QString s = QInputDialog::getText(this, _("UDAV - Go to slice"), _("Enter slice id:"), QLineEdit::Normal, "0", &ok);
486 if(ok) setSlice(s.toInt());
487 }
488 //-----------------------------------------------------------------------------
setNz(int nz)489 void DatPanel::setNz(int nz) { sb->setMaximum(nz-1); }
490 //-----------------------------------------------------------------------------
sizesDialog(const QString & cap,const QString & lab,const QString & desc1,const QString & desc2,const QString & desc3,QString & val1,QString & val2,QString & val3)491 bool DatPanel::sizesDialog(const QString &cap, const QString &lab, const QString &desc1, const QString &desc2, const QString &desc3, QString &val1, QString &val2, QString &val3)
492 {
493 QLabel *l;
494 QLineEdit *f1, *f2, *f3;
495 QPushButton *b;
496 QDialog *d = new QDialog(this);
497 d->setWindowTitle(cap);
498 QVBoxLayout *v = new QVBoxLayout(d);
499 l = new QLabel(lab, d); v->addWidget(l);
500 l = new QLabel(_("NOTE: All fields must be filled!"), d); v->addWidget(l);
501 QGridLayout *g = new QGridLayout(); v->addLayout(g);
502 l = new QLabel(desc1, d); g->addWidget(l, 0, 0);
503 l = new QLabel(desc2, d); g->addWidget(l, 0, 1);
504 l = new QLabel(desc3, d); g->addWidget(l, 0, 2);
505 f1 = new QLineEdit(val1, d); g->addWidget(f1, 1, 0);
506 f2 = new QLineEdit(val2, d); g->addWidget(f2, 1, 1);
507 f3 = new QLineEdit(val3, d); g->addWidget(f3, 1, 2);
508 QHBoxLayout *h = new QHBoxLayout(); v->addLayout(h);
509 h->addStretch(1);
510 b = new QPushButton(_("Cancel"), d); h->addWidget(b);
511 connect(b, SIGNAL(clicked()), d, SLOT(reject()));
512 b = new QPushButton(_("OK"), d); h->addWidget(b);
513 connect(b, SIGNAL(clicked()), d, SLOT(accept()));
514 b->setDefault(true);
515 // now execute dialog and get values
516 bool res = d->exec();
517 val1 = f1->text(); val2 = f2->text(); val3 = f3->text();
518 if(val1.isEmpty() || val2.isEmpty() || val3.isEmpty()) res = false;
519 delete d;
520 return res;
521 }
522 //-----------------------------------------------------------------------------
523 #include "xpm/size.xpm"
524 #include "xpm/crop.xpm"
525 #include "xpm/squize.xpm"
526 #include "xpm/hist.xpm"
527 #include "xpm/oper_dir.xpm"
528 #include "xpm/oper_of.xpm"
529 //-----------------------------------------------------------------------------
newdat()530 void DatPanel::newdat()
531 {
532 QLabel *l;
533 QLineEdit *f1, *f2;
534 QPushButton *b;
535 QDialog *d = new QDialog(this);
536 d->setWindowTitle(_("UDAV - make new data"));
537 QVBoxLayout *v = new QVBoxLayout(d);
538 QComboBox *c = new QComboBox(d); v->addWidget(c);
539 c->addItem(_("Sum along direction(s)"));
540 c->addItem(_("Min along direction(s)"));
541 c->addItem(_("Max along direction(s)"));
542 c->addItem(_("Momentum along 'x' for function"));
543 c->addItem(_("Momentum along 'y' for function"));
544 c->addItem(_("Momentum along 'z' for function"));
545 c->setCurrentIndex(0);
546
547 f1 = new QLineEdit("z",d); v->addWidget(f1);
548 QCheckBox *cb = new QCheckBox(_("Put into this data array"), d); v->addWidget(cb);
549 l = new QLabel(_("or enter name for new variable"), d); v->addWidget(l);
550 f2 = new QLineEdit(d); v->addWidget(f2);
551 QHBoxLayout *h = new QHBoxLayout(); v->addLayout(h); h->addStretch(1);
552 b = new QPushButton(_("Cancel"), d); h->addWidget(b);
553 connect(b, SIGNAL(clicked()), d, SLOT(reject()));
554 b = new QPushButton(_("OK"), d); h->addWidget(b);
555 connect(b, SIGNAL(clicked()), d, SLOT(accept()));
556 b->setDefault(true);
557 // now execute dialog and get values
558 bool res = d->exec();
559 QString val = f1->text(), mgl;
560 int k = c->currentIndex();
561 QString self = QString::fromWCharArray(var->Name());
562 if(res)
563 {
564 if(k<0)
565 {
566 QMessageBox::warning(d, _("UDAV - make new data"),
567 _("No action is selected. Do nothing."));
568 return;
569 }
570 if(val.isEmpty())
571 {
572 QMessageBox::warning(d, _("UDAV - make new data"),
573 _("No direction/formula is entered. Do nothing."));
574 return;
575 }
576 if(cb->isChecked()) k += 6;
577 QString name = f2->text();
578 switch(k)
579 {
580 case 0: mgl = "sum "+name+" "+self+" '"+val+"'"; break;
581 case 1: mgl = "min "+name+" "+self+" '"+val+"'"; break;
582 case 2: mgl = "max "+name+" "+self+" '"+val+"'"; break;
583 case 3: mgl = "momentum "+name+" "+self+" 'x' '"+val+"'"; break;
584 case 4: mgl = "momentum "+name+" "+self+" 'y' '"+val+"'"; break;
585 case 5: mgl = "momentum "+name+" "+self+" 'z' '"+val+"'"; break;
586 case 6: mgl = "copy "+self+" {sum "+self+" '"+val+"'}"; break;
587 case 7: mgl = "copy "+self+" {min "+self+" '"+val+"'}"; break;
588 case 8: mgl = "copy "+self+" {max "+self+" '"+val+"'}"; break;
589 case 9: mgl = "copy "+self+" {momentum "+self+" 'x' '"+val+"'}"; break;
590 case 10: mgl = "copy "+self+" {momentum "+self+" 'y' '"+val+"'}"; break;
591 case 11: mgl = "copy "+self+" {momentum "+self+" 'z' '"+val+"'}"; break;
592 }
593 }
594 if(!mgl.isEmpty())
595 {
596 mglGraph gr;
597 parser.Execute(&gr,mgl.toLocal8Bit().constData());
598 if(k>=6) opers += mgl+"\n";
599 updateDataItems();
600 }
601 }
602 //-----------------------------------------------------------------------------
oper()603 void DatPanel::oper()
604 {
605 QLineEdit *f1;
606 QPushButton *b;
607 QDialog *d = new QDialog(this);
608 d->setWindowTitle(_("UDAV - change data"));
609 QVBoxLayout *v = new QVBoxLayout(d);
610 QComboBox *c = new QComboBox(d); v->addWidget(c);
611 c->addItem(_("Fill data by formula"));
612 c->addItem(_("Transpose data with new dimensions"));
613 c->addItem(_("Smooth data along direction(s)"));
614 c->addItem(_("Summarize data along direction(s)"));
615 c->addItem(_("Integrate data along direction(s)"));
616 c->addItem(_("Differentiate data along direction(s)"));
617 c->addItem(_("Laplace transform along direction(s)"));
618 c->addItem(_("Swap data along direction(s)"));
619 c->addItem(_("Mirror data along direction(s)"));
620 c->addItem(_("Sin-Fourier transform along direction(s)"));
621 c->addItem(_("Cos-Fourier transform along direction(s)"));
622 c->addItem(_("Hankel transform along direction(s)"));
623 c->addItem(_("Sew data along direction(s)"));
624 c->addItem(_("Find envelope along direction(s)"));
625 c->setCurrentIndex(0);
626
627 f1 = new QLineEdit("z",d); v->addWidget(f1);
628 QHBoxLayout *h = new QHBoxLayout(); v->addLayout(h); h->addStretch(1);
629 b = new QPushButton(_("Cancel"), d); h->addWidget(b);
630 connect(b, SIGNAL(clicked()), d, SLOT(reject()));
631 b = new QPushButton(_("OK"), d); h->addWidget(b);
632 connect(b, SIGNAL(clicked()), d, SLOT(accept()));
633 b->setDefault(true);
634 // now execute dialog and get values
635 bool res = d->exec();
636 QString val = f1->text(), mgl;
637 int k = c->currentIndex();
638 QString self = QString::fromWCharArray(var->Name());
639 if(res)
640 {
641 if(k<0)
642 {
643 QMessageBox::warning(d, _("UDAV - make new data"),
644 _("No action is selected. Do nothing."));
645 return;
646 }
647 switch(k)
648 {
649 case 0: mgl = "modify "+self+" '"+val+"'"; break;
650 case 1: mgl = "transpose "+self+" '"+val+"'"; break;
651 case 2: mgl = "smooth "+self+" '"+val+"'"; break;
652 case 3: mgl = "cumsum "+self+" '"+val+"'"; break;
653 case 4: mgl = "integrate "+self+" '"+val+"'"; break;
654 case 5: mgl = "diff "+self+" '"+val+"'"; break;
655 case 6: mgl = "diff2 "+self+" '"+val+"'"; break;
656 case 7: mgl = "swap "+self+" '"+val+"'"; break;
657 case 8: mgl = "mirror "+self+" '"+val+"'"; break;
658 case 9: mgl = "sinfft "+self+" '"+val+"'"; break;
659 case 10: mgl = "cosfft "+self+" '"+val+"'"; break;
660 case 11: mgl = "hankel "+self+" '"+val+"'"; break;
661 case 12: mgl = "sew "+self+" '"+val+"'"; break;
662 case 13: mgl = "envelop "+self+" '"+val+"'"; break;
663 }
664 }
665 if(!mgl.isEmpty())
666 {
667 mglGraph gr;
668 parser.Execute(&gr,mgl.toLocal8Bit().constData());
669 opers += mgl+"\n";
670 updateDataItems();
671 }
672 }
673 //-----------------------------------------------------------------------------
toolTop(QBoxLayout * l)674 void DatPanel::toolTop(QBoxLayout *l)
675 {
676 QAction *a;
677 QMenu *o;
678 QToolButton *bb;
679
680 // file menu
681 o = menu->addMenu(_("File"));
682 a = new QAction(QPixmap(":/png/document-open.png"), _("Load data"), this);
683 connect(a, SIGNAL(triggered()), this, SLOT(load()));
684 a->setToolTip(_("Load data from file. Data will be deleted only\nat exit but UDAV will not ask to save it (Ctrl+Shift+O)."));
685 a->setShortcut(Qt::CTRL+Qt::SHIFT+Qt::Key_O); o->addAction(a);
686 bb = new QToolButton(this); l->addWidget(bb); bb->setDefaultAction(a);
687
688 a = new QAction(QPixmap(":/png/document-save.png"), _("Save data"), this);
689 connect(a, SIGNAL(triggered()), this, SLOT(save()));
690 a->setToolTip(_("Save data to a file (Ctrl+Shift+S)."));
691 a->setShortcut(Qt::CTRL+Qt::SHIFT+Qt::Key_S); o->addAction(a);
692 bb = new QToolButton(this); l->addWidget(bb); bb->setDefaultAction(a);
693
694 // o->addSeparator(); bb->addSeparator();
695 // a = new QAction(QPixmap(insert_xpm), _("Insert as list"), this);
696 // connect(a, SIGNAL(triggered()), this, SLOT(list()));
697 // o->addAction(a);
698 // bb = new QToolButton(this); l->addWidget(bb); bb->setDefaultAction(a);
699
700
701 a = new QAction(QPixmap(":/png/office-chart-line.png"), _("Plot data"), this);
702 connect(a, SIGNAL(triggered()), this, SLOT(plot()));
703 a->setToolTip(_("Plot data in new script window. You may select the kind\nof plot, its style and so on."));
704 o->addAction(a);
705 bb = new QToolButton(this); l->addWidget(bb); bb->setDefaultAction(a);
706
707 a = new QAction(QPixmap(":/png/edit-copy.png"), _("Copy data"), this);
708 connect(a, SIGNAL(triggered()), this, SLOT(copy()));
709 a->setToolTip(_("Copy range of numbers to clipboard (Ctrl+Shift+C)."));
710 a->setShortcut(Qt::CTRL+Qt::SHIFT+Qt::Key_C); o->addAction(a);
711 bb = new QToolButton(this); l->addWidget(bb); bb->setDefaultAction(a);
712
713 a = new QAction(QPixmap(":/png/edit-paste.png"), _("Paste data"), this);
714 connect(a, SIGNAL(triggered()), this, SLOT(copy()));
715 a->setToolTip(_("Paste range of numbers from clipboard (Ctrl+Shift+P)."));
716 a->setShortcut(Qt::CTRL+Qt::SHIFT+Qt::Key_V); o->addAction(a);
717 bb = new QToolButton(this); l->addWidget(bb); bb->setDefaultAction(a);
718
719 // navigation menu
720 o = menu->addMenu(_("Navigation"));
721 a = new QAction(QPixmap(":/png/go-first.png"), _("First slice"), this);
722 connect(a, SIGNAL(triggered()), this, SLOT(first()));
723 a->setToolTip(_("Go to first slice for 3D data (Ctrl-F1)."));
724 a->setShortcut(Qt::CTRL+Qt::Key_F1); o->addAction(a);
725 bb = new QToolButton(this); l->addWidget(bb); bb->setDefaultAction(a);
726
727 a = new QAction(QPixmap(":/png/go-previous.png"), _("Prev slice"), this);
728 connect(a, SIGNAL(triggered()), this, SLOT(prev()));
729 a->setToolTip(_("Go to the previous slice for 3D data."));
730 o->addAction(a);
731 bb = new QToolButton(this); l->addWidget(bb); bb->setDefaultAction(a);
732
733 sb = new QSpinBox(this);
734 l->addWidget(sb); sb->setRange(0,0);
735 sb->setToolTip(_("Go to the specified slice for 3D data."));
736 connect(sb, SIGNAL(valueChanged(int)), this, SLOT(setSlice(int)));
737 connect(this, SIGNAL(sliceChanged(int)), sb, SLOT(setValue(int)));
738 connect(this, SIGNAL(nzChanged(int)), this, SLOT(setNz(int)));
739
740 a = new QAction(_("Go to slice"), this);
741 connect(a, SIGNAL(triggered()), this, SLOT(gosl()));
742 a->setToolTip(_("Go to the specified slice for 3D data."));
743 o->addAction(a);
744
745 a = new QAction(QPixmap(":/png/go-next.png"), _("Next slice"), this);
746 connect(a, SIGNAL(triggered()), this, SLOT(next()));
747 a->setToolTip(_("Go to the next slice for 3D data."));
748 o->addAction(a);
749 bb = new QToolButton(this); l->addWidget(bb); bb->setDefaultAction(a);
750
751 a = new QAction(QPixmap(":/png/go-last.png"), _("Last slice"), this);
752 connect(a, SIGNAL(triggered()), this, SLOT(last()));
753 a->setToolTip(_("Go to last slice for 3D data (Ctrl-F4)."));
754 a->setShortcut(Qt::CTRL+Qt::Key_F4); o->addAction(a);
755 bb = new QToolButton(this); l->addWidget(bb); bb->setDefaultAction(a);
756 }
757 //-----------------------------------------------------------------------------
toolLeft(QBoxLayout * l)758 void DatPanel::toolLeft(QBoxLayout *l)
759 {
760 QAction *a;
761 QMenu *o;
762 QToolButton *bb;
763
764 // size menu
765 o = menu->addMenu(_("Sizes"));
766 a = new QAction(QPixmap(":/png/document-new.png"), _("Create new"), this);
767 connect(a, SIGNAL(triggered()), this, SLOT(create()));
768 a->setToolTip(_("Recreate the data with new sizes and fill it by zeros (Ctrl+Shift+N)."));
769 a->setShortcut(Qt::CTRL+Qt::SHIFT+Qt::Key_N); o->addAction(a);
770 bb = new QToolButton(this); l->addWidget(bb); bb->setDefaultAction(a);
771
772 a = new QAction(QPixmap(size_xpm), _("Resize"), this);
773 connect(a, SIGNAL(triggered()), this, SLOT(reSize()));
774 a->setToolTip(_("Resize (interpolate) the data to specified sizes (Ctrl+Shift+R)."));
775 a->setShortcut(Qt::CTRL+Qt::SHIFT+Qt::Key_R); o->addAction(a);
776 bb = new QToolButton(this); l->addWidget(bb); bb->setDefaultAction(a);
777
778 a = new QAction(QPixmap(squize_xpm), _("Squeeze"), this);
779 connect(a, SIGNAL(triggered()), this, SLOT(squize()));
780 a->setToolTip(_("Keep only each n-th element of the data array."));
781 o->addAction(a);
782 bb = new QToolButton(this); l->addWidget(bb); bb->setDefaultAction(a);
783
784 a = new QAction(QPixmap(crop_xpm), _("Crop"), this);
785 connect(a, SIGNAL(triggered()), this, SLOT(crop()));
786 a->setToolTip(_("Crop the data edges. Useful to cut off the zero-filled area."));
787 o->addAction(a);
788 bb = new QToolButton(this); l->addWidget(bb); bb->setDefaultAction(a);
789
790 a = new QAction(QPixmap(oper_of_xpm), _("Transform"), this);
791 connect(a, SIGNAL(triggered()), this, SLOT(newdat()));
792 a->setToolTip(_("Transform data along dimension(s) (Ctrl+Shift+T)."));
793 a->setShortcut(Qt::CTRL+Qt::SHIFT+Qt::Key_T); o->addAction(a);
794 bb = new QToolButton(this); l->addWidget(bb); bb->setDefaultAction(a);
795
796 a = new QAction(QPixmap(oper_dir_xpm), _("Make new (Ctrl+Shift+M)"), this);
797 connect(a, SIGNAL(triggered()), this, SLOT(oper()));
798 a->setToolTip(_("Make another data."));
799 a->setShortcut(Qt::CTRL+Qt::SHIFT+Qt::Key_M); o->addAction(a);
800 bb = new QToolButton(this); l->addWidget(bb); bb->setDefaultAction(a);
801
802 a = new QAction(QPixmap(hist_xpm), _("Histogram (Ctrl+Shift+H)"), this);
803 connect(a, SIGNAL(triggered()), this, SLOT(hist()));
804 a->setToolTip(_("Find histogram of data."));
805 a->setShortcut(Qt::CTRL+Qt::SHIFT+Qt::Key_H); o->addAction(a);
806 bb = new QToolButton(this); l->addWidget(bb); bb->setDefaultAction(a);
807
808 /* a = new QAction(QPixmap(":/png/view-refresh.png"), _("Refresh"), this);
809 connect(a, SIGNAL(triggered()), this, SLOT(refresh()));
810 a->setToolTip(_("Refresh data values."));
811 o->addAction(a);
812 bb = new QToolButton(this); l->addWidget(bb); bb->setDefaultAction(a);*/
813
814 /* a = new QAction(_("Rearrange"), this); // TODO: move in generalized dialog
815 connect(a, SIGNAL(triggered()), this, SLOT(rearrange()));
816 a->setToolTip(_("Rearrange data sizes without changing data values."));
817 o->addAction(a);
818 a = new QAction(_("Fill in range"), this);
819 connect(a, SIGNAL(triggered()), this, SLOT(inrange()));
820 a->setToolTip(_("Fill data equidistantly from one value to another."));
821 o->addAction(a);
822 a = new QAction(_("Normalize"), this);
823 connect(a, SIGNAL(triggered()), this, SLOT(norm()));
824 a->setToolTip(_("Normalize data so that its minimal\nand maximal values be in specified range."));
825 o->addAction(a);
826 a = new QAction(_("Norm. slices"), this);
827 connect(a, SIGNAL(triggered()), this, SLOT(normsl()));
828 a->setToolTip(_("Normalize each data slice perpendicular to some direction\nso that its minimal and maximal values be in specified range."));
829 o->addAction(a);*/
830
831 l->addStretch(1);
832
833 a = new QAction(QPixmap(":/png/tab-close.png"), _("Close tab"), this);
834 connect(a, SIGNAL(triggered()), this, SLOT(close()));
835 a->setToolTip(_("Close this data tab."));
836 bb = new QToolButton(this); l->addWidget(bb); bb->setDefaultAction(a);
837 }
838 //-----------------------------------------------------------------------------
dataName()839 QString DatPanel::dataName() { return QString::fromWCharArray(var->Name()); }
840 //-----------------------------------------------------------------------------
841