]> SALOME platform Git repositories - modules/yacs.git/blob - src/genericgui/EditionScript.cxx
Salome HOME
Update copyrights 2014.
[modules/yacs.git] / src / genericgui / EditionScript.cxx
1 // Copyright (C) 2006-2014  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 #if HAS_QSCI4>0
29 #include <qsciscintilla.h>
30 #include <qscilexerpython.h>
31 #endif
32
33 #include <QSplitter>
34 #include <QTemporaryFile>
35 #include <QTextStream>
36 #include <QProcess>
37
38 #include <cassert>
39
40 //#define _DEVDEBUG_
41 #include "YacsTrace.hxx"
42
43 using namespace std;
44
45 using namespace YACS;
46 using namespace YACS::HMI;
47
48 #if HAS_QSCI4>0
49 class myQsciScintilla: public QsciScintilla
50 {
51 public:
52   myQsciScintilla(QWidget *parent=0)
53     : QsciScintilla(parent) {};
54   ~myQsciScintilla(){};
55   virtual QSize sizeHint() const { return QSize(350, 150); };
56 protected:
57   virtual bool event(QEvent *e);
58 };
59
60 bool myQsciScintilla::event(QEvent *e)
61 {
62   if (e->type() == QEvent::ShortcutOverride)
63     {
64       e->accept();
65       return true;
66     }
67   return QsciScintilla::event(e);
68 }
69
70 #endif
71
72
73 EditionScript::EditionScript(Subject* subject,
74                          QWidget* parent,
75                          const char* name)
76   : EditionElementaryNode(subject, parent, name)
77 {
78   _subInlineNode = 0;
79   _sci = 0;
80
81   _subInlineNode = dynamic_cast<SubjectInlineNode*>(_subject);
82   YASSERT(_subInlineNode);
83
84   QSplitter *splitter = new QSplitter(this);
85   splitter->setOrientation(Qt::Vertical);
86   _wid->gridLayout1->addWidget(splitter);
87
88   QWidget* widg=new QWidget;
89   _portslayout = new QVBoxLayout;
90   widg->setLayout(_portslayout);
91   _portslayout->setMargin(1);
92   splitter->addWidget(widg);
93
94   QWidget* window=new QWidget;
95   _glayout=new QVBoxLayout;
96   window->setLayout(_glayout);
97   _glayout->setMargin(1);
98   splitter->addWidget(window);
99
100   fr_container = new QFrame();
101   QHBoxLayout* hboxLayout2 = new QHBoxLayout(fr_container);
102   hboxLayout2->setMargin(0);
103   QLabel* laContainer = new QLabel("Container:");
104   hboxLayout2->addWidget(laContainer);
105   cb_container = new ComboBox();
106   hboxLayout2->addWidget(cb_container);
107   _portslayout->addWidget(fr_container);
108
109   formcontainer = new FormContainer(this);
110   formcontainer->on_tb_container_toggled(false);
111   _portslayout->addWidget(formcontainer);
112   //end of insertion of execution mode
113
114   createTablePorts(_portslayout);
115   setEditablePorts(true);
116
117   _haveScript = true;
118 #if HAS_QSCI4>0
119   _sci = new myQsciScintilla(this);
120 #else
121   _sci = new QTextEdit(this);
122 #endif
123   _wid->gridLayout->removeItem(_wid->spacerItem);
124
125   _editor = new QPushButton("External Editor", this);
126   connect(_editor, SIGNAL(clicked()), this, SLOT(onEdit()));
127   if(!Resource::pythonExternalEditor.isEmpty())
128     {
129       _glayout->addWidget( _editor );
130     }
131   _glayout->addWidget( _sci );
132
133 #if HAS_QSCI4>0
134   _sci->setUtf8(1);
135   QsciLexerPython *lex = new QsciLexerPython(_sci);
136   lex->setFont(Resource::pythonfont);
137   _sci->setLexer(lex);
138   _sci->setBraceMatching(QsciScintilla::SloppyBraceMatch);
139   _sci->setAutoIndent(1);
140   _sci->setIndentationWidth(4);
141   _sci->setIndentationGuides(1);
142   _sci->setIndentationsUseTabs(0);
143   _sci->setAutoCompletionThreshold(2);
144   //_sci->setMarginLineNumbers(1,true);
145   _sci->setMarginWidth(1,0);
146   _sci->setFolding(QsciScintilla::PlainFoldStyle);
147 #endif
148
149   if (!QtGuiContext::getQtCurrent()->isEdition())
150     _sci->setReadOnly(true);
151
152   if (YACS::ENGINE::InlineNode* pyNode =
153       dynamic_cast<YACS::ENGINE::InlineNode*>(_subInlineNode->getNode()))
154     {
155       _sci->append(pyNode->getScript().c_str());
156     }
157   connect(_sci, SIGNAL(textChanged()), this, SLOT(onScriptModified()));
158
159   connect(cb_container, SIGNAL(mousePressed()), this, SLOT(fillContainerPanel()));
160   connect(cb_container, SIGNAL(activated(int)), this, SLOT(changeContainer(int)));
161
162   update(UPDATE,0,0);
163   changeContainer(0);
164 }
165
166 EditionScript::~EditionScript()
167 {
168 }
169
170 void EditionScript::synchronize()
171 {
172   DEBTRACE("EditionScript::synchronize " << this->_isEdited);
173   EditionElementaryNode::synchronize();
174   YACS::ENGINE::InlineNode* pyNode = dynamic_cast<YACS::ENGINE::InlineNode*>(_subInlineNode->getNode());
175   YASSERT(pyNode);
176   disconnect(_sci, SIGNAL(textChanged()), this, SLOT(onScriptModified()));
177   if (!_isEdited)
178   {
179     _sci->clear();
180     _sci->append(pyNode->getScript().c_str());
181   }
182   connect(_sci, SIGNAL(textChanged()), this, SLOT(onScriptModified()));
183 }
184
185 void EditionScript::onApply()
186 {
187   DEBTRACE("EditionScript::onApply");
188   bool scriptEdited = false;
189 #if HAS_QSCI4>0
190   _sci->lexer()->setFont(Resource::pythonfont);
191 #endif
192
193   if(Resource::pythonExternalEditor.isEmpty())
194     {
195       _editor->hide();
196       _glayout->removeWidget(_editor);
197     }
198   else
199     {
200       _editor->show();
201       if(_glayout->itemAt(0)->widget() != _editor)
202         _glayout->insertWidget ( 0, _editor );
203     }
204
205   if (_haveScript)
206     {
207 #if HAS_QSCI4>0
208       if (_sci->isModified())
209         {
210           scriptEdited = true;
211           std::string text=_sci->text().toStdString();
212           if(text[text.length()-1] != '\n')
213             text=text+'\n';
214           bool ret = _subInlineNode->setScript(text);
215           if (ret) scriptEdited = false;
216         }
217 #else
218       if (_sci->document()->isModified())
219         {
220           scriptEdited = true;
221           std::string text=_sci->document()->toPlainText().toStdString();
222           if(text[text.length()-1] != '\n')
223             text=text+'\n';
224           bool ret = _subInlineNode->setScript(text);
225           if (ret) scriptEdited = false;
226         }
227 #endif
228     }
229
230   bool containerEdited = true;
231   if (formcontainer->onApply()) {
232     fillContainerPanel();
233     containerEdited = false;
234   } else {
235     Message mess(GuiContext::getCurrent()->_lastErrorMessage);
236     return;
237   }
238
239   _isEdited = _isEdited || scriptEdited || containerEdited;
240
241   EditionElementaryNode::onApply();
242 }
243
244 void EditionScript::onCancel()
245 {
246   if (_haveScript)
247     _sci->setText(_subInlineNode->getScript().c_str());
248   formcontainer->onCancel();
249   EditionElementaryNode::onCancel();
250 }
251
252 void EditionScript::onScriptModified()
253 {
254   DEBTRACE("EditionScript::onScriptModified");
255   _isEdited = true;
256   setEdited(true);
257 }
258
259 void EditionScript::onEdit()
260 {
261   DEBTRACE("EditionScript::onEdit");
262   QTemporaryFile outFile;
263   if (!outFile.open())
264     return;
265   QString fileName = outFile.fileName();
266   QTextStream out(&outFile);
267 #if HAS_QSCI4>0
268   out << _sci->text();
269 #else
270   out << _sci->toPlainText();
271 #endif
272   outFile.close();
273
274   QStringList options=Resource::pythonExternalEditor.split(" ");
275   QString prog=options.takeAt(0);
276   QProcess::execute(prog, QStringList() << options << fileName);
277
278   QFile inFile(fileName);
279   if (!inFile.open(QIODevice::ReadOnly))
280     return;
281   QTextStream in(&inFile);
282 #if HAS_QSCI4>0
283   _sci->setText(in.readAll());
284 #else
285   _sci->setPlainText(in.readAll());
286 #endif
287   onApply();
288 }
289
290 void EditionScript::fillContainerPanel()
291 {
292   DEBTRACE("EditionScript::fillContainerPanel ");
293   YACS::ENGINE::Proc* proc = GuiContext::getCurrent()->getProc();
294
295   cb_container->clear();
296   std::map<string,YACS::ENGINE::Container*>::const_iterator it = proc->containerMap.begin();
297   for(; it != proc->containerMap.end(); ++it)
298     cb_container->addItem( QString((*it).first.c_str()));
299
300   YACS::ENGINE::InlineNode *pyNode = dynamic_cast<YACS::ENGINE::InlineNode*>(_subInlineNode->getNode());
301
302   YACS::ENGINE::Container * cont = pyNode->getContainer();
303   if (cont)
304     {
305       int index = cb_container->findText(cont->getName().c_str());
306       cb_container->setCurrentIndex(index);
307       formcontainer->FillPanel(cont);
308     }
309 }
310
311 void EditionScript::changeContainer(int index)
312 {
313   DEBTRACE("EditionScript::changeContainer ");
314   string contName = cb_container->itemText(index).toStdString();
315   DEBTRACE(contName);
316   YACS::ENGINE::InlineNode *pyNode = dynamic_cast<YACS::ENGINE::InlineNode*>(_subInlineNode->getNode());
317   YACS::ENGINE::Container *oldContainer = pyNode->getContainer();
318
319   YACS::ENGINE::Container *newContainer = 0;
320   YACS::ENGINE::Proc* proc = GuiContext::getCurrent()->getProc();
321   if (proc->containerMap.count(contName))
322     newContainer = proc->containerMap[contName];
323   if (!newContainer)
324     {
325       DEBTRACE("-------------> not found : " << contName);
326       return;
327     }
328   YASSERT(GuiContext::getCurrent()->_mapOfSubjectContainer.count(newContainer));
329   SubjectContainer *scnt = GuiContext::getCurrent()->_mapOfSubjectContainer[newContainer];
330
331   _subInlineNode->setContainer(scnt);
332   
333   // show the selected container parameters
334   formcontainer->FillPanel(newContainer);
335 }
336
337 void EditionScript::update(GuiEvent event, int type, Subject* son)
338 {
339   DEBTRACE("EditionScript::update " << eventName(event) <<" "<<type<<" "<<son);
340   EditionElementaryNode::update(event, type, son);
341   if(event == ASSOCIATE)
342     {
343       fillContainerPanel();
344       SubjectContainer *scont = dynamic_cast<SubjectContainer*>(son);
345       YASSERT(scont);
346       formcontainer->FillPanel(scont->getContainer());
347     }
348   else if(event == UPDATE)
349     {
350       fillContainerPanel();
351     }
352 }
353