preparing merge of master to release
[engrid.git] / src / guimainwindow.cpp
blob49596cab96194e8e4f0895b30a6a8c93b31af938
1 //
2 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 // + +
4 // + This file is part of enGrid. +
5 // + +
6 // + Copyright 2008,2009 Oliver Gloth +
7 // + +
8 // + enGrid is free software: you can redistribute it and/or modify +
9 // + it under the terms of the GNU General Public License as published by +
10 // + the Free Software Foundation, either version 3 of the License, or +
11 // + (at your option) any later version. +
12 // + +
13 // + enGrid is distributed in the hope that it will be useful, +
14 // + but WITHOUT ANY WARRANTY; without even the implied warranty of +
15 // + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +
16 // + GNU General Public License for more details. +
17 // + +
18 // + You should have received a copy of the GNU General Public License +
19 // + along with enGrid. If not, see <http://www.gnu.org/licenses/>. +
20 // + +
21 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
23 #include "guimainwindow.h"
24 #include "guiselectboundarycodes.h"
25 #include "guiimproveaspectratio.h"
26 #include "guinormalextrusion.h"
27 #include "guisetboundarycode.h"
28 #include "guipick.h"
30 #include "vtkEgPolyDataToUnstructuredGridFilter.h"
31 #include "stlreader.h"
32 #include "gmshreader.h"
33 #include "gmshwriter.h"
34 #include "neutralwriter.h"
35 #include "stlwriter.h"
36 #include "plywriter.h"
37 #include "correctsurfaceorientation.h"
38 #include "guieditboundaryconditions.h"
39 #include "laplacesmoother.h"
40 #include "swaptriangles.h"
42 #include <vtkRenderer.h>
43 #include <vtkRenderWindow.h>
44 #include <vtkXMLUnstructuredGridWriter.h>
45 #include <vtkXMLUnstructuredGridReader.h>
46 #include <vtkProperty.h>
47 #include <vtkCallbackCommand.h>
48 #include <vtkCamera.h>
49 #include <vtkCharArray.h>
50 #include <vtkTextActor.h>
51 #include <vtkVectorText.h>
52 #include <vtkFollower.h>
53 #include <vtkLookupTable.h>
54 #include <vtkScalarBarActor.h>
56 #include <QFileDialog>
57 #include <QFileSystemWatcher>
58 #include <QFileInfo>
59 #include <stdlib.h>
60 #include <stdio.h>
62 #include "geometrytools.h"
64 using namespace GeometryTools;
66 #include "guisettingsviewer.h"
67 #include "guitransform.h"
68 #include "egvtkinteractorstyle.h"
69 #include "showinfo.h"
71 QString GuiMainWindow::m_cwd = ".";
72 QSettings GuiMainWindow::m_qset("enGits","enGrid");
73 GuiMainWindow* GuiMainWindow::THIS = NULL;
74 QMutex GuiMainWindow::m_Mutex;
75 bool GuiMainWindow::m_UnSaved = true;
77 GuiMainWindow::GuiMainWindow() : QMainWindow(NULL)
79 ui.setupUi(this);
80 THIS = this;
82 // restore window size
83 if(m_qset.contains("GuiMainWindow")) {
84 setGeometry(m_qset.value("GuiMainWindow").toRect());
86 else {
87 this->setWindowState(Qt::WindowMaximized);
90 // restore dockwidget positions
91 if(m_qset.contains("dockWidget_states")) {
92 restoreState(m_qset.value("dockWidget_states").toByteArray());
94 else {
95 tabifyDockWidget(ui.dockWidget_output, ui.dockWidget_node_cell_info);
96 tabifyDockWidget(ui.dockWidget_DisplayOptions, ui.dockWidget_DebuggingUtilities);
97 ui.dockWidget_node_cell_info->hide();
98 ui.dockWidget_DebuggingUtilities->hide();
101 # include "std_connections.h"
103 if (m_qset.contains("working_directory")) {
104 m_cwd = m_qset.value("working_directory").toString();
107 setupVtk();
109 resetOperationCounter();//clears undo/redo list and disables undo/redo
110 m_CurrentFilename = "untitled.egc";
111 setWindowTitle(m_CurrentFilename + " - enGrid - " + QString("%1").arg(m_CurrentOperation) );
112 setUnsaved(true);
114 m_StatusLabel = new QLabel(this);
115 statusBar()->addWidget(m_StatusLabel);
117 QString txt = "0 volume cells (0 tetras, 0 hexas, 0 pyramids, 0 prisms), ";
118 txt += "0 surface cells (0 triangles, 0 quads), 0 nodes";
119 m_StatusLabel->setText(txt);
120 ui.label_node_cell_info->setText(txt);
122 QString user = QString(getenv("USER"));
123 QString basename="enGrid_output.txt";
125 // define temporary path
126 QDir dir("/");
127 if (m_qset.contains("tmp_directory")) {
128 m_LogDir = m_qset.value("tmp_directory").toString();
129 } else {
130 m_LogDir = dir.tempPath();
132 QDateTime now = QDateTime::currentDateTime();
133 m_LogDir = m_LogDir + "/" + "enGrid_" + QDateTime::currentDateTime().toString("yyyyMMddhhmmsszzz") + "/";
134 dir.mkpath(m_LogDir);
136 m_LogFileName = m_LogDir + basename;
137 cout << "m_LogFileName = " << qPrintable(m_LogFileName) << endl;
139 m_SystemStdout = stdout;
140 if(freopen (qPrintable(m_LogFileName), "w", stdout)==NULL) EG_BUG;
142 m_Busy = false;
144 setPickMode(true,true);
145 m_PickedPoint = -1;
146 m_PickedCell = -1;
148 updateStatusBar();
150 connect(&m_GarbageTimer, SIGNAL(timeout()), this, SLOT(periodicUpdate()));
151 m_GarbageTimer.start(1000);
153 connect(&m_LogTimer, SIGNAL(timeout()), this, SLOT(updateOutput()));
154 m_LogTimer.start(1000);
156 m_N_chars = 0;
158 bool exp_features=false;
159 getSet("General","enable experimental features",false,exp_features);
160 getSet("General","enable undo+redo",false,m_undo_redo_enabled);
161 bool undo_redo_mode;
162 getSet("General","use RAM for undo+redo operations",false,undo_redo_mode);
164 ui.actionFoamWriter->setEnabled(exp_features);
166 m_ReferenceSize=0.2;
168 ui.doubleSpinBox_HueMin->setValue(0.667);
169 ui.doubleSpinBox_HueMax->setValue(0);
171 egvtkInteractorStyle *style = egvtkInteractorStyle::New();
172 getInteractor()->SetInteractorStyle(style);
173 style->Delete();
175 // initialise XML document
176 // QDomElement root = m_XmlDoc.createElement("engridcase");
177 // m_XmlDoc.appendChild(root);
178 this->resetXmlDoc();
180 m_SolverIndex = 0;
182 readRecentFiles();
184 //end of GuiMainWindow::GuiMainWindow() : QMainWindow(NULL)
186 void GuiMainWindow::resetXmlDoc()
188 m_XmlDoc.clear();
189 QDomElement root = m_XmlDoc.createElement("engridcase");
190 m_XmlDoc.appendChild(root);
193 GuiMainWindow::~GuiMainWindow()
195 writeRecentFiles();
197 m_qset.setValue("GuiMainWindow", this->geometry());
198 m_qset.setValue("dockWidget_states", this->saveState());
200 #ifndef QT_DEBUG
201 QDirIterator it(m_LogDir);
202 while (it.hasNext()) {
203 QString str = it.next();
204 QFileInfo fileinfo(str);
205 if(fileinfo.isFile()) {
206 QFile file(str);
207 if(!file.remove()) qDebug() << "Failed to remove " << file.fileName();
210 QDir dir(m_LogDir);
211 dir.rmdir(m_LogDir);
212 #endif
216 void GuiMainWindow::setupVtk()
218 m_Grid = vtkUnstructuredGrid::New();
219 m_Renderer = vtkRenderer::New();
220 getRenderWindow()->AddRenderer(m_Renderer);
222 // coordinate axes
223 m_Axes = vtkCubeAxesActor2D::New();
225 m_Axes->SetCamera(getRenderer()->GetActiveCamera());
226 getRenderer()->AddActor(m_Axes);
227 m_Axes->SetVisibility(0);
229 // surface pipelines
230 m_BackfaceProperty = vtkProperty::New();
231 m_SurfaceFilter = vtkGeometryFilter::New();
232 m_SurfaceMapper = vtkPolyDataMapper::New();
233 m_SurfaceWireMapper = vtkPolyDataMapper::New();
234 m_BCodesFilter = vtkEgBoundaryCodesFilter::New();
235 m_LookupTable = vtkLookupTable::New();
236 m_SurfaceActor = vtkActor::New();
237 m_SurfaceWireActor = vtkActor::New();
238 m_LegendActor = vtkScalarBarActor::New();
240 m_BCodesFilter->SetBoundaryCodes(m_DisplayBoundaryCodes);
241 m_BCodesFilter->SetInput(m_Grid);
242 m_SurfaceFilter->SetInput(m_BCodesFilter->GetOutput());
243 m_SurfaceMapper->SetInput(m_SurfaceFilter->GetOutput());
244 m_SurfaceWireMapper->SetInput(m_SurfaceFilter->GetOutput());
245 m_SurfaceMapper->SetLookupTable(m_LookupTable);
246 m_SurfaceActor->GetProperty()->SetRepresentationToSurface();
247 m_SurfaceActor->GetProperty()->SetColor(0.5,1,0.5);
248 m_SurfaceActor->SetBackfaceProperty(m_BackfaceProperty);
249 m_SurfaceActor->GetBackfaceProperty()->SetColor(1,1,0.5);
250 m_SurfaceActor->SetMapper(m_SurfaceMapper);
251 getRenderer()->AddActor(m_SurfaceActor);
252 m_SurfaceActor->SetVisibility(1);
253 m_LegendActor->SetLookupTable(m_LookupTable);
254 getRenderer()->AddActor(m_LegendActor);
255 m_LegendActor->SetVisibility(0);
256 m_SurfaceWireActor->GetProperty()->SetRepresentationToWireframe();
257 m_SurfaceWireActor->GetProperty()->SetColor(0,0,1);
258 m_SurfaceWireActor->SetMapper(m_SurfaceWireMapper);
259 getRenderer()->AddActor(m_SurfaceWireActor);
260 m_SurfaceWireActor->SetVisibility(1);
262 // tetra pipline
263 m_ExtrTetras = vtkEgExtractVolumeCells::New();
264 m_TetraActor = vtkActor::New();
265 m_TetraGeometry = vtkGeometryFilter::New();
266 m_TetraMapper = vtkPolyDataMapper::New();
268 m_ExtrTetras->SetInput(m_Grid);
269 m_ExtrTetras->SetAllOff();
270 m_ExtrTetras->SetTetrasOn();;
271 m_TetraGeometry->SetInput(m_ExtrTetras->GetOutput());
272 m_TetraMapper->SetInput(m_TetraGeometry->GetOutput());
273 m_TetraActor->SetMapper(m_TetraMapper);
274 m_TetraActor->GetProperty()->SetColor(1,0,0);
275 getRenderer()->AddActor(m_TetraActor);
276 m_TetraActor->SetVisibility(0);
278 // pyramid pipeline
279 m_PyramidActor = vtkActor::New();
280 m_ExtrPyramids = vtkEgExtractVolumeCells::New();
281 m_PyramidGeometry = vtkGeometryFilter::New();
282 m_PyramidMapper = vtkPolyDataMapper::New();
284 m_ExtrPyramids->SetInput(m_Grid);
285 m_ExtrPyramids->SetAllOff();
286 m_ExtrPyramids->SetPyramidsOn();
287 m_PyramidGeometry->SetInput(m_ExtrPyramids->GetOutput());
288 m_PyramidMapper->SetInput(m_PyramidGeometry->GetOutput());
289 m_PyramidActor->SetMapper(m_PyramidMapper);
290 m_PyramidActor->GetProperty()->SetColor(1,1,0);
291 getRenderer()->AddActor(m_PyramidActor);
292 m_PyramidActor->SetVisibility(0);
294 // wedge pipeline
295 m_WedgeActor = vtkActor::New();
296 m_ExtrWedges = vtkEgExtractVolumeCells::New();
297 m_WedgeGeometry = vtkGeometryFilter::New();
298 m_WedgeMapper = vtkPolyDataMapper::New();
300 m_ExtrWedges->SetInput(m_Grid);
301 m_ExtrWedges->SetAllOff();
302 m_ExtrWedges->SetWedgesOn();
303 m_WedgeGeometry->SetInput(m_ExtrWedges->GetOutput());
304 m_WedgeMapper->SetInput(m_WedgeGeometry->GetOutput());
305 m_WedgeActor->SetMapper(m_WedgeMapper);
306 m_WedgeActor->GetProperty()->SetColor(0,1,0);
307 getRenderer()->AddActor(m_WedgeActor);
308 m_WedgeActor->SetVisibility(0);
310 // hexa pipeline
311 m_HexaActor = vtkActor::New();
312 m_ExtrHexes = vtkEgExtractVolumeCells::New();
313 m_HexaGeometry = vtkGeometryFilter::New();
314 m_HexaMapper = vtkPolyDataMapper::New();
316 m_ExtrHexes->SetInput(m_Grid);
317 m_ExtrHexes->SetAllOff();
318 m_ExtrHexes->SetHexesOn();
319 m_HexaGeometry->SetInput(m_ExtrHexes->GetOutput());
320 m_HexaMapper->SetInput(m_HexaGeometry->GetOutput());
321 m_HexaActor->SetMapper(m_HexaMapper);
322 m_HexaActor->GetProperty()->SetColor(0,0.7,1);
323 getRenderer()->AddActor(m_HexaActor);
324 m_HexaActor->SetVisibility(0);
326 // volume wire pipeline
327 m_VolumeWireActor = vtkActor::New();
328 m_ExtrVol = vtkEgExtractVolumeCells::New();
329 m_VolumeGeometry = vtkGeometryFilter::New();
330 m_VolumeWireMapper = vtkPolyDataMapper::New();
332 m_ExtrVol->SetInput(m_Grid);
333 m_ExtrVol->SetAllOn();
334 m_VolumeGeometry->SetInput(m_ExtrVol->GetOutput());
335 m_VolumeWireMapper->SetInput(m_VolumeGeometry->GetOutput());
336 m_VolumeWireActor->SetMapper(m_VolumeWireMapper);
337 m_VolumeWireActor->GetProperty()->SetRepresentationToWireframe();
338 m_VolumeWireActor->GetProperty()->SetColor(0,0,1);
339 getRenderer()->AddActor(m_VolumeWireActor);
340 m_VolumeWireActor->SetVisibility(0);
342 // picker stuff
343 m_PickSphere = vtkSphereSource::New();
344 m_PickMapper = vtkPolyDataMapper::New();
345 m_PickActor = vtkActor::New();
346 m_CellPicker = vtkCellPicker::New();
347 m_PointPicker = vtkPointPicker::New();
349 m_PickSphere->SetRadius(0.25); //in case the user starts picking points instead of cells
350 m_PickMapper->SetInput(m_PickSphere->GetOutput());
351 m_PickActor->SetMapper(m_PickMapper);
352 m_PickActor->GetProperty()->SetRepresentationToSurface();
353 m_PickActor->GetProperty()->SetColor(0,0,1);
354 m_PickActor->VisibilityOff();
355 getRenderer()->AddActor(m_PickActor);
357 vtkCallbackCommand *cbc = vtkCallbackCommand::New();
358 cbc->SetCallback(pickCallBack);
360 m_CellPicker->AddObserver(vtkCommand::EndPickEvent, cbc);
361 m_PointPicker->AddObserver(vtkCommand::EndPickEvent, cbc);
363 // cbc->Delete();
366 void GuiMainWindow::updateOutput()
368 QFile log_file(m_LogFileName);
369 log_file.open(QIODevice::ReadOnly);
370 QByteArray buffer = log_file.readAll();
371 if (buffer.size() > m_N_chars) {
372 QByteArray newchars = buffer.right(buffer.size() - m_N_chars);
373 m_N_chars = buffer.size();
374 QString txt(newchars);
375 if (txt.right(1) == "\n") {
376 txt = txt.left(txt.size()-1);
378 ui.textEditOutput->append(txt);
382 void GuiMainWindow::exit()
384 QCoreApplication::exit();
387 vtkRenderWindow* GuiMainWindow::getRenderWindow()
389 return ui.qvtkWidget->GetRenderWindow();
392 vtkRenderer* GuiMainWindow::getRenderer()
394 return m_Renderer;
397 QVTKInteractor* GuiMainWindow::getInteractor()
399 return ui.qvtkWidget->GetInteractor();
402 QString GuiMainWindow::getCwd()
404 return m_cwd;
407 void GuiMainWindow::setCwd(QString dir)
409 m_cwd = dir;
410 m_qset.setValue("working_directory",dir);
413 void GuiMainWindow::setUnsaved(bool unsaved)
415 m_UnSaved = unsaved;
418 void GuiMainWindow::scaleToData()
420 int current_field=ui.comboBox_Field->currentIndex();
421 if(current_field>0)
423 double range[2];
425 m_SurfaceFilter->GetOutput()->GetPointData()->GetArray(current_field-1)->GetRange(range);
426 //boundary_pd->GetPointData()->GetArray(current_field-1)->GetRange(range);
427 cout<<"current_field="<<current_field<<endl;
428 cout<<"range[0]="<<range[0]<<endl;
429 cout<<"range[1]="<<range[1]<<endl;
430 ui.doubleSpinBox_FieldMin->setRange(range[0],range[1]);
431 ui.doubleSpinBox_FieldMax->setRange(range[0],range[1]);
432 ui.doubleSpinBox_FieldMin->setValue(range[0]);
433 ui.doubleSpinBox_FieldMax->setValue(range[1]);
437 void GuiMainWindow::setClipX(const QString &txt)
439 m_ExtrVol->Setx(txt.toDouble());
440 m_ExtrTetras->Setx(txt.toDouble());
441 m_ExtrPyramids->Setx(txt.toDouble());
442 m_ExtrWedges->Setx(txt.toDouble());
443 m_ExtrHexes->Setx(txt.toDouble());
446 void GuiMainWindow::setClipY(const QString &txt)
448 m_ExtrVol->Sety(txt.toDouble());
449 m_ExtrTetras->Sety(txt.toDouble());
450 m_ExtrPyramids->Sety(txt.toDouble());
451 m_ExtrWedges->Sety(txt.toDouble());
452 m_ExtrHexes->Sety(txt.toDouble());
455 void GuiMainWindow::setClipZ(const QString &txt)
457 m_ExtrVol->Setz(txt.toDouble());
458 m_ExtrTetras->Setz(txt.toDouble());
459 m_ExtrPyramids->Setz(txt.toDouble());
460 m_ExtrWedges->Setz(txt.toDouble());
461 m_ExtrHexes->Setz(txt.toDouble());
464 void GuiMainWindow::setClipNX(const QString &txt)
466 m_ExtrVol->Setnx(txt.toDouble());
467 m_ExtrTetras->Setnx(txt.toDouble());
468 m_ExtrPyramids->Setnx(txt.toDouble());
469 m_ExtrWedges->Setnx(txt.toDouble());
470 m_ExtrHexes->Setnx(txt.toDouble());
473 void GuiMainWindow::setClipNY(const QString &txt)
475 m_ExtrVol->Setny(txt.toDouble());
476 m_ExtrTetras->Setny(txt.toDouble());
477 m_ExtrPyramids->Setny(txt.toDouble());
478 m_ExtrWedges->Setny(txt.toDouble());
479 m_ExtrHexes->Setny(txt.toDouble());
482 void GuiMainWindow::setClipNZ(const QString &txt)
484 m_ExtrVol->Setnz(txt.toDouble());
485 m_ExtrTetras->Setnz(txt.toDouble());
486 m_ExtrPyramids->Setnz(txt.toDouble());
487 m_ExtrWedges->Setnz(txt.toDouble());
488 m_ExtrHexes->Setnz(txt.toDouble());
491 void GuiMainWindow::updateSurfaceActors(bool forced)
493 if (ui.checkBoxSurface->isChecked()) {
494 if (forced) {
495 m_SurfaceFilter->Update();
498 // fill node field combobox
499 int current_field=ui.comboBox_Field->currentIndex();
500 ui.comboBox_Field->clear();
501 ui.comboBox_Field->addItem("None");
502 for (int i = 0; i < m_Grid->GetPointData()->GetNumberOfArrays(); ++i) {
503 ui.comboBox_Field->addItem(m_Grid->GetPointData()->GetArrayName(i));
505 if(current_field == -1) {
506 ui.comboBox_Field->setCurrentIndex(0);
507 } else {
508 ui.comboBox_Field->setCurrentIndex(current_field);
511 // fill cell field combobox
512 int current_cell_field = ui.comboBox_CellTextField->currentIndex();
513 ui.comboBox_CellTextField->clear();
514 ui.comboBox_CellTextField->addItem("Cell ID");
515 for (int i = 0; i < m_SurfaceFilter->GetOutput()->GetCellData()->GetNumberOfArrays(); ++i) {
516 ui.comboBox_CellTextField->addItem(m_Grid->GetCellData()->GetArrayName(i));
518 if(current_cell_field == -1) {
519 ui.comboBox_CellTextField->setCurrentIndex(0);
520 } else {
521 ui.comboBox_CellTextField->setCurrentIndex(current_cell_field);
523 current_field = ui.comboBox_Field->currentIndex();
524 if(current_field > 0) {
525 double range[2];
526 m_SurfaceFilter->GetOutput()->GetPointData()->GetArray(current_field-1)->GetRange(range);
527 ui.doubleSpinBox_FieldMin->setRange(range[0],range[1]);
528 ui.doubleSpinBox_FieldMax->setRange(range[0],range[1]);
531 if(ui.comboBox_Field->currentIndex() > 0) {
532 m_SurfaceMapper->SetColorModeToMapScalars();
533 m_LookupTable->SetNumberOfColors(ui.spinBox_Color->value());
534 m_LookupTable->SetHueRange(ui.doubleSpinBox_HueMin->value(),ui.doubleSpinBox_HueMax->value());
535 m_LookupTable->Build();
536 m_SurfaceMapper->SetScalarModeToUsePointFieldData();
537 m_SurfaceMapper->ColorByArrayComponent(qPrintable(ui.comboBox_Field->currentText()),0);
538 m_SurfaceMapper->SetScalarRange(ui.doubleSpinBox_FieldMin->value(),ui.doubleSpinBox_FieldMax->value());
539 m_SurfaceMapper->ScalarVisibilityOn();
540 if(ui.checkBox_Legend->checkState()) {
541 m_LegendActor->SetVisibility(1);
542 } else {
543 m_LegendActor->SetVisibility(0);
545 } else {
546 m_SurfaceMapper->SetColorModeToDefault();
547 m_SurfaceMapper->ScalarVisibilityOff();
548 m_LegendActor->SetVisibility(0);
550 if (forced) {
551 m_BCodesFilter->Update();
553 if(ui.checkBox_ShowPickSphere->checkState()) {
554 if(m_UseVTKInteractor) {
555 if(ui.radioButton_CellPicker->isChecked()) {
556 getInteractor()->SetPicker(m_CellPicker);
557 vtkIdType id_cell = getPickedCell();
558 pickCell(id_cell);
559 } else {
560 getInteractor()->SetPicker(m_PointPicker);
561 vtkIdType id_node = getPickedPoint();
562 pickPoint(id_node);
564 } else {
565 if (ui.radioButton_CellPicker->isChecked()) {
566 pickCell(m_PickedCell);
567 } else {
568 pickPoint(m_PickedPoint);
572 m_SurfaceActor->SetVisibility(1);
573 m_SurfaceWireActor->SetVisibility(1);
574 } else {
575 m_SurfaceActor->SetVisibility(0);
576 m_SurfaceWireActor->SetVisibility(0);
580 void GuiMainWindow::updateVolumeActors(bool forced)
582 if (ui.checkBoxVolume->isChecked()) {
583 if (ui.checkBoxTetra->isChecked()) {
584 m_ExtrVol->SetTetrasOn();
585 if (ui.checkBoxClip->isChecked()) {
586 m_ExtrTetras->SetClippingOn();
587 } else {
588 m_ExtrTetras->SetClippingOff();
590 if (forced) {
591 m_TetraGeometry->Update();
593 m_TetraActor->SetVisibility(1);
594 } else {
595 m_ExtrVol->SetTetrasOff();
596 m_TetraActor->SetVisibility(0);
598 if (ui.checkBoxPyramid->isChecked()) {
599 m_ExtrVol->SetPyramidsOn();
600 if (ui.checkBoxClip->isChecked()) {
601 m_ExtrPyramids->SetClippingOn();
602 } else {
603 m_ExtrPyramids->SetClippingOff();
605 if (forced) {
606 m_PyramidGeometry->Update();
608 m_PyramidActor->SetVisibility(1);
609 } else {
610 m_ExtrVol->SetPyramidsOff();
611 m_PyramidActor->SetVisibility(0);
613 if (ui.checkBoxWedge->isChecked()) {
614 m_ExtrVol->SetWedgesOn();
615 if (ui.checkBoxClip->isChecked()) {
616 m_ExtrWedges->SetClippingOn();
617 } else {
618 m_ExtrWedges->SetClippingOff();
620 if (forced) {
621 m_WedgeGeometry->Update();
623 m_WedgeActor->SetVisibility(1);
624 } else {
625 m_ExtrVol->SetWedgesOff();
626 m_WedgeActor->SetVisibility(0);
628 if (ui.checkBoxHexa->isChecked()) {
629 m_ExtrVol->SetHexesOn();
630 if (ui.checkBoxClip->isChecked()) {
631 m_ExtrHexes->SetClippingOn();
632 } else {
633 m_ExtrHexes->SetClippingOff();
635 if (forced) {
636 m_HexaGeometry->Update();
638 m_HexaActor->SetVisibility(1);
639 } else {
640 m_ExtrVol->SetHexesOff();
641 m_HexaActor->SetVisibility(0);
644 // wireframe
645 if (ui.checkBoxClip->isChecked()) {
646 m_ExtrVol->SetClippingOn();
647 } else {
648 m_ExtrVol->SetClippingOff();
650 if (forced) {
651 m_VolumeGeometry->Update();
653 m_VolumeWireActor->SetVisibility(1);
654 } else {
655 m_TetraActor->VisibilityOff();
656 m_PyramidActor->VisibilityOff();
657 m_WedgeActor->VisibilityOff();
658 m_HexaActor->VisibilityOff();
659 m_VolumeWireActor->VisibilityOff();
663 void GuiMainWindow::updateActors(bool forced)
665 // qDebug()<<"QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); called()";
666 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
668 //if (!tryLock()) return;
669 try {
670 m_Axes->SetInput(m_Grid);
671 updateSurfaceActors(forced);
672 updateVolumeActors(forced);
673 updateStatusBar();
674 } catch (Error err) {
675 err.display();
677 //unlock();
679 // qDebug()<<"QApplication::restoreOverrideCursor(); called()";
680 QApplication::restoreOverrideCursor();
685 void GuiMainWindow::forceUpdateActors()
687 // qDebug()<<"void GuiMainWindow::forceUpdateActors() START";
688 updateActors(true);
689 getRenderWindow()->Render();
690 // qDebug()<<"void GuiMainWindow::forceUpdateActors() END";
693 void GuiMainWindow::setPickMode(bool a_UseVTKInteractor,bool a_CellPickerMode)
695 m_UseVTKInteractor=a_UseVTKInteractor;
696 if (a_UseVTKInteractor) {
697 ui.checkBox_UseVTKInteractor->setCheckState(Qt::Checked);
698 } else {
699 ui.checkBox_UseVTKInteractor->setCheckState(Qt::Unchecked);
701 if (a_CellPickerMode) {
702 ui.radioButton_CellPicker->toggle();
703 } else {
704 ui.radioButton_PointPicker->toggle();
708 void GuiMainWindow::setUseVTKInteractor(int a_UseVTKInteractor)
710 m_UseVTKInteractor = a_UseVTKInteractor;
713 bool GuiMainWindow::pickPoint(vtkIdType id_node)
715 if ((id_node >= 0) && (id_node < m_Grid->GetNumberOfPoints())) {
716 vec3_t x(0,0,0);
717 m_Grid->GetPoints()->GetPoint(id_node, x.data());
718 m_PickSphere->SetCenter(x.data());
719 m_PickedPoint = id_node;
720 m_PickActor->GetProperty()->SetColor(0,0,1);
721 m_PickActor->VisibilityOn();
722 return(true);
723 } else {
724 m_PickActor->VisibilityOff();
725 return(false);
729 bool GuiMainWindow::pickCell(vtkIdType id_cell)
731 if ((id_cell >= 0) && (id_cell < m_Grid->GetNumberOfCells())) {
732 vtkIdType *pts, Npts;
733 m_Grid->GetCellPoints(id_cell, Npts, pts);
734 vec3_t x(0,0,0);
735 for (vtkIdType i = 0; i < Npts; ++i) {
736 vec3_t xp;
737 m_Grid->GetPoints()->GetPoint(pts[i], xp.data());
738 x += double(1)/Npts * xp;
740 m_PickSphere->SetCenter(x.data());
741 double R = 1e99;
742 for (vtkIdType i = 0; i < Npts; ++i) {
743 vec3_t xp;
744 m_Grid->GetPoints()->GetPoint(pts[i], xp.data());
745 R = min(R, 0.25*(xp-x).abs());
747 m_ReferenceSize = R; //Used for text annotations too!
748 m_PickSphere->SetRadius(R);
749 m_PickedCell = id_cell;
750 m_PickActor->GetProperty()->SetColor(1,0,0);
751 m_PickActor->VisibilityOn();
752 return(true);
753 } else {
754 m_PickActor->VisibilityOff();
755 return(false);
759 void GuiMainWindow::importSTL()
761 StlReader stl;
762 stl();
763 updateBoundaryCodes(true);
764 updateActors();
765 updateStatusBar();
766 zoomAll();
769 void GuiMainWindow::importGmsh1Ascii()
771 GmshReader gmsh;
772 gmsh.setV1Ascii();
773 gmsh();
774 updateBoundaryCodes(true);
775 updateActors();
776 updateStatusBar();
777 zoomAll();
780 void GuiMainWindow::exportGmsh1Ascii()
782 GmshWriter gmsh;
783 gmsh.setV1Ascii();
784 gmsh();
787 void GuiMainWindow::importGmsh2Ascii()
789 GmshReader gmsh;
790 gmsh.setV2Ascii();
791 gmsh();
792 updateBoundaryCodes(true);
793 updateActors();
794 updateStatusBar();
795 zoomAll();
798 void GuiMainWindow::exportGmsh2Ascii()
800 GmshWriter gmsh;
801 gmsh.setV2Ascii();
802 gmsh();
805 void GuiMainWindow::exportNeutral()
807 NeutralWriter neutral;
808 neutral();
811 void GuiMainWindow::zoomAll()
813 getRenderer()->ResetCamera();
814 getRenderWindow()->Render();
817 void GuiMainWindow::zoomOnPickedObject()
819 if(m_PickActor->GetVisibility()) {
820 getRenderer()->ResetCamera(m_PickActor->GetBounds());
821 getRenderWindow()->Render();
825 void GuiMainWindow::deselectAll()
827 cout << "void GuiMainWindow::deselectAll()" << endl;
828 m_PickActor->VisibilityOff();
829 updateActors();
832 ///\todo Should display a window
833 void GuiMainWindow::info()
835 ShowInfo info(ui.radioButton_CellPicker->isChecked(), m_PickedPoint, m_PickedCell);
836 info();
839 int GuiMainWindow::quickSave()
841 ///\todo add RAM support
842 if(m_undo_redo_enabled) {
843 if(m_Grid->GetNumberOfPoints()>0)
845 m_CurrentOperation++;
846 QFileInfo fileinfo(m_CurrentFilename);
847 QString l_filename = m_LogDir + fileinfo.completeBaseName() + "_" + QString("%1").arg(m_CurrentOperation);
848 m_LastOperation=m_CurrentOperation;
849 cout<<"Operation "<<m_CurrentOperation<<endl;
850 saveAs(l_filename, false);
851 if(m_CurrentOperation>0) ui.actionUndo->setEnabled(true);
852 ui.actionRedo->setEnabled(false);
854 else cout<<"No grid to save!"<<endl;
855 return(m_CurrentOperation);
857 return 0;
860 void GuiMainWindow::quickLoad(int a_operation)
862 ///\todo add RAM support
863 if(m_undo_redo_enabled) {
864 QFileInfo fileinfo(m_CurrentFilename);
865 QString l_filename = m_LogDir + fileinfo.completeBaseName() + "_" + QString("%1").arg(a_operation) + ".egc";
866 open(l_filename, false);
870 void GuiMainWindow::undo()
872 if(m_undo_redo_enabled) {
873 cout << "Undoing operation " << m_CurrentOperation << endl;
874 m_CurrentOperation--;
875 quickLoad(m_CurrentOperation);
876 ui.actionRedo->setEnabled(true);
877 if(m_CurrentOperation<=0) ui.actionUndo->setEnabled(false);
879 else {
880 resetOperationCounter();
881 QMessageBox::critical(this, "de-activated", "Undo is not doing anything at the moment!");
885 void GuiMainWindow::redo()
887 if(m_undo_redo_enabled) {
888 m_CurrentOperation++;
889 cout << "Redoing operation " << m_CurrentOperation << endl;
890 quickLoad(m_CurrentOperation);
891 ui.actionUndo->setEnabled(true);
892 if(m_CurrentOperation>=m_LastOperation) ui.actionRedo->setEnabled(false);
894 else {
895 resetOperationCounter();
896 QMessageBox::critical(this, "de-activated", "Redo is not doing anything at the moment!");
900 void GuiMainWindow::resetOperationCounter()
902 m_CurrentOperation=-1;
903 m_LastOperation=m_CurrentOperation;
904 ui.actionUndo->setEnabled(false);
905 ui.actionRedo->setEnabled(false);
908 QString GuiMainWindow::getXmlSection(QString name)
910 QStringList tags = name.toLower().split("/", QString::SkipEmptyParts);
911 QDomElement element = m_XmlDoc.documentElement();
912 bool found = true;
913 QString section_text = "";
914 try {
915 foreach (QString tag, tags) {
916 QDomNodeList nodes = element.elementsByTagName(tag);
917 if (nodes.size() > 1) {
918 EG_ERR_RETURN("error retrieving XML section '" + name + "'");
920 if (nodes.size() == 0) {
921 found = false;
922 break;
924 if (!nodes.at(0).isElement()) {
925 EG_ERR_RETURN("error retrieving XML section '" + name + "'");
927 element = nodes.at(0).toElement();
929 } catch (Error err) {
930 err.display();
932 if (found) {
933 section_text = element.text();
935 return section_text;
938 void GuiMainWindow::setXmlSection(QString name, QString contents)
940 QStringList tags = name.toLower().split("/", QString::SkipEmptyParts);
941 QDomElement element = m_XmlDoc.documentElement();
942 try {
943 foreach (QString tag, tags) {
944 QDomNodeList nodes = element.elementsByTagName(tag);
945 if (nodes.size() > 1) {
946 EG_ERR_RETURN("error retrieving XML section '" + name + "'");
948 if (nodes.size() == 0) {
949 QDomElement new_element = m_XmlDoc.createElement(tag);
950 element.appendChild(new_element);
951 element = new_element;
952 } else if (!nodes.at(0).isElement()) {
953 EG_ERR_RETURN("error retrieving XML section '" + name + "'");
954 } else {
955 element = nodes.at(0).toElement();
958 while (element.hasChildNodes()) {
959 element.removeChild(element.firstChild());
961 QDomText text_node = m_XmlDoc.createTextNode(contents);
962 element.appendChild(text_node);
963 } catch (Error err) {
964 err.display();
968 void GuiMainWindow::openPhysicalBoundaryConditions()
970 m_PhysicalBoundaryConditionsMap.clear();
971 QString buffer = getXmlSection("engrid/physical");
972 QTextStream f(&buffer, QIODevice::ReadOnly);
973 while (!f.atEnd()) {
974 QString name, type;
975 int index;
976 f >> index >> name >> type;
977 if ((name != "") && (type != "")) {
978 PhysicalBoundaryCondition PBC;
979 PBC.setName(name);
980 PBC.setIndex(index);
981 PBC.setType(type);
982 for (int i = 0; i < PBC.getNumVars(); ++i) {
983 double v;
984 f >> v;
985 PBC.setValue(i, v);
987 m_PhysicalBoundaryConditionsMap[name] = PBC;
992 void GuiMainWindow::savePhysicalBoundaryConditions()
994 QString buffer("");
995 QTextStream f(&buffer, QIODevice::WriteOnly);
996 f << "\n";
997 foreach (PhysicalBoundaryCondition PBC, m_PhysicalBoundaryConditionsMap) {
998 f << PBC.getIndex() << " " << PBC.getName() << " " << PBC.getType();
999 for (int i = 0; i < PBC.getNumVars(); ++i) {
1000 f << " " << PBC.getVarValue(i);
1002 f << "\n";
1004 setXmlSection("engrid/physical", buffer);
1007 void GuiMainWindow::openBC()
1009 m_bcmap.clear();
1010 m_VolMap.clear();
1011 QString buffer = getXmlSection("engrid/bc");
1012 QTextStream f(&buffer, QIODevice::ReadOnly);
1013 while (!f.atEnd()) {
1014 QString name, type;
1015 int i;
1016 f >> i >> name >> type;
1017 if(name!="" && type!="") {
1018 if (i >= 0) {
1019 m_bcmap[i] = BoundaryCondition(name,type);
1020 } else {
1021 VolumeDefinition V(name, -i);
1022 QString text = type.replace(",", " ").replace(":", " ");
1023 QTextStream s(&text);
1024 while (!s.atEnd()) {
1025 QString bc_txt, sign_txt;
1026 s >> bc_txt >> sign_txt;
1027 V.addBC(bc_txt.toInt(), sign_txt.toInt());
1029 m_VolMap[name] = V;
1035 void GuiMainWindow::saveBC()
1037 QString buffer("");
1038 QTextStream f(&buffer, QIODevice::WriteOnly);
1039 f << "\n";
1040 foreach (int i, m_AllBoundaryCodes) {
1041 BoundaryCondition bc = m_bcmap[i];
1042 f << i << " " << bc.getName() << " " << bc.getType() << "\n";
1044 foreach (VolumeDefinition V, m_VolMap) {
1045 QString dirs = "";
1046 bool first = true;
1047 foreach (int i, m_AllBoundaryCodes) {
1048 BoundaryCondition bc = m_bcmap[i];
1049 if (!first) {
1050 dirs += ",";
1051 } else {
1052 first = false;
1054 QString num;
1055 num.setNum(i);
1056 dirs += num + ":";
1057 num.setNum(V.getSign(i));
1058 dirs += num;
1060 f << "-" << V.getVC() << " " << V.getName() << " " << dirs << "\n";
1062 setXmlSection("engrid/bc", buffer);
1065 void GuiMainWindow::openGrid(QString file_name)
1067 file_name += ".vtu";
1068 EG_VTKSP(vtkXMLUnstructuredGridReader,vtu);
1069 vtu->SetFileName(qPrintable(file_name));
1070 vtu->Update();
1071 m_Grid->DeepCopy(vtu->GetOutput());
1072 createBasicFields(m_Grid, m_Grid->GetNumberOfCells(), m_Grid->GetNumberOfPoints());
1073 openBC();
1074 openPhysicalBoundaryConditions();
1075 updateBoundaryCodes(true);
1076 createIndices(m_Grid);
1077 updateActors();
1078 updateStatusBar();
1079 zoomAll();
1082 ///\todo I think this should also be a done by a subclass of IOOperation just like for import operations
1083 void GuiMainWindow::open()
1085 QFileDialog dialog(NULL, "open grid from file", getCwd(), "enGrid case files (*.egc *.EGC);; legacy grid files(*.vtu *.VTU)");
1086 QFileInfo file_info(m_CurrentFilename);
1087 qDebug()<<"m_CurrentFilename="<<m_CurrentFilename;
1088 dialog.selectFile(file_info.completeBaseName() + ".egc");
1089 if (dialog.exec()) {
1090 QStringList selected_files = dialog.selectedFiles();
1091 QString file_name = selected_files[0];
1092 if (!file_name.isNull()) {
1093 this->open(file_name);
1098 void GuiMainWindow::open(QString file_name, bool update_current_filename)
1100 cout << "Opening " << qPrintable(file_name) << endl;
1102 QFileInfo file_info(file_name);
1103 bool no_case_file = false;
1104 QString file_extension = getExtension(file_name);
1105 QString grid_file_name = file_name;
1106 if (file_extension.toLower() == "vtu") {
1107 no_case_file = true;
1108 grid_file_name = stripFromExtension(file_name);
1110 if(update_current_filename) {
1111 GuiMainWindow::setCwd(QFileInfo(file_name).absolutePath());
1113 if (!no_case_file) {
1114 openXml(file_name);
1116 openGrid(grid_file_name);
1117 openBC();
1118 openPhysicalBoundaryConditions();
1119 // update current filename
1120 if(update_current_filename) m_CurrentFilename = stripFromExtension(file_name) + ".egc";
1121 setWindowTitle(m_CurrentFilename + " - enGrid - " + QString("%1").arg(m_CurrentOperation) );
1122 setUnsaved(false);
1124 if(update_current_filename) {
1125 this->addRecentFile(file_name,QDateTime::currentDateTime());
1126 resetOperationCounter();
1127 quickSave();
1131 void GuiMainWindow::openXml(QString file_name)
1133 QFile xml_file(file_name);
1134 if (!xml_file.open(QIODevice::ReadOnly)) {
1135 qWarning()<<"Failed to open xml_file "<<xml_file.fileName();
1136 qWarning()<<"QDir::current()="<<QDir::current();
1137 qWarning()<<"QDir::currentPath()="<<QDir::currentPath();
1138 qWarning()<<"getCwd()="<<getCwd();
1139 EG_BUG;
1141 if (!m_XmlDoc.setContent(&xml_file)) {
1142 QMessageBox::critical(this, tr("Open failed"), tr("Error reading enGrid case file:\n%1").arg(file_name));
1144 xml_file.close();
1147 void GuiMainWindow::saveXml(QString file_name)
1149 QString buffer = m_XmlDoc.toString(0);
1150 QFile xml_file(file_name);
1151 xml_file.open(QIODevice::WriteOnly | QIODevice::Text);
1152 QTextStream f(&xml_file);
1153 f << buffer << endl;
1156 QString GuiMainWindow::saveAs(QString file_name, bool update_current_filename)
1158 QString buffer = m_XmlDoc.toString(0);
1160 if(update_current_filename) QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
1162 QFileInfo file_info(file_name);
1163 if (file_info.suffix().toLower() != "egc") {
1164 file_name += ".egc";
1166 cout << "Saving as " << qPrintable(file_name) << endl;
1167 if(update_current_filename) {
1168 // update current filename
1169 GuiMainWindow::setCwd(file_info.absolutePath());
1170 m_CurrentFilename = file_name;
1172 if(!saveGrid(m_Grid, file_name)) {
1173 QMessageBox::critical(this, QObject::tr("Save failed"), QObject::tr("The grid could not be saved as:\n%1").arg(file_name));
1176 saveBC();
1177 savePhysicalBoundaryConditions();
1178 saveXml(file_name);
1180 setWindowTitle(m_CurrentFilename + " - enGrid - " + QString("%1").arg(m_CurrentOperation) );
1181 setUnsaved(false);
1183 if(update_current_filename) QApplication::restoreOverrideCursor();
1185 if(update_current_filename) {
1186 this->addRecentFile(file_name,QDateTime::currentDateTime());
1189 return(file_name);
1192 void GuiMainWindow::save()
1194 if ( m_CurrentFilename == "untitled.egc" || m_UnSaved ) {
1195 saveAs();
1196 } else {
1197 saveAs(m_CurrentFilename);
1201 void GuiMainWindow::saveAs()
1203 QFileDialog dialog(NULL, "write case to file", getCwd(), "enGrid case files (*.egc)");
1204 QFileInfo file_info(m_CurrentFilename);
1205 dialog.selectFile(file_info.completeBaseName() + ".egc");
1206 dialog.setAcceptMode(QFileDialog::AcceptSave);
1207 dialog.setConfirmOverwrite(true);
1208 if (dialog.exec()) {
1209 QStringList selected_files = dialog.selectedFiles();
1210 QString file_name = selected_files[0];
1211 if (!file_name.isNull()) {
1212 saveAs(file_name);
1213 //for the undo/redo operations
1214 resetOperationCounter();
1215 quickSave();
1220 void GuiMainWindow::updateStatusBar()
1222 QString num, txt = "enGrid is currently busy with an operation ...";
1223 if (!m_Busy) {
1224 txt = "";
1226 if (!tryLock()) {
1227 m_StatusLabel->setText(txt);
1228 ui.label_node_cell_info->setText(txt);
1229 return;
1231 vtkIdType Ncells = m_Grid->GetNumberOfCells();
1232 vtkIdType Nnodes = m_Grid->GetNumberOfPoints();
1233 vtkIdType Ntris = 0;
1234 vtkIdType Nquads = 0;
1235 vtkIdType Ntets = 0;
1236 vtkIdType Npyras = 0;
1237 vtkIdType Nprism = 0;
1238 vtkIdType Nhexas = 0;
1239 for (vtkIdType i = 0; i < Ncells; ++i) {
1240 int ct = m_Grid->GetCellType(i);
1241 if (ct == VTK_TRIANGLE) ++Ntris;
1242 else if (ct == VTK_QUAD) ++Nquads;
1243 else if (ct == VTK_TETRA) ++Ntets;
1244 else if (ct == VTK_WEDGE) ++Nprism;
1245 else if (ct == VTK_PYRAMID) ++Npyras;
1246 else if (ct == VTK_HEXAHEDRON) ++Nhexas;
1248 num.setNum(Ntets + Npyras + Nprism + Nhexas); txt += num + " volume cells(";
1249 num.setNum(Ntets); txt += num + " tetras, ";
1250 num.setNum(Npyras); txt += num + " pyramids, ";
1251 num.setNum(Nprism); txt += num + " prisms, ";
1252 num.setNum(Nhexas); txt += num + " hexas), ";
1253 num.setNum(Ntris + Nquads); txt += num + " surface cells(";
1254 num.setNum(Ntris); txt += num + " triangles, ";
1255 num.setNum(Nquads); txt += num + " quads), ";
1256 num.setNum(Nnodes); txt += num + " nodes";
1258 if(ui.radioButton_CellPicker->isChecked())
1260 QString pick_txt = ", picked cell: ";
1261 vtkIdType id_cell = m_PickedCell;
1262 if (id_cell < 0 || id_cell>=m_Grid->GetNumberOfCells()) {
1263 pick_txt += "no cell picked";
1264 } else {
1265 vtkIdType type_cell = m_Grid->GetCellType(id_cell);
1266 if (type_cell == VTK_TRIANGLE) pick_txt += "tri";
1267 else if (type_cell == VTK_QUAD) pick_txt += "qua";
1268 else if (type_cell == VTK_TETRA) pick_txt += "tet";
1269 else if (type_cell == VTK_PYRAMID) pick_txt += "pyr";
1270 else if (type_cell == VTK_WEDGE) pick_txt += "pri";
1271 else if (type_cell == VTK_HEXAHEDRON) pick_txt += "hex";
1272 vtkIdType N_pts, *pts;
1273 m_Grid->GetCellPoints(id_cell, N_pts, pts);
1274 pick_txt += " [";
1275 for (int i_pts = 0; i_pts < N_pts; ++i_pts) {
1276 QString num;
1277 num.setNum(pts[i_pts]);
1278 pick_txt += num;
1279 if (i_pts < N_pts-1) {
1280 pick_txt += ",";
1283 pick_txt += "]";
1284 QString tmp;
1285 EG_VTKDCC(vtkIntArray, cell_code, m_Grid, "cell_code");
1286 tmp.setNum(cell_code->GetValue(id_cell));
1287 pick_txt += " code=" + tmp;
1288 tmp.setNum(id_cell);
1289 pick_txt += " id=" + tmp;
1291 txt += pick_txt;
1293 else
1295 QString pick_txt = ", picked node: ";
1296 vtkIdType id_node = m_PickedPoint;
1297 if (id_node < 0) {
1298 pick_txt += "no node picked";
1299 } else {
1300 vec3_t x;
1301 m_Grid->GetPoints()->GetPoint(id_node,x.data());
1302 pick_txt += " [";
1303 for (int i = 0; i < 3; i++) {
1304 QString num;
1305 num.setNum(x[i]);
1306 pick_txt += num;
1307 if (i < 2) {
1308 pick_txt += ",";
1311 pick_txt += "]";
1312 QString tmp;
1313 EG_VTKDCN(vtkDoubleArray, characteristic_length_desired, m_Grid, "node_meshdensity_desired");
1314 tmp.setNum(characteristic_length_desired->GetValue(id_node));
1315 pick_txt += " wanted density=" + tmp;
1316 EG_VTKDCN(vtkDoubleArray, node_meshdensity_current, m_Grid, "node_meshdensity_current");
1317 tmp.setNum(node_meshdensity_current->GetValue(id_node));
1318 pick_txt += " current density=" + tmp;
1319 EG_VTKDCN(vtkIntArray, node_specified_density, m_Grid, "node_specified_density");
1320 tmp.setNum(node_specified_density->GetValue(id_node));
1321 pick_txt += " node_specified_density=" + tmp;
1322 EG_VTKDCN(vtkCharArray, node_type, m_Grid, "node_type");
1323 pick_txt += " type=" + QString(VertexType2Str( node_type->GetValue(id_node)));
1324 tmp.setNum(id_node);
1325 pick_txt += " id_node=" + tmp;
1328 txt += pick_txt;
1331 m_StatusLabel->setText(txt);
1332 ui.label_node_cell_info->setText(txt);
1333 unlock();
1336 void GuiMainWindow::selectBoundaryCodes()
1338 GuiSelectBoundaryCodes bcodes;
1339 bcodes.setDisplayBoundaryCodes(m_DisplayBoundaryCodes);
1340 bcodes.setBoundaryCodes(m_AllBoundaryCodes);
1341 bcodes();
1342 bcodes.getThread().wait();
1343 bcodes.getSelectedBoundaryCodes(m_DisplayBoundaryCodes);
1344 m_BCodesFilter->SetBoundaryCodes(m_DisplayBoundaryCodes);
1345 updateActors();
1348 void GuiMainWindow::updateBoundaryCodes(bool all_on)
1350 try {
1351 m_AllBoundaryCodes.clear();
1352 EG_VTKDCC(vtkIntArray, cell_code, m_Grid, "cell_code");
1353 for (vtkIdType i = 0; i < m_Grid->GetNumberOfCells(); ++i) {
1354 int ct = m_Grid->GetCellType(i);
1355 if ((ct == VTK_TRIANGLE) || (ct == VTK_QUAD)) {
1356 m_AllBoundaryCodes.insert(cell_code->GetValue(i));
1359 if (all_on) {
1360 m_DisplayBoundaryCodes.clear();
1361 foreach (int bc, m_AllBoundaryCodes) {
1362 m_DisplayBoundaryCodes.insert(bc);
1364 } else {
1365 QSet<int> dbcs;
1366 foreach (int bc, m_DisplayBoundaryCodes) {
1367 if (m_AllBoundaryCodes.contains(bc)) {
1368 dbcs.insert(bc);
1371 m_DisplayBoundaryCodes.clear();
1372 foreach (int bc, m_AllBoundaryCodes) {
1373 if (dbcs.contains(bc)) {
1374 m_DisplayBoundaryCodes.insert(bc);
1378 m_BCodesFilter->SetBoundaryCodes(m_DisplayBoundaryCodes);
1379 } catch (Error err) {
1380 err.display();
1384 void GuiMainWindow::normalExtrusion()
1386 GuiNormalExtrusion extr;
1387 extr();
1388 updateBoundaryCodes(false);
1389 updateActors();
1392 void GuiMainWindow::setAxesVisibility()
1394 if (ui.actionViewAxes->isChecked()) {
1395 m_Axes->VisibilityOn();
1396 } else {
1397 m_Axes->VisibilityOff();
1399 getRenderWindow()->Render();
1402 void GuiMainWindow::setViewingMode()
1404 if (ui.actionViewOrthogonal->isChecked()) getRenderer()->GetActiveCamera()->ParallelProjectionOn();
1405 else getRenderer()->GetActiveCamera()->ParallelProjectionOff();
1406 getRenderWindow()->Render();
1409 void GuiMainWindow::viewNodeIDs()
1411 int N = m_Grid->GetNumberOfPoints();
1412 cout<<"N="<<N<<endl;
1413 if (ui.actionViewNodeIDs->isChecked()) {
1414 cout<<"Activating node ID view"<<endl;
1415 m_NodeTextVectorText.resize(N);
1416 m_NodeTextPolyDataMapper.resize(N);
1417 m_NodeTextFollower.resize(N);
1418 for(int i = 0; i < N; ++i){
1419 m_NodeTextVectorText[i]=vtkVectorText::New();
1420 QString tmp;
1421 tmp.setNum(i);
1422 m_NodeTextVectorText[i]->SetText(qPrintable(tmp));
1423 m_NodeTextPolyDataMapper[i]=vtkPolyDataMapper::New();
1424 m_NodeTextPolyDataMapper[i]->SetInputConnection(m_NodeTextVectorText[i]->GetOutputPort());
1425 m_NodeTextFollower[i]=vtkFollower::New();
1426 m_NodeTextFollower[i]->SetMapper(m_NodeTextPolyDataMapper[i]);
1427 m_NodeTextFollower[i]->SetScale(m_ReferenceSize, m_ReferenceSize, m_ReferenceSize);
1428 vec3_t M;
1429 m_Grid->GetPoint(i, M.data());
1430 vec3_t tmp_M = M;
1431 vec3_t OffSet = m_ReferenceSize*tmp_M.normalise();
1432 M = M + OffSet;
1433 m_NodeTextFollower[i]->AddPosition(M[0], M[1], M[2]);
1434 m_NodeTextFollower[i]->SetCamera(getRenderer()->GetActiveCamera());
1435 m_NodeTextFollower[i]->GetProperty()->SetColor(0,0,1);
1436 getRenderer()->AddActor(m_NodeTextFollower[i]);
1439 else {
1440 cout<<"Deactivating node ID view"<<endl;
1441 for(unsigned int i = 0; i < m_NodeTextFollower.size();i++){
1442 getRenderer()->RemoveActor(m_NodeTextFollower[i]);
1443 m_NodeTextFollower[i]->Delete();
1444 m_NodeTextPolyDataMapper[i]->Delete();
1445 m_NodeTextVectorText[i]->Delete();
1447 m_NodeTextFollower.clear();
1448 m_NodeTextPolyDataMapper.clear();
1449 m_NodeTextVectorText.clear();
1452 getRenderWindow()->Render();
1455 void GuiMainWindow::viewCellIDs()
1457 vtkIdType N = m_Grid->GetNumberOfCells();
1458 cout<<"N="<<N<<endl;
1459 if (ui.actionViewCellIDs->isChecked()) {
1460 cout<<"Activating cell ID view"<<endl;
1461 m_CellTextVectorText.resize(N);
1462 m_CellTextPolyDataMapper.resize(N);
1463 m_CellTextFollower.resize(N);
1464 for (vtkIdType id_cell = 0; id_cell < N; ++id_cell){
1465 m_CellTextVectorText[id_cell] = vtkVectorText::New();
1467 QString tmp;
1469 if(ui.comboBox_CellTextField->currentIndex()==0) {
1470 tmp.setNum(id_cell);
1471 } else if (ui.comboBox_CellTextField->currentIndex()>0) {
1472 EG_VTKDCC(vtkIntArray, current_cell_field, m_Grid, qPrintable(ui.comboBox_CellTextField->currentText()));
1473 tmp.setNum(current_cell_field->GetValue(id_cell));
1475 else EG_BUG;
1477 m_CellTextVectorText[id_cell]->SetText(qPrintable(tmp));
1478 m_CellTextPolyDataMapper[id_cell]=vtkPolyDataMapper::New();
1479 m_CellTextPolyDataMapper[id_cell]->SetInputConnection(m_CellTextVectorText[id_cell]->GetOutputPort());
1480 m_CellTextFollower[id_cell]=vtkFollower::New();
1481 m_CellTextFollower[id_cell]->SetMapper(m_CellTextPolyDataMapper[id_cell]);
1482 m_CellTextFollower[id_cell]->SetScale(m_ReferenceSize, m_ReferenceSize, m_ReferenceSize);
1483 vtkIdType N_pts,*pts;
1484 m_Grid->GetCellPoints(id_cell,N_pts,pts);
1485 vec3_t Center(0,0,0);
1486 for (int p = 0; p < N_pts; ++p) {
1487 vec3_t M;
1488 m_Grid->GetPoint(pts[p],M.data());
1489 Center+=M.data();
1491 vec3_t OffSet = m_ReferenceSize*triNormal(m_Grid, pts[0], pts[1], pts[2]).normalise();
1492 Center = 1.0/(double)N_pts*Center+OffSet;
1493 m_CellTextFollower[id_cell]->AddPosition(Center[0], Center[1], Center[2]);
1494 m_CellTextFollower[id_cell]->SetCamera(getRenderer()->GetActiveCamera());
1495 m_CellTextFollower[id_cell]->GetProperty()->SetColor(1, 0, 0);
1496 getRenderer()->AddActor(m_CellTextFollower[id_cell]);
1498 } else {
1499 cout<<"Deactivating cell ID view"<<endl;
1500 for (vtkIdType id_cell = 0; id_cell < (vtkIdType) m_CellTextFollower.size(); ++id_cell) {
1501 getRenderer()->RemoveActor(m_CellTextFollower[id_cell]);
1502 m_CellTextFollower[id_cell]->Delete();
1503 m_CellTextPolyDataMapper[id_cell]->Delete();
1504 m_CellTextVectorText[id_cell]->Delete();
1506 m_CellTextFollower.clear();
1507 m_CellTextPolyDataMapper.clear();
1508 m_CellTextVectorText.clear();
1511 getRenderWindow()->Render();
1514 void GuiMainWindow::pickCallBack
1516 vtkObject *caller,
1517 unsigned long int eid,
1518 void *clientdata,
1519 void *calldata
1522 caller = caller;
1523 eid = eid;
1524 clientdata = clientdata;
1525 calldata = calldata;
1526 THIS->updateActors();
1527 THIS->updateStatusBar();
1530 vtkIdType GuiMainWindow::getPickedCell()
1532 vtkIdType picked_cell = -1;
1533 if (m_Grid->GetNumberOfCells() > 0) {
1534 m_BCodesFilter->Update();
1535 if (m_BCodesFilter->GetOutput()->GetNumberOfCells() > 0) {
1536 EG_VTKDCC(vtkLongArray_t, cell_index, m_BCodesFilter->GetOutput(), "cell_index");
1537 if (m_UseVTKInteractor) {
1538 picked_cell = cell_index->GetValue(m_CellPicker->GetCellId());
1539 } else {
1540 picked_cell = m_PickedCell;
1544 return picked_cell;
1547 vtkIdType GuiMainWindow::getPickedPoint()
1549 vtkIdType picked_point = -1;
1550 if (m_Grid->GetNumberOfCells() > 0) {
1551 m_BCodesFilter->Update();
1552 if (m_BCodesFilter->GetOutput()->GetNumberOfCells() > 0) {
1553 EG_VTKDCN(vtkLongArray_t, node_index, m_BCodesFilter->GetOutput(), "node_index");
1554 if (m_UseVTKInteractor) {
1555 picked_point = node_index->GetValue(m_PointPicker->GetPointId());
1556 } else {
1557 picked_point = m_PickedPoint;
1561 return picked_point;
1564 void GuiMainWindow::changeSurfaceOrientation()
1566 for (vtkIdType cellId = 0; cellId < m_Grid->GetNumberOfCells(); ++cellId) {
1567 vtkIdType Npts, *pts;
1568 m_Grid->GetCellPoints(cellId, Npts, pts);
1569 QVector<vtkIdType> nodes(Npts);
1570 for (vtkIdType j = 0; j < Npts; ++j) nodes[j] = pts[j];
1571 for (vtkIdType j = 0; j < Npts; ++j) pts[Npts - j - 1] = nodes[j];
1573 updateActors();
1574 m_Grid->Modified();// to make sure VTK notices the changes and changes the cell colors
1577 void GuiMainWindow::checkSurfaceOrientation()
1579 CorrectSurfaceOrientation corr_surf;
1580 vtkIdType picked_cell = getPickedCell();
1581 if (picked_cell >= 0) {
1582 corr_surf.setStart(picked_cell);
1584 corr_surf();
1585 updateActors();
1588 void GuiMainWindow::improveAspectRatio()
1590 GuiImproveAspectRatio impr_ar;
1591 impr_ar();
1592 updateActors();
1595 void GuiMainWindow::exportAsciiStl()
1597 StlWriter stl;
1598 stl.setFileTypeToASCII();
1599 stl();
1602 void GuiMainWindow::exportBinaryStl()
1604 StlWriter stl;
1605 stl.setFileTypeToBinary();
1606 stl();
1609 void GuiMainWindow::exportAsciiPly()
1611 PlyWriter ply;
1612 ply.setFileTypeToASCII();
1613 ply();
1616 void GuiMainWindow::exportBinaryPly()
1618 PlyWriter ply;
1619 ply.setFileTypeToBinary();
1620 ply();
1623 void GuiMainWindow::periodicUpdate()
1625 Operation::collectGarbage();
1626 updateStatusBar();
1629 void GuiMainWindow::viewXP()
1631 getRenderer()->ResetCamera();
1632 double x[3];
1633 getRenderer()->GetActiveCamera()->GetFocalPoint(x);
1634 x[0] += 1;
1635 getRenderer()->GetActiveCamera()->SetPosition(x);
1636 getRenderer()->GetActiveCamera()->ComputeViewPlaneNormal();
1637 getRenderer()->GetActiveCamera()->SetViewUp(0,1,0);
1638 getRenderer()->ResetCamera();
1639 getRenderWindow()->Render();
1642 void GuiMainWindow::viewXM()
1644 getRenderer()->ResetCamera();
1645 double x[3];
1646 getRenderer()->GetActiveCamera()->GetFocalPoint(x);
1647 x[0] -= 1;
1648 getRenderer()->GetActiveCamera()->SetPosition(x);
1649 getRenderer()->GetActiveCamera()->ComputeViewPlaneNormal();
1650 getRenderer()->GetActiveCamera()->SetViewUp(0,1,0);
1651 getRenderer()->ResetCamera();
1652 getRenderWindow()->Render();
1655 void GuiMainWindow::viewYP()
1657 getRenderer()->ResetCamera();
1658 double x[3];
1659 getRenderer()->GetActiveCamera()->GetFocalPoint(x);
1660 x[1] += 1;
1661 getRenderer()->GetActiveCamera()->SetPosition(x);
1662 getRenderer()->GetActiveCamera()->ComputeViewPlaneNormal();
1663 getRenderer()->GetActiveCamera()->SetViewUp(0,0,-1);
1664 getRenderer()->ResetCamera();
1665 getRenderWindow()->Render();
1668 void GuiMainWindow::viewYM()
1670 getRenderer()->ResetCamera();
1671 double x[3];
1672 getRenderer()->GetActiveCamera()->GetFocalPoint(x);
1673 x[1] -= 1;
1674 getRenderer()->GetActiveCamera()->SetPosition(x);
1675 getRenderer()->GetActiveCamera()->ComputeViewPlaneNormal();
1676 getRenderer()->GetActiveCamera()->SetViewUp(0,0,-1);
1677 getRenderer()->ResetCamera();
1678 getRenderWindow()->Render();
1681 void GuiMainWindow::viewZP()
1683 getRenderer()->ResetCamera();
1684 double x[3];
1685 getRenderer()->GetActiveCamera()->GetFocalPoint(x);
1686 x[2] += 1;
1687 getRenderer()->GetActiveCamera()->SetPosition(x);
1688 getRenderer()->GetActiveCamera()->ComputeViewPlaneNormal();
1689 getRenderer()->GetActiveCamera()->SetViewUp(0,1,0);
1690 getRenderer()->ResetCamera();
1691 getRenderWindow()->Render();
1694 void GuiMainWindow::viewZM()
1696 getRenderer()->ResetCamera();
1697 double x[3];
1698 getRenderer()->GetActiveCamera()->GetFocalPoint(x);
1699 x[2] -= 1;
1700 getRenderer()->GetActiveCamera()->SetPosition(x);
1701 getRenderer()->GetActiveCamera()->ComputeViewPlaneNormal();
1702 getRenderer()->GetActiveCamera()->SetViewUp(0,1,0);
1703 getRenderer()->ResetCamera();
1704 getRenderWindow()->Render();
1707 void GuiMainWindow::callFixSTL()
1709 FixSTL *fix;
1710 fix = new FixSTL();
1711 fix->setLockGui();
1712 (*fix)();
1713 updateBoundaryCodes(false);
1714 updateActors();
1717 void GuiMainWindow::callDeletePickedPoint()
1719 EG_STDINTERSLOT( DeletePickedPoint );
1722 void GuiMainWindow::editBoundaryConditions()
1724 GuiEditBoundaryConditions editbcs;
1725 editbcs.setBoundaryCodes(m_AllBoundaryCodes);
1726 editbcs.setMap(&m_bcmap);
1727 editbcs();
1730 void GuiMainWindow::configure()
1733 // Just to create initial entries in the settings file
1734 // so that the options menu isn't empty at first start.
1735 try {
1736 GridSmoother tmp01;
1737 GuiCreateBoundaryLayer tmp02;
1738 SurfaceProjection tmp03;
1739 SurfaceMesher tmp04;
1740 UpdateDesiredMeshDensity tmp05;
1741 InsertPoints tmp06;
1742 RemovePoints tmp07;
1743 LaplaceSmoother tmp08;
1744 SwapTriangles tmp09;
1745 OpenFOAMTools tmp10;
1746 } catch (Error err) {
1747 err.display();
1750 GuiSettingsViewer settings(&m_qset);
1751 settings.CreateViewer();
1752 settings.exec();
1754 getSet("General","enable undo+redo",false,m_undo_redo_enabled);
1757 void GuiMainWindow::about()
1759 QMessageBox box(this);
1761 QString title="ENGRID";
1762 QString version = QString("version ") + ENGRID_VERSION;
1763 #ifdef GIT_DESCRIBE
1764 if(!QString(GIT_DESCRIBE).isEmpty()) {
1765 version += QString(" - ") + GIT_DESCRIBE;
1767 #endif
1769 version += " built on ";
1770 version += QString(__DATE__);
1771 version += " at ";
1772 version += QString(__TIME__);
1774 QString address = tr("ENGRID is being developed and maintained by:<br/>"
1775 "enGits GmbH<br/>"
1776 "Marie-Curie-Strasse 8<br/>"
1777 "79539 Loerrach<br/>"
1778 "Germany<br/>");
1780 QString mainurl="<a href=\"http://www.engits.com\">www.engits.com</a>";
1781 QString mail="<a href=\"mailto:info@engits.com\">info@engits.com</a>";
1782 QString gnuurl="<a href=\"http://www.gnu.org/licenses\">http://www.gnu.org/licenses</a>";
1783 QString license=tr("ENGRID is licenced under the GPL version 3.<br/>"
1784 "(see ")+gnuurl+tr(" for details)<br/>");
1785 QString bugurl="<a href=\"http://sourceforge.net/tracker2/?func=add&group_id=245110&atid=1126548\">the bugtracker available on Sourceforge</a>";
1786 QString bugreporting=tr("To submit a bug report, please use ")+bugurl;
1787 box.setText(QString::fromLatin1("<center><img src=\":/icons/resources/icons/G.png\">"
1788 "<h3>%1</h3>"
1789 "<p>%2</p>"
1790 "<p>%3</p>"
1791 "<p>Homepage: %4</p>"
1792 "<p>E-mail: %5</p>"
1793 "<p>%6</p>"
1794 "<p>%7</p></center>")
1795 .arg(title).arg(version).arg(address).arg(mainurl).arg(mail).arg(license).arg(bugreporting));
1796 box.setWindowTitle(tr("about ENGRID"));
1797 box.setIcon(QMessageBox::NoIcon);
1798 box.exec();
1802 ///\todo Why not use bcs = m_AllBoundaryCodes; ?
1803 void GuiMainWindow::getAllBoundaryCodes(QSet<int> &bcs)
1805 bcs = m_AllBoundaryCodes;
1806 // qWarning()<<"m_AllBoundaryCodes="<<m_AllBoundaryCodes;
1807 // bcs.clear();
1808 // foreach (int bc, m_AllBoundaryCodes) {
1809 // bcs.insert(bc);
1810 // }
1813 QSet<int> GuiMainWindow::getAllBoundaryCodes()
1815 return m_AllBoundaryCodes;
1818 void GuiMainWindow::getDisplayBoundaryCodes(QSet<int> &bcs)
1820 bcs.clear();
1821 foreach (int bc, m_DisplayBoundaryCodes) {
1822 bcs.insert(bc);
1826 QList<VolumeDefinition> GuiMainWindow::getAllVols()
1828 QList<VolumeDefinition> vols;
1829 foreach(VolumeDefinition vol, m_VolMap) {
1830 vols.push_back(vol);
1832 return vols;
1835 void GuiMainWindow::setAllVols(QList<VolumeDefinition> vols)
1837 m_VolMap.clear();
1838 foreach (VolumeDefinition V, vols) {
1839 m_VolMap[V.getName()] = V;
1843 QList<PhysicalBoundaryCondition> GuiMainWindow::getAllPhysicalBoundaryConditions()
1845 QList<PhysicalBoundaryCondition> physical_boundary_conditions;
1846 foreach(PhysicalBoundaryCondition PBC, m_PhysicalBoundaryConditionsMap) {
1847 physical_boundary_conditions.push_back(PBC);
1849 return physical_boundary_conditions;
1852 void GuiMainWindow::setAllPhysicalBoundaryConditions(QList<PhysicalBoundaryCondition> physical_boundary_conditions)
1854 m_PhysicalBoundaryConditionsMap.clear();
1855 foreach (PhysicalBoundaryCondition PBC, physical_boundary_conditions) {
1856 m_PhysicalBoundaryConditionsMap[PBC.getName()] = PBC;
1860 void GuiMainWindow::setAllPhysicalBoundaryConditions(QMap<QString,PhysicalBoundaryCondition> physical_boundary_conditions) {
1861 m_PhysicalBoundaryConditionsMap = physical_boundary_conditions;
1864 void GuiMainWindow::createDefaultVol()
1866 QList<VolumeDefinition> vols = getAllVols();
1867 if (vols.size() == 0) {
1868 VolumeDefinition V("default", 1);
1869 QSet<int> bcs;
1870 getAllBoundaryCodes(bcs);
1871 foreach (int bc, bcs) {
1872 V.addBC(bc, 1);
1874 vols.append(V);
1875 setAllVols(vols);
1879 QString GuiMainWindow::getFilePath()
1881 QFileInfo fileinfo(m_CurrentFilename);
1882 return fileinfo.absolutePath()+"/";
1885 void GuiMainWindow::markOutputLine()
1887 cout << "\n****************************************\n";
1888 cout << qPrintable(QTime::currentTime().toString("hh:mm:ss"));
1889 cout << "\n****************************************\n" << endl;
1892 void GuiMainWindow::storeSurfaceProjection()
1894 qDebug()<<"@@@ GuiMainWindow::storeSurfaceProjection called";
1895 foreach (SurfaceProjection* proj, m_SurfProj) {
1896 delete proj;
1898 m_SurfProj.clear();
1899 cout << "storing background grid for surface projection:" << endl;
1901 foreach (int bc, m_AllBoundaryCodes) {
1902 SurfaceProjection *proj = new SurfaceProjection();
1903 m_SurfProj[bc] = proj;
1904 QSet<int> bcs;
1905 bcs.insert(bc);
1906 QVector<vtkIdType> cls;
1907 getSurfaceCells(bcs, cls, m_Grid);
1908 proj->setBackgroundGrid(m_Grid, cls);
1909 if (proj->usesLevelSet()) {
1910 QString file_name;
1911 file_name.setNum(bc);
1912 file_name = "OctreeBC" + file_name;
1913 proj->writeOctree(file_name);
1914 cout << " bc " << bc << ": " << proj->getNumOctreeCells() << endl;
1919 SurfaceProjection* GuiMainWindow::getSurfProj(int bc)
1921 if (!m_SurfProj.contains(bc)) {
1922 QString bc_txt;
1923 bc_txt.setNum(bc);
1924 EG_ERR_RETURN("No surface projection found for boundary code " + bc_txt);
1926 return m_SurfProj[bc];
1929 bool GuiMainWindow::checkSurfProj()
1931 bool ok = true;
1932 foreach (int bc, m_AllBoundaryCodes) {
1933 if (!m_SurfProj.contains(bc)) {
1934 ok = false;
1935 break;
1938 return ok;
1941 void GuiMainWindow::openRecent(QAction *action)
1943 qDebug()<<"GuiMainWindow::openRecent called";
1944 QString file_name = action->text().right(action->text().length()-23);
1945 this->open(file_name);
1946 // this->addRecentFile(file_name,QDateTime::currentDateTime());
1949 void GuiMainWindow::readRecentFiles()
1951 m_RecentFiles.clear();
1952 this->recentFileMenu()->clear();
1953 QStringList file_names = m_qset.value("FileNames").toStringList();
1954 QStringList file_dates = m_qset.value("FileDates").toStringList();
1955 int N = min(10,m_qset.value("NumberOfFiles").toInt());
1956 cout << "NumberOfFiles=" << N << endl;
1957 for (int i = 0; i < N; ++i) {
1958 QString new_file = file_names.at(i);
1959 QString date_text = file_dates.at(i);
1960 QDateTime date = QDateTime::fromString(date_text,"dd.MM.yyyy_hh:mm:ss");
1961 addRecentFile(new_file,date);
1965 void GuiMainWindow::writeRecentFiles()
1967 m_qset.setValue("NumberOfFiles",m_RecentFiles.size());
1968 QStringList file_names;
1969 QStringList file_dates;
1970 for (QMap<QString,QDateTime>::iterator i = m_RecentFiles.begin(); i != m_RecentFiles.end(); ++i) {
1971 QString file_name = i.key();
1972 QString date_text = i.value().toString("dd.MM.yyyy_hh:mm:ss");
1973 file_names.append(file_name);
1974 file_dates.append(date_text);
1976 m_qset.setValue("FileNames",file_names);
1977 m_qset.setValue("FileDates",file_dates);
1980 void GuiMainWindow::addRecentFile(QString file_name, QDateTime date)
1982 m_RecentFiles[file_name] = date;
1983 while (m_RecentFiles.size() > 10) {
1984 QMap<QString,QDateTime>::iterator i,j;
1985 QDateTime old = QDateTime::currentDateTime();
1986 for (i = m_RecentFiles.begin(); i != m_RecentFiles.end(); ++i) {
1987 if (i.value() <= old) {
1988 old = i.value();
1989 j = i;
1992 m_RecentFiles.erase(j);
1994 this->recentFileMenu()->clear();
1995 QMap<int,QString> menu_map;
1996 QDateTime now = QDateTime::currentDateTime();
1997 for (QMap<QString,QDateTime>::iterator i = m_RecentFiles.begin(); i != m_RecentFiles.end(); ++i) {
1998 QString action_text = i.value().toString("dd.MM.yyyy hh:mm:ss");
1999 action_text += " -> ";
2000 action_text += i.key();
2001 menu_map[i.value().secsTo(now)] = action_text;
2004 for (QMap<int,QString>::iterator i = menu_map.begin(); i != menu_map.end(); ++i) {
2005 QAction *action = new QAction(i.value(),this);
2006 this->recentFileMenu()->addAction(action);