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 "BuildIndexDialog.h"
23 
24 #include <QMessageBox>
25 #include <QPushButton>
26 
27 #include <U2Algorithm/DnaAssemblyAlgRegistry.h>
28 
29 #include <U2Core/AppContext.h>
30 #include <U2Core/DocumentUtils.h>
31 #include <U2Core/ExternalToolRegistry.h>
32 #include <U2Core/GUrlUtils.h>
33 #include <U2Core/QObjectScopedPointer.h>
34 #include <U2Core/U2SafePoints.h>
35 
36 #include <U2Gui/AppSettingsGUI.h>
37 #include <U2Gui/HelpButton.h>
38 #include <U2Gui/LastUsedDirHelper.h>
39 #include <U2Gui/U2FileDialog.h>
40 
41 #include "DnaAssemblyGUIExtension.h"
42 
43 namespace U2 {
44 
45 QString BuildIndexDialog::genomePath;
46 
BuildIndexDialog(const DnaAssemblyAlgRegistry * registry,QWidget * p)47 BuildIndexDialog::BuildIndexDialog(const DnaAssemblyAlgRegistry *registry, QWidget *p)
48     : QDialog(p), assemblyRegistry(registry), customGUI(nullptr) {
49     setupUi(this);
50     QMap<QString, QString> helpPagesMap;
51     helpPagesMap.insert("BWA", "65930872");
52     helpPagesMap.insert("BWA-MEM", "65930886");
53     helpPagesMap.insert("BWA-SW", "65930879");
54     helpPagesMap.insert("Bowtie", "65930855");
55     helpPagesMap.insert("Bowtie2", "65930864");
56     helpPagesMap.insert("UGENE Genome Aligner", "65930893");
57     new ComboboxDependentHelpButton(this, buttonBox, methodNamesBox, helpPagesMap);
58     buttonBox->button(QDialogButtonBox::Ok)->setText(tr("Start"));
59     buttonBox->button(QDialogButtonBox::Cancel)->setText(tr("Cancel"));
60 
61     QStringList names = registry->getRegisteredAlgorithmsWithIndexFileSupport();
62     methodNamesBox->addItems(names);
63     // TODO: change the way default method is set
64     if (names.size() > 0) {
65         methodNamesBox->setCurrentIndex(names.size() - 1);
66     }
67     sl_onAlgorithmChanged(methodNamesBox->currentText());
68     connect(setIndexFileNameButton, SIGNAL(clicked()), SLOT(sl_onSetIndexFileNameButtonClicked()));
69     connect(addRefButton, SIGNAL(clicked()), SLOT(sl_onAddRefButtonClicked()));
70     connect(methodNamesBox, SIGNAL(currentIndexChanged(const QString &)), SLOT(sl_onAlgorithmChanged(const QString &)));
71 
72     if (!genomePath.isEmpty()) {
73         refSeqEdit->setText(genomePath);
74         buildIndexUrl(genomePath);
75         SAFE_POINT(nullptr != customGUI, "Build Index dialog referenced null pointer", );
76         customGUI->validateReferenceSequence(genomePath);
77     }
78 }
79 
sl_onAddRefButtonClicked()80 void BuildIndexDialog::sl_onAddRefButtonClicked() {
81     LastUsedDirHelper lod;
82     QString filter;
83 
84     if (qgetenv(ENV_GUI_TEST).toInt() == 1 && qgetenv(ENV_USE_NATIVE_DIALOGS).toInt() == 0) {
85         lod.url = U2FileDialog::getOpenFileName(this, tr("Open reference sequence"), lod.dir, filter, 0, QFileDialog::DontUseNativeDialog);
86     } else {
87         lod.url = U2FileDialog::getOpenFileName(this, tr("Open reference sequence"), lod.dir, filter);
88     }
89     if (lod.url.isEmpty()) {
90         return;
91     }
92 
93     if (nullptr != customGUI) {
94         customGUI->validateReferenceSequence(GUrl(lod.url));
95     }
96     refSeqEdit->setText(lod.url);
97     buildIndexUrl(lod.url);
98 }
99 
sl_onSetIndexFileNameButtonClicked()100 void BuildIndexDialog::sl_onSetIndexFileNameButtonClicked() {
101     LastUsedDirHelper lod;
102     lod.url = U2FileDialog::getSaveFileName(this, tr("Set index file name"), lod.dir);
103     if (!lod.url.isEmpty()) {
104         GUrl index = lod.url;
105         if (index.lastFileSuffix().isEmpty() && customGUI != nullptr) {
106             QString extension = customGUI->getIndexFileExtension();
107             if (extension.isEmpty()) {
108                 index = QString("%1").arg(index.getURLString());
109             } else {
110                 index = QString("%1.%2").arg(index.getURLString()).arg(extension);
111             }
112         }
113         indexFileNameEdit->setText(index.getURLString());
114     }
115 }
116 
sl_onAlgorithmChanged(const QString &)117 void BuildIndexDialog::sl_onAlgorithmChanged(const QString &) {
118     updateState();
119 }
120 
updateState()121 void BuildIndexDialog::updateState() {
122     addGuiExtension();
123 }
124 
addGuiExtension()125 void BuildIndexDialog::addGuiExtension() {
126     // cleanup previous extension
127     if (customGUI != nullptr) {
128         layout()->removeWidget(customGUI);
129         setMinimumHeight(minimumHeight() - customGUI->minimumHeight());
130         delete customGUI;
131         customGUI = nullptr;
132     }
133 
134     // insert new extension widget
135     DnaAssemblyAlgorithmEnv *env = assemblyRegistry->getAlgorithm(methodNamesBox->currentText());
136     if (nullptr == env) {
137         adjustSize();
138         return;
139     }
140     DnaAssemblyGUIExtensionsFactory *gui = env->getGUIExtFactory();
141     if (gui != nullptr && gui->hasBuildIndexWidget()) {
142         customGUI = gui->createBuildIndexWidget(this);
143         int insertPos = verticalLayout->count() - 1;
144         verticalLayout->insertWidget(insertPos, customGUI);
145         if (!refSeqEdit->text().isEmpty()) {
146             buildIndexUrl(refSeqEdit->text());
147             customGUI->validateReferenceSequence(GUrl(refSeqEdit->text()));
148         }
149         customGUI->show();
150     }
151     adjustSize();
152 }
153 
buildIndexUrl(const GUrl & refUrl)154 void BuildIndexDialog::buildIndexUrl(const GUrl &refUrl) {
155     QString extension("");
156     GUrl url;
157     if (nullptr != customGUI) {
158         extension = customGUI->getIndexFileExtension();
159         url = customGUI->buildIndexUrl(refUrl);
160     }
161     if (url.isEmpty()) {
162         if (extension.isEmpty()) {
163             url = GUrlUtils::rollFileName(refUrl.dirPath() + "/" + refUrl.baseFileName(), DocumentUtils::getNewDocFileNameExcludesHint());
164         } else {
165             url = GUrlUtils::rollFileName(refUrl.dirPath() + "/" + refUrl.baseFileName() + "." + extension, DocumentUtils::getNewDocFileNameExcludesHint());
166         }
167     }
168 
169     indexFileNameEdit->setText(url.getURLString());
170 }
171 
accept()172 void BuildIndexDialog::accept() {
173     if ((getAlgorithmName() == "Bowtie") || (getAlgorithmName() == "Bowtie2") || (getAlgorithmName() == "BWA") || (getAlgorithmName() == "BWA-MEM") || (getAlgorithmName() == "BWA-SW")) {
174         QString externalToolId;
175 
176         if (getAlgorithmName() == "Bowtie2") {
177             externalToolId = "USUPP_BOWTIE2_BUILD";
178         }
179         if (getAlgorithmName() == "Bowtie") {
180             externalToolId = "USUPP_BOWTIE_BUILD";
181         }
182         if ((getAlgorithmName() == "BWA") || (getAlgorithmName() == "BWA-MEM") || (getAlgorithmName() == "BWA-SW")) {
183             externalToolId = "USUPP_BWA";
184         }
185         if (AppContext::getExternalToolRegistry()->getById(externalToolId)->getPath().isEmpty()) {
186             QObjectScopedPointer<QMessageBox> msgBox = new QMessageBox(this);
187             msgBox->setWindowTitle(tr("DNA Assembly"));
188             msgBox->setInformativeText(tr("Do you want to select it now?"));
189             msgBox->setStandardButtons(QMessageBox::Yes | QMessageBox::No);
190             msgBox->setDefaultButton(QMessageBox::Yes);
191             msgBox->setText(tr(QString("Path for <i>" + AppContext::getExternalToolRegistry()->getToolNameById(externalToolId) + "</i> tool is not selected.").toLatin1().data()));
192             const int ret = msgBox->exec();
193             CHECK(!msgBox.isNull(), );
194 
195             switch (ret) {
196                 case QMessageBox::Yes:
197                     AppContext::getAppSettingsGUI()->showSettingsDialog(APP_SETTINGS_EXTERNAL_TOOLS);
198                     break;
199                 case QMessageBox::No:
200                     return;
201                     break;
202                 default:
203                     assert(false);
204                     break;
205             }
206             if (AppContext::getExternalToolRegistry()->getById(externalToolId)->getPath().isEmpty()) {
207                 return;
208             }
209         }
210     }
211     if (refSeqEdit->text().isEmpty()) {
212         QMessageBox::information(this, tr("Build Index"), tr("Reference sequence url is not set!"));
213     } else if (indexFileNameEdit->text().isEmpty()) {
214         QMessageBox::information(this, tr("Build Index"), tr("Index file name is not set!"));
215     } else {
216         genomePath.clear();
217         genomePath = refSeqEdit->text();
218 
219         QDialog::accept();
220     }
221 }
222 
getRefSeqUrl()223 const GUrl BuildIndexDialog::getRefSeqUrl() {
224     return refSeqEdit->text();
225 }
226 
getAlgorithmName()227 const QString BuildIndexDialog::getAlgorithmName() {
228     return methodNamesBox->currentText();
229 }
230 
getIndexFileName()231 const QString BuildIndexDialog::getIndexFileName() {
232     return indexFileNameEdit->text();
233 }
234 
getCustomSettings()235 QMap<QString, QVariant> BuildIndexDialog::getCustomSettings() {
236     if (customGUI != nullptr) {
237         return customGUI->getBuildIndexCustomSettings();
238     } else {
239         return QMap<QString, QVariant>();
240     }
241 }
242 
243 }  // namespace U2
244