OSDN Git Service

\[denncoCreator\] implemented remove page / cell functionality and several refactoring.
[dennco/denncoCreator.git] / Source / visualizer / toolwindow / dctoolwindowcelleditor.cpp
1 //  Copyright (c) 2012 Dennco Project
2 //
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.
7 //
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.
12 //
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/>.
15
16 //
17 //  Created by tkawata on Sep-30, 2012.
18 //
19 #include "dctoolwindowcelleditor.h"
20
21 #include "dceditablelabel.h"
22 #include "dceditabletreeview.h"
23 #include "dccell.h"
24 #include "dccreator.h"
25 #include "dcreceptor.h"
26 #include "dcaxon.h"
27 #include "dccellcode.h"
28 #include "dcaxonterminal.h"
29 #include "dccontainer.h"
30 #include "utils/dcresources.h"
31 #include "utils/dcqtitemmodel.h"
32
33 #include <QGridLayout>
34 #include <QLineEdit>
35 #include <QTreeView>
36 #include <QSizePolicy>
37 #include <QIcon>
38
39 DCToolWindowCellEditor::DCToolWindowCellEditor(DCCreator *creator) :
40     DCToolWindowBase("CELL:", creator), d_cell(NULL)
41 {
42     d_layout = new QGridLayout;
43     d_layout->setSpacing(6);
44     d_layout->setContentsMargins(0,0,0,0);
45     d_layout->addWidget(new QLabel(tr("page")),0,0);
46     d_layout->addWidget(new QLabel(tr("type")),1,0);
47     d_layout->addWidget(new QLabel(tr("cell code")),2,0);
48     d_layout->addWidget(new QLabel(tr("custom script")),3,0);
49
50     d_detailButton = new QPushButton(tr("detail..."));
51     d_detailButton->setStyleSheet("background-color: rgba(255,255,255,60);");
52
53     d_layout->addWidget(d_detailButton,6,0,1,2);
54
55     d_textPage = new DCEditableLabel(this, "");
56     d_textType = new DCEditableLabel(this, "");
57     d_layout->addWidget(d_textPage, 0,1);
58     d_layout->addWidget(d_textType, 1,1);
59
60     d_classButton = new QPushButton("...");
61     QPushButton *customScriptEditButton = new QPushButton(tr("edit..."));
62
63     d_layout->addWidget(d_classButton, 2,1);
64     d_layout->addWidget(customScriptEditButton, 3,1);
65
66     d_receptors = new DCEditableTreeView(this);
67     d_receptors->setHeaderHidden(true);
68     d_receptors->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
69
70     d_axonTerminals = new DCEditableTreeView(this);
71     d_axonTerminals->setHeaderHidden(true);
72     d_axonTerminals->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
73
74
75     d_receptorItemModel = new DCQtItemModel(QStringList("name"));
76     d_axonTerminalItemModel = new DCQtItemModel(QStringList("name"));
77
78     d_receptors->setModel(d_receptorItemModel);
79     d_axonTerminals->setModel(d_axonTerminalItemModel);
80
81     d_layout->addWidget(d_receptors, 4,0,1,2);
82     d_layout->addWidget(d_axonTerminals, 5, 0, 1, 2);
83
84     contentLayout()->addLayout(d_layout);
85
86     connect(d_receptors, SIGNAL(collapsed(QModelIndex)), this, SLOT(slotReceptorTreeCollapsed(QModelIndex)));
87     connect(d_receptors, SIGNAL(expanded(QModelIndex)), this, SLOT(slotReceptorTreeExpanded(QModelIndex)));
88     connect(d_receptors, SIGNAL(clicked(QModelIndex)), this, SLOT(slotReceptorItemClicked(QModelIndex)));
89     connect(d_receptors, SIGNAL(vscrollbarShown()), this, SLOT(adjustTreeColumnWidth()));
90     connect(d_receptors, SIGNAL(vscrollbarHidden()), this, SLOT(adjustTreeColumnWidth()));
91     connect(d_axonTerminals, SIGNAL(collapsed(QModelIndex)), this, SLOT(slotAxonTerminalTreeCollapsed(QModelIndex)));
92     connect(d_axonTerminals, SIGNAL(expanded(QModelIndex)), this, SLOT(slotAxonTerminalTreeExpanded(QModelIndex)));
93     connect(d_axonTerminals, SIGNAL(clicked(QModelIndex)), this, SLOT(slotAxonTerminalItemClicked(QModelIndex)));
94     connect(d_axonTerminals, SIGNAL(vscrollbarShown()), this, SLOT(adjustTreeColumnWidth()));
95     connect(d_axonTerminals, SIGNAL(vscrollbarHidden()), this, SLOT(adjustTreeColumnWidth()));
96
97     connect(d_classButton, SIGNAL(clicked()), this, SLOT(slotCellCodeEditButtonPressed()));
98     connect(customScriptEditButton, SIGNAL(clicked()), this, SLOT(slotCustomScriptEditButtonPressed()));
99
100 }
101
102 DCToolWindowCellEditor::~DCToolWindowCellEditor()
103 {
104     d_receptors->disconnect(this);
105     d_axonTerminals->disconnect(this);
106
107     if (d_receptorItemModel)
108         d_receptorItemModel->deleteLater();
109
110     if (d_axonTerminalItemModel)
111         d_axonTerminalItemModel->deleteLater();
112 }
113
114 void DCToolWindowCellEditor::setCell(DCCell *cell)
115 {
116     d_cell = cell;
117     QString title = "CELL:";
118     if (cell)
119     {
120         title.append(QString::fromStdString(cell->getName()));
121         if (cell->getCellCode() && cell->getCellCode() != getController()->getCurrentContainer()->getEmptyCellCodeClass())
122         {
123             d_classButton->setText(QString::fromStdString(cell->getCellCode()->getName()));
124         }
125         else
126         {
127             d_classButton->setText("...");
128         }
129         connect(cell, SIGNAL(destroyed(QObject*)), this, SLOT(slotCellDestroyed()));
130     }
131
132     setButtonedWindowTitle(title);
133
134     updateView();
135 }
136
137 void DCToolWindowCellEditor::updateView()
138 {
139     d_receptorItemModel->removeAllItems();
140     d_axonTerminalItemModel->removeAllItems();
141
142     if (d_cell)
143     {
144         d_textPage->setText(QString::fromStdString(d_cell->getLocation()));
145         d_textType->setText(d_cell->getType());
146
147         d_receptorItemModel->insertString("receptors");
148         d_receptorItemModel->insertColumns(1,2);
149         d_receptorItemModel->setReadOnly(0,false);
150         d_receptorItemModel->setData(d_receptorItemModel->index(0,1), QVariant::fromValue(DCResources::addItemIcon()));
151
152         d_axonTerminalItemModel->insertString("axonTerminals");
153         d_axonTerminalItemModel->insertColumns(1,2);
154         d_axonTerminalItemModel->setReadOnly(0,false);
155         d_axonTerminalItemModel->setData(d_axonTerminalItemModel->index(0,1), QVariant::fromValue(DCResources::addItemIcon()));
156
157         const TKReceptorMap *receptors = d_cell->getReceptors();
158         TKReceptorMap::const_iterator it = receptors->begin();
159         QModelIndex rroot = d_receptorItemModel->index(0,0);
160         int i = 0;
161         while( it != receptors->end())
162         {
163
164             QString receptorName = QString::fromStdString((*it).first);
165             d_receptorItemModel->insertString(receptorName,rroot);
166             d_receptorItemModel->setData(rroot.child(i,2), QVariant::fromValue(DCResources::deleteItemIcon()));
167             ++it;
168             ++i;
169         }
170
171         QModelIndex aroot = d_axonTerminalItemModel->index(0,0);
172         DCAxon *axon = d_cell->getAxon();
173         int acnt = axon->getNumberOfTerminals();
174         for (int i = 0; i < acnt; i++)
175         {
176             DCReceptor *targetReceptor = NULL;
177             DCCell *targetCell = NULL;
178             DCAxonTerminal *tarminal = axon->getTerminalAt(i);
179             if (tarminal)
180             {
181                 targetReceptor = dynamic_cast<DCReceptor*>(tarminal->getTarget());
182                 if (targetReceptor)
183                 {
184                     targetCell = dynamic_cast<DCCell*>(targetReceptor->getOwnerCell());
185                 }
186             }
187             QString axonTerminalName;
188
189             if (targetCell)
190             {
191                 QTextStream(&axonTerminalName)
192                         << QString::fromStdString(targetCell->getLocation())
193                         << "/"
194                         << QString::fromStdString(targetCell->getName())
195                         << "#"
196                         << QString::fromStdString(targetCell->getReceptorName(targetReceptor));
197             }
198             else
199             {
200                 axonTerminalName = "-";
201             }
202
203             d_axonTerminalItemModel->insertString(axonTerminalName,aroot);
204             d_receptorItemModel->setData(aroot.child(i,2), QVariant::fromValue(DCResources::deleteItemIcon()));
205         }
206         d_receptors->expandAll();
207         d_axonTerminals->expandAll();
208
209         resizeView();
210     }
211 }
212
213 void DCToolWindowCellEditor::slotReceptorTreeCollapsed(const QModelIndex &index)
214 {
215     resizeView();
216 }
217
218 void DCToolWindowCellEditor::slotReceptorTreeExpanded(const QModelIndex &index)
219 {
220     resizeView();
221 }
222
223 void DCToolWindowCellEditor::slotReceptorItemClicked(const QModelIndex &index)
224 {
225     switch (index.column())
226     {
227     case 1:
228         qDebug() << "add item clicked..";
229         if (!index.parent().isValid())
230         {
231             getController()->doCommandStartAddAxonTerminalFromReceptor(this, d_cell);
232         }
233         break;
234
235     case 2:
236         qDebug() << "delete item clicked..";
237         if (index.parent().row() == 0)
238         {
239             int itemRowIndex = index.row();
240             if (itemRowIndex >= 0)
241             {
242                 QModelIndex itemIndex = d_receptorItemModel->index(itemRowIndex,0,index.parent());
243                 QString receptorName = d_receptorItemModel->data(itemIndex,Qt::DisplayRole).toString();
244                 if (receptorName.length()>0)
245                 {
246                     d_receptors->setCurrentIndex(itemIndex);
247                     getController()->doCommandRemoveAxonTerminal(this, d_cell, receptorName);
248                 }
249             }
250         }
251         break;
252
253     default:
254         qDebug() << "other clicked..";
255         break;
256
257     }
258
259 }
260
261 void DCToolWindowCellEditor::slotAxonTerminalTreeCollapsed(const QModelIndex &index)
262 {
263     resizeView();
264 }
265
266 void DCToolWindowCellEditor::slotAxonTerminalTreeExpanded(const QModelIndex &index)
267 {
268     resizeView();
269 }
270
271 void DCToolWindowCellEditor::slotAxonTerminalItemClicked(const QModelIndex &index)
272 {
273     switch (index.column())
274     {
275     case 1:
276         qDebug() << "add item clicked..";
277         if (!index.parent().isValid())
278         {
279             getController()->doCommandStartAddAxonTerminalFromAxon(this, d_cell);
280         }
281         break;
282
283     case 2:
284         qDebug() << "delete item clicked..";
285         if (index.parent().row() == 0)
286         {
287             int itemIndex = index.row();
288             if (itemIndex >= 0)
289             {
290                 d_axonTerminals->setCurrentIndex(d_axonTerminalItemModel->index(itemIndex,0,index.parent()));
291                 getController()->doCommandRemoveAxonTerminal(this, d_cell, d_cell->getAxon()->getTerminalAt(itemIndex));
292             }
293         }
294         break;
295
296     default:
297         qDebug() << "other clicked..";
298         break;
299
300     }
301 }
302
303 void DCToolWindowCellEditor::slotCellCodeEditButtonPressed()
304 {
305     if (d_cell)
306     {
307         getController()->doCommandStartEditCellCode(this, d_cell);
308     }
309 }
310
311 void DCToolWindowCellEditor::slotCustomScriptEditButtonPressed()
312 {
313     if (d_cell)
314     {
315         getController()->doCommandStartEditCellCode(this, d_cell);
316     }
317 }
318
319 // TODO
320 // There may be better / proper way to do this.
321 // The goal is to adjust the window height to fit all inside components
322 // with its desigered size.
323 void DCToolWindowCellEditor::resizeView()
324 {
325     int totalHeight = 0;
326     int spacing = d_layout->verticalSpacing();
327     for (int i = 0 ; i < d_layout->rowCount(); i++ )
328     {
329         int maxHeightInRow = 0;
330         for (int j = 0; j < d_layout->columnCount(); j++)
331         {
332             QLayoutItem *item = d_layout->itemAtPosition(i,j);
333             if (item)
334             {
335                 QWidget *pWidget = item->widget();
336                 if (pWidget)
337                 {
338                     QSize sh = pWidget->sizeHint();
339                     pWidget->setFixedHeight(sh.height());
340                     if (sh.height() > maxHeightInRow)
341                     {
342                         maxHeightInRow = sh.height();
343                     }
344                 }
345             }
346         }
347         totalHeight += maxHeightInRow  + spacing;
348     }
349
350     QSize s = size();
351     int left,top,right,bottom;
352     contentLayout()->getContentsMargins(&left,&top,&right,&bottom);
353     s.setHeight(totalHeight + getTitleButtonHeight() + top + bottom);
354     resize(s);
355
356     adjustTreeColumnWidth();
357 }
358
359 void DCToolWindowCellEditor::adjustTreeColumnWidth()
360 {
361     d_receptors->setColumnWidth(1, 18);
362     d_receptors->setColumnWidth(2, 18);
363     QScrollBar *sb = d_receptors->verticalScrollBar();
364     if (sb && sb->isVisible())
365         d_receptors->setColumnWidth(0, d_receptors->width()-44 - sb->width());
366     else
367         d_receptors->setColumnWidth(0, d_receptors->width()-42);
368
369     d_axonTerminals->setColumnWidth(1, 18);
370     d_axonTerminals->setColumnWidth(2, 18);
371     d_axonTerminals->setColumnWidth(0, d_axonTerminals->width()-42);
372     sb = d_axonTerminals->verticalScrollBar();
373     if (sb && sb->isVisible())
374         d_axonTerminals->setColumnWidth(0, d_axonTerminals->width()-44 - sb->width());
375     else
376         d_axonTerminals->setColumnWidth(0, d_axonTerminals->width()-42);
377 }
378
379 void DCToolWindowCellEditor::slotCellDestroyed()
380 {
381     setCell(NULL);
382 }