]> SALOME platform Git repositories - modules/yacs.git/blob - src/genericgui/EditionScript.cxx
Salome HOME
Remove dependency on QScintilla
[modules/yacs.git] / src / genericgui / EditionScript.cxx
1 // Copyright (C) 2006-2015  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);
58   YASSERT(_subInlineNode);
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
123   createTablePorts(_portslayout);
124   setEditablePorts(true);
125
126   _haveScript = true;
127 #ifdef HAS_PYEDITOR
128   _sci = new PyEditor_Editor(false, 0, 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
161 EditionScript::~EditionScript()
162 {
163 }
164
165 void EditionScript::synchronize()
166 {
167   DEBTRACE("EditionScript::synchronize " << this->_isEdited);
168   EditionElementaryNode::synchronize();
169   YACS::ENGINE::InlineNode* pyNode = dynamic_cast<YACS::ENGINE::InlineNode*>(_subInlineNode->getNode());
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
180 void EditionScript::onApply()
181 {
182   DEBTRACE("EditionScript::onApply");
183   bool scriptEdited = false;
184 #ifdef HAS_PYEDITOR
185   _sci->settings()->p_Font = Resource::pythonfont;
186 #endif
187
188   if(Resource::pythonExternalEditor.isEmpty())
189     {
190       _editor->hide();
191       _glayout->removeWidget(_editor);
192     }
193   else
194     {
195       _editor->show();
196       if(_glayout->itemAt(0)->widget() != _editor)
197         _glayout->insertWidget ( 0, _editor );
198     }
199
200   if (_haveScript)
201     {
202       if (_sci->document()->isModified())
203         {
204           scriptEdited = true;
205           std::string text=_sci->document()->toPlainText().toStdString();
206           if(text[text.length()-1] != '\n')
207             text=text+'\n';
208           bool ret = _subInlineNode->setScript(text);
209           if (ret) scriptEdited = false;
210         }
211     }
212
213   bool containerEdited = true;
214   if (formcontainer->onApply()) {
215     fillContainerPanel();
216     containerEdited = false;
217   } else {
218     Message mess(GuiContext::getCurrent()->_lastErrorMessage);
219     return;
220   }
221
222   _isEdited = _isEdited || scriptEdited || containerEdited;
223
224   EditionElementaryNode::onApply();
225 }
226
227 void EditionScript::onCancel()
228 {
229   if (_haveScript)
230     _sci->setText(_subInlineNode->getScript().c_str());
231   formcontainer->onCancel();
232   EditionElementaryNode::onCancel();
233 }
234
235 void EditionScript::onScriptModified()
236 {
237   DEBTRACE("EditionScript::onScriptModified");
238   _isEdited = true;
239   setEdited(true);
240 }
241
242 void EditionScript::onEdit()
243 {
244   DEBTRACE("EditionScript::onEdit");
245   QTemporaryFile outFile;
246   if (!outFile.open())
247     return;
248   QString fileName = outFile.fileName();
249   QTextStream out(&outFile);
250   out << _sci->toPlainText();
251   outFile.close();
252
253   QStringList options=Resource::pythonExternalEditor.split(" ");
254   QString prog=options.takeAt(0);
255   QProcess::execute(prog, QStringList() << options << fileName);
256
257   QFile inFile(fileName);
258   if (!inFile.open(QIODevice::ReadOnly))
259     return;
260   QTextStream in(&inFile);
261   _sci->setPlainText(in.readAll());
262   onApply();
263 }
264
265 void EditionScript::on_tb_options_toggled(bool checked)
266 {
267   DEBTRACE("EditionScript::on_tb_options_toggled " << checked);
268   _checked = checked;
269   if(_checked)
270     {
271       fr_options->show();
272       if(_remote)
273         {
274           fr_container->show();
275           formcontainer->show();
276         }
277     }
278   else
279     {
280       fr_options->hide();
281       fr_container->hide();
282       formcontainer->hide();
283     }
284 }
285
286 void EditionScript::on_remote_toggled(bool checked)
287 {
288   DEBTRACE("EditionScript::on_remote_toggled " << checked);
289   _remote=checked;
290   YACS::ENGINE::InlineNode *pyNode = dynamic_cast<YACS::ENGINE::InlineNode*>(_subInlineNode->getNode());
291   std::string mode = pyNode->getExecutionMode();
292   DEBTRACE(mode);
293
294   if(checked)
295     {
296       //remote radio button is checked
297       if(mode != "remote")
298         _subInlineNode->setExecutionMode("remote");
299       fr_container->show();
300       formcontainer->show();
301       fillContainerPanel();
302     }
303   else
304     {
305       //remote radio button is unchecked
306       if(mode != "local")
307         _subInlineNode->setExecutionMode("local");
308       fr_container->hide();
309       formcontainer->hide();
310     }
311 }
312
313 void EditionScript::fillContainerPanel()
314 {
315   DEBTRACE("EditionScript::fillContainerPanel ");
316   YACS::ENGINE::Proc* proc = GuiContext::getCurrent()->getProc();
317
318   cb_container->clear();
319   std::map<string,YACS::ENGINE::Container*>::const_iterator it = proc->containerMap.begin();
320   for(; it != proc->containerMap.end(); ++it)
321     cb_container->addItem( QString((*it).first.c_str()));
322
323   YACS::ENGINE::InlineNode *pyNode = dynamic_cast<YACS::ENGINE::InlineNode*>(_subInlineNode->getNode());
324
325   YACS::ENGINE::Container * cont = pyNode->getContainer();
326   if (cont)
327     {
328       int index = cb_container->findText(cont->getName().c_str());
329       cb_container->setCurrentIndex(index);
330       formcontainer->FillPanel(cont);
331     } 
332   else if (cb_container->count()) {
333     changeContainer(0);
334   }
335 }
336
337 void EditionScript::changeContainer(int index)
338 {
339   DEBTRACE("EditionScript::changeContainer ");
340   string contName = cb_container->itemText(index).toStdString();
341   DEBTRACE(contName);
342   YACS::ENGINE::InlineNode *pyNode = dynamic_cast<YACS::ENGINE::InlineNode*>(_subInlineNode->getNode());
343   YACS::ENGINE::Container *oldContainer = pyNode->getContainer();
344
345   YACS::ENGINE::Container *newContainer = 0;
346   YACS::ENGINE::Proc* proc = GuiContext::getCurrent()->getProc();
347   if (proc->containerMap.count(contName))
348     newContainer = proc->containerMap[contName];
349   if (!newContainer)
350     {
351       DEBTRACE("-------------> not found : " << contName);
352       return;
353     }
354   YASSERT(GuiContext::getCurrent()->_mapOfSubjectContainer.count(newContainer));
355   SubjectContainerBase *scnt(GuiContext::getCurrent()->_mapOfSubjectContainer[newContainer]);
356
357   _subInlineNode->setContainer(scnt);
358   
359   // show the selected container parameters
360   formcontainer->FillPanel(newContainer);
361 }
362
363 void EditionScript::update(GuiEvent event, int type, Subject* son)
364 {
365   DEBTRACE("EditionScript::update " << eventName(event) <<" "<<type<<" "<<son);
366   EditionElementaryNode::update(event, type, son);
367   if(event == ASSOCIATE)
368     {
369       fillContainerPanel();
370       SubjectContainer *scont = dynamic_cast<SubjectContainer*>(son);
371       YASSERT(scont);
372       formcontainer->FillPanel(scont->getContainer());
373     }
374   else if(event == UPDATE)
375     {
376       YACS::ENGINE::InlineNode *pyNode = dynamic_cast<YACS::ENGINE::InlineNode*>(_subInlineNode->getNode());
377       std::string mode = pyNode->getExecutionMode();
378       if(mode == "remote")
379         {
380           _remote=true;
381           radioremote->setChecked(true);
382         }
383       else if(mode == "local")
384         {
385           _remote=false;
386           radiolocal->setChecked(true);
387         }
388
389       fillContainerPanel();
390     }
391 }
392