1 // Copyright (C) 2006-2012 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.
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"
27 #include <qsciscintilla.h>
28 #include <qscilexerpython.h>
31 #include <QToolButton>
33 #include <QTemporaryFile>
34 #include <QTextStream>
40 #include "YacsTrace.hxx"
45 using namespace YACS::HMI;
48 class myQsciScintilla: public QsciScintilla
51 myQsciScintilla(QWidget *parent=0)
52 : QsciScintilla(parent) {};
54 virtual QSize sizeHint() const { return QSize(350, 150); };
56 virtual bool event(QEvent *e);
59 bool myQsciScintilla::event(QEvent *e)
61 if (e->type() == QEvent::ShortcutOverride)
66 return QsciScintilla::event(e);
72 EditionScript::EditionScript(Subject* subject,
75 : EditionElementaryNode(subject, parent, name)
80 _subInlineNode = dynamic_cast<SubjectInlineNode*>(_subject);
81 YASSERT(_subInlineNode);
83 QSplitter *splitter = new QSplitter(this);
84 splitter->setOrientation(Qt::Vertical);
85 _wid->gridLayout1->addWidget(splitter);
87 QWidget* widg=new QWidget;
88 _portslayout = new QVBoxLayout;
89 widg->setLayout(_portslayout);
90 _portslayout->setMargin(1);
91 splitter->addWidget(widg);
93 QWidget* window=new QWidget;
94 _glayout=new QVBoxLayout;
95 window->setLayout(_glayout);
96 _glayout->setMargin(1);
97 splitter->addWidget(window);
99 //add an options section in ports layout for execution mode (local or remote)
100 QHBoxLayout* hboxLayout = new QHBoxLayout();
101 hboxLayout->setMargin(0);
102 QToolButton* tb_options = new QToolButton();
103 tb_options->setCheckable(true);
105 icon.addFile("icons:icon_down.png");
106 icon.addFile("icons:icon_up.png", QSize(), QIcon::Normal, QIcon::On);
107 tb_options->setIcon(icon);
108 hboxLayout->addWidget(tb_options);
110 QLabel* label = new QLabel("Execution Mode");
114 label->setFont(font);
115 hboxLayout->addWidget(label);
117 _portslayout->addLayout(hboxLayout);
119 fr_options = new QFrame();
120 QHBoxLayout* hboxLayout1 = new QHBoxLayout(fr_options);
121 hboxLayout1->setMargin(0);
122 radiolocal= new QRadioButton("Local");
123 radioremote= new QRadioButton("Remote");
124 radiolocal->setChecked(true);
125 hboxLayout1->addWidget(radiolocal);
126 hboxLayout1->addWidget(radioremote);
127 hboxLayout->addWidget(fr_options);
129 fr_container = new QFrame();
130 QHBoxLayout* hboxLayout2 = new QHBoxLayout(fr_container);
131 hboxLayout2->setMargin(0);
132 QLabel* laContainer = new QLabel("Container:");
133 hboxLayout2->addWidget(laContainer);
134 cb_container = new ComboBox();
135 hboxLayout2->addWidget(cb_container);
136 _portslayout->addWidget(fr_container);
137 //end of insertion of execution mode
139 createTablePorts(_portslayout);
140 setEditablePorts(true);
144 _sci = new myQsciScintilla(this);
146 _sci = new QTextEdit(this);
148 _wid->gridLayout->removeItem(_wid->spacerItem);
150 _editor = new QPushButton("External Editor", this);
151 connect(_editor, SIGNAL(clicked()), this, SLOT(onEdit()));
152 if(!Resource::pythonExternalEditor.isEmpty())
154 _glayout->addWidget( _editor );
156 _glayout->addWidget( _sci );
160 QsciLexerPython *lex = new QsciLexerPython(_sci);
161 lex->setFont(Resource::pythonfont);
163 _sci->setBraceMatching(QsciScintilla::SloppyBraceMatch);
164 _sci->setAutoIndent(1);
165 _sci->setIndentationWidth(4);
166 _sci->setIndentationGuides(1);
167 _sci->setIndentationsUseTabs(0);
168 _sci->setAutoCompletionThreshold(2);
169 //_sci->setMarginLineNumbers(1,true);
170 _sci->setMarginWidth(1,0);
171 _sci->setFolding(QsciScintilla::PlainFoldStyle);
174 if (!QtGuiContext::getQtCurrent()->isEdition())
175 _sci->setReadOnly(true);
177 if (YACS::ENGINE::InlineNode* pyNode =
178 dynamic_cast<YACS::ENGINE::InlineNode*>(_subInlineNode->getNode()))
180 _sci->append(pyNode->getScript().c_str());
182 connect(_sci, SIGNAL(textChanged()), this, SLOT(onScriptModified()));
184 connect(tb_options, SIGNAL(toggled(bool)), this, SLOT(on_tb_options_toggled(bool)));
185 connect(radioremote, SIGNAL(toggled(bool)), this, SLOT(on_remote_toggled(bool)));
186 connect(cb_container, SIGNAL(mousePressed()), this, SLOT(fillContainerPanel()));
187 connect(cb_container, SIGNAL(activated(int)), this, SLOT(changeContainer(int)));
190 on_tb_options_toggled(false);
193 EditionScript::~EditionScript()
197 void EditionScript::synchronize()
199 DEBTRACE("EditionScript::synchronize " << this->_isEdited);
200 EditionElementaryNode::synchronize();
201 YACS::ENGINE::InlineNode* pyNode = dynamic_cast<YACS::ENGINE::InlineNode*>(_subInlineNode->getNode());
203 disconnect(_sci, SIGNAL(textChanged()), this, SLOT(onScriptModified()));
207 _sci->append(pyNode->getScript().c_str());
209 connect(_sci, SIGNAL(textChanged()), this, SLOT(onScriptModified()));
212 void EditionScript::onApply()
214 DEBTRACE("EditionScript::onApply");
215 bool scriptEdited = false;
217 _sci->lexer()->setFont(Resource::pythonfont);
220 if(Resource::pythonExternalEditor.isEmpty())
223 _glayout->removeWidget(_editor);
228 if(_glayout->itemAt(0)->widget() != _editor)
229 _glayout->insertWidget ( 0, _editor );
235 if (_sci->isModified())
238 std::string text=_sci->text().toStdString();
239 if(text[text.length()-1] != '\n')
241 bool ret = _subInlineNode->setScript(text);
242 if (ret) scriptEdited = false;
245 if (_sci->document()->isModified())
248 std::string text=_sci->document()->toPlainText().toStdString();
249 if(text[text.length()-1] != '\n')
251 bool ret = _subInlineNode->setScript(text);
252 if (ret) scriptEdited = false;
256 _isEdited = _isEdited || scriptEdited;
258 EditionElementaryNode::onApply();
261 void EditionScript::onCancel()
264 _sci->setText(_subInlineNode->getScript().c_str());
265 EditionElementaryNode::onCancel();
268 void EditionScript::onScriptModified()
270 DEBTRACE("EditionScript::onScriptModified");
275 void EditionScript::onEdit()
277 DEBTRACE("EditionScript::onEdit");
278 QTemporaryFile outFile;
281 QString fileName = outFile.fileName();
282 QTextStream out(&outFile);
286 out << _sci->toPlainText();
290 QStringList options=Resource::pythonExternalEditor.split(" ");
291 QString prog=options.takeAt(0);
292 QProcess::execute(prog, QStringList() << options << fileName);
294 QFile inFile(fileName);
295 if (!inFile.open(QIODevice::ReadOnly))
297 QTextStream in(&inFile);
299 _sci->setText(in.readAll());
301 _sci->setPlainText(in.readAll());
306 void EditionScript::on_tb_options_toggled(bool checked)
308 DEBTRACE("EditionScript::on_tb_options_toggled " << checked);
313 if(_remote)fr_container->show();
318 fr_container->hide();
322 void EditionScript::on_remote_toggled(bool checked)
324 DEBTRACE("EditionScript::on_remote_toggled " << checked);
326 YACS::ENGINE::InlineNode *pyNode = dynamic_cast<YACS::ENGINE::InlineNode*>(_subInlineNode->getNode());
327 std::string mode = pyNode->getExecutionMode();
332 //remote radio button is checked
334 _subInlineNode->setExecutionMode("remote");
335 fr_container->show();
336 fillContainerPanel();
340 //remote radio button is unchecked
342 _subInlineNode->setExecutionMode("local");
343 fr_container->hide();
347 void EditionScript::fillContainerPanel()
349 DEBTRACE("EditionScript::fillContainerPanel ");
350 YACS::ENGINE::Proc* proc = GuiContext::getCurrent()->getProc();
352 cb_container->clear();
353 std::map<string,YACS::ENGINE::Container*>::const_iterator it = proc->containerMap.begin();
354 for(; it != proc->containerMap.end(); ++it)
355 cb_container->addItem( QString((*it).first.c_str()));
357 YACS::ENGINE::InlineNode *pyNode = dynamic_cast<YACS::ENGINE::InlineNode*>(_subInlineNode->getNode());
359 YACS::ENGINE::Container * cont = pyNode->getContainer();
362 int index = cb_container->findText(cont->getName().c_str());
363 cb_container->setCurrentIndex(index);
367 void EditionScript::changeContainer(int index)
369 DEBTRACE("EditionScript::changeContainer ");
370 string contName = cb_container->itemText(index).toStdString();
372 YACS::ENGINE::InlineNode *pyNode = dynamic_cast<YACS::ENGINE::InlineNode*>(_subInlineNode->getNode());
373 YACS::ENGINE::Container *oldContainer = pyNode->getContainer();
375 YACS::ENGINE::Container *newContainer = 0;
376 YACS::ENGINE::Proc* proc = GuiContext::getCurrent()->getProc();
377 if (proc->containerMap.count(contName))
378 newContainer = proc->containerMap[contName];
381 DEBTRACE("-------------> not found : " << contName);
384 YASSERT(GuiContext::getCurrent()->_mapOfSubjectContainer.count(newContainer));
385 SubjectContainer *scnt = GuiContext::getCurrent()->_mapOfSubjectContainer[newContainer];
387 _subInlineNode->setContainer(scnt);
390 void EditionScript::update(GuiEvent event, int type, Subject* son)
392 DEBTRACE("EditionScript::update " << eventName(event) <<" "<<type<<" "<<son);
393 EditionElementaryNode::update(event, type, son);
394 if(event == ASSOCIATE)
396 fillContainerPanel();
398 else if(event == UPDATE)
400 YACS::ENGINE::InlineNode *pyNode = dynamic_cast<YACS::ENGINE::InlineNode*>(_subInlineNode->getNode());
401 std::string mode = pyNode->getExecutionMode();
405 radioremote->setChecked(true);
407 else if(mode == "local")
410 radiolocal->setChecked(true);
413 fillContainerPanel();