1 /**
2 * UGENE - Integrated Bioinformatics Tools.
3 * Copyright (C) 2008-2021 UniPro <ugene@unipro.ru>
4 * http://ugene.net
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 * MA 02110-1301, USA.
20 */
21
22 #include "CreateScriptWorker.h"
23
24 #include <QAbstractItemModel>
25 #include <QFileDialog>
26 #include <QHeaderView>
27 #include <QMessageBox>
28 #include <QPushButton>
29 #include <QTableView>
30
31 #include <U2Core/Log.h>
32
33 #include <U2Gui/HelpButton.h>
34
35 #include <U2Lang/ActorPrototypeRegistry.h>
36 #include <U2Lang/BaseSlots.h>
37 #include <U2Lang/BaseTypes.h>
38 #include <U2Lang/WorkflowSettings.h>
39
40 #include "WorkflowEditorDelegates.h"
41 #include "library/ScriptWorker.h"
42 #include "util/WorkerNameValidator.h"
43
44 namespace U2 {
45
46 #define WORKFLOW_DOC "GB2WORKFLOW"
47 #define ACTOR_ELEMENT "Actor"
48 #define INPUT_PORT_ELEMENT "Input-port"
49 #define OUTPUT_PORT_ELEMENT "Output-port"
50 #define ATTRIBUTE_ELEMENT "Attributes"
51 #define IN_SLOT_ELEMENT "In-Slots"
52 #define OUT_SLOT_ELEMENT "Out-Slots"
53 #define SLOT_ID "Slot"
54 #define ATTR_ELEMENT "Attribute"
55 #define NAME_ID "Name"
56 #define TYPE_ID "Type"
57 #define NAME_ELEMENT "Element-name"
58 #define DESCR_ELEMENT "Element-description"
59 #define DESCR_ID "Description"
60
61 // Q_DECLARE_METATYPE(DataTypePtr);
62
63 class MapForTypesDelegate {
64 public:
MapForTypesDelegate()65 MapForTypesDelegate() {
66 }
67
getAttrTypes()68 static QVariantMap getAttrTypes() {
69 QVariantMap res;
70 DataTypePtr ptr = BaseTypes::BOOL_TYPE();
71 res[ptr->getDisplayName()] = BaseTypes::BOOL_TYPE()->getId();
72
73 ptr = BaseTypes::NUM_TYPE();
74 res[ptr->getDisplayName()] = BaseTypes::NUM_TYPE()->getId();
75
76 ptr = BaseTypes::STRING_TYPE();
77 res[ptr->getDisplayName()] = BaseTypes::STRING_TYPE()->getId();
78
79 return res;
80 }
81
getPortTypes()82 static QVariantMap getPortTypes() {
83 QVariantMap res;
84 DataTypePtr ptr = BaseTypes::DNA_SEQUENCE_TYPE();
85 res[ptr->getDisplayName()] = BaseTypes::DNA_SEQUENCE_TYPE()->getId();
86
87 ptr = BaseTypes::ANNOTATION_TABLE_TYPE();
88 res[ptr->getDisplayName()] = BaseTypes::ANNOTATION_TABLE_TYPE()->getId();
89
90 ptr = BaseTypes::MULTIPLE_ALIGNMENT_TYPE();
91 res[ptr->getDisplayName()] = BaseTypes::MULTIPLE_ALIGNMENT_TYPE()->getId();
92
93 ptr = BaseTypes::STRING_TYPE();
94 res[ptr->getDisplayName()] = BaseTypes::STRING_TYPE()->getId();
95 /*Descriptor ptr = BaseSlots::DNA_SEQUENCE_SLOT();
96 res[ptr.getDisplayName()] = BaseSlots::DNA_SEQUENCE_SLOT().getId();
97
98 ptr = BaseSlots::ANNOTATION_TABLE_SLOT();
99 res[ptr.getDisplayName()] = BaseSlots::ANNOTATION_TABLE_SLOT().getId();
100
101 ptr = BaseSlots::MULTIPLE_ALIGNMENT_SLOT();
102 res[ptr.getDisplayName()] = BaseSlots::MULTIPLE_ALIGNMENT_SLOT().getId();
103
104 ptr = BaseSlots::TEXT_SLOT();
105 res[ptr.getDisplayName()] = BaseSlots::TEXT_SLOT().getId();*/
106 return res;
107 }
108
109 static QVariantMap portMap;
110 static QVariantMap attrMap;
111 };
112
113 QVariantMap MapForTypesDelegate::attrMap = MapForTypesDelegate::getAttrTypes();
114 QVariantMap MapForTypesDelegate::portMap = MapForTypesDelegate::getPortTypes();
115
116 enum DelegateType {
117 DelegateForPort,
118 DelegateForAttribute
119 };
120
121 class CfgListItem {
122 Q_DISABLE_COPY(CfgListItem)
123 public:
CfgListItem(DelegateType t)124 CfgListItem(DelegateType t) {
125 if (t == DelegateForPort) {
126 delegate = new ComboBoxDelegate(MapForTypesDelegate::portMap);
127 dataTypeId = BaseTypes::DNA_SEQUENCE_TYPE()->getId();
128 } else if (t == DelegateForAttribute) {
129 delegate = new ComboBoxDelegate(MapForTypesDelegate::attrMap);
130 dataTypeId = BaseTypes::STRING_TYPE()->getId();
131 } else {
132 assert(0);
133 }
134 }
~CfgListItem()135 ~CfgListItem() {
136 delete delegate;
137 }
getDelegate() const138 PropertyDelegate *getDelegate() const {
139 return delegate;
140 }
getDataType() const141 QString getDataType() const {
142 return dataTypeId;
143 }
setDataType(const QString & id)144 void setDataType(const QString &id) {
145 dataTypeId = id;
146 }
147
getName() const148 QString getName() const {
149 return name;
150 }
setName(const QString & _name)151 void setName(const QString &_name) {
152 name = _name;
153 }
154
155 private:
156 PropertyDelegate *delegate;
157 QString dataTypeId;
158 QString name;
159 // DataTypePtr dataType;
160 };
161
162 class CfgListModel : public QAbstractListModel {
163 public:
164 // Hint for row height. We use non-default row to make combo-boxes fit.
165 int itemHeight;
CfgListModel(int rowHeightHint,QObject * obj=nullptr)166 CfgListModel(int rowHeightHint, QObject *obj = nullptr)
167 : QAbstractListModel(obj), itemHeight(rowHeightHint) {
168 items.append(new CfgListItem(DelegateForPort));
169 }
170
~CfgListModel()171 ~CfgListModel() {
172 foreach (CfgListItem *item, items) {
173 delete item;
174 }
175 }
176
getItems() const177 QStringList getItems() const {
178 QStringList result;
179 foreach (CfgListItem *item, items) {
180 result.append(item->getDataType());
181 }
182 return result;
183 }
184
rowCount(const QModelIndex & parent=QModelIndex ()) const185 int rowCount(const QModelIndex &parent = QModelIndex()) const {
186 Q_UNUSED(parent);
187 return items.count();
188 }
189
flags(const QModelIndex &) const190 Qt::ItemFlags flags(const QModelIndex &) const {
191 return Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsSelectable;
192 }
193
getItem(const QModelIndex & index) const194 CfgListItem *getItem(const QModelIndex &index) const {
195 // CfgListItem *item = static_cast<CfgListItem*>(index.internalPointer());
196 return items.at(index.row());
197 }
198
parent(const QModelIndex &) const199 QModelIndex parent(const QModelIndex &) const {
200 return QModelIndex();
201 }
202
data(const QModelIndex & index,int role) const203 QVariant data(const QModelIndex &index, int role /* = Qt::DisplayRole */) const {
204 CfgListItem *item = getItem(index);
205 PropertyDelegate *dg = item->getDelegate();
206 switch (role) {
207 case Qt::DisplayRole:
208 case Qt::ToolTipRole:
209 return dg->getDisplayValue(item->getDataType());
210 case DelegateRole:
211 return qVariantFromValue<PropertyDelegate *>(dg);
212 case Qt::EditRole:
213 case ConfigurationEditor::ItemValueRole:
214 return item->getDataType();
215 case Qt::SizeHintRole:
216 return QSize(0, itemHeight);
217 default:
218 return QVariant();
219 }
220 }
221
setData(const QModelIndex & index,const QVariant & value,int role)222 bool setData(const QModelIndex &index, const QVariant &value, int role /* = Qt::EditRole */) {
223 switch (role) {
224 case Qt::EditRole:
225 case ConfigurationEditor::ItemValueRole:
226 CfgListItem *item = getItem(index);
227 if (item->getDataType() != value.toString()) {
228 if (!value.toString().isEmpty()) {
229 item->setDataType(value.toString());
230 }
231 }
232 emit dataChanged(index, index);
233 }
234 return true;
235 }
236
insertRows(int row,int count=0,const QModelIndex & parent=QModelIndex ())237 bool insertRows(int row, int count = 0, const QModelIndex &parent = QModelIndex()) {
238 Q_UNUSED(row);
239 beginInsertRows(parent, items.size(), items.size() + count);
240 for (int i = 0; i < count; i++) {
241 items.append(new CfgListItem(DelegateForPort));
242 }
243 endInsertRows();
244 return true;
245 }
246
removeRows(int row,int count,const QModelIndex & parent)247 bool removeRows(int row, int count, const QModelIndex &parent /* = QModelIndex */) {
248 Q_UNUSED(count);
249 if (rowCount() == 0 || row < 0 || row > rowCount()) {
250 return false;
251 }
252
253 beginRemoveRows(parent, row, row);
254 items.removeAt(row);
255 endRemoveRows();
256 return true;
257 }
258
259 private:
260 QList<CfgListItem *> items;
261 };
262
263 class CfgTableModel : public QAbstractTableModel {
264 public:
CfgTableModel(QObject * obj=nullptr)265 CfgTableModel(QObject *obj = nullptr)
266 : QAbstractTableModel(obj) {
267 // attrs.append(new CfgListItem());
268 }
269
rowCount(const QModelIndex &) const270 int rowCount(const QModelIndex & /* = QModelIndex */) const {
271 return attrs.size();
272 }
273
columnCount(const QModelIndex &) const274 int columnCount(const QModelIndex & /* = QModelIndex */) const {
275 return 2;
276 }
277
flags(const QModelIndex &) const278 Qt::ItemFlags flags(const QModelIndex &) const {
279 return Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsSelectable;
280 }
281
getItem(const QModelIndex & index) const282 CfgListItem *getItem(const QModelIndex &index) const {
283 // CfgListItem *item = static_cast<CfgListItem*>(index.internalPointer());
284 return attrs.at(index.row());
285 }
286
getItems() const287 QList<CfgListItem *> getItems() const {
288 return attrs;
289 }
290
data(const QModelIndex & index,int role) const291 QVariant data(const QModelIndex &index, int role /* = Qt::DisplayRole */) const {
292 CfgListItem *item = getItem(index);
293 int col = index.column();
294 PropertyDelegate *dg = item->getDelegate();
295
296 switch (role) {
297 case Qt::DisplayRole:
298 if (col == 0)
299 return item->getName();
300 else
301 return dg->getDisplayValue(item->getDataType());
302 case DelegateRole:
303 if (col == 1)
304 return qVariantFromValue<PropertyDelegate *>(dg);
305 else
306 return QVariant();
307 case Qt::EditRole:
308 case ConfigurationEditor::ItemValueRole:
309 if (col == 1)
310 return item->getDataType();
311 else
312 return item->getName();
313 default:
314 return QVariant();
315 }
316 }
317
headerData(int section,Qt::Orientation orientation,int role=Qt::DisplayRole) const318 QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const {
319 if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
320 switch (section) {
321 case 0:
322 return CreateScriptElementDialog::tr("Name");
323 case 1:
324 return CreateScriptElementDialog::tr("Type");
325 default:
326 return QVariant();
327 }
328 }
329 return QVariant();
330 }
331
setData(const QModelIndex & index,const QVariant & value,int role)332 bool setData(const QModelIndex &index, const QVariant &value, int role) {
333 int col = index.column();
334 CfgListItem *item = getItem(index);
335 switch (role) {
336 case Qt::EditRole:
337 case ConfigurationEditor::ItemValueRole:
338 if (col == 1) {
339 if (item->getDataType() != value.toString()) {
340 if (!value.toString().isEmpty()) {
341 item->setDataType(value.toString());
342 }
343 }
344 } else {
345 if (item->getName() != value.toString()) {
346 item->setName(value.toString());
347 }
348 }
349 emit dataChanged(index, index);
350 }
351 return true;
352 }
353
insertRows(int row,int count=0,const QModelIndex & parent=QModelIndex ())354 bool insertRows(int row, int count = 0, const QModelIndex &parent = QModelIndex()) {
355 Q_UNUSED(row);
356 Q_UNUSED(count);
357 beginInsertRows(parent, attrs.size(), attrs.size());
358 attrs.append(new CfgListItem(DelegateForAttribute));
359 endInsertRows();
360 return true;
361 }
362
removeRows(int row,int count=0,const QModelIndex & parent=QModelIndex ())363 bool removeRows(int row, int count = 0, const QModelIndex &parent = QModelIndex()) {
364 Q_UNUSED(count);
365 if (row >= 0 && row < attrs.size()) {
366 beginRemoveRows(parent, row, row);
367 attrs.removeAt(row);
368 endRemoveRows();
369 return true;
370 } else {
371 return false;
372 }
373 }
374
375 private:
376 QList<CfgListItem *> attrs;
377 };
378
CreateScriptElementDialog(QWidget * p,ActorPrototype * proto)379 CreateScriptElementDialog::CreateScriptElementDialog(QWidget *p, ActorPrototype *proto)
380 : QDialog(p), editing(false) {
381 setupUi(this);
382 new HelpButton(this, buttonBox, "65929977");
383 buttonBox->button(QDialogButtonBox::Ok)->setText(tr("OK"));
384 buttonBox->button(QDialogButtonBox::Cancel)->setText(tr("Cancel"));
385
386 // make list rows have the same size as buttons -> this must be enought to fit combo-boxes
387 int comboboxHeightHint = addInputButton->sizeHint().height();
388 inputList->setModel(new CfgListModel(comboboxHeightHint, this));
389 inputList->setItemDelegate(new ProxyDelegate());
390 outputList->setModel(new CfgListModel(comboboxHeightHint, this));
391 outputList->setItemDelegate(new ProxyDelegate());
392
393 attributeTable->setModel(new CfgTableModel());
394 attributeTable->setItemDelegate(new ProxyDelegate());
395
396 errorBox->hide();
397
398 connect(addInputButton, SIGNAL(clicked()), SLOT(sl_addInputClicked()));
399 connect(addOutputButton, SIGNAL(clicked()), SLOT(sl_addOutputClicked()));
400 connect(addAttributeButton, SIGNAL(clicked()), SLOT(sl_addAttribute()));
401
402 connect(deleteInputButton, SIGNAL(clicked()), SLOT(sl_deleteInputClicked()));
403 connect(deleteOutputButton, SIGNAL(clicked()), SLOT(sl_deleteOutputClicked()));
404 connect(deleteAttributeButton, SIGNAL(clicked()), SLOT(sl_deleteAttributeClicked()));
405
406 QPushButton *okButton = buttonBox->button(QDialogButtonBox::Ok);
407 QPushButton *cancelButton = buttonBox->button(QDialogButtonBox::Cancel);
408 connect(fileButton, SIGNAL(clicked()), SLOT(sl_getDirectory()));
409 connect(okButton, SIGNAL(clicked()), SLOT(sl_okClicked()));
410 connect(cancelButton, SIGNAL(clicked()), SLOT(sl_cancelClicked()));
411
412 attributeTable->horizontalHeader()->setStretchLastSection(true);
413 attributeTable->verticalHeader()->hide();
414
415 nameEdit->setValidator(new DeprecatedWorkerNameValidator(this));
416
417 if (proto) {
418 fillFields(proto);
419 editing = true;
420 }
421 }
422
getDatatypeOfSlotDesc(const Descriptor & dt)423 static DataTypePtr getDatatypeOfSlotDesc(const Descriptor &dt) {
424 QString dtId = dt.getId();
425 if (dtId == BaseSlots::DNA_SEQUENCE_SLOT().getId()) {
426 return BaseTypes::DNA_SEQUENCE_TYPE();
427 }
428 if (dtId == BaseSlots::ANNOTATION_TABLE_SLOT().getId()) {
429 return BaseTypes::ANNOTATION_TABLE_TYPE();
430 }
431 if (dtId == BaseSlots::MULTIPLE_ALIGNMENT_SLOT().getId()) {
432 return BaseTypes::MULTIPLE_ALIGNMENT_TYPE();
433 }
434 if (dtId == BaseSlots::TEXT_SLOT().getId()) {
435 return BaseTypes::STRING_TYPE();
436 }
437 assert(false);
438 return DataTypePtr();
439 }
440
fillFields(ActorPrototype * proto)441 void CreateScriptElementDialog::fillFields(ActorPrototype *proto) {
442 int inputInd = 0;
443 int outputInd = 0;
444 QList<PortDescriptor *> portDescriptors = proto->getPortDesciptors();
445 for (const PortDescriptor *desc : qAsConst(portDescriptors)) {
446 if (desc->isInput()) {
447 inputList->model()->insertRows(0, desc->getType()->getAllDescriptors().size() - 1, QModelIndex());
448 foreach (const Descriptor &d, desc->getType()->getAllDescriptors()) {
449 QModelIndex mi = inputList->model()->index(inputInd, 0);
450 inputList->model()->setData(mi, getDatatypeOfSlotDesc(d)->getId());
451 inputInd++;
452 }
453
454 } else {
455 outputList->model()->insertRows(0, desc->getType()->getAllDescriptors().size() - 1, QModelIndex());
456 foreach (const Descriptor &d, desc->getType()->getAllDescriptors()) {
457 QModelIndex mi = outputList->model()->index(outputInd, 0);
458 outputList->model()->setData(mi, getDatatypeOfSlotDesc(d)->getId());
459 outputInd++;
460 }
461 }
462 }
463
464 int ind = 0;
465 foreach (const Attribute *attr, proto->getAttributes()) {
466 attributeTable->model()->insertRow(1, QModelIndex());
467 QModelIndex mi1 = attributeTable->model()->index(ind, 0);
468 QModelIndex mi2 = attributeTable->model()->index(ind, 1);
469 attributeTable->model()->setData(mi1, attr->getId());
470 attributeTable->model()->setData(mi2, attr->getAttributeType()->getId());
471 ind++;
472 }
473
474 nameEdit->setText(proto->getDisplayName());
475 descriptionEdit->setText(proto->getDocumentation());
476 }
477
sl_getDirectory()478 void CreateScriptElementDialog::sl_getDirectory() {
479 QString url = WorkflowSettings::getUserDirectory();
480
481 QFileDialog dialog(this);
482 dialog.setFileMode(QFileDialog::Directory);
483 dialog.setViewMode(QFileDialog::List);
484 dialog.setDirectory(url);
485 if (dialog.exec() == QDialog::Accepted) {
486 QString dir = dialog.selectedFiles().first();
487 fileEdit->setText(dir);
488 }
489 }
490
sl_addInputClicked()491 void CreateScriptElementDialog::sl_addInputClicked() {
492 inputList->model()->insertRow(0, QModelIndex());
493 }
494
sl_addOutputClicked()495 void CreateScriptElementDialog::sl_addOutputClicked() {
496 outputList->model()->insertRow(0, QModelIndex());
497 }
498
sl_addAttribute()499 void CreateScriptElementDialog::sl_addAttribute() {
500 attributeTable->model()->insertRow(0, QModelIndex());
501 }
502
sl_deleteInputClicked()503 void CreateScriptElementDialog::sl_deleteInputClicked() {
504 QModelIndex index = inputList->currentIndex();
505 inputList->model()->removeRow(index.row());
506 }
507
sl_deleteOutputClicked()508 void CreateScriptElementDialog::sl_deleteOutputClicked() {
509 QModelIndex index = outputList->currentIndex();
510 outputList->model()->removeRow(index.row());
511 }
512
sl_deleteAttributeClicked()513 void CreateScriptElementDialog::sl_deleteAttributeClicked() {
514 QModelIndex index = attributeTable->currentIndex();
515 attributeTable->model()->removeRow(index.row());
516 }
517
sl_cancelClicked()518 void CreateScriptElementDialog::sl_cancelClicked() {
519 reject();
520 }
521
sl_okClicked()522 void CreateScriptElementDialog::sl_okClicked() {
523 CfgListModel *inputPorts = static_cast<CfgListModel *>(inputList->model());
524 QList<QString> typeIds = inputPorts->getItems();
525 DataTypeRegistry *dtr = WorkflowEnv::getDataTypeRegistry();
526 assert(dtr);
527 input.clear();
528 foreach (const QString &id, typeIds) {
529 DataTypePtr ptr = dtr->getById(id);
530 if (input.contains(ptr)) {
531 QMessageBox::critical(this, tr("error"), tr("Two identical types for input port"));
532 coreLog.error(tr("two identical types for input port"));
533 return;
534 }
535 input << ptr;
536 }
537
538 CfgListModel *outputPorts = static_cast<CfgListModel *>(outputList->model());
539 typeIds = outputPorts->getItems();
540 assert(dtr);
541 output.clear();
542 foreach (const QString &id, typeIds) {
543 DataTypePtr ptr = dtr->getById(id);
544 if (output.contains(ptr)) {
545 QMessageBox::critical(this, tr("error"), tr("Two identical types for output port"));
546 coreLog.error(tr("two identical types for output port"));
547 return;
548 }
549 output << ptr;
550 }
551
552 CfgTableModel *attrTableModel = static_cast<CfgTableModel *>(attributeTable->model());
553 QList<CfgListItem *> attributes = attrTableModel->getItems();
554 attrs.clear();
555 for (CfgListItem *item : qAsConst(attributes)) {
556 QString itemName = item->getName();
557 if (itemName.isEmpty()) {
558 QMessageBox::critical(this, tr("error"), tr("Name for some attributes is empty"));
559 coreLog.error(tr("Name for some attributes is empty"));
560 return;
561 }
562 for (const Attribute *attr : qAsConst(attrs)) {
563 if (attr->getId() == itemName) {
564 QMessageBox::critical(this, tr("error"), tr("Two attributes with name %1").arg(itemName));
565 coreLog.error(tr("Two attributes with name %1").arg(itemName));
566 return;
567 }
568 }
569
570 DataTypePtr ptr = dtr->getById(item->getDataType());
571 Descriptor desc(itemName, itemName, ptr->getDisplayName());
572 if (ptr == BaseTypes::BOOL_TYPE()) {
573 attrs << new Attribute(desc, ptr, false, QVariant(false));
574 } else {
575 attrs << new Attribute(desc, ptr);
576 }
577 }
578
579 name = nameEdit->text();
580 if (name.isEmpty()) {
581 QMessageBox::critical(this, tr("error"), tr("Name for block is empty"));
582 coreLog.error(tr("Name for block is empty"));
583 return;
584 }
585
586 ActorPrototypeRegistry *pr = WorkflowEnv::getProtoRegistry();
587 if (pr) {
588 if (pr->getProto(LocalWorkflow::ScriptWorkerFactory::ACTOR_ID + name) && !editing) {
589 QMessageBox::critical(this, tr("error"), tr("Actor with this name already registered"));
590 coreLog.error(tr("Actor with this name already registered"));
591 return;
592 }
593 }
594
595 description = descriptionEdit->toPlainText();
596 if (description.isEmpty()) {
597 QMessageBox::critical(this, tr("error"), tr("Description for block is empty"));
598 coreLog.error(tr("Description for block is empty"));
599 return;
600 }
601
602 if (!fileEdit->text().isEmpty()) {
603 changeDirectoryForActors();
604 }
605
606 if (!saveParams()) {
607 errorBox->show();
608 return;
609 }
610
611 accept();
612 }
613
changeDirectoryForActors()614 void CreateScriptElementDialog::changeDirectoryForActors() {
615 QString url = WorkflowSettings::getUserDirectory();
616 QString newUrl = fileEdit->text() + "/";
617
618 if (url != newUrl) {
619 WorkflowSettings::setUserDirectory(newUrl);
620
621 QDir dir(url);
622 if (!dir.exists()) {
623 // coreLog.info(tr("There isn't folder with users workflow elements"));
624 return;
625 }
626 dir.setNameFilters(QStringList() << "*.usa");
627 QFileInfoList fileList = dir.entryInfoList();
628 foreach (const QFileInfo &fileInfo, fileList) {
629 QString newFileUrl = newUrl + fileInfo.fileName();
630 QFile::copy(fileInfo.filePath(), newFileUrl);
631 }
632 }
633 }
634
saveParams()635 bool CreateScriptElementDialog::saveParams() {
636 QDomDocument doc = saveXml();
637 QString url = WorkflowSettings::getUserDirectory();
638 QDir dir(url);
639 if (!dir.exists()) {
640 dir.mkpath(url);
641 }
642
643 IOAdapterFactory *iof = AppContext::getIOAdapterRegistry()->getIOAdapterFactoryById(BaseIOAdapters::LOCAL_FILE);
644 IOAdapter *io = iof->createIOAdapter();
645 actorFilePath = url + name + ".usa";
646 if (io->open(actorFilePath, IOAdapterMode_Write)) {
647 io->writeBlock(doc.toByteArray());
648 io->close();
649 return true;
650 } else {
651 coreLog.error(tr("Can't save user's workflow element"));
652 return false;
653 }
654 }
655
saveXml()656 QDomDocument CreateScriptElementDialog::saveXml() {
657 QDomDocument xml(WORKFLOW_DOC);
658 QDomElement actor = xml.createElement(ACTOR_ELEMENT);
659 xml.appendChild(actor);
660
661 CfgListModel *inputPorts = static_cast<CfgListModel *>(inputList->model());
662 QList<QString> typeIds = inputPorts->getItems();
663 QDomElement inputPort = xml.createElement(INPUT_PORT_ELEMENT);
664 actor.appendChild(inputPort);
665 foreach (const QString &str, typeIds) {
666 QDomElement slot = xml.createElement(IN_SLOT_ELEMENT);
667 slot.setAttribute(SLOT_ID, str);
668 inputPort.appendChild(slot);
669 }
670
671 CfgListModel *outputPorts = static_cast<CfgListModel *>(outputList->model());
672 typeIds = outputPorts->getItems();
673 QDomElement outputPort = xml.createElement(OUTPUT_PORT_ELEMENT);
674 actor.appendChild(outputPort);
675 foreach (const QString &str, typeIds) {
676 QDomElement slot = xml.createElement(OUT_SLOT_ELEMENT);
677 slot.setAttribute(SLOT_ID, str);
678 outputPort.appendChild(slot);
679 }
680
681 CfgTableModel *attrTableModel = static_cast<CfgTableModel *>(attributeTable->model());
682 QList<CfgListItem *> attributes = attrTableModel->getItems();
683 QDomElement attribute = xml.createElement(ATTRIBUTE_ELEMENT);
684 actor.appendChild(attribute);
685 foreach (CfgListItem *item, attributes) {
686 QString itemName = item->getName();
687 QString itemId = item->getDataType();
688 QDomElement attr = xml.createElement(ATTR_ELEMENT);
689 attr.setAttribute(NAME_ID, itemName);
690 attr.setAttribute(TYPE_ID, itemId);
691 attribute.appendChild(attr);
692 }
693
694 QDomElement nameEl = xml.createElement(NAME_ELEMENT);
695 nameEl.setAttribute(NAME_ID, name);
696 actor.appendChild(nameEl);
697
698 QDomElement descriptionEl = xml.createElement(DESCR_ELEMENT);
699 descriptionEl.setAttribute(DESCR_ID, description);
700 actor.appendChild(descriptionEl);
701
702 return xml;
703 }
704
getInput() const705 QList<DataTypePtr> CreateScriptElementDialog::getInput() const {
706 return input;
707 }
getOutput() const708 QList<DataTypePtr> CreateScriptElementDialog::getOutput() const {
709 return output;
710 }
getAttributes() const711 QList<Attribute *> CreateScriptElementDialog::getAttributes() const {
712 return attrs;
713 }
getName() const714 const QString CreateScriptElementDialog::getName() const {
715 return name;
716 }
717
getDescription() const718 const QString CreateScriptElementDialog::getDescription() const {
719 return description;
720 }
721
getActorFilePath() const722 const QString CreateScriptElementDialog::getActorFilePath() const {
723 return actorFilePath;
724 }
725
726 } // namespace U2
727