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 "TaxonomySupport.h"
23
24 #include <QAbstractItemModel>
25 #include <QFileInfo>
26 #include <QPushButton>
27 #include <QVBoxLayout>
28 #include <QtCore/QVariant>
29 #include <QtWidgets/QAction>
30 #include <QtWidgets/QApplication>
31 #include <QtWidgets/QButtonGroup>
32 #include <QtWidgets/QDialog>
33 #include <QtWidgets/QHeaderView>
34 #include <QtWidgets/QWidget>
35
36 #include <U2Core/AppContext.h>
37 #include <U2Core/AppResources.h>
38 #include <U2Core/AppSettings.h>
39 #include <U2Core/BaseDocumentFormats.h>
40 #include <U2Core/Counter.h>
41 #include <U2Core/DataPathRegistry.h>
42 #include <U2Core/DocumentImport.h>
43 #include <U2Core/DocumentModel.h>
44 #include <U2Core/DocumentUtils.h>
45 #include <U2Core/FailTask.h>
46 #include <U2Core/FileAndDirectoryUtils.h>
47 #include <U2Core/GObject.h>
48 #include <U2Core/GObjectTypes.h>
49 #include <U2Core/GUrlUtils.h>
50 #include <U2Core/IOAdapter.h>
51 #include <U2Core/IOAdapterUtils.h>
52 #include <U2Core/L10n.h>
53 #include <U2Core/QObjectScopedPointer.h>
54 #include <U2Core/TaskSignalMapper.h>
55 #include <U2Core/Timer.h>
56 #include <U2Core/U2OpStatusUtils.h>
57 #include <U2Core/U2SafePoints.h>
58
59 #include <U2Designer/DelegateEditors.h>
60
61 #include <U2Formats/BAMUtils.h>
62 #include <U2Formats/FastaFormat.h>
63 #include <U2Formats/FastqFormat.h>
64
65 #include <U2Gui/HelpButton.h>
66
67 #include <U2Lang/WorkflowEnv.h>
68
69 namespace U2 {
70 namespace LocalWorkflow {
71
72 const QString TaxonomySupport::TAXONOMY_CLASSIFICATION_SLOT_ID("tax-data");
73 static const QString CLASSIFICATION_SLOT_TYPE_ID("tax-classification");
74
75 const TaxID TaxonomyTree::UNDEFINED_ID = (TaxID)-1;
76 const TaxID TaxonomyTree::UNCLASSIFIED_ID = 0;
77
78 TaxonomyTree *TaxonomyTree::the_tree = nullptr;
79 const int RANK_SHIFT = (sizeof(TaxID) - sizeof(char)) * 8;
80 const TaxID RANK_MASK = 0xFF << RANK_SHIFT;
81
82 /********************************************************************/
83 /*TaxonomySupport*/
84 /********************************************************************/
85
TAXONOMY_CLASSIFICATION_SLOT()86 const Descriptor TaxonomySupport::TAXONOMY_CLASSIFICATION_SLOT() {
87 return Descriptor(TAXONOMY_CLASSIFICATION_SLOT_ID, tr("Taxonomy classification data"), tr("Taxonomy classification data"));
88 }
89
TAXONOMY_CLASSIFICATION_TYPE()90 DataTypePtr TaxonomySupport::TAXONOMY_CLASSIFICATION_TYPE() {
91 DataTypeRegistry *dtr = Workflow::WorkflowEnv::getDataTypeRegistry();
92 assert(dtr);
93 static bool startup = true;
94 if (startup) {
95 dtr->registerEntry(DataTypePtr(new DataType(CLASSIFICATION_SLOT_TYPE_ID, tr("Taxonomy classification data"), tr("Taxonomy classification data"))));
96 startup = false;
97 }
98 return dtr->getById(CLASSIFICATION_SLOT_TYPE_ID);
99 }
100
getInstance()101 TaxonomyTree *TaxonomyTree::getInstance() {
102 if (the_tree == nullptr) {
103 // fixme data race???
104 the_tree = load(new TaxonomyTree);
105 }
106 return the_tree;
107 }
108
getName(TaxID id) const109 QString TaxonomyTree::getName(TaxID id) const {
110 if (unsigned(names.size()) > id) {
111 return names.at(id);
112 }
113 algoLog.info(QString("Unknown taxon ID requested: %1").arg(id));
114 return QString("Unknown taxon ID");
115 }
116
getRank(TaxID id) const117 QString TaxonomyTree::getRank(TaxID id) const {
118 if (unsigned(nodes.size()) > id) {
119 return ranks.at((nodes.at(id) & RANK_MASK) >> RANK_SHIFT);
120 }
121 algoLog.info(QString("Unknown taxon ID requested: %1").arg(id));
122 return QString("Unknown taxon ID");
123 }
124
getParent(TaxID id) const125 TaxID TaxonomyTree::getParent(TaxID id) const {
126 if (unsigned(nodes.size()) > id) {
127 return nodes.at(id) & ~RANK_MASK;
128 }
129 algoLog.info(QString("Unknown taxon ID requested: %1").arg(id));
130 return UNDEFINED_ID;
131 }
132
getChildren(TaxID id) const133 QList<TaxID> TaxonomyTree::getChildren(TaxID id) const {
134 return childs.values(id);
135 }
136
getNamesListSize() const137 int TaxonomyTree::getNamesListSize() const {
138 return names.size();
139 }
140
contains(TaxID id) const141 bool TaxonomyTree::contains(TaxID id) const {
142 return unsigned(nodes.size()) > id;
143 }
144
isValid() const145 bool TaxonomyTree::isValid() const {
146 return valid;
147 }
148
match(TaxID id,QSet<TaxID> filter)149 TaxID TaxonomyTree::match(TaxID id, QSet<TaxID> filter) {
150 // first try fastpath
151 if (id >= unsigned(nodes.size())) {
152 return UNDEFINED_ID;
153 }
154 if (filter.contains(id)) {
155 return id;
156 }
157 // then go searching by hierarchy
158 QList<TaxID> parents;
159 {
160 TaxID parent = id;
161 while (parent > 1) {
162 if (unsigned(nodes.size()) > parent) {
163 parents << parent;
164 parent = getParent(parent);
165 } else {
166 algoLog.error(TaxonomySupport::tr("Broken taxonomy tree: %1").arg(id));
167 break;
168 }
169 }
170 }
171 for (const TaxID &parent : qAsConst(parents)) {
172 if (filter.contains(parent)) {
173 return parent;
174 }
175 }
176 return UNDEFINED_ID;
177 }
178
TaxonomyTree()179 TaxonomyTree::TaxonomyTree()
180 : valid(false) {
181 }
182
183 class TaxonNameComparator {
184 public:
TaxonNameComparator(TaxonomyTree * tree)185 TaxonNameComparator(TaxonomyTree *tree)
186 : tree(tree) {
187 }
operator ()(const TaxID left,const TaxID right) const188 bool operator()(const TaxID left, const TaxID right) const {
189 return tree->getName(left).compare(tree->getName(right));
190 }
191
192 private:
193 TaxonomyTree *tree;
194 };
195
load(TaxonomyTree * tree)196 TaxonomyTree *TaxonomyTree::load(TaxonomyTree *tree) {
197 U2DataPathRegistry *dataPathRegistry = AppContext::getDataPathRegistry();
198 SAFE_POINT(nullptr != dataPathRegistry, "U2DataPathRegistry is NULL", tree);
199
200 U2DataPath *taxonomyDataPath = dataPathRegistry->getDataPathByName(NgsReadsClassificationPlugin::TAXONOMY_DATA_ID);
201 CHECK_EXT(nullptr != taxonomyDataPath && taxonomyDataPath->isValid(), algoLog.details(QString("Taxonomy data are not configured")), tree);
202
203 bool hasError = false;
204
205 QString nodesUrl = taxonomyDataPath->getPathByName(NgsReadsClassificationPlugin::TAXON_NODES_ITEM_ID);
206 QFile nodesFile(nodesUrl);
207 if (!nodesFile.open(QIODevice::ReadOnly)) {
208 algoLog.error(QString("Cannot open taxonomy classification data: %1").arg(nodesUrl.isEmpty() ? NgsReadsClassificationPlugin::TAXON_NODES_ITEM_ID : nodesUrl));
209 hasError = true;
210 } else {
211 GTIMER(cvar, tvar, "TaxonomyTree::nodes");
212 QList<TaxID> &nodes = tree->nodes;
213 nodes.reserve(2000000);
214 QByteArray line;
215 while ((line = nodesFile.readLine()).size() != 0) {
216 QList<QByteArray> row = line.split('|');
217 if (row.size() > 3) {
218 bool ok = true;
219 TaxID taxID = row[0].trimmed().toUInt(&ok);
220 if (ok) {
221 TaxID parentID = row[1].trimmed().toUInt(&ok);
222 if (ok) {
223 if (unsigned(nodes.size()) <= taxID) {
224 nodes.reserve(taxID + 1000);
225 }
226 while (unsigned(nodes.size()) <= taxID) {
227 nodes.append(0);
228 }
229
230 QString rank = row[2].trimmed();
231 int rankID = tree->ranks.indexOf(rank);
232 if (rankID < 0) {
233 rankID = tree->ranks.size();
234 tree->ranks << rank;
235 assert(tree->ranks.size() < 0xFF);
236 assert(rankID == tree->ranks.indexOf(rank));
237 }
238
239 // Hack to skip "cellular organisms" node, "to follow NCBI taxonomy browser"
240 const TaxID CELL_ORGMS_ID = 131567;
241 if (parentID == CELL_ORGMS_ID) {
242 parentID = 1;
243 }
244 if (taxID == CELL_ORGMS_ID) {
245 assert(rank == "no rank");
246 assert(parentID == 1);
247 }
248
249 assert(parentID == (parentID & ~RANK_MASK));
250 nodes[taxID] = parentID | (rankID << RANK_SHIFT);
251 assert(tree->getParent(taxID) == parentID);
252 assert(tree->getRank(taxID) == rank);
253
254 if (taxID != 1 && taxID != CELL_ORGMS_ID) {
255 tree->childs.insert(parentID, taxID);
256 }
257 continue;
258 }
259 }
260 }
261 algoLog.error(QString("Broken nodes.dmp file : %1").arg(nodesUrl));
262 hasError = true;
263 break;
264 }
265 nodesFile.close();
266 }
267
268 QString namesUrl = taxonomyDataPath->getPathByName(NgsReadsClassificationPlugin::TAXON_NAMES_ITEM_ID);
269 QFile namesFile(namesUrl);
270 if (!namesFile.open(QIODevice::ReadOnly)) {
271 algoLog.error(QString("Cannot open taxonomy classification data: %1").arg(namesUrl.isEmpty() ? NgsReadsClassificationPlugin::TAXON_NAMES_ITEM_ID : namesUrl));
272 hasError = true;
273 } else {
274 GTIMER(cvar, tvar, "TaxonomyTree::names");
275 QStringList &names = tree->names;
276 QByteArray line;
277 names.reserve(2000000);
278 while ((line = namesFile.readLine()).size() != 0) {
279 const QList<QByteArray> row = line.split('|');
280 bool ok = true;
281 if (row.size() > 3) {
282 if (row[3].trimmed() == "scientific name") {
283 TaxID taxID = row[0].trimmed().toUInt(&ok);
284 if (ok) {
285 QByteArray name = row[1].trimmed();
286 if (unsigned(names.size()) <= taxID) {
287 names.reserve(taxID + 1000);
288 }
289 while (unsigned(names.size()) <= taxID) {
290 names.append(QString());
291 }
292 if (!names.at(taxID).isEmpty()) {
293 algoLog.error(QString("Non-unique scientific name for taxon ID : %1").arg(taxID));
294 }
295 names[taxID] = name;
296 }
297 }
298 } else {
299 ok = false;
300 }
301 if (!ok) {
302 algoLog.error(QString("Broken names.dmp file : %1").arg(namesUrl));
303 hasError = true;
304 break;
305 }
306 }
307 namesFile.close();
308 }
309 tree->valid = !hasError;
310 return tree;
311 }
312
313 ////////////////////////// WD GUI ////////////////////////
314
315 class TreeItem;
316
317 /********************************************************************/
318 /*TaxonomyTreeModel*/
319 /********************************************************************/
320
321 namespace {
322
taxIdLessThan(const TaxID a,const TaxID b)323 bool taxIdLessThan(const TaxID a, const TaxID b) {
324 return TaxonomyTree::getInstance()->getName(a) < TaxonomyTree::getInstance()->getName(b);
325 }
326
327 } // namespace
328
TaxonomyTreeModel(const QString & data,QObject * parent)329 TaxonomyTreeModel::TaxonomyTreeModel(const QString &data, QObject *parent)
330 : QAbstractItemModel(parent), tree(TaxonomyTree::getInstance()) {
331 QStringList taxons = data.split(";", QString::SkipEmptyParts);
332 for (const QString &idStr : qAsConst(taxons)) {
333 selected.insert(idStr.toInt());
334 }
335 for (const TaxID &id : qAsConst(selected)) {
336 TaxID parentTaxId = tree->getParent(id);
337 while (parentTaxId > 1) {
338 tristate.insert(parentTaxId, id);
339 parentTaxId = tree->getParent(parentTaxId);
340 }
341 }
342 }
343
getChildrenSorted(TaxID id) const344 QList<TaxID> TaxonomyTreeModel::getChildrenSorted(TaxID id) const {
345 QList<TaxID> values = tree->getChildren(id);
346 if (values.size() > 1) {
347 // std::sort(values.begin(), values.end(), TaxonNameComparator(tree));
348 std::sort(values.begin(), values.end(), taxIdLessThan);
349 }
350 return values;
351 }
352
columnCount(const QModelIndex &) const353 int TaxonomyTreeModel::columnCount(const QModelIndex &) const {
354 return 3;
355 }
356
getSelected() const357 QString TaxonomyTreeModel::getSelected() const {
358 QString res;
359 foreach (TaxID id, selected) {
360 res += QString::number(id) + ";";
361 }
362 if (!res.isEmpty()) {
363 res.chop(1);
364 }
365 return res;
366 }
367
setData(const QModelIndex & index,const QVariant & v,int role)368 bool TaxonomyTreeModel::setData(const QModelIndex &index, const QVariant &v, int role) {
369 if (role != Qt::CheckStateRole || index.column() != 0)
370 return false;
371
372 TaxID item = static_cast<TaxID>(index.internalId());
373 bool result = false;
374 bool old = selected.contains(item);
375 int value = v.toInt();
376 if (value == Qt::PartiallyChecked) {
377 // workaround for Qt5.4: https://bugreports.qt.io/browse/QTBUG-43473
378 value = Qt::Checked;
379 }
380 algoLog.info(QString("check %1 for %2 ").arg(value).arg(item));
381
382 if (value == Qt::Unchecked && old) {
383 selected.remove(item);
384 result = true;
385 } else if (value == Qt::Checked && !old) {
386 selected << item;
387 result = true;
388 }
389
390 if (result) {
391 QVector<int> checkRole(1, Qt::CheckStateRole);
392 emit dataChanged(index, index, checkRole);
393
394 QList<TaxID> children = getChildrenSorted(item);
395 if (children.size() != 0) {
396 emit dataChanged(createIndex(0, 0, children.first()), createIndex(children.size() - 1, 3, children.last()));
397 }
398 TaxID parent = tree->getParent(item);
399 while (parent > 1) {
400 if (value == Qt::Checked) {
401 tristate.insert(parent, item);
402 } else {
403 tristate.remove(parent, item);
404 }
405 emit dataChanged(createIndex(0, 0, parent), createIndex(0, 3, parent), checkRole);
406 parent = tree->getParent(parent);
407 }
408 }
409 return result;
410 }
411
data(const QModelIndex & index,int role) const412 QVariant TaxonomyTreeModel::data(const QModelIndex &index, int role) const {
413 if (!index.isValid())
414 return QVariant();
415
416 TaxID item = static_cast<TaxID>(index.internalId());
417 if (role == Qt::CheckStateRole && index.column() == 0) {
418 while (item > 1) {
419 if (selected.contains(item)) {
420 return Qt::Checked;
421 }
422 item = tree->getParent(item);
423 }
424 item = static_cast<TaxID>(index.internalId());
425 return tristate.contains(item) ? Qt::PartiallyChecked : Qt::Unchecked;
426 }
427 if (role == Qt::DisplayRole) {
428 switch (index.column()) {
429 case 0:
430 return tree->getName(item);
431 case 1:
432 return tree->getRank(item);
433 case 2:
434 return item;
435 }
436 }
437 return QVariant();
438 }
439
flags(const QModelIndex & index) const440 Qt::ItemFlags TaxonomyTreeModel::flags(const QModelIndex &index) const {
441 if (!index.isValid())
442 return 0;
443
444 Qt::ItemFlags flags = Qt::ItemIsSelectable | Qt::ItemIsEnabled;
445
446 TaxID item = static_cast<TaxID>(index.internalId());
447
448 if (!selected.contains(item)) {
449 while (item > 1) {
450 item = tree->getParent(item);
451 if (selected.contains(item)) {
452 flags &= ~Qt::ItemIsEnabled;
453 break;
454 }
455 }
456 }
457
458 if (index.column() == 0) {
459 flags |= Qt::ItemIsUserCheckable | Qt::ItemIsAutoTristate;
460 }
461
462 return flags;
463 }
464
headerData(int section,Qt::Orientation orientation,int role) const465 QVariant TaxonomyTreeModel::headerData(int section, Qt::Orientation orientation, int role) const {
466 if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
467 switch (section) {
468 case 0:
469 return TaxonomySupport::tr("Taxon name");
470 case 1:
471 return TaxonomySupport::tr("Rank");
472 case 2:
473 return TaxonomySupport::tr("Taxon ID");
474 }
475 }
476
477 return QVariant();
478 }
479
index(int row,int column,const QModelIndex & parent) const480 QModelIndex TaxonomyTreeModel::index(int row, int column, const QModelIndex &parent)
481 const {
482 if (!hasIndex(row, column, parent))
483 return QModelIndex();
484
485 TaxID parentItem;
486
487 if (!parent.isValid())
488 parentItem = 1;
489 else
490 parentItem = static_cast<TaxID>(parent.internalId());
491
492 QList<TaxID> children = getChildrenSorted(parentItem);
493 if (row < children.size())
494 return createIndex(row, column, children.at(row));
495 else
496 return QModelIndex();
497 }
498
parent(const QModelIndex & index) const499 QModelIndex TaxonomyTreeModel::parent(const QModelIndex &index) const {
500 if (!index.isValid())
501 return QModelIndex();
502
503 TaxID childItem = static_cast<TaxID>(index.internalId());
504 TaxID parentItem = tree->getParent(childItem);
505
506 if (parentItem == 1)
507 return QModelIndex();
508
509 QList<TaxID> siblings = getChildrenSorted(tree->getParent(parentItem));
510 int row = siblings.indexOf(parentItem);
511 if (row >= 0)
512 return createIndex(row, 0, parentItem);
513 // else todo assert
514
515 return QModelIndex();
516 }
517
rowCount(const QModelIndex & parent) const518 int TaxonomyTreeModel::rowCount(const QModelIndex &parent) const {
519 TaxID parentItem;
520 if (parent.column() > 0)
521 return 0;
522
523 if (!parent.isValid())
524 parentItem = 1;
525 else
526 parentItem = static_cast<TaxID>(parent.internalId());
527
528 return tree->getChildren(parentItem).size();
529 }
530
531 /********************************************************************/
532 /*TaxonomyDelegate*/
533 /********************************************************************/
534
535 static const QString PLACEHOLDER("Select IDs...");
536
TaxonomyDelegate(QObject * parent)537 TaxonomyDelegate::TaxonomyDelegate(QObject *parent)
538 : PropertyDelegate(parent) {
539 }
540
getDisplayValue(const QVariant & value) const541 QVariant TaxonomyDelegate::getDisplayValue(const QVariant &value) const {
542 QString str = value.value<QString>();
543 return str.isEmpty() ? PLACEHOLDER : str;
544 }
545
createEditor(QWidget * parent,const QStyleOptionViewItem &,const QModelIndex &) const546 QWidget *TaxonomyDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &, const QModelIndex &) const {
547 TaxonomyPropertyWidget *editor = new TaxonomyPropertyWidget(parent);
548 connect(editor, SIGNAL(si_valueChanged(QVariant)), SLOT(sl_commit()));
549 return editor;
550 }
551
createWizardWidget(U2OpStatus &,QWidget * parent) const552 PropertyWidget *TaxonomyDelegate::createWizardWidget(U2OpStatus &, QWidget *parent) const {
553 return new TaxonomyPropertyWidget(parent);
554 }
555
setEditorData(QWidget * editor,const QModelIndex & index) const556 void TaxonomyDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const {
557 const QVariant value = index.model()->data(index, ConfigurationEditor::ItemValueRole);
558 TaxonomyPropertyWidget *propertyWidget = qobject_cast<TaxonomyPropertyWidget *>(editor);
559 propertyWidget->setValue(value);
560 }
561
setModelData(QWidget * editor,QAbstractItemModel * model,const QModelIndex & index) const562 void TaxonomyDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const {
563 TaxonomyPropertyWidget *propertyWidget = qobject_cast<TaxonomyPropertyWidget *>(editor);
564 model->setData(index, propertyWidget->value(), ConfigurationEditor::ItemValueRole);
565 }
566
clone()567 PropertyDelegate *TaxonomyDelegate::clone() {
568 return new TaxonomyDelegate(parent());
569 }
570
sl_commit()571 void TaxonomyDelegate::sl_commit() {
572 TaxonomyPropertyWidget *editor = qobject_cast<TaxonomyPropertyWidget *>(sender());
573 CHECK(editor != nullptr, );
574 emit commitData(editor);
575 }
576
577 /********************************************************************/
578 /*TaxonomyPropertyWidget*/
579 /********************************************************************/
580
TaxonomyPropertyWidget(QWidget * parent,DelegateTags * tags)581 TaxonomyPropertyWidget::TaxonomyPropertyWidget(QWidget *parent, DelegateTags *tags)
582 : PropertyWidget(parent, tags) {
583 lineEdit = new QLineEdit(this);
584 lineEdit->setPlaceholderText(PLACEHOLDER);
585 lineEdit->setReadOnly(true);
586 lineEdit->setObjectName("lineEdit");
587 lineEdit->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
588
589 addMainWidget(lineEdit);
590
591 toolButton = new QToolButton(this);
592 toolButton->setObjectName("toolButton");
593 toolButton->setText("...");
594 toolButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
595 connect(toolButton, SIGNAL(clicked()), SLOT(sl_showDialog()));
596 layout()->addWidget(toolButton);
597
598 setObjectName("TaxonomyPropertyWidget");
599 }
600
value()601 QVariant TaxonomyPropertyWidget::value() {
602 return text;
603 }
604
setValue(const QVariant & value)605 void TaxonomyPropertyWidget::setValue(const QVariant &value) {
606 text = value.value<QString>();
607 lineEdit->setText(text);
608 }
609
sl_showDialog()610 void TaxonomyPropertyWidget::sl_showDialog() {
611 QObjectScopedPointer<TaxonSelectionDialog> dialog(new TaxonSelectionDialog(text, this));
612 if (QDialog::Accepted == dialog->exec()) {
613 CHECK(!dialog.isNull(), );
614 text = dialog->getValue();
615 lineEdit->setText(text);
616 emit si_valueChanged(value());
617 }
618 }
619
620 /********************************************************************/
621 /*TaxonSelectionDialog*/
622 /********************************************************************/
623
TaxonSelectionDialog(const QString & value,QWidget * parent)624 TaxonSelectionDialog::TaxonSelectionDialog(const QString &value, QWidget *parent)
625 : QDialog(parent) {
626 if (objectName().isEmpty()) {
627 setObjectName(QStringLiteral("TaxonSelectionDialog"));
628 }
629 mainLayout = new QVBoxLayout(this);
630 mainLayout->setObjectName(QStringLiteral("mainLayout"));
631 mainLayout->setSizeConstraint(QLayout::SetMinAndMaxSize);
632
633 treeView = new QTreeView(this);
634 treeModel = new TaxonomyTreeModel(value); // fixme delete
635 treeView->setModel(treeModel);
636 for (int column = 0; column < treeModel->columnCount(); ++column) {
637 treeView->resizeColumnToContents(column);
638 }
639 treeView->header()->resizeSection(0, 370);
640 treeView->header()->resizeSection(1, 120);
641 mainLayout->addWidget(treeView);
642
643 buttonBox = new QDialogButtonBox(this);
644 buttonBox->setObjectName(QStringLiteral("buttonBox"));
645 buttonBox->setOrientation(Qt::Horizontal);
646 buttonBox->setStandardButtons(QDialogButtonBox::Cancel | QDialogButtonBox::Ok);
647
648 mainLayout->addWidget(buttonBox);
649
650 setWindowTitle(QApplication::translate("TaxonSelectionDialog", "Select Taxa", 0));
651 QObject::connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
652 QObject::connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
653
654 QMetaObject::connectSlotsByName(this);
655
656 new HelpButton(this, buttonBox, "43");
657 buttonBox->button(QDialogButtonBox::Ok)->setText(tr("Select"));
658 buttonBox->button(QDialogButtonBox::Cancel)->setText(tr("Cancel"));
659
660 // adjustSize();
661 resize(580, 440);
662 setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
663 }
664
getValue() const665 QString TaxonSelectionDialog::getValue() const {
666 return treeModel->getSelected();
667 }
668
669 } // namespace LocalWorkflow
670 } // namespace U2
671