Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ElmerCSC
GitHub Repository: ElmerCSC/elmerfem
Path: blob/devel/ElmerGUI/Application/src/edfeditor.cpp
3203 views
1
/*****************************************************************************
2
* *
3
* Elmer, A Finite Element Software for Multiphysical Problems *
4
* *
5
* Copyright 1st April 1995 - , CSC - IT Center for Science Ltd., Finland *
6
* *
7
* This program is free software; you can redistribute it and/or *
8
* modify it under the terms of the GNU General Public License *
9
* as published by the Free Software Foundation; either version 2 *
10
* of the License, or (at your option) any later version. *
11
* *
12
* This program is distributed in the hope that it will be useful, *
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15
* GNU General Public License for more details. *
16
* *
17
* You should have received a copy of the GNU General Public License *
18
* along with this program (in file fem/GPL-2); if not, write to the *
19
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, *
20
* Boston, MA 02110-1301, USA. *
21
* *
22
*****************************************************************************/
23
24
/*****************************************************************************
25
* *
26
* ElmerGUI edfeditor *
27
* *
28
*****************************************************************************
29
* *
30
* Authors: Mikko Lyly, Juha Ruokolainen and Peter R�back *
31
* Email: [email protected] *
32
* Web: http://www.csc.fi/elmer *
33
* Address: CSC - IT Center for Science Ltd. *
34
* Keilaranta 14 *
35
* 02101 Espoo, Finland *
36
* *
37
* Original Date: 15 Mar 2008 *
38
* *
39
*****************************************************************************/
40
41
#include <QtGui>
42
#include <iostream>
43
#include <QPushButton>
44
#include <QMainWindow>
45
#include <QMdiArea>
46
#include <QMdiSubWindow>
47
#include <QFileDialog>
48
#include <QMessageBox>
49
50
#if WITH_QT6
51
#define QRegExp QRegularExpression
52
#endif
53
54
#include "edfeditor.h"
55
//#include "MainWindow.h"
56
57
using namespace std;
58
59
// ctor...
60
//----------------------------------------------------------------------------
61
EdfEditor::EdfEditor(QWidget *parent)
62
: QWidget(parent)
63
{
64
addIcon = QIcon::fromTheme("list-add");
65
removeIcon = QIcon::fromTheme("list-remove");
66
collapseIcon = QIcon::fromTheme("triangle-up");
67
expandIcon = QIcon::fromTheme("triangle-down");
68
openIcon = QIcon::fromTheme("document-open");
69
appendIcon = QIcon::fromTheme("tab-new"); // todo
70
saveAsIcon = QIcon::fromTheme("document-save");
71
applyIcon = QIcon::fromTheme("dialog-error-round");
72
previewIcon = QIcon::fromTheme("edit-find");
73
74
lastActiveItem = NULL;
75
ctrlPressed = false;
76
77
// Set up tree widget:
78
//--------------------
79
edfTree = new QTreeWidget;
80
81
connect(edfTree, SIGNAL(itemClicked(QTreeWidgetItem*,int)),
82
this, SLOT(treeItemClicked(QTreeWidgetItem*,int)));
83
84
edfTree->setColumnCount(3);
85
edfTree->setColumnWidth(0,200);
86
edfTree->setColumnWidth(1,200);
87
edfTree->setColumnWidth(2,200);
88
89
edfTree->setAnimated(true);
90
91
// Set internal drag'n drop mode on:
92
//----------------------------------
93
edfTree->setDragEnabled(true);
94
edfTree->setDragDropMode(QAbstractItemView::InternalMove);
95
edfTree->setDropIndicatorShown(true);
96
edfTree->setDragDropOverwriteMode(false);
97
98
QStringList qsl;
99
qsl << "Tag" << "Attributes" << "Value";
100
edfTree->setHeaderLabels(qsl);
101
edfTree->setAlternatingRowColors(true);
102
103
// Buttons:
104
//---------
105
addButton = new QPushButton(tr("&Add child"));
106
addButton->setIcon(addIcon);
107
connect(addButton, SIGNAL(clicked()), this, SLOT(addButtonClicked()));
108
109
removeButton = new QPushButton(tr("&Remove item"));
110
removeButton->setIcon(removeIcon);
111
connect(removeButton, SIGNAL(clicked()), this, SLOT(removeButtonClicked()));
112
113
expandCollapseAllButton = new QPushButton(tr("Collapse all"));
114
expandCollapseAllButton->setIcon(collapseIcon);
115
connect(expandCollapseAllButton, SIGNAL(clicked()),
116
this, SLOT(expandCollapseAllButtonClicked()));
117
118
openButton = new QPushButton(tr("&Open"));
119
openButton->setIcon(openIcon);
120
connect(openButton, SIGNAL(clicked()), this, SLOT(openButtonClicked()));
121
122
appendButton = new QPushButton(tr("&Append"));
123
appendButton->setIcon(appendIcon);
124
connect(appendButton, SIGNAL(clicked()), this, SLOT(appendButtonClicked()));
125
126
previewButton = new QPushButton(tr("&Preview"));
127
previewButton->setIcon(previewIcon);
128
connect(previewButton, SIGNAL(clicked()), this, SLOT(previewButtonClicked()));
129
130
saveAsButton = new QPushButton(tr("&Save as"));
131
saveAsButton->setIcon(saveAsIcon);
132
connect(saveAsButton, SIGNAL(clicked()), this, SLOT(saveAsButtonClicked()));
133
134
applyButton = new QPushButton(tr("&Close"));
135
applyButton->setIcon(applyIcon);
136
connect(applyButton, SIGNAL(clicked()), this, SLOT(applyButtonClicked()));
137
138
QHBoxLayout *buttonLayout = new QHBoxLayout;
139
buttonLayout->addWidget(addButton);
140
buttonLayout->addWidget(removeButton);
141
buttonLayout->addWidget(expandCollapseAllButton);
142
buttonLayout->addWidget(openButton);
143
buttonLayout->addWidget(appendButton);
144
buttonLayout->addWidget(previewButton);
145
buttonLayout->addWidget(saveAsButton);
146
buttonLayout->addWidget(applyButton);
147
148
// Main layout:
149
//-------------
150
QVBoxLayout *mainLayout = new QVBoxLayout;
151
mainLayout->addWidget(edfTree);
152
mainLayout->addLayout(buttonLayout);
153
setLayout(mainLayout);
154
155
setWindowTitle("Elmer Definitions File editor");
156
157
setFocusPolicy(Qt::ClickFocus);
158
159
expandCollapseAll = false;
160
161
dynamicEditorSimulation = new DynamicEditor;
162
dynamicEditorConstants = new DynamicEditor;
163
dynamicEditorEquation = new DynamicEditor;
164
dynamicEditorSolver = new DynamicEditor;
165
dynamicEditorMaterial = new DynamicEditor;
166
dynamicEditorBodyForce = new DynamicEditor;
167
dynamicEditorBC = new DynamicEditor;
168
dynamicEditorIC = new DynamicEditor;
169
170
setWindowIcon(QIcon(":/icons/Mesh3D.png"));
171
172
173
#ifdef __APPLE__DONTGO_HERE_TODO
174
defaultDir = ((MainWindow*)paernt->homePath ;
175
#else
176
defaultDir =
177
QCoreApplication::applicationDirPath() + "/../share/ElmerGUI";
178
179
QString elmerGuiHome = QString(getenv("ELMERGUI_HOME"));
180
181
if (!elmerGuiHome.isEmpty())
182
defaultDir = elmerGuiHome;
183
184
defaultDir.replace('\\', '/');
185
#endif
186
187
// Commented out as restoring defaultDir is not so useful
188
//defaultDir = ((MainWindow*) parent)->settings_value("defaultDir/edfEditor", defaultDir).toString();
189
190
}
191
192
193
// dtor...
194
//----------------------------------------------------------------------------
195
EdfEditor::~EdfEditor()
196
{
197
198
}
199
200
// Min window size...
201
//----------------------------------------------------------------------------
202
QSize EdfEditor::minimumSizeHint() const
203
{
204
return QSize(64, 64);
205
}
206
207
// Default window size...
208
//----------------------------------------------------------------------------
209
QSize EdfEditor::sizeHint() const
210
{
211
return QSize(720, 480);
212
}
213
214
// preview panels
215
//-----------------------------------------------------------------------------
216
void EdfEditor::previewButtonClicked()
217
{
218
if(elmerDefs == NULL)
219
return;
220
221
// always create a new instance:
222
QMainWindow *sandBox = new QMainWindow;
223
QMdiArea *mdiArea = new QMdiArea;
224
225
sandBox->setCentralWidget(mdiArea);
226
sandBox->setWindowTitle(tr("Preview definitions"));
227
sandBox->show();
228
229
if(dynamicEditorSimulation) delete dynamicEditorSimulation;
230
dynamicEditorSimulation = new DynamicEditor;
231
dynamicEditorSimulation->setupTabs(elmerDefs, "Simulation",1);
232
QMdiSubWindow *simulationSubWindow = new QMdiSubWindow;
233
simulationSubWindow->setWidget(dynamicEditorSimulation);
234
mdiArea->addSubWindow(simulationSubWindow);
235
simulationSubWindow->show();
236
237
if(dynamicEditorConstants) delete dynamicEditorConstants;
238
dynamicEditorConstants = new DynamicEditor;
239
dynamicEditorConstants->setupTabs(elmerDefs, "Constants",1);
240
QMdiSubWindow *constantsSubWindow = new QMdiSubWindow;
241
constantsSubWindow->setWidget(dynamicEditorConstants);
242
mdiArea->addSubWindow(constantsSubWindow);
243
constantsSubWindow->show();
244
245
if(dynamicEditorEquation) delete dynamicEditorEquation;
246
dynamicEditorEquation = new DynamicEditor;
247
dynamicEditorEquation->setupTabs(elmerDefs, "Equation",1);
248
QMdiSubWindow *equationSubWindow = new QMdiSubWindow;
249
equationSubWindow->setWidget(dynamicEditorEquation);
250
mdiArea->addSubWindow(equationSubWindow);
251
equationSubWindow->show();
252
253
if(dynamicEditorSolver) delete dynamicEditorSolver;
254
dynamicEditorSolver = new DynamicEditor;
255
dynamicEditorSolver->setupTabs(elmerDefs, "Solver",1 );
256
QMdiSubWindow *solverSubWindow = new QMdiSubWindow;
257
solverSubWindow->setWidget(dynamicEditorSolver);
258
mdiArea->addSubWindow(solverSubWindow);
259
solverSubWindow->show();
260
261
if(dynamicEditorMaterial) delete dynamicEditorMaterial;
262
dynamicEditorMaterial = new DynamicEditor;
263
dynamicEditorMaterial->setupTabs(elmerDefs, "Material",1 );
264
QMdiSubWindow *materialSubWindow = new QMdiSubWindow;
265
materialSubWindow->setWidget(dynamicEditorMaterial);
266
mdiArea->addSubWindow(materialSubWindow);
267
materialSubWindow->show();
268
269
if(dynamicEditorBodyForce) delete dynamicEditorBodyForce;
270
dynamicEditorBodyForce = new DynamicEditor;
271
dynamicEditorBodyForce->setupTabs(elmerDefs, "BodyForce",1 );
272
QMdiSubWindow *bodyForceSubWindow = new QMdiSubWindow;
273
bodyForceSubWindow->setWidget(dynamicEditorBodyForce);
274
mdiArea->addSubWindow(bodyForceSubWindow);
275
bodyForceSubWindow->show();
276
277
if(dynamicEditorIC) delete dynamicEditorIC;
278
dynamicEditorIC = new DynamicEditor;
279
dynamicEditorIC->setupTabs(elmerDefs, "InitialCondition",1 );
280
QMdiSubWindow *initialConditionSubWindow = new QMdiSubWindow;
281
initialConditionSubWindow->setWidget(dynamicEditorIC);
282
mdiArea->addSubWindow(initialConditionSubWindow);
283
initialConditionSubWindow->show();
284
285
if(dynamicEditorBC) delete dynamicEditorBC;
286
dynamicEditorBC = new DynamicEditor;
287
dynamicEditorBC->setupTabs(elmerDefs, "BoundaryCondition",1 );
288
QMdiSubWindow *bcSubWindow = new QMdiSubWindow;
289
bcSubWindow->setWidget(dynamicEditorBC);
290
mdiArea->addSubWindow(bcSubWindow);
291
bcSubWindow->show();
292
293
mdiArea->tileSubWindows();
294
//mdiArea->cascadeSubWindows();
295
296
}
297
298
299
300
// Add items from document to tree view...
301
//----------------------------------------------------------------------------
302
void EdfEditor::insertItemForElement(QDomElement element,
303
QTreeWidgetItem *parentItem)
304
{
305
if(element.isNull())
306
return;
307
308
// set expanded
309
// if(parentItem != NULL)
310
// parentItem->setExpanded(true);
311
312
// create new tree item
313
QTreeWidgetItem *newItem = new QTreeWidgetItem(parentItem);
314
315
newItem->setText(0, element.tagName().trimmed());
316
newItem->setFlags(newItem->flags() | Qt::ItemIsEditable);
317
318
// display attributes
319
QStringList list;
320
QDomNamedNodeMap attributeMap = element.attributes();
321
for(int index = 0; index < (int)attributeMap.length(); index++) {
322
QDomNode attribute = attributeMap.item(index);
323
list << attribute.nodeName() + "=\"" + attribute.nodeValue() + "\"";
324
}
325
newItem->setText(1, list.join(" "));
326
327
// display value
328
if(element.firstChildElement().isNull())
329
newItem->setText(2, element.text().split("\n").join(" ").trimmed());
330
331
// update hash
332
elementForItem.insert(newItem, element);
333
334
// add item
335
edfTree->addTopLevelItem(newItem);
336
337
if(!element.firstChildElement().isNull())
338
insertItemForElement(element.firstChildElement(), newItem);
339
340
insertItemForElement(element.nextSiblingElement(), parentItem);
341
}
342
343
// Construct tree view...
344
//----------------------------------------------------------------------------
345
void EdfEditor::setupEditor(QDomDocument *elmerDefs)
346
{
347
this->elmerDefs = elmerDefs;
348
349
disconnect(edfTree, SIGNAL(itemChanged(QTreeWidgetItem*, int)),
350
this, SLOT(updateElement(QTreeWidgetItem*, int)));
351
352
// clear tree view & hash
353
edfTree->clear();
354
elementForItem.clear();
355
356
// get root entry & recursively add items to the tree:
357
QDomElement root = elmerDefs->documentElement();
358
insertItemForElement(root, NULL);
359
edfTree->setCurrentItem(NULL);
360
361
connect(edfTree, SIGNAL(itemChanged(QTreeWidgetItem*, int)),
362
this, SLOT(updateElement(QTreeWidgetItem*, int)));
363
364
edfTree->expandAll();
365
expandCollapseAllButton->setText("Collapse all");
366
expandCollapseAllButton->setIcon(collapseIcon);
367
expandCollapseAll = false;
368
369
edfTree->setCurrentItem(NULL);
370
}
371
372
// Tree view item has been edited: update document accordingly...
373
//----------------------------------------------------------------------------
374
void EdfEditor::updateElement(QTreeWidgetItem *item, int column)
375
{
376
// get element from hash
377
QDomElement element = elementForItem.value(item);
378
379
if(element.isNull())
380
return;
381
382
// set new tag
383
element.setTagName(item->text(0).trimmed());
384
385
// delete old attributes
386
QDomNamedNodeMap oldAttributes = element.attributes();
387
for(int i = 0; i<(int)oldAttributes.length(); i++) {
388
QDomNode node = oldAttributes.item(i);
389
QString name = node.nodeName();
390
element.removeAttribute(name);
391
}
392
393
// parse and set new attributes
394
QString pattern = "([a-zA-Z0-9]+)[ \t]*=[ \t]*[\"]([^\"]+)[\"]";
395
QRegExp expression(pattern);
396
QString qs = item->text(1).trimmed();
397
398
#if WITH_QT6
399
QRegularExpressionMatch rem;
400
int index = qs.indexOf(expression, 0, &rem);
401
#else
402
int index = qs.indexOf(expression);
403
#endif
404
405
QString parsedString = "";
406
if(index < 0)
407
parsedString = qs;
408
409
while(index >= 0) {
410
#if WITH_QT6
411
QString currentMatch = rem.captured(0);
412
int length = currentMatch.length();
413
#else
414
int length = expression.matchedLength();
415
QString currentMatch = qs.mid(index, length);
416
#endif
417
418
QStringList currentList = currentMatch.split("=");
419
QString name = currentList.at(0);
420
QString value = currentList.at(1);
421
422
int firstPar = value.indexOf("\"", 0);
423
int secondPar = value.indexOf("\"", firstPar+1);
424
value = value.mid(firstPar+1, secondPar-firstPar-1);
425
426
parsedString.append(name + "=\"" + value + "\" ");
427
428
element.setAttribute(name.trimmed(), value.trimmed());
429
430
#if WITH_QT6
431
index = qs.indexOf(expression, index + length, &rem);
432
#else
433
index = qs.indexOf(expression, index + length);
434
#endif
435
436
}
437
438
// update display with parsed attributes
439
item->setText(1, parsedString);
440
441
// set new text (iff old element has no children)
442
if(element.firstChildElement().isNull()) {
443
444
// remove old text node
445
QDomNodeList children = element.childNodes();
446
for(int i=0; i<(int)children.length(); i++) {
447
QDomNode node = children.at(i);
448
if(node.isText())
449
element.removeChild(node);
450
}
451
452
// new text node
453
QDomText text = elmerDefs->createTextNode(item->text(2));
454
element.appendChild(text);
455
456
} else {
457
458
// clear value from tree view to avoid confusions:
459
item->setText(2, "");
460
}
461
462
// no need to update hash
463
}
464
465
// Add tree view item & document element...
466
//----------------------------------------------------------------------------
467
void EdfEditor::addButtonClicked()
468
{
469
QTreeWidgetItem *current = edfTree->currentItem();
470
471
if(current == NULL)
472
return;
473
474
QString newTag = "empty";
475
QString newAttribute = "attribute";
476
QString newAttributeValue = "empty";
477
QString newValue = "empty";
478
479
// add item to tree view:
480
QTreeWidgetItem *newItem = new QTreeWidgetItem(current);
481
482
newItem->setFlags(newItem->flags() | Qt::ItemIsEditable);
483
484
newItem->setText(0, newTag);
485
newItem->setText(1, newAttribute + "=\"" + newAttributeValue + "\"");
486
newItem->setText(2, newValue);
487
current->addChild(newItem);
488
newItem->parent()->setExpanded(true);
489
490
// clear the value field for current item (as it just became parent)
491
current->setText(2, "");
492
493
// add to document
494
QDomElement newElement = elmerDefs->createElement(newTag);
495
newElement.setAttribute(newAttribute, newAttributeValue);
496
497
QDomText newText = elmerDefs->createTextNode(newValue);
498
newElement.appendChild(newText);
499
500
QDomElement parent = elementForItem.value(newItem->parent());
501
parent.appendChild(newElement);
502
503
// update hash
504
elementForItem.insert(newItem, newElement);
505
506
edfTree->setCurrentItem(newItem);
507
}
508
509
// Remove item from tree view item & element from document...
510
//----------------------------------------------------------------------------
511
void EdfEditor::removeButtonClicked()
512
{
513
QTreeWidgetItem *currentItem = edfTree->currentItem();
514
515
if(currentItem == NULL)
516
return;
517
518
QTreeWidgetItem *parentItem = currentItem->parent();
519
QDomElement element = elementForItem.value(currentItem);
520
QDomElement parentElement = elementForItem.value(parentItem);
521
522
parentItem->removeChild(currentItem);
523
parentElement.removeChild(element);
524
525
// update hash
526
elementForItem.remove(currentItem);
527
528
edfTree->setCurrentItem(NULL);
529
}
530
531
// Save as...
532
//----------------------------------------------------------------------------
533
void EdfEditor::saveAsButtonClicked()
534
{
535
QString fileName;
536
537
fileName = QFileDialog::getSaveFileName(this,
538
tr("Save definitions"), defaultDir, tr("EDF (*.xml)") );
539
540
if(fileName.isEmpty())
541
return;
542
543
const int indent = 3;
544
545
QFile file;
546
file.setFileName(fileName);
547
file.open(QIODevice::WriteOnly);
548
QTextStream out(&file);
549
elmerDefs->save(out, indent);
550
551
// Commented out as restoring defaultDir is not so useful
552
// QFileInfo info(file);
553
// defaultDir = info.dir().absolutePath();
554
}
555
556
557
// Expand/collapse tree view...
558
//----------------------------------------------------------------------------
559
void EdfEditor::expandCollapseAllButtonClicked()
560
{
561
if(expandCollapseAll) {
562
edfTree->expandAll();
563
expandCollapseAllButton->setText("Collapse all");
564
expandCollapseAllButton->setIcon(collapseIcon);
565
expandCollapseAll = false;
566
} else {
567
edfTree->collapseAll();
568
expandCollapseAllButton->setText("Expand all");
569
expandCollapseAllButton->setIcon(expandIcon);
570
expandCollapseAll = true;
571
}
572
}
573
574
// Open...
575
//----------------------------------------------------------------------------
576
void EdfEditor::openButtonClicked()
577
{
578
QString fileName;
579
580
fileName = QFileDialog::getOpenFileName(this,
581
tr("Open definitions"), defaultDir, tr("EDF (*.xml)") );
582
583
if(fileName.isEmpty())
584
return;
585
586
QFile file;
587
file.setFileName(fileName);
588
file.open(QIODevice::ReadOnly);
589
590
QString errStr;
591
int errRow;
592
int errCol;
593
594
if(!elmerDefs->setContent(&file, true, &errStr, &errRow, &errCol)) {
595
QMessageBox::information(window(), tr("Elmer definitions file"),
596
tr("Parse error at line %1, col %2:\n%3")
597
.arg(errRow).arg(errCol).arg(errStr));
598
file.close();
599
return;
600
601
} else {
602
603
if(elmerDefs->documentElement().tagName() != "edf") {
604
QMessageBox::information(window(), tr("Elmer definitions file"),
605
tr("This is not an edf file"));
606
delete elmerDefs;
607
file.close();
608
return;
609
610
}
611
}
612
613
setupEditor(elmerDefs);
614
615
edfTree->setCurrentItem(NULL);
616
617
// Commented out as restoring defaultDir is not so useful
618
//QFileInfo info(file);
619
//defaultDir = info.dir().absolutePath();
620
}
621
622
// Append...
623
//----------------------------------------------------------------------------
624
void EdfEditor::appendButtonClicked()
625
{
626
QString fileName;
627
628
fileName = QFileDialog::getOpenFileName(this,
629
tr("Open definitions"), defaultDir, tr("EDF (*.xml)") );
630
631
if(fileName.isEmpty())
632
return;
633
634
QFile file;
635
file.setFileName(fileName);
636
file.open(QIODevice::ReadOnly);
637
638
QDomDocument tmpDoc;
639
640
QString errStr;
641
int errRow;
642
int errCol;
643
644
if(!tmpDoc.setContent(&file, true, &errStr, &errRow, &errCol)) {
645
QMessageBox::information(window(), tr("Elmer definitions file"),
646
tr("Parse error at line %1, col %2:\n%3")
647
.arg(errRow).arg(errCol).arg(errStr));
648
file.close();
649
return;
650
651
} else {
652
653
if(tmpDoc.documentElement().tagName() != "edf") {
654
QMessageBox::information(window(), tr("Elmer definitions file"),
655
tr("This is not an edf file"));
656
file.close();
657
return;
658
}
659
}
660
661
// add new elements to the document
662
QDomElement root = elmerDefs->documentElement();
663
QDomElement tmpRoot = tmpDoc.documentElement();
664
665
QDomElement element = tmpRoot.firstChildElement();
666
while(!element.isNull()) {
667
root.appendChild(element);
668
element = tmpRoot.firstChildElement();
669
}
670
671
setupEditor(elmerDefs);
672
673
edfTree->setCurrentItem(NULL);
674
675
// Commented out as restoring defaultDir is not so useful
676
//QFileInfo info(file);
677
//defaultDir = info.dir().absolutePath();
678
}
679
680
681
// Close...
682
//----------------------------------------------------------------------------
683
void EdfEditor::applyButtonClicked()
684
{
685
// rebuild document from tree view:
686
//---------------------------------
687
this->close();
688
}
689
690
// Change the place of two items and elements...
691
//----------------------------------------------------------------------------
692
void EdfEditor::treeItemClicked(QTreeWidgetItem *item, int column)
693
{
694
if(item == lastActiveItem)
695
return;
696
697
if(lastActiveItem == NULL) {
698
lastActiveItem = item;
699
return;
700
}
701
702
if(!ctrlPressed)
703
return;
704
705
// items must have the same parent:
706
if(item->parent() != lastActiveItem->parent()) {
707
// cout << "Items have different parent - unable to swap" << endl;
708
// cout.flush();
709
lastActiveItem = item;
710
return;
711
}
712
713
// get elements:
714
QDomElement element = elementForItem.value(item);
715
QDomElement lastActiveItemElement = elementForItem.value(lastActiveItem);
716
717
// elements must have the same parent (should always be true):
718
if(element.parentNode() != lastActiveItemElement.parentNode()) {
719
// cout << "Parent element mismatch - unable to swap items" << endl;
720
// cout.flush();
721
lastActiveItem = item;
722
return;
723
}
724
725
// clone elements:
726
QDomNode clone = element.cloneNode(true);
727
QDomNode lastActiveItemClone = lastActiveItemElement.cloneNode(true);
728
729
// replace elements with their clones:
730
element.parentNode().replaceChild(lastActiveItemClone, element);
731
lastActiveItemElement.parentNode().replaceChild(clone, lastActiveItemElement);
732
733
// remove old elements from the document:
734
element.parentNode().removeChild(element);
735
lastActiveItemElement.parentNode().removeChild(lastActiveItemElement);
736
737
// make sure that old elements are cleared (they should be already):
738
element.clear();
739
lastActiveItemElement.clear();
740
741
// rebuild tree & hash:
742
setupEditor(elmerDefs);
743
744
// set focus back to the last selected item:
745
lastActiveItem = NULL;
746
for(int i = 0; i < elementForItem.count(); i++) {
747
if(elementForItem.values().at(i) == lastActiveItemClone) {
748
edfTree->setCurrentItem(elementForItem.keys().at(i));
749
edfTree->scrollToItem(elementForItem.keys().at(i),
750
QAbstractItemView::PositionAtCenter);
751
}
752
}
753
754
return;
755
}
756
757
// Key pressed...
758
//-----------------------------------------------------------------------------
759
void EdfEditor::keyPressEvent(QKeyEvent *event)
760
{
761
if(event->key() == Qt::Key_Control)
762
ctrlPressed = true;
763
764
if(event->key() == Qt::Key_Alt)
765
altPressed = true;
766
}
767
768
769
// Key released...
770
//-----------------------------------------------------------------------------
771
void EdfEditor::keyReleaseEvent(QKeyEvent *event)
772
{
773
if(event->key() == Qt::Key_Control)
774
ctrlPressed = false;
775
776
if(event->key() == Qt::Key_Alt)
777
altPressed = false;
778
}
779
780
// Append from specified file path Nov 2019 by TS
781
//----------------------------------------------------------------------------
782
bool EdfEditor::appendFrom(QString path)
783
{
784
QString fileName = path;
785
786
if(fileName.isEmpty())
787
return false;
788
789
QFile file;
790
file.setFileName(fileName);
791
file.open(QIODevice::ReadOnly);
792
793
QDomDocument tmpDoc;
794
795
QString errStr;
796
int errRow;
797
int errCol;
798
799
if(!tmpDoc.setContent(&file, true, &errStr, &errRow, &errCol)) {
800
QMessageBox::information(window(), tr("Elmer definitions file"),
801
tr("Parse error at line %1, col %2:\n%3")
802
.arg(errRow).arg(errCol).arg(errStr));
803
file.close();
804
return false;
805
806
} else {
807
808
if(tmpDoc.documentElement().tagName() != "edf") {
809
QMessageBox::information(window(), tr("Elmer definitions file"),
810
tr("This is not an edf file"));
811
file.close();
812
return false;
813
}
814
}
815
816
// add new elements to the document
817
QDomElement root = elmerDefs->documentElement();
818
QDomElement tmpRoot = tmpDoc.documentElement();
819
820
QDomElement element = tmpRoot.firstChildElement();
821
while(!element.isNull()) {
822
root.appendChild(element);
823
element = tmpRoot.firstChildElement();
824
}
825
826
setupEditor(elmerDefs);
827
828
edfTree->setCurrentItem(NULL);
829
830
return true;
831
}
832
833
QString EdfEditor::defaultEdfDir(){
834
return defaultDir;
835
}
836
837