1 // Copyright (c) 2012 Dennco Project
3 // This program is free software: you can redistribute it and/or modify
4 // it under the terms of the GNU General Public License as published by
5 // the Free Software Foundation, either version 3 of the License, or
6 // (at your option) any later version.
8 // This program is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 // GNU General Public License for more details.
13 // You should have received a copy of the GNU General Public License
14 // along with this program. If not, see <http://www.gnu.org/licenses/>.
17 // Created by tkawata on Sep-30, 2012.
19 #include "dctoolwindowcelleditor.h"
21 #include "dceditablelabel.h"
22 #include "dceditabletreeview.h"
23 #include "dccelltypecombobox.h"
25 #include "dccreator.h"
26 #include "dcreceptor.h"
28 #include "dccellcode.h"
29 #include "dcaxonterminal.h"
30 #include "dccontainer.h"
31 #include "utils/dcresources.h"
32 #include "utils/dcqtitemmodel.h"
33 #include "utils/dcutil.h"
34 #include "codeeditor/dccellscriptseditorwindow.h"
36 #include <QGridLayout>
39 #include <QSizePolicy>
42 class ReceptorModel : public DCQtItemModel
44 DCToolWindowCellEditor *d_owner;
46 ReceptorModel(DCToolWindowCellEditor *owner) : DCQtItemModel(QStringList("name")), d_owner(owner)
51 virtual ~ReceptorModel()
55 virtual bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole)
57 if (role != Qt::EditRole)
60 DCCell *cell = d_owner->getCell();
64 if (index.column() != 0)
66 return DCQtItemModel::setData(index, value, role);
69 DCQtItemModelItem *item = getItem(index);
70 QString oldReceptorName = item->data(index.column()).toString();
71 QString newReceptorName = value.toString().trimmed();
72 if (newReceptorName.length() == 0)
77 if (oldReceptorName == newReceptorName)
79 //nothing actually changes
83 if (!d_owner->getIsViewUpdating())
85 if (cell->getReceptor(newReceptorName))
88 QMessageBox::warning(NULL, tr("Rename receptor failed"), tr("The receptor name already exist"));
92 bool result = item->setData(index.column(), newReceptorName);
96 DCCreator *creator = d_owner->getController();
97 if (creator->doCommandRenameReceptorName(d_owner, cell, oldReceptorName, newReceptorName, true))
99 emit dataChanged(index, index);
103 item->setData(index.column(), oldReceptorName);
110 return item->setData(index.column(), newReceptorName);
114 virtual Qt::ItemFlags flags(const QModelIndex &index) const
116 if (!index.isValid())
119 Qt::ItemFlags flags = Qt::ItemIsEnabled;
121 if (index.column() == 0 && index.isValid() && index.parent().isValid() && !index.parent().parent().isValid())
123 flags |= Qt::ItemIsEditable | Qt::ItemIsSelectable;
130 class AxonTerminalModel : public DCQtItemModel
132 DCToolWindowCellEditor *d_owner;
134 AxonTerminalModel(DCToolWindowCellEditor *owner) : DCQtItemModel(QStringList("name")), d_owner(owner)
139 virtual ~AxonTerminalModel()
143 virtual bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole)
145 if (role != Qt::EditRole)
148 DCCell *cell = d_owner->getCell();
152 if (index.column() != 0)
154 return DCQtItemModel::setData(index, value, role);
157 DCQtItemModelItem *item = getItem(index);
158 QString oldReceptorName = item->data(index.column()).toString();
159 QString newReceptorName = value.toString().trimmed();
160 if (newReceptorName.length() == 0)
165 if (oldReceptorName == newReceptorName)
167 //nothing actually changes
171 DCCell *axonTargetCell = NULL;
172 if (!d_owner->getIsViewUpdating())
174 bool alreadyExist = false;
175 DCAxon *axon = cell->getAxon();
176 int num = axon->getNumberOfTerminals();
177 for (int i = 0; i < num; i++)
179 DCReceptor *receptor = axon->getTerminalAt(i)->getTarget();
182 DCCell *targetCell = receptor->getOwnerCell();
185 QString targetReceptorName = QString::fromStdString(targetCell->getReceptorName(receptor));
186 if (targetReceptorName == newReceptorName)
191 else if (targetReceptorName == oldReceptorName)
193 axonTargetCell = targetCell;
201 QMessageBox::warning(NULL, tr("Rename receptor failed"), tr("The receptor name already exist"));
209 result = item->setData(index.column(), newReceptorName);
213 DCCreator *creator = d_owner->getController();
214 if (creator->doCommandRenameReceptorName(d_owner, axonTargetCell, oldReceptorName, newReceptorName, true))
216 emit dataChanged(index, index);
220 item->setData(index.column(), oldReceptorName);
228 return item->setData(index.column(), newReceptorName);
232 virtual Qt::ItemFlags flags(const QModelIndex &index) const
234 if (!index.isValid())
237 Qt::ItemFlags flags = Qt::ItemIsEnabled;
239 if (index.column() == 0 && index.isValid() && index.parent().isValid() && index.parent().parent().isValid() && !index.parent().parent().parent().isValid())
241 flags |= Qt::ItemIsEditable | Qt::ItemIsSelectable;
249 DCToolWindowCellEditor::DCToolWindowCellEditor(DCCreator *creator) :
250 DCToolWindowBase("CELL:", creator), d_cell(NULL), d_isViewUpdating(false)
252 d_layout = new QGridLayout;
254 d_layout->setSpacing(10);
256 d_layout->setSpacing(6);
258 d_layout->setContentsMargins(0,0,0,0);
259 d_layout->addWidget(new QLabel(tr("page")),0,0);
260 d_layout->addWidget(new QLabel(tr("type")),1,0);
261 d_layout->addWidget(new QLabel(tr("cell code")),2,0);
262 d_layout->addWidget(new QLabel(tr("custom script")),3,0);
264 d_detailButton = new QPushButton(tr("detail..."));
265 d_detailButton->setStyleSheet("background-color: rgba(255,255,255,60);");
267 d_layout->addWidget(d_detailButton,6,0,1,2);
269 d_textPage = new DCEditableLabel(this, "");
270 d_comboType = new DCCellTypeComboBox(creator, this);
271 d_layout->addWidget(d_textPage, 0,1);
272 d_layout->addWidget(d_comboType, 1,1);
274 d_classButton = new QPushButton("...");
275 d_customScriptButton = new QPushButton(tr("edit..."));
277 d_layout->addWidget(d_classButton, 2,1);
278 d_layout->addWidget(d_customScriptButton, 3,1);
280 d_receptors = new DCEditableTreeView(this);
281 d_receptors->setHeaderHidden(true);
282 d_receptors->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
284 d_axonTerminals = new DCEditableTreeView(this);
285 d_axonTerminals->setHeaderHidden(true);
286 d_axonTerminals->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
289 d_receptorItemModel = new ReceptorModel(this);
290 d_axonTerminalItemModel = new AxonTerminalModel(this);
292 d_receptors->setModel(d_receptorItemModel);
293 d_axonTerminals->setModel(d_axonTerminalItemModel);
295 d_layout->addWidget(d_receptors, 4,0,1,2);
296 d_layout->addWidget(d_axonTerminals, 5, 0, 1, 2);
298 contentLayout()->addLayout(d_layout);
300 connect(d_receptors, SIGNAL(collapsed(QModelIndex)), this, SLOT(slotReceptorTreeCollapsed(QModelIndex)));
301 connect(d_receptors, SIGNAL(expanded(QModelIndex)), this, SLOT(slotReceptorTreeExpanded(QModelIndex)));
302 connect(d_receptors, SIGNAL(clicked(QModelIndex)), this, SLOT(slotReceptorItemClicked(QModelIndex)));
303 connect(d_receptors, SIGNAL(vscrollbarShown()), this, SLOT(adjustTreeColumnWidth()));
304 connect(d_receptors, SIGNAL(vscrollbarHidden()), this, SLOT(adjustTreeColumnWidth()));
305 connect(d_axonTerminals, SIGNAL(collapsed(QModelIndex)), this, SLOT(slotAxonTerminalTreeCollapsed(QModelIndex)));
306 connect(d_axonTerminals, SIGNAL(expanded(QModelIndex)), this, SLOT(slotAxonTerminalTreeExpanded(QModelIndex)));
307 connect(d_axonTerminals, SIGNAL(clicked(QModelIndex)), this, SLOT(slotAxonTerminalItemClicked(QModelIndex)));
308 connect(d_axonTerminals, SIGNAL(vscrollbarShown()), this, SLOT(adjustTreeColumnWidth()));
309 connect(d_axonTerminals, SIGNAL(vscrollbarHidden()), this, SLOT(adjustTreeColumnWidth()));
311 connect(d_classButton, SIGNAL(clicked()), this, SLOT(slotCellCodeEditButtonPressed()));
312 connect(d_customScriptButton, SIGNAL(clicked()), this, SLOT(slotCustomScriptEditButtonPressed()));
315 DCToolWindowCellEditor::~DCToolWindowCellEditor()
317 d_receptors->disconnect(this);
318 d_axonTerminals->disconnect(this);
320 if (d_receptorItemModel)
321 d_receptorItemModel->deleteLater();
323 if (d_axonTerminalItemModel)
324 d_axonTerminalItemModel->deleteLater();
327 void DCToolWindowCellEditor::setCell(DCCell *cell)
330 d_cell->disconnect(this);
333 QString title = "CELL:";
336 title.append(QString::fromStdString(cell->getName()));
337 connect(cell, SIGNAL(destroyed(QObject*)), this, SLOT(slotCellDestroyed()));
338 d_comboType->setEditingCell(cell);
341 setButtonedWindowTitle(title);
346 void DCToolWindowCellEditor::updateView()
348 d_isViewUpdating = true;
349 d_receptorItemModel->removeAllItems();
350 d_axonTerminalItemModel->removeAllItems();
352 DCContainer *container = getController()->getCurrentContainer();
354 if (d_cell && container)
356 if (container->getIsScriptable(d_cell->getType()))
358 if (d_cell->getIsCellCodeAssgined())
360 d_classButton->setText(QString::fromStdString(d_cell->getCellCode()->getFQNName()));
364 d_classButton->setText("...");
366 d_classButton->setEnabled(true);
368 d_customScriptButton->setText("Edit...");
369 d_customScriptButton->setEnabled(true);
373 d_classButton->setText("N/A");
374 d_classButton->setEnabled(false);
375 d_customScriptButton->setText("N/A");
376 d_customScriptButton->setEnabled(false);
379 d_comboType->updateSelection();
380 if (container->getIsPluginType(d_cell->getType()))
382 d_comboType->setEnabled(false);
386 d_comboType->setEnabled(!d_cell->getIsCellCodeAssgined());
389 d_textPage->setText(QString::fromStdString(d_cell->getLocation()));
391 d_receptorItemModel->insertString("receptors");
392 d_receptorItemModel->insertColumns(1,2);
393 d_receptorItemModel->setData(d_receptorItemModel->index(0,1), QVariant::fromValue(DCResources::addItemIcon()));
395 d_axonTerminalItemModel->insertString("axonTerminals");
396 d_axonTerminalItemModel->insertColumns(1,2);
397 d_axonTerminalItemModel->setData(d_axonTerminalItemModel->index(0,1), QVariant::fromValue(DCResources::addItemIcon()));
399 const TKReceptorMap *receptors = d_cell->getReceptors();
400 TKReceptorMap::const_iterator it = receptors->begin();
401 QModelIndex rroot = d_receptorItemModel->index(0,0);
403 while( it != receptors->end())
406 QString receptorName = QString::fromStdString((*it).first);
407 d_receptorItemModel->insertString(receptorName,rroot);
408 d_receptorItemModel->setData(rroot.child(i,2), QVariant::fromValue(DCResources::deleteItemIcon()));
410 DCReceptor *receptor = dynamic_cast<DCReceptor*>((*it).second);
411 DCAxonTerminal *terminal = receptor->getTarget();
414 DCCell *targetCell = dynamic_cast<DCCell*>(terminal->getOwner()->getOwner());
417 QString targetPath = DCUtil::getFQNPath(targetCell->getLocation(), targetCell->getName());
418 d_receptorItemModel->insertString(targetPath,rroot.child(i,0));
426 d_receptors->expand(rroot);
427 for (int i = 0; i < d_receptorItemModel->rowCount(rroot); i++)
429 QModelIndex index = rroot.child(i,0);
430 d_receptors->collapse(index);
431 if (d_receptorItemModel->rowCount(index) > 0)
433 d_receptors->collapse(index.child(0,0));
437 QModelIndex aroot = d_axonTerminalItemModel->index(0,0);
438 DCAxon *axon = d_cell->getAxon();
439 int acnt = axon->getNumberOfTerminals();
440 for (int i = 0; i < acnt; i++)
442 DCReceptor *targetReceptor = NULL;
443 DCCell *targetCell = NULL;
444 DCAxonTerminal *tarminal = axon->getTerminalAt(i);
447 targetReceptor = tarminal->getTarget();
450 targetCell = targetReceptor->getOwnerCell();
456 QString targetPath = DCUtil::getFQNPath(targetCell->getLocation(), targetCell->getName());
457 QString targetReceptorName = QString::fromStdString(targetCell->getReceptorName(targetReceptor));
458 d_axonTerminalItemModel->insertString(targetPath,aroot);
459 d_receptorItemModel->setData(aroot.child(i,2), QVariant::fromValue(DCResources::deleteItemIcon()));
460 d_axonTerminalItemModel->insertString(targetReceptorName,aroot.child(i,0));
468 d_axonTerminals->expand(aroot);
469 for (int i = 0; i < d_axonTerminalItemModel->rowCount(aroot); i++)
471 QModelIndex index = aroot.child(i,0);
472 d_axonTerminals->collapse(index);
473 if (d_axonTerminalItemModel->rowCount(index) > 0)
475 d_axonTerminals->collapse(index.child(0,0));
481 d_isViewUpdating = false;
484 void DCToolWindowCellEditor::slotReceptorTreeCollapsed(const QModelIndex &index)
490 void DCToolWindowCellEditor::slotReceptorTreeExpanded(const QModelIndex &index)
496 void DCToolWindowCellEditor::slotReceptorItemClicked(const QModelIndex &index)
498 switch (index.column())
501 qDebug() << "add item clicked..";
502 if (!index.parent().isValid())
504 getController()->doCommandStartAddAxonTerminalFromReceptor(this, d_cell);
509 qDebug() << "delete item clicked..";
510 if (index.parent().row() == 0)
512 int itemRowIndex = index.row();
513 if (itemRowIndex >= 0)
515 QModelIndex itemIndex = d_receptorItemModel->index(itemRowIndex,0,index.parent());
516 QString receptorName = d_receptorItemModel->data(itemIndex,Qt::DisplayRole).toString();
517 if (receptorName.length()>0)
519 d_receptors->setCurrentIndex(itemIndex);
520 getController()->doCommandRemoveAxonTerminal(this, d_cell, receptorName);
527 qDebug() << "other clicked..";
534 void DCToolWindowCellEditor::slotAxonTerminalTreeCollapsed(const QModelIndex &index)
540 void DCToolWindowCellEditor::slotAxonTerminalTreeExpanded(const QModelIndex &index)
546 void DCToolWindowCellEditor::slotAxonTerminalItemClicked(const QModelIndex &index)
548 switch (index.column())
551 qDebug() << "add item clicked..";
552 if (!index.parent().isValid())
554 getController()->doCommandStartAddAxonTerminalFromAxon(this, d_cell);
559 qDebug() << "delete item clicked..";
560 if (index.parent().row() == 0)
562 int itemIndex = index.row();
565 d_axonTerminals->setCurrentIndex(d_axonTerminalItemModel->index(itemIndex,0,index.parent()));
566 getController()->doCommandRemoveAxonTerminal(this, d_cell, d_cell->getAxon()->getTerminalAt(itemIndex));
572 qDebug() << "other clicked..";
578 void DCToolWindowCellEditor::slotCellCodeEditButtonPressed()
580 if (d_cell && d_cell->getCellCode())
582 DCCellScriptsEditorWindow::startEditing(d_cell, true);
586 void DCToolWindowCellEditor::slotCustomScriptEditButtonPressed()
590 DCCellScriptsEditorWindow::startEditing(d_cell, false);
595 // There may be better / proper way to do this.
596 // The goal is to adjust the window height to fit all inside components
597 // with its desigered size.
598 void DCToolWindowCellEditor::resizeView()
601 int spacing = d_layout->verticalSpacing();
602 for (int i = 0 ; i < d_layout->rowCount(); i++ )
604 int maxHeightInRow = 0;
605 for (int j = 0; j < d_layout->columnCount(); j++)
607 QLayoutItem *item = d_layout->itemAtPosition(i,j);
610 QWidget *pWidget = item->widget();
613 QSize sh = pWidget->sizeHint();
614 pWidget->setFixedHeight(sh.height());
615 if (sh.height() > maxHeightInRow)
617 maxHeightInRow = sh.height();
622 totalHeight += maxHeightInRow + spacing;
626 int left,top,right,bottom;
627 contentLayout()->getContentsMargins(&left,&top,&right,&bottom);
628 s.setHeight(totalHeight + getTitleButtonHeight() + top + bottom);
631 adjustTreeColumnWidth();
634 void DCToolWindowCellEditor::adjustTreeColumnWidth()
636 d_receptors->setColumnWidth(1, 18);
637 d_receptors->setColumnWidth(2, 18);
638 QScrollBar *sb = d_receptors->verticalScrollBar();
639 if (sb && sb->isVisible())
640 d_receptors->setColumnWidth(0, d_receptors->width()-44 - sb->width());
642 d_receptors->setColumnWidth(0, d_receptors->width()-42);
644 d_axonTerminals->setColumnWidth(1, 18);
645 d_axonTerminals->setColumnWidth(2, 18);
646 d_axonTerminals->setColumnWidth(0, d_axonTerminals->width()-42);
647 sb = d_axonTerminals->verticalScrollBar();
648 if (sb && sb->isVisible())
649 d_axonTerminals->setColumnWidth(0, d_axonTerminals->width()-44 - sb->width());
651 d_axonTerminals->setColumnWidth(0, d_axonTerminals->width()-42);
654 void DCToolWindowCellEditor::slotCellDestroyed()