Version: 8.3.0
EditionScript.cxx
Go to the documentation of this file.
1 // Copyright (C) 2006-2016 CEA/DEN, EDF R&D
2 //
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.
7 //
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.
12 //
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
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19 
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"
27 
28 #ifdef HAS_PYEDITOR
29 #include <PyEditor_Editor.h>
30 #include <PyEditor_Settings.h>
31 #endif
32 
33 #include <QToolButton>
34 #include <QSplitter>
35 #include <QTemporaryFile>
36 #include <QTextStream>
37 #include <QProcess>
38 
39 #include <cassert>
40 
41 //#define _DEVDEBUG_
42 #include "YacsTrace.hxx"
43 
44 using namespace std;
45 
46 using namespace YACS;
47 using namespace YACS::HMI;
48 
49 EditionScript::EditionScript(Subject* subject,
50  QWidget* parent,
51  const char* name)
52  : EditionElementaryNode(subject, parent, name)
53 {
54  _subInlineNode = 0;
55  _sci = 0;
56 
57  _subInlineNode = dynamic_cast<SubjectInlineNode*>(_subject);
59 
60  QSplitter *splitter = new QSplitter(this);
61  splitter->setOrientation(Qt::Vertical);
62  _wid->gridLayout1->addWidget(splitter);
63 
64  QWidget* widg=new QWidget;
65  _portslayout = new QVBoxLayout;
66  widg->setLayout(_portslayout);
67  _portslayout->setMargin(1);
68  splitter->addWidget(widg);
69 
70  QWidget* window=new QWidget;
71  _glayout=new QVBoxLayout;
72  window->setLayout(_glayout);
73  _glayout->setMargin(1);
74  splitter->addWidget(window);
75 
76  //add an options section in ports layout for execution mode (local or remote)
77  QHBoxLayout* hboxLayout = new QHBoxLayout();
78  hboxLayout->setMargin(0);
79  QToolButton* tb_options = new QToolButton();
80  tb_options->setCheckable(true);
81  QIcon icon;
82  icon.addFile("icons:icon_down.png");
83  icon.addFile("icons:icon_up.png", QSize(), QIcon::Normal, QIcon::On);
84  tb_options->setIcon(icon);
85  hboxLayout->addWidget(tb_options);
86 
87  QLabel* label = new QLabel("Execution Mode");
88  QFont font;
89  font.setBold(true);
90  font.setWeight(75);
91  label->setFont(font);
92  hboxLayout->addWidget(label);
93 
94  _portslayout->addLayout(hboxLayout);
95 
96  fr_options = new QFrame();
97  QHBoxLayout* hboxLayout1 = new QHBoxLayout(fr_options);
98  hboxLayout1->setMargin(0);
99  radiolocal= new QRadioButton("YACS");
100  radioremote= new QRadioButton("Container");
101  radiolocal->setChecked(true);
102  hboxLayout1->addWidget(radiolocal);
103  hboxLayout1->addWidget(radioremote);
104  hboxLayout->addWidget(fr_options);
105 
106  fr_container = new QFrame();
107  QHBoxLayout* hboxLayout2 = new QHBoxLayout(fr_container);
108  hboxLayout2->setMargin(0);
109  QLabel* laContainer = new QLabel("Container:");
110  hboxLayout2->addWidget(laContainer);
111  cb_container = new ComboBox();
112  hboxLayout2->addWidget(cb_container);
113  _portslayout->addWidget(fr_container);
114 
115  //
116  YACS::ENGINE::InlineNode *pyNode(dynamic_cast<YACS::ENGINE::InlineNode*>(_subInlineNode->getNode()));
117  YACS::ENGINE::Container *cont(pyNode->getContainer());
118  formcontainer = new FormContainerDecorator(cont,this);
119  _portslayout->addWidget(formcontainer);
120  //_portslayout->addWidget(formcontainer->getWidget());
121  //end of insertion of execution mode
122 
124  setEditablePorts(true);
125 
126  _haveScript = true;
127 #ifdef HAS_PYEDITOR
128  _sci = new PyEditor_Editor(this);
129 #else
130  _sci = new QTextEdit(this);
131 #endif
132  _wid->gridLayout->removeItem(_wid->spacerItem);
133 
134  _editor = new QPushButton("External Editor", this);
135  connect(_editor, SIGNAL(clicked()), this, SLOT(onEdit()));
136  if(!Resource::pythonExternalEditor.isEmpty())
137  {
138  _glayout->addWidget( _editor );
139  }
140  _glayout->addWidget( _sci );
141 
142  if (!QtGuiContext::getQtCurrent()->isEdition())
143  _sci->setReadOnly(true);
144 
145  if (YACS::ENGINE::InlineNode* pyNode =
146  dynamic_cast<YACS::ENGINE::InlineNode*>(_subInlineNode->getNode()))
147  {
148  _sci->append(pyNode->getScript().c_str());
149  }
150  connect(_sci, SIGNAL(textChanged()), this, SLOT(onScriptModified()));
151 
152  connect(tb_options, SIGNAL(toggled(bool)), this, SLOT(on_tb_options_toggled(bool)));
153  connect(radioremote, SIGNAL(toggled(bool)), this, SLOT(on_remote_toggled(bool)));
154  connect(cb_container, SIGNAL(mousePressed()), this, SLOT(fillContainerPanel()));
155  connect(cb_container, SIGNAL(activated(int)), this, SLOT(changeContainer(int)));
156 
157  update(UPDATE,0,0);
158  on_tb_options_toggled(false);
159 }
160 
162 {
163 }
164 
166 {
167  DEBTRACE("EditionScript::synchronize " << this->_isEdited);
170  YASSERT(pyNode);
171  disconnect(_sci, SIGNAL(textChanged()), this, SLOT(onScriptModified()));
172  if (!_isEdited)
173  {
174  _sci->clear();
175  _sci->append(pyNode->getScript().c_str());
176  }
177  connect(_sci, SIGNAL(textChanged()), this, SLOT(onScriptModified()));
178 }
179 
181 {
182  DEBTRACE("EditionScript::onApply");
183  bool scriptEdited = false;
184 #ifdef HAS_PYEDITOR
185  PyEditor_Settings settings = _sci->settings();
186  settings.setFont(Resource::pythonfont);
187  _sci->setSettings(settings);
188 #endif
189 
190  if(Resource::pythonExternalEditor.isEmpty())
191  {
192  _editor->hide();
193  _glayout->removeWidget(_editor);
194  }
195  else
196  {
197  _editor->show();
198  if(_glayout->itemAt(0)->widget() != _editor)
199  _glayout->insertWidget ( 0, _editor );
200  }
201 
202  if (_haveScript)
203  {
204  if (_sci->document()->isModified())
205  {
206  scriptEdited = true;
207  std::string text=_sci->document()->toPlainText().toStdString();
208  if(text[text.length()-1] != '\n')
209  text=text+'\n';
210  bool ret = _subInlineNode->setScript(text);
211  if (ret) scriptEdited = false;
212  }
213  }
214 
215  bool containerEdited = true;
216  if (formcontainer->onApply()) {
218  containerEdited = false;
219  } else {
220  Message mess(GuiContext::getCurrent()->_lastErrorMessage);
221  return;
222  }
223 
224  _isEdited = _isEdited || scriptEdited || containerEdited;
225 
227 }
228 
230 {
231  if (_haveScript)
232  _sci->setText(_subInlineNode->getScript().c_str());
235 }
236 
238 {
239  DEBTRACE("EditionScript::onScriptModified");
240  _isEdited = true;
241  setEdited(true);
242 }
243 
245 {
246  DEBTRACE("EditionScript::onEdit");
247  QTemporaryFile outFile;
248  if (!outFile.open())
249  return;
250  QString fileName = outFile.fileName();
251  QTextStream out(&outFile);
252  out << _sci->toPlainText();
253  outFile.close();
254 
255  QStringList options=Resource::pythonExternalEditor.split(" ");
256  QString prog=options.takeAt(0);
257  QProcess::execute(prog, QStringList() << options << fileName);
258 
259  QFile inFile(fileName);
260  if (!inFile.open(QIODevice::ReadOnly))
261  return;
262  QTextStream in(&inFile);
263  _sci->setPlainText(in.readAll());
264  onApply();
265 }
266 
268 {
269  DEBTRACE("EditionScript::on_tb_options_toggled " << checked);
270  _checked = checked;
271  if(_checked)
272  {
273  fr_options->show();
274  if(_remote)
275  {
276  fr_container->show();
277  formcontainer->show();
278  }
279  }
280  else
281  {
282  fr_options->hide();
283  fr_container->hide();
284  formcontainer->hide();
285  }
286 }
287 
289 {
290  DEBTRACE("EditionScript::on_remote_toggled " << checked);
291  _remote=checked;
293  std::string mode = pyNode->getExecutionMode();
294  DEBTRACE(mode);
295 
296  if(checked)
297  {
298  //remote radio button is checked
299  if(mode != "remote")
300  _subInlineNode->setExecutionMode("remote");
301  fr_container->show();
302  formcontainer->show();
304  }
305  else
306  {
307  //remote radio button is unchecked
308  if(mode != "local")
310  fr_container->hide();
311  formcontainer->hide();
312  }
313 }
314 
316 {
317  DEBTRACE("EditionScript::fillContainerPanel ");
319 
320  cb_container->clear();
321  std::map<string,YACS::ENGINE::Container*>::const_iterator it = proc->containerMap.begin();
322  for(; it != proc->containerMap.end(); ++it)
323  cb_container->addItem( QString((*it).first.c_str()));
324 
326 
327  YACS::ENGINE::Container * cont = pyNode->getContainer();
328  if (cont)
329  {
330  int index = cb_container->findText(cont->getName().c_str());
331  cb_container->setCurrentIndex(index);
332  formcontainer->FillPanel(cont);
333  }
334  else if (cb_container->count()) {
335  changeContainer(0);
336  }
337 }
338 
340 {
341  DEBTRACE("EditionScript::changeContainer ");
342  string contName = cb_container->itemText(index).toStdString();
343  DEBTRACE(contName);
345  YACS::ENGINE::Container *oldContainer = pyNode->getContainer();
346 
347  YACS::ENGINE::Container *newContainer = 0;
349  if (proc->containerMap.count(contName))
350  newContainer = proc->containerMap[contName];
351  if (!newContainer)
352  {
353  DEBTRACE("-------------> not found : " << contName);
354  return;
355  }
356  YASSERT(GuiContext::getCurrent()->_mapOfSubjectContainer.count(newContainer));
357  SubjectContainerBase *scnt(GuiContext::getCurrent()->_mapOfSubjectContainer[newContainer]);
358 
360 
361  // show the selected container parameters
362  formcontainer->FillPanel(newContainer);
363 }
364 
365 void EditionScript::update(GuiEvent event, int type, Subject* son)
366 {
367  DEBTRACE("EditionScript::update " << eventName(event) <<" "<<type<<" "<<son);
368  EditionElementaryNode::update(event, type, son);
369  if(event == ASSOCIATE)
370  {
372  SubjectContainer *scont = dynamic_cast<SubjectContainer*>(son);
373  YASSERT(scont);
375  }
376  else if(event == UPDATE)
377  {
379  std::string mode = pyNode->getExecutionMode();
380  if(mode == "remote")
381  {
382  _remote=true;
383  radioremote->setChecked(true);
384  }
385  else if(mode == "local")
386  {
387  _remote=false;
388  radiolocal->setChecked(true);
389  }
390 
392  }
393 }
394