Path: blob/devel/ElmerGUI/Application/src/dynamiceditor.cpp
3203 views
/*****************************************************************************1* *2* Elmer, A Finite Element Software for Multiphysical Problems *3* *4* Copyright 1st April 1995 - , CSC - IT Center for Science Ltd., Finland *5* *6* This program is free software; you can redistribute it and/or *7* modify it under the terms of the GNU General Public License *8* as published by the Free Software Foundation; either version 2 *9* of the License, or (at your option) any later version. *10* *11* This program is distributed in the hope that it will be useful, *12* but WITHOUT ANY WARRANTY; without even the implied warranty of *13* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *14* GNU General Public License for more details. *15* *16* You should have received a copy of the GNU General Public License *17* along with this program (in file fem/GPL-2); if not, write to the *18* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, *19* Boston, MA 02110-1301, USA. *20* *21*****************************************************************************/2223/*****************************************************************************24* *25* ElmerGUI dynamiceditor *26* *27*****************************************************************************28* *29* Authors: Mikko Lyly, Juha Ruokolainen and Peter R�back *30* Email: [email protected] *31* Web: http://www.csc.fi/elmer *32* Address: CSC - IT Center for Science Ltd. *33* Keilaranta 14 *34* 02101 Espoo, Finland *35* *36* Original Date: 15 Mar 2008 *37* *38*****************************************************************************/3940#include <QtGui>41#include <iostream>42#include "dynamiceditor.h"4344using namespace std;4546DynLineEdit::DynLineEdit(QWidget *parent) : QWidget(parent)47{48name = "";49label = NULL;50frame = NULL;51layout = NULL;52textEdit = NULL;53closeButton = NULL;54lineEdit = new QLineEdit;55}5657DynLineEdit::~DynLineEdit()58{59}6061DynamicEditor::DynamicEditor(QWidget *parent)62: QWidget(parent)63{64newIcon = QIcon::fromTheme("document-new");65addIcon = QIcon::fromTheme("list-add");66okIcon = QIcon::fromTheme("dialog-accept");67removeIcon = QIcon::fromTheme("dialog-error-round");68setWindowFlags(Qt::Window);6970menuAction = NULL;71ID = -1;72touched = false;7374setWindowIcon(QIcon(":/icons/Mesh3D.png"));75}7677//----------------------------------------------------------------------------78DynamicEditor::~DynamicEditor()79{80}8182//----------------------------------------------------------------------------83void DynamicEditor::setupTabs(QDomDocument *elmerDefs, const QString &Section, int ID)84{85// Clear:86//-------87this->ID = ID;8889hash.clear();9091QLayout *layout = this->layout();92if(layout != NULL) {93QLayoutItem *item;94while((item = layout->takeAt(0)) != 0)95delete item;96if(tabWidget != NULL) {97tabWidget->clear();98delete tabWidget;99}100delete layout;101}102103// Get root element of elmerDefs:104//-------------------------------105root = elmerDefs->documentElement();106107tabWidget = new QTabWidget;108//tabWidget->setTabShape(QTabWidget::Triangular);109tabWidget->setUsesScrollButtons(true);110tabWidget->setElideMode(Qt::ElideNone);111all_stuff = root.firstChildElement("ALL");112element = root.firstChildElement("PDE");113114tabs = 0;115116while(!element.isNull()) {117118name = element.firstChildElement("Name");119120QGridLayout *grid = new QGridLayout;121122int params = 0;123124for( int iter=0; iter<2; iter++ )125{126if ( iter==0 ) {127if ( name.text().trimmed() == "General" ) continue;128section = all_stuff.firstChildElement(Section);129} else {130section = element.firstChildElement(Section);131}132133param = section.firstChildElement("Parameter");134135// ML: Added argument "Parameter" for nextSiblingElement(), 5. August 2010:136for( ; !param.isNull(); param=param.nextSiblingElement("Parameter"), params++ ) {137138// label139QString widget_type = param.attribute("Widget","Edit");140QString widget_enabled = param.attribute("Enabled","True");141QString widget_visible = param.attribute("Visible","True");142QString paramType = param.firstChildElement("Type").text().trimmed();143QString labelName = param.firstChildElement("Name").text().trimmed();144QString sifName = param.firstChildElement("SifName").text().trimmed();145if ( sifName == "" ) sifName = labelName;146QString paramDefault = param.firstChildElement("DefaultValue").text().trimmed();147QString whatis = param.firstChildElement("Whatis").text().trimmed();148QString statusTip = param.firstChildElement("StatusTip").text().trimmed();149QString fullName = "/"+name.text().trimmed()+"/"+Section+"/"+labelName+"/"+QString::number(ID);150h.widget = NULL;151152if ( widget_type == "Edit" ) {153DynLineEdit *edit = new DynLineEdit;154h.widget = edit->lineEdit;155edit->lineEdit->setText(paramDefault);156edit->name = fullName;157connect(edit->lineEdit, SIGNAL(returnPressed()),158edit, SLOT(editSlot()));159connect(edit->lineEdit, SIGNAL(textChanged(QString)),160this, SLOT(textChangedSlot(QString)));161162} else if (widget_type == "TextEdit") {163QTextEdit *textEdit = new QTextEdit;164// set height to 5..8 lines of current font:165QFont currentFont = textEdit->currentFont();166QFontMetrics fontMetrics(currentFont);167int fontHeight = fontMetrics.height();168textEdit->setMinimumHeight(5*fontHeight);169textEdit->setMaximumHeight(8*fontHeight);170h.widget = textEdit;171172} else if ( widget_type == "Combo" ) {173QComboBox *combo = new QComboBox;174h.widget = combo;175176// combo->setObjectName(labelName); // removed 30. sept. 2008, ML177int count = 0, active=0;178179QDomElement item = param.firstChildElement("Item");180for( ; !item.isNull(); item=item.nextSiblingElement("Item") ) {181QString itemType = item.attribute( "Type", "" );182if ( itemType == "Active" ) active=count;183QDomElement itemName = item.firstChildElement("Name");184combo->insertItem(count++,itemName.text().trimmed() );185}186combo->setCurrentIndex(active);187// connect(combo, SIGNAL(activated(QString)), this, SLOT(comboSlot(QString)));188connect(combo, SIGNAL(currentTextChanged(const QString)), this, SLOT(comboSlot(QString)));189190} else if ( widget_type == "CheckBox" ) {191QCheckBox *l = new QCheckBox;192h.widget = l;193194l->setText("");195l->setChecked(false);196if ( paramDefault == "True" ) l->setChecked(true);197connect(l, SIGNAL(stateChanged(int)), this, SLOT(lSlot(int)));198199} else if ( widget_type == "Label" ) {200QLabel *label = new QLabel;201QFont font;202font.setBold(true);203font.setUnderline(true);204label->setFont(font);205label->setText(labelName);206h.widget = label;207}208209if ( h.widget ) {210h.widget->setWhatsThis(whatis);211// h.widget->setToolTip(whatis); // This is to show whatis just by hovering mouse cursor212h.widget->setStatusTip(statusTip);213h.widget->setProperty( "dom address",fullName);214h.elem = param;215216if ( widget_enabled == "False" ) h.widget->setEnabled(false);217218// The next line was commented out for display scaling. ST219//if(widget_type != "TextEdit") h.widget->setFixedHeight(18);220221if(widget_type == "TextEdit") {222QLabel *textEditLabel = new QLabel;223textEditLabel->setText(labelName);224h.label = textEditLabel;225grid->addWidget(h.widget, params, 0, 1, 2);226227if ( widget_visible == "False" ) {228h.label->hide();229h.widget->hide();230}231232} else if ( widget_type != "Label" ) {233QLabel *label = new QLabel;234label->setText(labelName);235h.label = label;236grid->addWidget(h.label, params, 0);237grid->addWidget(h.widget, params, 1);238239if ( widget_visible == "False" ) {240h.label->hide();241h.widget->hide();242}243} else {244h.label = NULL;245grid->addWidget(h.widget, params, 0);246}247hash[fullName] = h;248}249}250}251252// add a dummy widget in the left bottom corner:253QWidget *dummyWidget = new QWidget;254grid->addWidget(dummyWidget, params, 0);255grid->setRowStretch(params, 1);256257// put the grid in a widget:258QWidget *frmWidget = new QWidget;259frmWidget->setLayout(grid);260261// set up the scroll area:262QScrollArea *src = new QScrollArea;263src->setWidget(frmWidget);264src->setMinimumHeight(300);265src->setWidgetResizable(true);266267// add the scroll area to the tab:268if (params>0)269tabWidget->addTab(src, name.text().trimmed());270271tabs++;272element = element.nextSiblingElement("PDE"); // ML: Added "PDE" 5. August 2010273}274275// Buttons:276//----------277QLabel *lbl = new QLabel;278lbl->setText("Name:");279280nameEdit = new QLineEdit;281nameEdit->setText(Section + " " + QString::number(ID+1));282applyButton = new QPushButton(tr("&Add"));283applyButton->setIcon(addIcon);284connect(applyButton, SIGNAL(clicked()), this, SLOT(applyButtonClicked()));285nameEdit->setWhatsThis("Name of this " + Section);286287discardButton = new QPushButton(tr("&Remove"));288discardButton->setIcon(removeIcon);289connect(discardButton, SIGNAL(clicked()), this, SLOT(discardButtonClicked()));290291whatsThisButton = new QPushButton(tr("Whatis"));292whatsThisButton->setIcon(QIcon::fromTheme("text-questionmark"));293connect(whatsThisButton, SIGNAL(clicked()), this, SLOT(whatsThisButtonClicked()));294whatsThisButton->setWhatsThis("Press this button, then click the widget to be explained.");295296okButton = new QPushButton(tr("&OK"));297okButton->setIcon(okIcon);298connect(okButton, SIGNAL(clicked()), this, SLOT(okButtonClicked()));299300newButton = new QPushButton(tr("&New"));301newButton->setIcon(newIcon);302connect(newButton, SIGNAL(clicked()), this, SLOT(newButtonClicked()));303304QHBoxLayout *nameLayout = new QHBoxLayout;305nameLayout->addWidget(lbl);306nameLayout->addWidget(nameEdit);307308QHBoxLayout *buttonLayout = new QHBoxLayout;309buttonLayout->addWidget(newButton);310buttonLayout->addWidget(applyButton);311buttonLayout->addWidget(okButton);312buttonLayout->addWidget(discardButton);313buttonLayout->addWidget(whatsThisButton);314315QHBoxLayout *spareButtonLayout = new QHBoxLayout;316spareButton = new QPushButton(tr("SpareButton"));;317spareButton->setVisible(false);318spareButtonLayout->addWidget(spareButton);319connect(spareButton, SIGNAL(clicked()), this, SLOT(spareButtonClicked()));320321spareScroll = new QScrollArea;322spareScroll->hide();323324// Main layout:325//-------------326QVBoxLayout *mainLayout = new QVBoxLayout;327mainLayout->addWidget(tabWidget);328mainLayout->addWidget(spareScroll);329mainLayout->addLayout(spareButtonLayout);330mainLayout->addLayout(nameLayout);331mainLayout->addLayout(buttonLayout);332setLayout(mainLayout);333334// Window title:335//---------------336setWindowTitle(Section);337}338339//----------------------------------------------------------------------------340void DynLineEdit::editSlot()341{342QLineEdit *q = lineEdit;343QString s = q->text();344#if WITH_QT5 || WITH_QT6345cout << string(s.toLatin1()) << endl;346#else347cout << string(s.toAscii()) << endl;348#endif349350if ( frame ) {351frame->show();352frame->raise();353return;354}355356textEdit = new QTextEdit;357textEdit->setLineWrapMode(QTextEdit::NoWrap);358359s.replace( ';', '\n' );360textEdit->append(s);361362closeButton = new QPushButton(tr("&Close"));363connect(closeButton, SIGNAL(clicked()), this, SLOT(lineEditClose()));364365label = new QLabel;366label->setText(name);367368layout = new QVBoxLayout;369layout->addWidget(label);370layout->addWidget(textEdit);371layout->addWidget(closeButton);372373frame = new QFrame;374frame->setLayout(layout);375frame->show();376frame->setWindowTitle(name);377}378379//----------------------------------------------------------------------------380void DynLineEdit::lineEditClose()381{382QString q = textEdit->toPlainText();383384//q.replace( '\n', ';' );385386lineEdit->setText(q);387388frame->close();389390name = "";391392delete label;393label = NULL;394395delete textEdit;396textEdit = NULL;397398delete closeButton;399closeButton = NULL;400401delete layout;402layout = NULL;403404delete frame;405frame = NULL;406}407408//----------------------------------------------------------------------------409void DynamicEditor::lSlot(int state)410{411QDomElement param;412QString q = QObject::sender()->property("dom address").toString();413414int ind = q.lastIndexOf( '/', -1);415QString ID = q.mid(ind,-1);416417param = hash[q].elem.firstChildElement("Activate");418for( ;!param.isNull(); param=param.nextSiblingElement("Activate") ) {419q = param.text().trimmed() + ID;420hash[q].widget->setEnabled(state);421QString widget_visible = hash[q].elem.attribute("Visible","Unknown");422if ( state == false && widget_visible != "Unknown" ) {423hash[q].label->hide(); hash[q].widget->hide();424} else {425hash[q].label->show(); hash[q].widget->show();426}427}428429param = hash[q].elem.firstChildElement("Deactivate");430for( ;!param.isNull(); param=param.nextSiblingElement("Deactivate") ) {431q = param.text().trimmed() + ID;432hash[q].widget->setEnabled(!state);433QString widget_visible = hash[q].elem.attribute("Visible","Unknown");434if ( state == true && widget_visible != "Unknown" ) {435hash[q].label->hide(); hash[q].widget->hide();436} else {437hash[q].label->show(); hash[q].widget->show();438}439}440}441442//----------------------------------------------------------------------------443void DynamicEditor::textChangedSlot(QString text)444{445QDomElement param;446QString q = QObject::sender()->property("dom address").toString();447448int ind = q.lastIndexOf( '/', -1);449QString ID = q.mid(ind,-1);450451param = hash[q].elem.firstChildElement("Activate");452for( ;!param.isNull(); param=param.nextSiblingElement("Activate") ) {453q = param.text().trimmed() + ID;454QString widget_visible = hash[q].elem.attribute("Visible","Uknown");455456if ( text != "" ) {457hash[q].widget->setEnabled(true);458hash[q].widget->show();459hash[q].label->show();460} else {461hash[q].widget->setEnabled(false);462if ( widget_visible != "Unknown" ) {463hash[q].label->hide();464hash[q].widget->hide();465}466}467}468}469470//----------------------------------------------------------------------------471void DynamicEditor::comboSlot(QString select)472{473QString q = QObject::sender()->property("dom address").toString();474QDomElement item;475476int ind = q.lastIndexOf( '/', -1);477QString ID = q.mid(ind,-1);478479item = hash[q].elem.firstChildElement("Item");480for( ;!item.isNull(); item=item.nextSiblingElement("Item") ) {481QDomElement itemName = item.firstChildElement("Name");482if ( itemName.text().trimmed() != select ) {483QDomElement activ;484485activ = item.firstChildElement("Activate");486for( ;!activ.isNull(); activ=activ.nextSiblingElement("Activate") ) {487QString s=activ.text().trimmed() + ID;488hash_entry_t h = hash[s];489490QString widget_enabled = h.elem.attribute("Enabled","True");491QString widget_visible = h.elem.attribute("Visible","Unknown");492493h.widget->setEnabled(false);494if ( widget_visible != "Unknown" ) {495h.label->hide(); h.widget->hide();496}497}498}499}500501item = hash[q].elem.firstChildElement("Item");502for( ;!item.isNull(); item=item.nextSiblingElement("Item") ) {503QDomElement itemName = item.firstChildElement("Name");504if ( itemName.text().trimmed() == select ) {505QDomElement activ;506activ = item.firstChildElement("Activate");507for( ;!activ.isNull(); activ=activ.nextSiblingElement("Activate") ) {508QString s=activ.text().trimmed() + ID;509hash_entry_t h = hash[s];510h.widget->setEnabled(true);511h.label->show(); h.widget->show();512}513}514}515// this->show(); // Removed 30. sept. 2008, ML516}517518519//----------------------------------------------------------------------------520QSize DynamicEditor::minimumSizeHint() const521{522return QSize(128, 128);523}524525//----------------------------------------------------------------------------526QSize DynamicEditor::sizeHint() const527{528return QSize(400, 500);529}530531//----------------------------------------------------------------------------532void DynamicEditor::spareButtonClicked()533{534emit(dynamicEditorSpareButtonClicked(tabWidget->currentIndex(), ID));535}536537//----------------------------------------------------------------------------538void DynamicEditor::applyButtonClicked()539{540541cout << "Dynamic editor: apply-button clicked" << endl;542cout.flush();543544touched = true;545546emit(dynamicEditorReady(MAT_APPLY, ID));547548}549550551//----------------------------------------------------------------------------552void DynamicEditor::discardButtonClicked()553{554555cout << "Dynamic editor: Remove-button clicked" << endl;556cout.flush();557558touched = false;559560emit(dynamicEditorReady(MAT_DELETE, ID));561}562563//----------------------------------------------------------------------------564void DynamicEditor::okButtonClicked()565{566567// cout << "Dynamic editor: ok-button clicked" << endl;568// cout.flush();569570touched = false;571572emit(dynamicEditorReady(MAT_OK, ID));573}574575//----------------------------------------------------------------------------576void DynamicEditor::newButtonClicked()577{578cout << "Dynamic editor: next-button clicked" << endl;579cout.flush();580581touched = false;582583emit(dynamicEditorReady(MAT_NEW, ID));584}585586//----------------------------------------------------------------------------587void DynamicEditor::whatsThisButtonClicked()588{589QWhatsThis::enterWhatsThisMode();590}591592//----------------------------------------------------------------------------593void DynamicEditor::dumpHash(QDomDocument *projectDoc, QDomElement *item)594{595for(int j = 0; j < this->hash.count(); j++) {596QString key = this->hash.keys().at(j);597hash_entry_t value = this->hash.values().at(j);598QDomElement elem = value.elem;599QWidget *widget = value.widget;600601QDomElement itemWidget = projectDoc->createElement("widget");602item->appendChild(itemWidget);603604QDomElement itemKey = projectDoc->createElement("key");605QDomText itemKeyValue = projectDoc->createTextNode(key);606itemKey.appendChild(itemKeyValue);607itemWidget.appendChild(itemKey);608609if(elem.attribute("Widget") == "CheckBox") {610QCheckBox *checkBox = (QCheckBox*)widget;611QDomElement itemCheckBox = projectDoc->createElement("value");612QDomText itemCheckBoxValue = projectDoc->createTextNode(QString::number(checkBox->isChecked()));613itemCheckBox.appendChild(itemCheckBoxValue);614itemWidget.appendChild(itemCheckBox);615itemWidget.setAttribute("type", "CheckBox");616617} else if(elem.attribute("Widget") == "Edit") {618QLineEdit *lineEdit = (QLineEdit*)widget;619QDomElement itemLineEdit = projectDoc->createElement("value");620QDomText itemLineEditValue = projectDoc->createTextNode(lineEdit->text().trimmed());621itemLineEdit.appendChild(itemLineEditValue);622itemWidget.appendChild(itemLineEdit);623itemWidget.setAttribute("type", "Edit");624625} else if(elem.attribute("Widget") == "TextEdit") {626QTextEdit *textEdit = (QTextEdit*)widget;627QDomElement itemTextEdit = projectDoc->createElement("value");628QDomText itemTextEditValue = projectDoc->createTextNode(textEdit->toPlainText());629itemTextEdit.appendChild(itemTextEditValue);630itemWidget.appendChild(itemTextEdit);631itemWidget.setAttribute("type", "TextEdit");632633} else if(elem.attribute("Widget") == "Combo") {634QComboBox *comboBox = (QComboBox*)widget;635QDomElement itemComboBox = projectDoc->createElement("value");636QDomText itemComboBoxValue = projectDoc->createTextNode(comboBox->currentText().trimmed());637itemComboBox.appendChild(itemComboBoxValue);638itemWidget.appendChild(itemComboBox);639itemWidget.setAttribute("type", "Combo");640641} else if(elem.attribute("Widget") == "Label") {642QLabel *label = (QLabel*)widget;643QDomElement itemLabel = projectDoc->createElement("value");644QDomText itemLabelValue = projectDoc->createTextNode(label->text().trimmed());645itemLabel.appendChild(itemLabelValue);646itemWidget.appendChild(itemLabel);647itemWidget.setAttribute("type", "Label");648}649}650}651652void DynamicEditor::populateHash(QDomElement *item)653{654QDomElement widget = item->firstChildElement("widget");655656// ML: Added argument "widget" for nextSiblingElement(), 5. August 2010:657for(; !widget.isNull(); widget = widget.nextSiblingElement("widget")) {658QString type = widget.attribute("type").trimmed();659QString key = widget.firstChildElement("key").text().trimmed();660QString value = widget.firstChildElement("value").text().trimmed();661662if(value.isEmpty())663continue;664665QStringList splittedKey = key.split("/");666667// Compare with current hash:668//----------------------------669bool match_found = false;670for(int j = 0; j < this->hash.count(); j++) {671QString hashkey = this->hash.keys().at(j);672QStringList splittedHashKey = hashkey.split("/");673hash_entry_t hashvalue = this->hash.values().at(j);674QWidget *widget = hashvalue.widget;675QDomElement elem = hashvalue.elem;676677if((splittedKey.at(1) == splittedHashKey.at(1)) &&678(splittedKey.at(2) == splittedHashKey.at(2)) &&679(splittedKey.at(3) == splittedHashKey.at(3))) {680681match_found = true;682683if(elem.attribute("Widget") == "CheckBox") {684if(type != "CheckBox")685cout << "Load project: type mismatch with checkBox" << endl;686QCheckBox *checkBox = (QCheckBox*)widget;687if(value.toInt() == 1)688checkBox->setChecked(true);689else690checkBox->setChecked(false);691692} else if(elem.attribute("Widget") == "Edit") {693if(type != "Edit")694cout << "Load project: type mismatch with lineEdit" << endl;695QLineEdit *lineEdit = (QLineEdit*)widget;696lineEdit->setText(value);697698} else if(elem.attribute("Widget") == "TextEdit") {699if(type != "TextEdit")700cout << "Load project: type mismatch with textEdit" << endl;701QTextEdit *textEdit = (QTextEdit*)widget;702textEdit->clear();703textEdit->append(value);704705} else if(elem.attribute("Widget") == "Combo") {706if(type != "Combo")707cout << "Load project: type mismatch with comboBox" << endl;708QComboBox *comboBox = (QComboBox*)widget;709for(int k = 0; k < comboBox->count(); k++) {710QString current = comboBox->itemText(k).trimmed();711if(current == value.trimmed())712comboBox->setCurrentIndex(k);713}714}715}716}717718if(!match_found) {719#if WITH_QT5 || WITH_QT6720cout << "Error: Unable to set menu entry: key: " << key.toLatin1().data() << endl;721#else722cout << "Error: Unable to set menu entry: key: " << key.toAscii().data() << endl;723#endif724cout.flush();725}726}727}728729730