Hardware Design: SIE
Sign in or create your account | Project List | Help
Hardware Design: SIE Git Source Tree
Root/
Source at commit 2efe106cf30654a74ec979a00de820e2aca3021e created 13 years 4 months ago. By Juan64Bits, Adding bases to the code generator. Code text edit, fixing input/output ID control, etc. | |
---|---|
1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). |
4 | ** All rights reserved. |
5 | ** Contact: Nokia Corporation (qt-info@nokia.com) |
6 | ** |
7 | ** This file is part of the examples of the Qt Toolkit. |
8 | ** |
9 | ** $QT_BEGIN_LICENSE:LGPL$ |
10 | ** Commercial Usage |
11 | ** Licensees holding valid Qt Commercial licenses may use this file in |
12 | ** accordance with the Qt Commercial License Agreement provided with the |
13 | ** Software or, alternatively, in accordance with the terms contained in |
14 | ** a written agreement between you and Nokia. |
15 | ** |
16 | ** GNU Lesser General Public License Usage |
17 | ** Alternatively, this file may be used under the terms of the GNU Lesser |
18 | ** General Public License version 2.1 as published by the Free Software |
19 | ** Foundation and appearing in the file LICENSE.LGPL included in the |
20 | ** packaging of this file. Please review the following information to |
21 | ** ensure the GNU Lesser General Public License version 2.1 requirements |
22 | ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
23 | ** |
24 | ** In addition, as a special exception, Nokia gives you certain additional |
25 | ** rights. These rights are described in the Nokia Qt LGPL Exception |
26 | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
27 | ** |
28 | ** GNU General Public License Usage |
29 | ** Alternatively, this file may be used under the terms of the GNU |
30 | ** General Public License version 3.0 as published by the Free Software |
31 | ** Foundation and appearing in the file LICENSE.GPL included in the |
32 | ** packaging of this file. Please review the following information to |
33 | ** ensure the GNU General Public License version 3.0 requirements will be |
34 | ** met: http://www.gnu.org/copyleft/gpl.html. |
35 | ** |
36 | ** If you have questions regarding the use of this file, please contact |
37 | ** Nokia at qt-info@nokia.com. |
38 | ** $QT_END_LICENSE$ |
39 | ** |
40 | ****************************************************************************/ |
41 | |
42 | #include <QtGui> |
43 | #include <QHash> |
44 | #include "diagramscene.h" |
45 | #include "arrow.h" |
46 | |
47 | DiagramScene::DiagramScene(QMenu *itemMenu, MainWindow *ownerWindow, |
48 | QObject *parent) |
49 | : QGraphicsScene(parent) |
50 | { |
51 | myItemMenu = itemMenu; |
52 | myMode = MoveItem; |
53 | myItemType = ""; |
54 | line = 0; |
55 | textItem = 0; |
56 | myItemColor = Qt::white; |
57 | myTextColor = Qt::black; |
58 | myLineColor = Qt::black; |
59 | snapToGrid=1; |
60 | myGrid=10; |
61 | drawGrid=1; |
62 | myOwnerWindow=ownerWindow; |
63 | } |
64 | |
65 | void DiagramScene::setLineColor(const QColor &color) |
66 | { |
67 | myLineColor = color; |
68 | if (isItemChange(Arrow::Type)) { |
69 | Arrow *item = |
70 | qgraphicsitem_cast<Arrow *>(selectedItems().first()); |
71 | item->setColor(myLineColor); |
72 | update(); |
73 | } |
74 | } |
75 | |
76 | void DiagramScene::setTextColor(const QColor &color) |
77 | { |
78 | myTextColor = color; |
79 | if (isItemChange(DiagramTextItem::Type)) { |
80 | DiagramTextItem *item = |
81 | qgraphicsitem_cast<DiagramTextItem *>(selectedItems().first()); |
82 | item->setDefaultTextColor(myTextColor); |
83 | } |
84 | } |
85 | |
86 | void DiagramScene::setItemColor(const QColor &color) |
87 | { |
88 | myItemColor = color; |
89 | if (isItemChange(DiagramItem::Type)) { |
90 | DiagramItem *item = |
91 | qgraphicsitem_cast<DiagramItem *>(selectedItems().first()); |
92 | item->setColor(myItemColor); |
93 | } |
94 | } |
95 | |
96 | void DiagramScene::setFont(const QFont &font) |
97 | { |
98 | myFont = font; |
99 | |
100 | if (isItemChange(DiagramTextItem::Type)) { |
101 | QGraphicsTextItem *item = |
102 | qgraphicsitem_cast<DiagramTextItem *>(selectedItems().first()); |
103 | //At this point the selection can change so the first selected item might not be a DiagramTextItem |
104 | if (item) |
105 | item->setFont(myFont); |
106 | } |
107 | } |
108 | |
109 | void DiagramScene::setMode(Mode mode) |
110 | { |
111 | myMode = mode; |
112 | } |
113 | |
114 | void DiagramScene::setItemType(QString type) |
115 | { |
116 | myItemType = type; |
117 | } |
118 | |
119 | void DiagramScene::editorLostFocus(DiagramTextItem *item) |
120 | { |
121 | QTextCursor cursor = item->textCursor(); |
122 | cursor.clearSelection(); |
123 | item->setTextCursor(cursor); |
124 | |
125 | if (item->toPlainText().isEmpty()) { |
126 | removeItem(item); |
127 | item->deleteLater(); |
128 | } |
129 | } |
130 | |
131 | void DiagramScene::mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent) |
132 | { |
133 | doSnapToGrid(mouseEvent); |
134 | |
135 | if (mouseEvent->button() != Qt::LeftButton) |
136 | return; |
137 | |
138 | DiagramItem *item; |
139 | switch (myMode) { |
140 | case InsertItem: |
141 | item = new DiagramItem(myItemMenu,myItemType, |
142 | domElementsByName.value(myItemType),0,this); |
143 | item->setColor(myItemColor); |
144 | addItem(item); |
145 | item->setPos(mouseEvent->scenePos()); |
146 | emit itemInserted(item); |
147 | break; |
148 | case InsertLine: |
149 | line = new QGraphicsLineItem(QLineF(mouseEvent->scenePos(), |
150 | mouseEvent->scenePos())); |
151 | line->setPen(QPen(myLineColor, 2)); |
152 | line->setZValue(1000.0); |
153 | addItem(line); |
154 | snapToGrid=0; |
155 | break; |
156 | case InsertText: |
157 | textItem = new DiagramTextItem(); |
158 | textItem->setFont(myFont); |
159 | textItem->setTextInteractionFlags(Qt::TextEditorInteraction); |
160 | textItem->setZValue(1000.0); |
161 | connect(textItem, SIGNAL(lostFocus(DiagramTextItem*)), |
162 | this, SLOT(editorLostFocus(DiagramTextItem*))); |
163 | connect(textItem, SIGNAL(selectedChange(QGraphicsItem*)), |
164 | this, SIGNAL(itemSelected(QGraphicsItem*))); |
165 | addItem(textItem); |
166 | textItem->setDefaultTextColor(myTextColor); |
167 | textItem->setPos(mouseEvent->scenePos()); |
168 | emit textInserted(textItem); |
169 | default: |
170 | ; |
171 | } |
172 | QGraphicsScene::mousePressEvent(mouseEvent); |
173 | } |
174 | |
175 | void DiagramScene::doSnapToGrid(QGraphicsSceneMouseEvent *mouseEvent) |
176 | { |
177 | if(snapToGrid){ |
178 | mouseEvent->setScenePos(QPointF( |
179 | round(mouseEvent->scenePos().x()/myGrid)*myGrid, |
180 | round(mouseEvent->scenePos().y()/myGrid)*myGrid |
181 | )); |
182 | } |
183 | } |
184 | |
185 | void DiagramScene::mouseMoveEvent(QGraphicsSceneMouseEvent *mouseEvent) |
186 | { |
187 | doSnapToGrid(mouseEvent); |
188 | if (myMode == InsertLine && line != 0) { |
189 | QLineF newLine(line->line().p1(), mouseEvent->scenePos()); |
190 | line->setLine(newLine); |
191 | } else if (myMode == MoveItem) { |
192 | QGraphicsScene::mouseMoveEvent(mouseEvent); |
193 | } |
194 | } |
195 | |
196 | void DiagramScene::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *mouseEvent) |
197 | { |
198 | doSnapToGrid(mouseEvent); |
199 | QGraphicsScene::mouseDoubleClickEvent(mouseEvent); |
200 | } |
201 | |
202 | void DiagramScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *mouseEvent) |
203 | { |
204 | doSnapToGrid(mouseEvent); |
205 | if (line != 0 && myMode == InsertLine) { |
206 | QList<QGraphicsItem *> startItems = items(line->line().p1()); |
207 | if (startItems.count() && startItems.first() == line) |
208 | startItems.removeFirst(); |
209 | QList<QGraphicsItem *> endItems = items(line->line().p2()); |
210 | if (endItems.count() && endItems.first() == line) |
211 | endItems.removeFirst(); |
212 | |
213 | removeItem(line); |
214 | delete line; |
215 | //Diferents items and valid type |
216 | if (startItems.count() > 0 && endItems.count() > 0 && |
217 | startItems.first()->type() == DiagramTextItem::Type && |
218 | endItems.first()->type() == DiagramTextItem::Type && |
219 | startItems.first() != endItems.first()) |
220 | { |
221 | DiagramTextItem *startItem_ = |
222 | qgraphicsitem_cast<DiagramTextItem *>(startItems.first()); |
223 | DiagramTextItem *endItem_ = |
224 | qgraphicsitem_cast<DiagramTextItem *>(endItems.first()); |
225 | |
226 | //Real first and end item |
227 | DiagramTextItem *startItem = startItem_; |
228 | DiagramTextItem *endItem = endItem_; |
229 | if(startItem_->styleIO()>>7) |
230 | { |
231 | startItem = endItem_; |
232 | endItem = startItem_; |
233 | } |
234 | |
235 | //Inputs to outputs and diferent owner diagram item |
236 | if(startItem->styleIO()>0 && |
237 | endItem->styleIO()>0 && |
238 | (startItem->styleIO()>>7 != endItem->styleIO()>>7) && |
239 | (startItem->ownerItem() != endItem->ownerItem()) && |
240 | !endItem->ownerItem()->existArrow(startItem,endItem) |
241 | ) |
242 | { |
243 | Arrow *arrow = new Arrow(startItem, endItem,0,this); |
244 | arrow->setColor(myLineColor); |
245 | startItem->ownerItem()->addArrow(arrow); |
246 | endItem->ownerItem()->addArrow(arrow); |
247 | arrow->setZValue(0.0); |
248 | addItem(arrow); |
249 | arrow->updatePosition(); |
250 | } |
251 | } |
252 | } |
253 | line = 0; |
254 | snapToGrid=1; |
255 | QGraphicsScene::mouseReleaseEvent(mouseEvent); |
256 | } |
257 | |
258 | bool DiagramScene::isItemChange(int type) |
259 | { |
260 | foreach (QGraphicsItem *item, selectedItems()) { |
261 | if (item->type() == type) |
262 | return true; |
263 | } |
264 | return false; |
265 | } |
266 | |
267 | QDomDocument DiagramScene::toXmlFormat() |
268 | { |
269 | QDomDocument document; |
270 | QDomComment initialComments=document.createComment( |
271 | "\nFile for SIE Code Generator.\n" |
272 | "**WARNING**If you are going to edit this file note that:\n" |
273 | "In order to segmentation faults prevention the load process \n" |
274 | "is started loading the libraries, then items and finally arrows.\n" |
275 | "Arrows depend of items, and items depend of libraries!!!!\n"); |
276 | document.appendChild(initialComments); |
277 | QDomElement diagram = document.createElement("Diagram"); |
278 | document.appendChild(diagram); |
279 | |
280 | //Lists of items |
281 | QList<DiagramItem *> Items; |
282 | QList<Arrow *> Arrows; |
283 | foreach(QGraphicsItem *item, items()) |
284 | { |
285 | if(item->type() == DiagramItem::Type) |
286 | Items.append(qgraphicsitem_cast<DiagramItem *>(item)); |
287 | else if(item->type() == Arrow::Type) |
288 | Arrows.append(qgraphicsitem_cast<Arrow *>(item)); |
289 | } |
290 | //Create the XML structure |
291 | QDomElement element; |
292 | if(!libraryList.isEmpty()) |
293 | { |
294 | QDomElement libraries = document.createElement("Libraries"); |
295 | foreach(QString lib, libraryList) |
296 | { |
297 | element = document.createElement("Library"); |
298 | element.setAttribute("Dir",lib); |
299 | libraries.appendChild(element); |
300 | } |
301 | diagram.appendChild(libraries); |
302 | |
303 | } |
304 | if(!Items.isEmpty()) |
305 | { |
306 | QDomElement diagramItems = document.createElement("DiagramItems"); |
307 | foreach(DiagramItem *item, Items) |
308 | { |
309 | element = item->toXml(document); |
310 | element.setAttribute("ID",Items.indexOf(item)); //save index |
311 | diagramItems.appendChild(element); |
312 | } |
313 | diagram.appendChild(diagramItems); |
314 | } |
315 | if(!Arrows.isEmpty()) |
316 | { |
317 | QDomElement arrowItems = document.createElement("Arrows"); |
318 | foreach(Arrow *item, Arrows) |
319 | { |
320 | element = item->toXml(document,Items); |
321 | element.setAttribute("ID",Arrows.indexOf(item)); //save index |
322 | arrowItems.appendChild(element); |
323 | } |
324 | diagram.appendChild(arrowItems); |
325 | } |
326 | return(document); |
327 | } |
328 | |
329 | int DiagramScene::fromXmlFormat(QDomDocument document) |
330 | { |
331 | //Read diagrams TODO: in future... add multi projects functionality |
332 | DiagramsID.clear(); |
333 | QDomNodeList diagrams = document.elementsByTagName("Diagram"); |
334 | if(!diagrams.at(0).isElement()) |
335 | return 0; |
336 | //Load the first diagram in the document |
337 | QDomElement diagram = diagrams.at(0).toElement(); |
338 | //In order to segmentation faults prevention the load process |
339 | //is started loading the libraries, then items and finally arrows. |
340 | //Arrows depend of items, and items depend of libraries!!! |
341 | //TODO: rewrite this process for reading in the order specified |
342 | for (QDomNode node = diagram.firstChild() ; |
343 | !node.isNull() ; |
344 | node = node.nextSibling()) |
345 | { |
346 | QDomElement element = node.toElement(); |
347 | if(element.tagName()=="Libraries") |
348 | { |
349 | libraryList.clear(); |
350 | for (QDomNode node = element.firstChild() ; |
351 | !node.isNull() ; |
352 | node = node.nextSibling()) |
353 | { |
354 | //Load library directory |
355 | QDomElement Library = node.toElement(); |
356 | if(Library.tagName()!="Library") |
357 | return 0; |
358 | libraryList.append(Library.attribute("Dir")); |
359 | } |
360 | myOwnerWindow->updateLibraries(); |
361 | } |
362 | else if(element.tagName()=="DiagramItems") //Load diagram items |
363 | { |
364 | for (QDomNode node = element.firstChild() ; |
365 | !node.isNull() ; |
366 | node = node.nextSibling()) |
367 | { |
368 | //Load diagram item and add to scene |
369 | QDomElement diagramItem = node.toElement(); |
370 | if(diagramItem.tagName()!="DiagramItem") |
371 | return 0; |
372 | |
373 | QPointF position = QPointF(diagramItem.attribute("x").toFloat(), |
374 | diagramItem.attribute("y").toFloat()); |
375 | //PREVENT Segmentation faults: |
376 | if(!domElementsByName.contains( |
377 | diagramItem.attribute("type"))) |
378 | { |
379 | QMessageBox::critical(0,"Error",QObject::tr( |
380 | "Diagram can't be loaded, because the" |
381 | " library for block [") + |
382 | diagramItem.attribute("type") +tr( |
383 | "] can't be found.")); |
384 | return 0; |
385 | } |
386 | |
387 | DiagramItem *newItem=new DiagramItem( |
388 | myItemMenu, |
389 | diagramItem.attribute("type"), |
390 | domElementsByName.value(diagramItem.attribute("type")), |
391 | 0,this, position, |
392 | diagramItem.attribute("z").toDouble()); |
393 | |
394 | newItem->setColor(QColor(diagramItem.attribute("color"))); |
395 | |
396 | addItem(newItem); |
397 | DiagramsID.insert(diagramItem.attribute("ID").toInt(),newItem); |
398 | for (QDomNode node = diagramItem.firstChild() ; |
399 | !node.isNull() ; |
400 | node = node.nextSibling()) |
401 | { |
402 | //Load diagram text values and set on diagram item |
403 | QDomElement diagramValues = node.toElement(); |
404 | if(diagramValues.tagName()!="diagramValues") |
405 | return 0; |
406 | |
407 | for (QDomNode node = diagramValues.firstChild() ; |
408 | !node.isNull() ; |
409 | node = node.nextSibling()) |
410 | { |
411 | QDomElement diagramValue = node.toElement(); |
412 | if(diagramValue.tagName()!="diagramValue") |
413 | return 0; |
414 | newItem->setValue(diagramValue.attribute("ID").toInt(), |
415 | diagramValue.attribute("value")); |
416 | } |
417 | } |
418 | } |
419 | } |
420 | else if(element.tagName()=="Arrows") |
421 | { |
422 | |
423 | for (QDomNode node = element.firstChild() ; |
424 | !node.isNull() ; |
425 | node = node.nextSibling()) |
426 | { |
427 | //Load arrow item and add to scene |
428 | QDomElement arrow = node.toElement(); |
429 | if(arrow.tagName()!="Arrow") |
430 | return 0; |
431 | |
432 | DiagramTextItem *startItem= |
433 | DiagramsID.value(arrow.attribute("start-Owner").toInt()) |
434 | ->pointerText(arrow.attribute("start-ID").toInt()); |
435 | bool startIsIO = |
436 | DiagramsID.value(arrow.attribute("start-Owner").toInt()) |
437 | ->textIsIO(arrow.attribute("start-ID").toInt()); |
438 | DiagramTextItem *endItem= |
439 | DiagramsID.value(arrow.attribute("end-Owner").toInt()) |
440 | ->pointerText(arrow.attribute("end-ID").toInt()); |
441 | bool endIsIO = |
442 | DiagramsID.value(arrow.attribute("end-Owner").toInt()) |
443 | ->textIsIO(arrow.attribute("end-ID").toInt()); |
444 | |
445 | if(!startIsIO||!endIsIO) |
446 | { |
447 | QMessageBox::warning(0,"Arrow can't be loaded.", |
448 | tr("An arrow can not be loaded because ")+ |
449 | tr("will be connected to a label")+ |
450 | tr(" that isn't an Input/Output type. ")+ |
451 | tr("Probable cause may be that the start")+ |
452 | tr(" or end block has been modified.")); |
453 | } |
454 | else if(startItem==0 || endItem==0) |
455 | { |
456 | QMessageBox::warning(0,"Arrow can't be loaded", |
457 | tr("An arrow can not be loaded because ")+ |
458 | tr("her IO label ID could not be found. ")+ |
459 | tr("Probable cause may be that the start")+ |
460 | tr(" or end block has been modified.")); |
461 | } |
462 | else |
463 | { |
464 | Arrow *newArrow = new Arrow(startItem, endItem,0,this); |
465 | newArrow->setColor(QColor(arrow.attribute("color"))); |
466 | startItem->ownerItem()->addArrow(newArrow); |
467 | endItem->ownerItem()->addArrow(newArrow); |
468 | newArrow->setZValue(0.0); |
469 | addItem(newArrow); |
470 | newArrow->updatePosition(); |
471 | |
472 | for (QDomNode node = arrow.firstChild() ; |
473 | !node.isNull() ; |
474 | node = node.nextSibling()) |
475 | { |
476 | //Load diagram text values and set on diagram item |
477 | QDomElement arrowCorners = node.toElement(); |
478 | if(arrowCorners.tagName()!="arrowCorners") |
479 | return 0; |
480 | int i=0; |
481 | for (QDomNode node = arrowCorners.firstChild() ; |
482 | !node.isNull() ; |
483 | node = node.nextSibling()) |
484 | { |
485 | QDomElement arrowCorner = node.toElement(); |
486 | if(arrowCorner.tagName()!="arrowCorner") |
487 | return 0; |
488 | |
489 | QPointF cornerPos = |
490 | QPointF(arrowCorner.attribute("x").toFloat(), |
491 | arrowCorner.attribute("y").toFloat()); |
492 | |
493 | newArrow->createCorner(cornerPos,++i); |
494 | } |
495 | } |
496 | } |
497 | } |
498 | } |
499 | } |
500 | |
501 | return 1; |
502 | } |
503 | |
504 | void DiagramScene::cleanScene() |
505 | { |
506 | //Lists of items |
507 | QList<DiagramItem *> Items; |
508 | QList<Arrow *> Arrows; |
509 | foreach(QGraphicsItem *item, items()) |
510 | { |
511 | if(item->type() == DiagramItem::Type) |
512 | Items.append(qgraphicsitem_cast<DiagramItem *>(item)); |
513 | else if(item->type() == Arrow::Type) |
514 | Arrows.append(qgraphicsitem_cast<Arrow *>(item)); |
515 | } |
516 | //Delete only DiagramItems: When a diagramitem is deleted his arrows and |
517 | //textitems have to be deleted too, so if we delete only diagramitems then |
518 | //we are deleting all items in the scene. This is in order to prevent |
519 | //segmentation faults. |
520 | foreach(DiagramItem *item, Items) |
521 | { |
522 | item->removeArrows(); |
523 | item->removeTextItems(); |
524 | removeItem(item); |
525 | delete(item); |
526 | } |
527 | //Delete the text items without parents |
528 | foreach(QGraphicsItem *item, items()) |
529 | { |
530 | removeItem(item); |
531 | delete(item); |
532 | } |
533 | } |
534 | |
535 | void DiagramScene::drawBackground(QPainter *p, const QRectF &r) |
536 | { |
537 | QGraphicsScene::drawBackground(p,r); |
538 | if(drawGrid) |
539 | { |
540 | p -> save(); |
541 | |
542 | p -> setRenderHint(QPainter::Antialiasing, false); |
543 | p -> setRenderHint(QPainter::TextAntialiasing, true); |
544 | p -> setRenderHint(QPainter::SmoothPixmapTransform, false); |
545 | |
546 | p -> setPen(Qt::NoPen); |
547 | p -> setBrush(Qt::white); |
548 | p -> drawRect(r); |
549 | |
550 | |
551 | p -> setPen(Qt::black); |
552 | p -> setBrush(Qt::NoBrush); |
553 | qreal limite_x = r.x() + r.width(); |
554 | qreal limite_y = r.y() + r.height(); |
555 | |
556 | int g_x = (int)ceil(r.x()); |
557 | while (g_x % myGrid) ++ g_x; |
558 | int g_y = (int)ceil(r.y()); |
559 | while (g_y % myGrid) ++ g_y; |
560 | |
561 | QPolygon points; |
562 | for (int gx = g_x ; gx < limite_x ; gx += myGrid) { |
563 | for (int gy = g_y ; gy < limite_y ; gy += myGrid) { |
564 | points << QPoint(gx, gy); |
565 | } |
566 | } |
567 | p -> drawPoints(points); |
568 | p -> restore(); |
569 | } |
570 | } |
571 |
Branches:
master