1 // Copyright (C) 2006-2014 CEA/DEN, EDF R&D
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 #include "EditionScript.hxx"
21 #include "QtGuiContext.hxx"
22 #include "Resource.hxx"
23 #include "Container.hxx"
24 #include "InlineNode.hxx"
25 #include "FormContainer.hxx"
26 #include "Message.hxx"
29 #include <qsciscintilla.h>
30 #include <qscilexerpython.h>
33 #include <QToolButton>
35 #include <QTemporaryFile>
36 #include <QTextStream>
42 #include "YacsTrace.hxx"
47 using namespace YACS::HMI;
50 class myQsciScintilla: public QsciScintilla
53 myQsciScintilla(QWidget *parent=0)
54 : QsciScintilla(parent) {};
56 virtual QSize sizeHint() const { return QSize(350, 150); };
58 virtual bool event(QEvent *e);
61 bool myQsciScintilla::event(QEvent *e)
63 if (e->type() == QEvent::ShortcutOverride)
68 return QsciScintilla::event(e);
74 EditionScript::EditionScript(Subject* subject,
77 : EditionElementaryNode(subject, parent, name)
82 _subInlineNode = dynamic_cast<SubjectInlineNode*>(_subject);
83 YASSERT(_subInlineNode);
85 QSplitter *splitter = new QSplitter(this);
86 splitter->setOrientation(Qt::Vertical);
87 _wid->gridLayout1->addWidget(splitter);
89 QWidget* widg=new QWidget;
90 _portslayout = new QVBoxLayout;
91 widg->setLayout(_portslayout);
92 _portslayout->setMargin(1);
93 splitter->addWidget(widg);
95 QWidget* window=new QWidget;
96 _glayout=new QVBoxLayout;
97 window->setLayout(_glayout);
98 _glayout->setMargin(1);
99 splitter->addWidget(window);
101 //add an options section in ports layout for execution mode (local or remote)
102 QHBoxLayout* hboxLayout = new QHBoxLayout();
103 hboxLayout->setMargin(0);
104 QToolButton* tb_options = new QToolButton();
105 tb_options->setCheckable(true);
107 icon.addFile("icons:icon_down.png");
108 icon.addFile("icons:icon_up.png", QSize(), QIcon::Normal, QIcon::On);
109 tb_options->setIcon(icon);
110 hboxLayout->addWidget(tb_options);
112 QLabel* label = new QLabel("Execution Mode");
116 label->setFont(font);
117 hboxLayout->addWidget(label);
119 _portslayout->addLayout(hboxLayout);
121 fr_options = new QFrame();
122 QHBoxLayout* hboxLayout1 = new QHBoxLayout(fr_options);
123 hboxLayout1->setMargin(0);
124 radiolocal= new QRadioButton("YACS");
125 radioremote= new QRadioButton("Container");
126 radiolocal->setChecked(true);
127 hboxLayout1->addWidget(radiolocal);
128 hboxLayout1->addWidget(radioremote);
129 hboxLayout->addWidget(fr_options);
131 fr_container = new QFrame();
132 QHBoxLayout* hboxLayout2 = new QHBoxLayout(fr_container);
133 hboxLayout2->setMargin(0);
134 QLabel* laContainer = new QLabel("Container:");
135 hboxLayout2->addWidget(laContainer);
136 cb_container = new ComboBox();
137 hboxLayout2->addWidget(cb_container);
138 _portslayout->addWidget(fr_container);
141 YACS::ENGINE::InlineNode *pyNode(dynamic_cast<YACS::ENGINE::InlineNode*>(_subInlineNode->getNode()));
142 YACS::ENGINE::Container *cont(pyNode->getContainer());
143 formcontainer = new FormContainerDecorator(cont,this);
144 _portslayout->addWidget(formcontainer);
145 //_portslayout->addWidget(formcontainer->getWidget());
146 //end of insertion of execution mode
148 createTablePorts(_portslayout);
149 setEditablePorts(true);
153 _sci = new myQsciScintilla(this);
155 _sci = new QTextEdit(this);
157 _wid->gridLayout->removeItem(_wid->spacerItem);
159 _editor = new QPushButton("External Editor", this);
160 connect(_editor, SIGNAL(clicked()), this, SLOT(onEdit()));
161 if(!Resource::pythonExternalEditor.isEmpty())
163 _glayout->addWidget( _editor );
165 _glayout->addWidget( _sci );
169 QsciLexerPython *lex = new QsciLexerPython(_sci);
170 lex->setFont(Resource::pythonfont);
172 _sci->setBraceMatching(QsciScintilla::SloppyBraceMatch);
173 _sci->setAutoIndent(1);
174 _sci->setIndentationWidth(4);
175 _sci->setIndentationGuides(1);
176 _sci->setIndentationsUseTabs(0);
177 _sci->setAutoCompletionThreshold(2);
178 //_sci->setMarginLineNumbers(1,true);
179 _sci->setMarginWidth(1,0);
180 _sci->setFolding(QsciScintilla::PlainFoldStyle);
183 if (!QtGuiContext::getQtCurrent()->isEdition())
184 _sci->setReadOnly(true);
186 if (YACS::ENGINE::InlineNode* pyNode =
187 dynamic_cast<YACS::ENGINE::InlineNode*>(_subInlineNode->getNode()))
189 _sci->append(pyNode->getScript().c_str());
191 connect(_sci, SIGNAL(textChanged()), this, SLOT(onScriptModified()));
193 connect(tb_options, SIGNAL(toggled(bool)), this, SLOT(on_tb_options_toggled(bool)));
194 connect(radioremote, SIGNAL(toggled(bool)), this, SLOT(on_remote_toggled(bool)));
195 connect(cb_container, SIGNAL(mousePressed()), this, SLOT(fillContainerPanel()));
196 connect(cb_container, SIGNAL(activated(int)), this, SLOT(changeContainer(int)));
199 on_tb_options_toggled(false);
202 EditionScript::~EditionScript()
206 void EditionScript::synchronize()
208 DEBTRACE("EditionScript::synchronize " << this->_isEdited);
209 EditionElementaryNode::synchronize();
210 YACS::ENGINE::InlineNode* pyNode = dynamic_cast<YACS::ENGINE::InlineNode*>(_subInlineNode->getNode());
212 disconnect(_sci, SIGNAL(textChanged()), this, SLOT(onScriptModified()));
216 _sci->append(pyNode->getScript().c_str());
218 connect(_sci, SIGNAL(textChanged()), this, SLOT(onScriptModified()));
221 void EditionScript::onApply()
223 DEBTRACE("EditionScript::onApply");
224 bool scriptEdited = false;
226 _sci->lexer()->setFont(Resource::pythonfont);
229 if(Resource::pythonExternalEditor.isEmpty())
232 _glayout->removeWidget(_editor);
237 if(_glayout->itemAt(0)->widget() != _editor)
238 _glayout->insertWidget ( 0, _editor );
244 if (_sci->isModified())
247 std::string text=_sci->text().toStdString();
248 if(text[text.length()-1] != '\n')
250 bool ret = _subInlineNode->setScript(text);
251 if (ret) scriptEdited = false;
254 if (_sci->document()->isModified())
257 std::string text=_sci->document()->toPlainText().toStdString();
258 if(text[text.length()-1] != '\n')
260 bool ret = _subInlineNode->setScript(text);
261 if (ret) scriptEdited = false;
266 bool containerEdited = true;
267 if (formcontainer->onApply()) {
268 fillContainerPanel();
269 containerEdited = false;
271 Message mess(GuiContext::getCurrent()->_lastErrorMessage);
275 _isEdited = _isEdited || scriptEdited || containerEdited;
277 EditionElementaryNode::onApply();
280 void EditionScript::onCancel()
283 _sci->setText(_subInlineNode->getScript().c_str());
284 formcontainer->onCancel();
285 EditionElementaryNode::onCancel();
288 void EditionScript::onScriptModified()
290 DEBTRACE("EditionScript::onScriptModified");
295 void EditionScript::onEdit()
297 DEBTRACE("EditionScript::onEdit");
298 QTemporaryFile outFile;
301 QString fileName = outFile.fileName();
302 QTextStream out(&outFile);
306 out << _sci->toPlainText();
310 QStringList options=Resource::pythonExternalEditor.split(" ");
311 QString prog=options.takeAt(0);
312 QProcess::execute(prog, QStringList() << options << fileName);
314 QFile inFile(fileName);
315 if (!inFile.open(QIODevice::ReadOnly))
317 QTextStream in(&inFile);
319 _sci->setText(in.readAll());
321 _sci->setPlainText(in.readAll());
326 void EditionScript::on_tb_options_toggled(bool checked)
328 DEBTRACE("EditionScript::on_tb_options_toggled " << checked);
335 fr_container->show();
336 formcontainer->show();
342 fr_container->hide();
343 formcontainer->hide();
347 void EditionScript::on_remote_toggled(bool checked)
349 DEBTRACE("EditionScript::on_remote_toggled " << checked);
351 YACS::ENGINE::InlineNode *pyNode = dynamic_cast<YACS::ENGINE::InlineNode*>(_subInlineNode->getNode());
352 std::string mode = pyNode->getExecutionMode();
357 //remote radio button is checked
359 _subInlineNode->setExecutionMode("remote");
360 fr_container->show();
361 formcontainer->show();
362 fillContainerPanel();
366 //remote radio button is unchecked
368 _subInlineNode->setExecutionMode("local");
369 fr_container->hide();
370 formcontainer->hide();
374 void EditionScript::fillContainerPanel()
376 DEBTRACE("EditionScript::fillContainerPanel ");
377 YACS::ENGINE::Proc* proc = GuiContext::getCurrent()->getProc();
379 cb_container->clear();
380 std::map<string,YACS::ENGINE::Container*>::const_iterator it = proc->containerMap.begin();
381 for(; it != proc->containerMap.end(); ++it)
382 cb_container->addItem( QString((*it).first.c_str()));
384 YACS::ENGINE::InlineNode *pyNode = dynamic_cast<YACS::ENGINE::InlineNode*>(_subInlineNode->getNode());
386 YACS::ENGINE::Container * cont = pyNode->getContainer();
389 int index = cb_container->findText(cont->getName().c_str());
390 cb_container->setCurrentIndex(index);
391 formcontainer->FillPanel(cont);
393 else if (cb_container->count()) {
398 void EditionScript::changeContainer(int index)
400 DEBTRACE("EditionScript::changeContainer ");
401 string contName = cb_container->itemText(index).toStdString();
403 YACS::ENGINE::InlineNode *pyNode = dynamic_cast<YACS::ENGINE::InlineNode*>(_subInlineNode->getNode());
404 YACS::ENGINE::Container *oldContainer = pyNode->getContainer();
406 YACS::ENGINE::Container *newContainer = 0;
407 YACS::ENGINE::Proc* proc = GuiContext::getCurrent()->getProc();
408 if (proc->containerMap.count(contName))
409 newContainer = proc->containerMap[contName];
412 DEBTRACE("-------------> not found : " << contName);
415 YASSERT(GuiContext::getCurrent()->_mapOfSubjectContainer.count(newContainer));
416 SubjectContainerBase *scnt(GuiContext::getCurrent()->_mapOfSubjectContainer[newContainer]);
418 _subInlineNode->setContainer(scnt);
420 // show the selected container parameters
421 formcontainer->FillPanel(newContainer);
424 void EditionScript::update(GuiEvent event, int type, Subject* son)
426 DEBTRACE("EditionScript::update " << eventName(event) <<" "<<type<<" "<<son);
427 EditionElementaryNode::update(event, type, son);
428 if(event == ASSOCIATE)
430 fillContainerPanel();
431 SubjectContainer *scont = dynamic_cast<SubjectContainer*>(son);
433 formcontainer->FillPanel(scont->getContainer());
435 else if(event == UPDATE)
437 YACS::ENGINE::InlineNode *pyNode = dynamic_cast<YACS::ENGINE::InlineNode*>(_subInlineNode->getNode());
438 std::string mode = pyNode->getExecutionMode();
442 radioremote->setChecked(true);
444 else if(mode == "local")
447 radiolocal->setChecked(true);
450 fillContainerPanel();