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 "CfgExternalToolModel.h"
23 
24 #include <U2Core/AppContext.h>
25 #include <U2Core/BaseDocumentFormats.h>
26 #include <U2Core/DocumentModel.h>
27 
28 #include <U2Designer/DelegateEditors.h>
29 
30 #include <U2Lang/BaseTypes.h>
31 #include <U2Lang/WorkflowEnv.h>
32 #include <U2Lang/WorkflowUtils.h>
33 
34 #include "../WorkflowEditorDelegates.h"
35 
36 namespace U2 {
37 
38 //////////////////////////////////////////////////////////////////////////
39 /// CfgExternalToolModel
40 //////////////////////////////////////////////////////////////////////////
41 
CfgExternalToolItem()42 CfgExternalToolItem::CfgExternalToolItem() {
43     dfr = AppContext::getDocumentFormatRegistry();
44     dtr = Workflow::WorkflowEnv::getDataTypeRegistry();
45 
46     delegateForNames = nullptr;
47     delegateForIds = nullptr;
48     delegateForTypes = nullptr;
49     delegateForFormats = nullptr;
50     itemData.type = BaseTypes::DNA_SEQUENCE_TYPE()->getId();
51     itemData.format = BaseDocumentFormats::FASTA;
52 }
53 
~CfgExternalToolItem()54 CfgExternalToolItem::~CfgExternalToolItem() {
55     delete delegateForNames;
56     delete delegateForIds;
57     delete delegateForTypes;
58     delete delegateForFormats;
59 }
60 
getDataType() const61 const QString &CfgExternalToolItem::getDataType() const {
62     return itemData.type;
63 }
64 
setDataType(const QString & id)65 void CfgExternalToolItem::setDataType(const QString &id) {
66     itemData.type = id;
67 }
68 
getId() const69 const QString &CfgExternalToolItem::getId() const {
70     return itemData.attributeId;
71 }
72 
setId(const QString & _id)73 void CfgExternalToolItem::setId(const QString &_id) {
74     itemData.attributeId = _id;
75 }
76 
getName() const77 const QString &CfgExternalToolItem::getName() const {
78     return itemData.attrName;
79 }
80 
setName(const QString & _name)81 void CfgExternalToolItem::setName(const QString &_name) {
82     itemData.attrName = _name;
83 }
84 
getFormat() const85 const QString &CfgExternalToolItem::getFormat() const {
86     return itemData.format;
87 }
88 
setFormat(const QString & f)89 void CfgExternalToolItem::setFormat(const QString &f) {
90     itemData.format = f;
91 }
92 
getDescription() const93 const QString &CfgExternalToolItem::getDescription() const {
94     return itemData.description;
95 }
96 
setDescription(const QString & _descr)97 void CfgExternalToolItem::setDescription(const QString &_descr) {
98     itemData.description = _descr;
99 }
100 
101 //////////////////////////////////////////////////////////////////////////
102 /// CfgExternalToolModel
103 //////////////////////////////////////////////////////////////////////////
104 
CfgExternalToolModel(CfgExternalToolModel::ModelType _modelType,QObject * _obj)105 CfgExternalToolModel::CfgExternalToolModel(CfgExternalToolModel::ModelType _modelType, QObject *_obj)
106     : QAbstractTableModel(_obj),
107       isInput(Input == _modelType) {
108     init();
109 }
110 
rowCount(const QModelIndex &) const111 int CfgExternalToolModel::rowCount(const QModelIndex & /*index*/) const {
112     return items.size();
113 }
114 
columnCount(const QModelIndex &) const115 int CfgExternalToolModel::columnCount(const QModelIndex & /*index*/) const {
116     return COLUMNS_COUNT;
117 }
118 
flags(const QModelIndex &) const119 Qt::ItemFlags CfgExternalToolModel::flags(const QModelIndex & /*index*/) const {
120     return Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsSelectable;
121 }
122 
getItem(const QModelIndex & index) const123 CfgExternalToolItem *CfgExternalToolModel::getItem(const QModelIndex &index) const {
124     return items.at(index.row());
125 }
126 
getItems() const127 QList<CfgExternalToolItem *> CfgExternalToolModel::getItems() const {
128     return items;
129 }
130 
data(const QModelIndex & index,int role) const131 QVariant CfgExternalToolModel::data(const QModelIndex &index, int role) const {
132     CfgExternalToolItem *item = getItem(index);
133     int col = index.column();
134 
135     switch (role) {
136         case Qt::DisplayRole:  // fallthrough
137         case Qt::ToolTipRole:
138             switch (col) {
139                 case COLUMN_NAME:
140                     return item->getName();
141                 case COLUMN_ID:
142                     return item->getId();
143                 case COLUMN_DATA_TYPE:
144                     return item->delegateForTypes->getDisplayValue(item->getDataType());
145                 case COLUMN_FORMAT:
146                     return item->delegateForFormats->getDisplayValue(item->getFormat());
147                 case COLUMN_DESCRIPTION:
148                     return item->getDescription();
149                 default:
150                     // do nothing, inaccessible code
151                     Q_ASSERT(false);
152                     return QVariant();
153             }
154         case DelegateRole:
155             switch (col) {
156                 case COLUMN_NAME:
157                     return qVariantFromValue<PropertyDelegate *>(item->delegateForNames);
158                 case COLUMN_ID:
159                     return qVariantFromValue<PropertyDelegate *>(item->delegateForIds);
160                 case COLUMN_DATA_TYPE:
161                     return qVariantFromValue<PropertyDelegate *>(item->delegateForTypes);
162                 case COLUMN_FORMAT:
163                     return qVariantFromValue<PropertyDelegate *>(item->delegateForFormats);
164                 default:
165                     return QVariant();
166             }
167         case Qt::EditRole:  // fallthrough
168         case ConfigurationEditor::ItemValueRole:
169             switch (col) {
170                 case COLUMN_NAME:
171                     return item->getName();
172                 case COLUMN_ID:
173                     return item->getId();
174                 case COLUMN_DATA_TYPE:
175                     return item->getDataType();
176                 case COLUMN_FORMAT:
177                     return item->getFormat();
178                 case COLUMN_DESCRIPTION:
179                     return item->getDescription();
180                 default:
181                     // do nothing, inaccessible code
182                     Q_ASSERT(false);
183                     return QVariant();
184             }
185         default:
186             return QVariant();
187     }
188 }
189 
createFormatDelegate(const QString & newType,CfgExternalToolItem * item)190 void CfgExternalToolModel::createFormatDelegate(const QString &newType, CfgExternalToolItem *item) {
191     PropertyDelegate *delegate;
192     QString format;
193     if (newType == BaseTypes::DNA_SEQUENCE_TYPE()->getId()) {
194         delegate = new ComboBoxDelegate(seqFormatsW);
195         format = seqFormatsW.values().first().toString();
196     } else if (newType == BaseTypes::MULTIPLE_ALIGNMENT_TYPE()->getId()) {
197         delegate = new ComboBoxDelegate(msaFormatsW);
198         format = msaFormatsW.values().first().toString();
199     } else if (newType == BaseTypes::ANNOTATION_TABLE_TYPE()->getId()) {
200         delegate = new ComboBoxDelegate(annFormatsW);
201         format = annFormatsW.values().first().toString();
202     } else if (newType == SEQ_WITH_ANNS) {
203         delegate = new ComboBoxDelegate(annSeqFormatsW);
204         format = annSeqFormatsW.values().first().toString();
205     } else if (newType == BaseTypes::STRING_TYPE()->getId()) {
206         delegate = new ComboBoxDelegate(textFormat);
207         format = textFormat.values().first().toString();
208     } else {
209         return;
210     }
211     item->setFormat(format);
212     item->delegateForFormats = delegate;
213 }
214 
setData(const QModelIndex & index,const QVariant & value,int role)215 bool CfgExternalToolModel::setData(const QModelIndex &index, const QVariant &value, int role) {
216     int col = index.column();
217     CfgExternalToolItem *item = getItem(index);
218     switch (role) {
219         case Qt::EditRole:  // fall through
220         case ConfigurationEditor::ItemValueRole:
221             switch (col) {
222                 case COLUMN_NAME:
223                     if (item->getName() != value.toString()) {
224                         const QString oldGeneratedId = WorkflowUtils::generateIdFromName(item->getName());
225                         const bool wasIdEditedByUser = (oldGeneratedId != item->getId());
226                         item->setName(value.toString());
227                         if (!wasIdEditedByUser) {
228                             item->setId(WorkflowUtils::generateIdFromName(item->getName()));
229                         }
230                     }
231                     break;
232                 case COLUMN_ID:
233                     if (item->getId() != value.toString()) {
234                         item->setId(value.toString());
235                     }
236                     break;
237                 case COLUMN_DATA_TYPE: {
238                     QString newType = value.toString();
239                     if (item->getDataType() != newType) {
240                         if (!newType.isEmpty()) {
241                             item->setDataType(newType);
242                             createFormatDelegate(newType, item);
243                         }
244                     }
245                     break;
246                 }
247                 case COLUMN_FORMAT:
248                     if (item->getFormat() != value.toString() && !value.toString().isEmpty()) {
249                         item->setFormat(value.toString());
250                     }
251                     break;
252                 case COLUMN_DESCRIPTION:
253                     if (item->getDescription() != value.toString()) {
254                         item->setDescription(value.toString());
255                     }
256                     break;
257                 default:
258                     // do nothing, inaccessible code
259                     Q_ASSERT(false);
260             }
261             emit dataChanged(index, index);
262             break;
263         default:;  // do nothing
264     }
265     return true;
266 }
267 
headerData(int section,Qt::Orientation orientation,int role) const268 QVariant CfgExternalToolModel::headerData(int section, Qt::Orientation orientation, int role) const {
269     if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
270         switch (section) {
271             case COLUMN_NAME:
272                 return tr("Display name");
273             case COLUMN_ID:
274                 return tr("Argument name");
275             case COLUMN_DATA_TYPE:
276                 return tr("Type");
277             case COLUMN_FORMAT:
278                 if (isInput) {
279                     return tr("Argument value");
280                 } else {
281                     return tr("Argument value");
282                 }
283             case COLUMN_DESCRIPTION:
284                 return tr("Description");
285             default:
286                 // do nothing, inaccessible code
287                 Q_ASSERT(false);
288                 return QVariant();
289         }
290     }
291     return QVariant();
292 }
293 
insertRows(int,int,const QModelIndex & parent)294 bool CfgExternalToolModel::insertRows(int /*row*/, int /*count*/, const QModelIndex &parent) {
295     beginInsertRows(parent, items.size(), items.size());
296     CfgExternalToolItem *newItem = new CfgExternalToolItem();
297     newItem->delegateForNames = new LineEditWithValidatorDelegate(WorkflowEntityValidator::ACCEPTABLE_NAME);
298     newItem->delegateForIds = new LineEditWithValidatorDelegate(WorkflowEntityValidator::ACCEPTABLE_ID);
299     newItem->delegateForTypes = new ComboBoxDelegate(types);
300     newItem->delegateForFormats = new ComboBoxDelegate(seqFormatsW);
301     items.append(newItem);
302     endInsertRows();
303     return true;
304 }
305 
removeRows(int row,int count,const QModelIndex & parent)306 bool CfgExternalToolModel::removeRows(int row, int count, const QModelIndex &parent) {
307     CHECK(0 <= row && row < items.size(), false);
308     CHECK(0 <= row + count - 1 && row + count - 1 < items.size(), false);
309     CHECK(0 < count, false);
310 
311     beginRemoveRows(parent, row, row + count - 1);
312     for (int i = row + count - 1; i >= row; --i) {
313         delete items.takeAt(i);
314     }
315     endRemoveRows();
316     return true;
317 }
318 
init()319 void CfgExternalToolModel::init() {
320     initTypes();
321     initFormats();
322 }
323 
initFormats()324 void CfgExternalToolModel::initFormats() {
325     QList<DocumentFormatId> ids = AppContext::getDocumentFormatRegistry()->getRegisteredFormats();
326 
327     DocumentFormatConstraints commonConstraints;
328     commonConstraints.addFlagToSupport(DocumentFormatFlag_SupportWriting);
329     commonConstraints.addFlagToExclude(DocumentFormatFlag_SingleObjectFormat);
330     commonConstraints.addFlagToExclude(DocumentFormatFlag_CannotBeCreated);
331 
332     DocumentFormatConstraints seqWrite(commonConstraints);
333     seqWrite.supportedObjectTypes += GObjectTypes::SEQUENCE;
334 
335     DocumentFormatConstraints seqRead(commonConstraints);
336     seqRead.supportedObjectTypes += GObjectTypes::SEQUENCE;
337 
338     DocumentFormatConstraints msaWrite(commonConstraints);
339     msaWrite.supportedObjectTypes += GObjectTypes::MULTIPLE_SEQUENCE_ALIGNMENT;
340 
341     DocumentFormatConstraints msaRead(commonConstraints);
342     msaRead.supportedObjectTypes += GObjectTypes::MULTIPLE_SEQUENCE_ALIGNMENT;
343 
344     DocumentFormatConstraints annWrite(commonConstraints);
345     annWrite.supportedObjectTypes += GObjectTypes::ANNOTATION_TABLE;
346 
347     DocumentFormatConstraints annRead(commonConstraints);
348     annRead.supportedObjectTypes += GObjectTypes::ANNOTATION_TABLE;
349 
350     DocumentFormatConstraints annSeqWrite(commonConstraints);
351     annSeqWrite.supportedObjectTypes += GObjectTypes::ANNOTATION_TABLE;
352     annSeqWrite.supportedObjectTypes += GObjectTypes::SEQUENCE;
353 
354     DocumentFormatConstraints annSeqRead(commonConstraints);
355     annSeqRead.supportedObjectTypes += GObjectTypes::ANNOTATION_TABLE;
356     annSeqRead.supportedObjectTypes += GObjectTypes::SEQUENCE;
357 
358     QString argumentValue(tr("URL to %1 file with data"));
359     foreach (const DocumentFormatId &id, ids) {
360         DocumentFormat *df = AppContext::getDocumentFormatRegistry()->getFormatById(id);
361 
362         QString formatNameKey = argumentValue.arg(df->getFormatName());
363         QString formatId = df->getFormatId();
364         if (df->checkConstraints(seqWrite)) {
365             seqFormatsW[formatNameKey] = formatId;
366         }
367 
368         if (df->checkConstraints(seqRead)) {
369             seqFormatsR[formatNameKey] = formatId;
370         }
371 
372         if (df->checkConstraints(msaWrite)) {
373             msaFormatsW[formatNameKey] = formatId;
374         }
375 
376         if (df->checkConstraints(msaRead)) {
377             msaFormatsR[formatNameKey] = formatId;
378         }
379 
380         if (df->checkConstraints(annWrite)) {
381             annFormatsW[formatNameKey] = formatId;
382         }
383 
384         if (df->checkConstraints(annRead)) {
385             annFormatsR[formatNameKey] = formatId;
386         }
387 
388         if (df->checkConstraints(annSeqWrite)) {
389             annSeqFormatsW[formatNameKey] = formatId;
390         }
391 
392         if (df->checkConstraints(annSeqRead)) {
393             annSeqFormatsR[formatNameKey] = formatId;
394         }
395     }
396 
397     DocumentFormat *df = AppContext::getDocumentFormatRegistry()->getFormatById(BaseDocumentFormats::PLAIN_TEXT);
398     if (isInput) {
399         textFormat[tr("String data value")] = DataConfig::STRING_VALUE;
400     } else {
401         textFormat[tr("Output URL")] = DataConfig::OUTPUT_FILE_URL;
402     }
403     textFormat[argumentValue.arg("TXT")] = df->getFormatId();
404 }
405 
initTypes()406 void CfgExternalToolModel::initTypes() {
407     DataTypePtr ptr = BaseTypes::DNA_SEQUENCE_TYPE();
408     types[ptr->getDisplayName()] = ptr->getId();
409 
410     ptr = BaseTypes::ANNOTATION_TABLE_TYPE();
411     types[tr("Annotations")] = ptr->getId();
412 
413     ptr = BaseTypes::MULTIPLE_ALIGNMENT_TYPE();
414     types[tr("Alignment")] = ptr->getId();
415 
416     ptr = BaseTypes::STRING_TYPE();
417     types[ptr->getDisplayName()] = ptr->getId();
418 
419     types[tr("Annotated sequence")] = SEQ_WITH_ANNS;
420 }
421 
422 //////////////////////////////////////////////////////////////////////////
423 /// AttributeItem
424 //////////////////////////////////////////////////////////////////////////
425 
AttributeItem()426 AttributeItem::AttributeItem()
427     : delegateForNames(nullptr),
428       delegateForIds(nullptr),
429       delegateForDefaultValues(nullptr) {
430 }
431 
~AttributeItem()432 AttributeItem::~AttributeItem() {
433     delete delegateForNames;
434     delete delegateForIds;
435     delete delegateForDefaultValues;
436 }
437 
getId() const438 const QString &AttributeItem::getId() const {
439     return id;
440 }
441 
setId(const QString & _id)442 void AttributeItem::setId(const QString &_id) {
443     id = _id;
444 }
445 
getName() const446 const QString &AttributeItem::getName() const {
447     return name;
448 }
449 
setName(const QString & _name)450 void AttributeItem::setName(const QString &_name) {
451     name = _name;
452 }
453 
getDataType() const454 const QString &AttributeItem::getDataType() const {
455     return type;
456 }
457 
setDataType(const QString & _type)458 void AttributeItem::setDataType(const QString &_type) {
459     type = _type;
460 }
461 
getDefaultValue() const462 const QVariant &AttributeItem::getDefaultValue() const {
463     return defaultValue;
464 }
465 
setDefaultValue(const QVariant & _defaultValue)466 void AttributeItem::setDefaultValue(const QVariant &_defaultValue) {
467     defaultValue = _defaultValue;
468 }
469 
getDescription() const470 const QString &AttributeItem::getDescription() const {
471     return description;
472 }
473 
setDescription(const QString & _description)474 void AttributeItem::setDescription(const QString &_description) {
475     description = _description;
476 }
477 
478 //////////////////////////////////////////////////////////////////////////
479 /// CfgExternalToolModelAttributes
480 //////////////////////////////////////////////////////////////////////////
481 
CfgExternalToolModelAttributes(SchemaConfig * _schemaConfig,QObject * _parent)482 CfgExternalToolModelAttributes::CfgExternalToolModelAttributes(SchemaConfig *_schemaConfig, QObject *_parent)
483     : QAbstractTableModel(_parent),
484       schemaConfig(_schemaConfig) {
485     types.append(QPair<QString, QVariant>(tr("Boolean"), AttributeConfig::BOOLEAN_TYPE));
486     types.append(QPair<QString, QVariant>(tr("Integer"), AttributeConfig::INTEGER_TYPE));
487     types.append(QPair<QString, QVariant>(tr("Double"), AttributeConfig::DOUBLE_TYPE));
488     types.append(QPair<QString, QVariant>(tr("String"), AttributeConfig::STRING_TYPE));
489     types.append(QPair<QString, QVariant>(tr("Input file URL"), AttributeConfig::INPUT_FILE_URL_TYPE));
490     types.append(QPair<QString, QVariant>(tr("Input folder URL"), AttributeConfig::INPUT_FOLDER_URL_TYPE));
491     types.append(QPair<QString, QVariant>(tr("Output file URL"), AttributeConfig::OUTPUT_FILE_URL_TYPE));
492     types.append(QPair<QString, QVariant>(tr("Output folder URL"), AttributeConfig::OUTPUT_FOLDER_URL_TYPE));
493     typesDelegate = new ComboBoxDelegate(types);
494 }
495 
~CfgExternalToolModelAttributes()496 CfgExternalToolModelAttributes::~CfgExternalToolModelAttributes() {
497     foreach (AttributeItem *item, items) {
498         delete item;
499     }
500 }
501 
changeDefaultValueDelegate(const QString & newType,AttributeItem * item)502 void CfgExternalToolModelAttributes::changeDefaultValueDelegate(const QString &newType, AttributeItem *item) {
503     PropertyDelegate *propDelegate = nullptr;
504     QVariant defaultValue;
505     if (newType == AttributeConfig::BOOLEAN_TYPE) {
506         propDelegate = new ComboBoxWithBoolsDelegate();
507         defaultValue = true;
508     } else if (newType == AttributeConfig::STRING_TYPE) {
509         propDelegate = new LineEditWithValidatorDelegate(QRegularExpression("([^\"]*)"));
510     } else if (newType == AttributeConfig::INTEGER_TYPE) {
511         QVariantMap integerValues;
512         integerValues["minimum"] = QVariant(std::numeric_limits<int>::min());
513         integerValues["maximum"] = QVariant(std::numeric_limits<int>::max());
514         propDelegate = new SpinBoxDelegate(integerValues);
515         defaultValue = QVariant(0);
516     } else if (newType == AttributeConfig::DOUBLE_TYPE) {
517         QVariantMap doubleValues;
518         doubleValues["singleStep"] = 0.1;
519         doubleValues["minimum"] = QVariant(std::numeric_limits<double>::lowest());
520         doubleValues["maximum"] = QVariant(std::numeric_limits<double>::max());
521         doubleValues["decimals"] = 6;
522         propDelegate = new DoubleSpinBoxDelegate(doubleValues);
523         defaultValue = QVariant(0.0);
524     } else if (newType == AttributeConfig::INPUT_FILE_URL_TYPE) {
525         propDelegate = new URLDelegate("", "", false, false, false, nullptr, "", false, true);
526     } else if (newType == AttributeConfig::OUTPUT_FILE_URL_TYPE) {
527         propDelegate = new URLDelegate("", "", false, false, true, nullptr, "", false, false);
528     } else if (newType == AttributeConfig::INPUT_FOLDER_URL_TYPE) {
529         propDelegate = new URLDelegate("", "", false, true, false, nullptr, "", false, true);
530     } else if (newType == AttributeConfig::OUTPUT_FOLDER_URL_TYPE) {
531         propDelegate = new URLDelegate("", "", false, true, true, nullptr, "", false, false);
532     } else {
533         return;
534     }
535 
536     propDelegate->setSchemaConfig(schemaConfig);
537     item->setDefaultValue(defaultValue);
538     delete item->delegateForDefaultValues;
539     item->delegateForDefaultValues = propDelegate;
540 }
541 
rowCount(const QModelIndex &) const542 int CfgExternalToolModelAttributes::rowCount(const QModelIndex & /*index*/) const {
543     return items.size();
544 }
545 
columnCount(const QModelIndex &) const546 int CfgExternalToolModelAttributes::columnCount(const QModelIndex & /*index*/) const {
547     return COLUMNS_COUNT;
548 }
549 
flags(const QModelIndex &) const550 Qt::ItemFlags CfgExternalToolModelAttributes::flags(const QModelIndex & /*index*/) const {
551     return Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsSelectable;
552 }
553 
getItem(const QModelIndex & index) const554 AttributeItem *CfgExternalToolModelAttributes::getItem(const QModelIndex &index) const {
555     return items.at(index.row());
556 }
557 
getItems() const558 QList<AttributeItem *> CfgExternalToolModelAttributes::getItems() const {
559     return items;
560 }
561 
data(const QModelIndex & index,int role) const562 QVariant CfgExternalToolModelAttributes::data(const QModelIndex &index, int role) const {
563     AttributeItem *item = getItem(index);
564     int col = index.column();
565 
566     switch (role) {
567         case Qt::DisplayRole:  // fallthrough
568         case Qt::ToolTipRole:
569             switch (col) {
570                 case COLUMN_NAME:
571                     return item->getName();
572                 case COLUMN_ID:
573                     return item->getId();
574                 case COLUMN_DATA_TYPE:
575                     return typesDelegate->getDisplayValue(item->getDataType());
576                 case COLUMN_DEFAULT_VALUE:
577                     return item->delegateForDefaultValues->getDisplayValue(item->getDefaultValue());
578                 case COLUMN_DESCRIPTION:
579                     return item->getDescription();
580                 default:
581                     // do nothing, inaccessible code
582                     Q_ASSERT(false);
583                     return QVariant();
584             }
585         case DelegateRole:
586             switch (col) {
587                 case COLUMN_NAME:
588                     return qVariantFromValue<PropertyDelegate *>(item->delegateForNames);
589                 case COLUMN_ID:
590                     return qVariantFromValue<PropertyDelegate *>(item->delegateForIds);
591                 case COLUMN_DATA_TYPE:
592                     return qVariantFromValue<PropertyDelegate *>(typesDelegate);
593                 case COLUMN_DEFAULT_VALUE:
594                     return qVariantFromValue<PropertyDelegate *>(item->delegateForDefaultValues);
595                 default:
596                     return QVariant();
597             }
598         case Qt::EditRole:  // fallthrough
599         case ConfigurationEditor::ItemValueRole:
600             switch (col) {
601                 case COLUMN_NAME:
602                     return item->getName();
603                 case COLUMN_ID:
604                     return item->getId();
605                 case COLUMN_DATA_TYPE:
606                     return item->getDataType();
607                 case COLUMN_DEFAULT_VALUE:
608                     return item->getDefaultValue();
609                 case COLUMN_DESCRIPTION:
610                     return item->getDescription();
611                 default:
612                     // do nothing, inaccessible code
613                     Q_ASSERT(false);
614                     return QVariant();
615             }
616         default:
617             return QVariant();
618     }
619 }
620 
setData(const QModelIndex & index,const QVariant & value,int role)621 bool CfgExternalToolModelAttributes::setData(const QModelIndex &index, const QVariant &value, int role) {
622     int col = index.column();
623     AttributeItem *item = getItem(index);
624     switch (role) {
625         case Qt::EditRole:  // fallthrough
626         case ConfigurationEditor::ItemValueRole:
627             switch (col) {
628                 case COLUMN_NAME:
629                     if (item->getName() != value.toString()) {
630                         const QString oldGeneratedId = WorkflowUtils::generateIdFromName(item->getName());
631                         const bool wasIdEditedByUser = (oldGeneratedId != item->getId());
632                         item->setName(value.toString());
633                         if (!wasIdEditedByUser) {
634                             item->setId(WorkflowUtils::generateIdFromName(item->getName()));
635                         }
636                     }
637                     break;
638                 case COLUMN_ID:
639                     if (item->getId() != value.toString()) {
640                         item->setId(value.toString());
641                     }
642                     break;
643                 case COLUMN_DATA_TYPE: {
644                     QString newType = value.toString();
645                     if (item->getDataType() != newType) {
646                         if (!newType.isEmpty()) {
647                             item->setDataType(newType);
648                             changeDefaultValueDelegate(newType, item);
649                         }
650                     }
651                     break;
652                 }
653                 case COLUMN_DEFAULT_VALUE: {
654                     if (item->getDefaultValue() != value.toString()) {
655                         item->setDefaultValue(value.toString());
656                     }
657                     break;
658                 }
659                 case COLUMN_DESCRIPTION:
660                     if (item->getDescription() != value.toString()) {
661                         item->setDescription(value.toString());
662                     }
663                     break;
664                 default:
665                     // do nothing, inaccessible code
666                     Q_ASSERT(false);
667             }
668 
669             emit dataChanged(index, index);
670             break;
671         default:;  // do nothing
672     }
673     return true;
674 }
675 
headerData(int section,Qt::Orientation orientation,int role) const676 QVariant CfgExternalToolModelAttributes::headerData(int section, Qt::Orientation orientation, int role) const {
677     if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
678         switch (section) {
679             case COLUMN_NAME:
680                 return tr("Display name");
681             case COLUMN_ID:
682                 return tr("Argument name");
683             case COLUMN_DATA_TYPE:
684                 return tr("Type");
685             case COLUMN_DEFAULT_VALUE:
686                 return tr("Default value");
687             case COLUMN_DESCRIPTION:
688                 return tr("Description");
689             default:
690                 // do nothing, inaccessible code
691                 Q_ASSERT(false);
692                 return QVariant();
693         }
694     }
695     return QVariant();
696 }
697 
insertRows(int,int,const QModelIndex & parent)698 bool CfgExternalToolModelAttributes::insertRows(int /*row*/, int /*count*/, const QModelIndex &parent) {
699     beginInsertRows(parent, items.size(), items.size());
700     AttributeItem *newItem = new AttributeItem();
701     newItem->delegateForNames = new LineEditWithValidatorDelegate(WorkflowEntityValidator::ACCEPTABLE_NAME);
702     newItem->delegateForIds = new LineEditWithValidatorDelegate(WorkflowEntityValidator::ACCEPTABLE_ID);
703     newItem->setDataType(AttributeConfig::STRING_TYPE);
704     changeDefaultValueDelegate(newItem->getDataType(), newItem);
705     items.append(newItem);
706     endInsertRows();
707     return true;
708 }
709 
removeRows(int row,int count,const QModelIndex & parent)710 bool CfgExternalToolModelAttributes::removeRows(int row, int count, const QModelIndex &parent) {
711     CHECK(0 <= row && row < items.size(), false);
712     CHECK(0 <= row + count - 1 && row + count - 1 < items.size(), false);
713     CHECK(0 < count, false);
714 
715     beginRemoveRows(parent, row, row + count - 1);
716     for (int i = row + count - 1; i >= row; --i) {
717         delete items.takeAt(i);
718     }
719     endRemoveRows();
720     return true;
721 }
722 
723 }  // namespace U2
724