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 "PortAliasesConfigurationDialog.h"
23
24 #include <QMessageBox>
25 #include <QPushButton>
26
27 #include <U2Gui/HelpButton.h>
28
29 #include <U2Lang/ActorModel.h>
30 #include <U2Lang/WorkflowUtils.h>
31
32 namespace U2 {
33 namespace Workflow {
34
PortAliasesConfigurationDialog(const Schema & schema,QWidget * p)35 PortAliasesConfigurationDialog::PortAliasesConfigurationDialog(const Schema &schema, QWidget *p)
36 : QDialog(p), currentRow(-1) {
37 setupUi(this);
38 new HelpButton(this, buttonBox, "65930020");
39
40 buttonBox->button(QDialogButtonBox::Cancel)->setText(tr("Cancel"));
41 buttonBox->button(QDialogButtonBox::Ok)->setText(tr("OK"));
42 QPushButton *cancelPushButton = buttonBox->button(QDialogButtonBox::Cancel);
43 QPushButton *okPushButton = buttonBox->button(QDialogButtonBox::Ok);
44
45 connect(cancelPushButton, SIGNAL(clicked()), SLOT(reject()));
46 connect(okPushButton, SIGNAL(clicked()), SLOT(accept()));
47 connect(portAliasEdit, SIGNAL(textChanged(const QString &)), SLOT(sl_portAliasChanged(const QString &)));
48 connect(portDescriptionEdit, SIGNAL(textChanged(const QString &)), SLOT(sl_portDescriptionChanged(const QString &)));
49
50 okPushButton->setDefault(true);
51 portAliasesTableWidget->verticalHeader()->hide();
52
53 portAliasesTableWidget->horizontalHeader()->setSectionsClickable(false);
54 portAliasesTableWidget->horizontalHeader()->setStretchLastSection(true);
55
56 foreach (Actor *actor, schema.getProcesses()) {
57 assert(nullptr != actor);
58 foreach (Port *port, actor->getPorts()) {
59 assert(nullptr != port);
60 // show only output and free input ports
61 if (port->isInput()) {
62 if (!port->getLinks().isEmpty()) {
63 continue;
64 }
65 }
66 int pos = portListWidget->count();
67 QString itemName = actor->getLabel() + "." + port->getDisplayName();
68 QListWidgetItem *item = new QListWidgetItem(itemName);
69 portListWidget->insertItem(pos, item);
70 portListMap.insert(pos, port);
71 }
72 }
73 if (portListMap.isEmpty()) {
74 portInfoGroupBox->setVisible(false);
75 }
76
77 connect(portListWidget, SIGNAL(currentRowChanged(int)), SLOT(sl_portSelected(int)));
78 connect(portAliasesTableWidget, SIGNAL(cellChanged(int, int)), SLOT(sl_onDataChange(int, int)));
79
80 initializeModel(schema);
81 }
82
clearAliasTable()83 void PortAliasesConfigurationDialog::clearAliasTable() {
84 portAliasesTableWidget->clearContents();
85 portAliasesTableWidget->setRowCount(0);
86 }
87
sl_portSelected(int row)88 void PortAliasesConfigurationDialog::sl_portSelected(int row) {
89 if (row == -1) {
90 return;
91 }
92 currentRow = row;
93 clearAliasTable();
94
95 assert(row >= 0 && row < portListWidget->count());
96 Port *currentPort = portListMap.value(row);
97 assert(nullptr != currentPort);
98
99 int rowInd = 0;
100 QMap<Descriptor, QString> aliasMap = model.aliases.value(currentPort);
101 QMap<Descriptor, QString>::const_iterator it = aliasMap.constBegin();
102 while (it != aliasMap.constEnd()) {
103 portAliasesTableWidget->insertRow(rowInd);
104
105 QTableWidgetItem *portNameItem = new QTableWidgetItem(it.key().getDisplayName());
106 portAliasesTableWidget->setItem(rowInd, 0, portNameItem);
107 portNameItem->setData(Qt::UserRole, QVariant::fromValue(it.key()));
108 portNameItem->setFlags(portNameItem->flags() ^ Qt::ItemIsSelectable ^ Qt::ItemIsEditable);
109
110 QTableWidgetItem *aliasItem = new QTableWidgetItem(it.value());
111 portAliasesTableWidget->setItem(rowInd, 1, aliasItem);
112
113 rowInd++;
114 ++it;
115 }
116
117 if (currentPort->isInput()) {
118 portTypeLabel->setText(tr("Input"));
119 } else {
120 portTypeLabel->setText(tr("Output"));
121 }
122
123 portAliasEdit->setText(model.ports.value(currentPort).first);
124 portDescriptionEdit->setText(model.ports.value(currentPort).second);
125 }
126
sl_onDataChange(int row,int col)127 void PortAliasesConfigurationDialog::sl_onDataChange(int row, int col) {
128 assert(row >= 0 && row < portAliasesTableWidget->rowCount());
129 if (0 == col) {
130 return;
131 }
132
133 Port *port = portListMap.value(portListWidget->currentRow());
134 assert(nullptr != port);
135
136 Descriptor desc = portAliasesTableWidget->item(row, 0)->data(Qt::UserRole).value<Descriptor>();
137 assert(model.aliases.value(port).contains(desc));
138
139 model.aliases[port][desc] = portAliasesTableWidget->item(row, 1)->text();
140 }
141
sl_portAliasChanged(const QString & newStr)142 void PortAliasesConfigurationDialog::sl_portAliasChanged(const QString &newStr) {
143 Port *currentPort = portListMap.value(currentRow);
144 PortInfo info = model.ports.value(currentPort);
145 model.ports.insert(currentPort, PortInfo(newStr, info.second));
146 }
147
sl_portDescriptionChanged(const QString & newStr)148 void PortAliasesConfigurationDialog::sl_portDescriptionChanged(const QString &newStr) {
149 Port *currentPort = portListMap.value(currentRow);
150 PortInfo info = model.ports.value(currentPort);
151 model.ports.insert(currentPort, PortInfo(info.first, newStr));
152 }
153
initializeModel(const Schema & schema)154 void PortAliasesConfigurationDialog::initializeModel(const Schema &schema) {
155 foreach (Actor *actor, schema.getProcesses()) {
156 assert(nullptr != actor);
157 foreach (Port *port, actor->getPorts()) {
158 assert(nullptr != port);
159 if (port->isInput()) {
160 if (!port->getLinks().isEmpty()) {
161 continue;
162 }
163 }
164 model.ports.insert(port, PortInfo("", ""));
165 QList<Descriptor> slotList;
166 {
167 DataTypePtr to = WorkflowUtils::getToDatatypeForBusport(qobject_cast<IntegralBusPort *>(port));
168 if (port->isInput()) {
169 slotList = to->getDatatypesMap().keys();
170 } else {
171 DataTypePtr from = WorkflowUtils::getFromDatatypeForBusport(qobject_cast<IntegralBusPort *>(port), to);
172 slotList = from->getDatatypesMap().keys();
173 }
174 }
175
176 QList<SlotAlias> slotAliases;
177 foreach (const PortAlias &portAlias, schema.getPortAliases()) {
178 if (portAlias.getSourcePort() == port) {
179 slotAliases = portAlias.getSlotAliases();
180 model.ports.insert(port, PortInfo(portAlias.getAlias(), portAlias.getDescription()));
181 break;
182 }
183 }
184
185 QMap<Descriptor, QString> aliasMap;
186 foreach (Descriptor slotDescr, slotList) {
187 QString actorId;
188 QString slotId;
189 {
190 if (port->isInput()) {
191 actorId = port->owner()->getId();
192 slotId = slotDescr.getId();
193 } else {
194 QStringList tokens = slotDescr.getId().split(':');
195 assert(2 == tokens.size());
196 actorId = tokens[0];
197 slotId = tokens[1];
198 }
199 }
200
201 QString alias;
202 foreach (const SlotAlias &slotAlias, slotAliases) {
203 if (slotAlias.getSourceSlotId() == slotId) {
204 if (slotAlias.getSourcePort()->owner()->getId() == actorId) {
205 alias = slotAlias.getAlias();
206 break;
207 }
208 }
209 }
210 aliasMap.insert(slotDescr, alias);
211 }
212 model.aliases.insert(port, aliasMap);
213 }
214 }
215 }
216
accept()217 void PortAliasesConfigurationDialog::accept() {
218 foreach (Port *port, model.aliases.keys()) {
219 QStringList slotAliases = model.aliases.value(port).values();
220
221 bool slotsNotAliased = true;
222 foreach (const QString &alias, slotAliases) {
223 slotsNotAliased = slotsNotAliased && alias.isEmpty();
224 }
225
226 bool portNotAliases = model.ports.value(port).first.isEmpty();
227 if (!slotsNotAliased && portNotAliases) {
228 QString portStr = port->owner()->getLabel() + "." + port->getId();
229 QMessageBox::information(this, tr("Workflow Designer"), tr("There is a port with some aliased slots but without alias name:\n%1").arg(portStr));
230 return;
231 }
232
233 slotAliases.removeAll("");
234 if (0 != slotAliases.removeDuplicates()) {
235 QMessageBox::information(this, tr("Workflow Designer"), tr("Slot aliases of one port must be different!"));
236 return;
237 }
238
239 foreach (Port *otherPort, model.ports.keys()) {
240 if (otherPort == port) {
241 continue;
242 }
243 if (model.ports.value(port).first.isEmpty()) {
244 continue;
245 }
246 if (model.ports.value(port).first == model.ports.value(otherPort).first) {
247 QString portStr1 = port->owner()->getLabel() + "." + port->getId();
248 QString portStr2 = otherPort->owner()->getLabel() + "." + otherPort->getId();
249
250 QMessageBox::information(this, tr("Workflow Designer"), tr("Port aliases must be different! Rename one of ports:\n%1 or %2").arg(portStr1).arg(portStr2));
251 return;
252 }
253 }
254 }
255
256 QDialog::accept();
257 }
258
getModel() const259 PortAliasesCfgDlgModel PortAliasesConfigurationDialog::getModel() const {
260 PortAliasesCfgDlgModel ret;
261 foreach (Port *port, model.ports.keys()) {
262 QString newPortName = model.ports.value(port).first;
263 if (newPortName.isEmpty()) {
264 continue;
265 }
266 ret.ports.insert(port, model.ports.value(port));
267
268 QMap<Descriptor, QString> aliases = model.aliases.value(port);
269 foreach (const Descriptor &slotDescr, aliases.keys()) {
270 if (aliases.value(slotDescr).isEmpty()) {
271 aliases.remove(slotDescr);
272 }
273 }
274 ret.aliases.insert(port, aliases);
275 }
276 return ret;
277 }
278
279 } // namespace Workflow
280 } // namespace U2
281