nn-usb-fpga/Software/sie_cg/block_editor/diagramscene.cpp

431 lines
14 KiB
C++

/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial Usage
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QtGui>
#include <QHash>
#include "diagramscene.h"
DiagramScene::DiagramScene(QMenu *itemMenu, QObject *parent)
: QGraphicsScene(parent)
{
myItemMenu = itemMenu;
myMode = MoveItem;
line = 0;
textItem = 0;
myItemColor = Qt::white;
myTextColor = Qt::black;
myLineColor = Qt::black;
snapToGrid=1;
myGrid=10;
myPolygonPath=0;
myCorners=0;
TitleText = new DiagramTextItem(0,0,1,0xFFF,255,"BLOCK NAME HERE (not visible)",
QPointF(250,250));
addItem(TitleText);
}
void DiagramScene::editorLostFocus(DiagramTextItem *item)
{
QTextCursor cursor = item->textCursor();
cursor.clearSelection();
item->setTextCursor(cursor);
if (item->toPlainText().isEmpty()) {
removeItem(item);
item->deleteLater();
}
}
void DiagramScene::drawBackground(QPainter *p, const QRectF &r)
{
p -> save();
p -> setRenderHint(QPainter::Antialiasing, false);
p -> setRenderHint(QPainter::TextAntialiasing, true);
p -> setRenderHint(QPainter::SmoothPixmapTransform, false);
p -> setPen(Qt::NoPen);
p -> setBrush(Qt::white);
p -> drawRect(r);
p -> setPen(Qt::gray);
p -> setBrush(Qt::NoBrush);
qreal limite_x = r.x() + r.width();
qreal limite_y = r.y() + r.height();
int g_x = (int)ceil(r.x());
while (g_x % myGrid) ++ g_x;
int g_y = (int)ceil(r.y());
while (g_y % myGrid) ++ g_y;
QPolygon points;
for (int gx = g_x ; gx < limite_x ; gx += myGrid) {
for (int gy = g_y ; gy < limite_y ; gy += myGrid) {
points << QPoint(gx, gy);
}
}
p -> drawPoints(points);
p->drawLine(500,0,500,1000);
p->drawLine(0,500,1000,500);
p -> restore();
}
void DiagramScene::doSnapToGrid(QGraphicsSceneMouseEvent *mouseEvent)
{
if(snapToGrid){
mouseEvent->setScenePos(QPointF(
round(mouseEvent->scenePos().x()/myGrid)*myGrid,
round(mouseEvent->scenePos().y()/myGrid)*myGrid
));
}
}
void DiagramScene::mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent)
{
doSnapToGrid(mouseEvent);
QString Text;
if (mouseEvent->button() != Qt::LeftButton)
return;
switch (myMode)
{
case InsertText:
//TODO: limit text items to 255 maximum
if(myTextType<256)
if(myTextType & 0b10000000)
Text = "IN " +myTypeString;
else
Text = "OUT " +myTypeString;
else
Text = myTypeString;
textItem = new DiagramTextItem(0,0,1,myTextType,0,Text,
mouseEvent->scenePos());
if(addTextItem(textItem))
{
textItem->setZValue(1000.0);
connect(textItem, SIGNAL(lostFocus(DiagramTextItem*)),
this, SLOT(editorLostFocus(DiagramTextItem*)));
addItem(textItem);
}
else
{
delete(textItem);
QMessageBox::warning(0,"Full","The block can only have only"
"255 text items");
}
emit textInserted(textItem);
break;
case EditPolygon:
if(line == 0 && items().indexOf(myPolygonPath)==-1)
{
line = new QGraphicsLineItem(QLineF(mouseEvent->scenePos(),
mouseEvent->scenePos()));
line->setPen(QPen(Qt::blue, 2));
line->setZValue(1000.0);
addItem(line);
}
else if(line != 0 && items().indexOf(myPolygonPath)==-1 &&
line->line().length()>5)
{
myPolygonPath = new Arrow(line->line().p1(),line->line().p2(),
0,this);
QLineF newLine(line->line().p2(),line->line().p2());
line->setLine(newLine);
}
else if(line != 0 && items().indexOf(myPolygonPath)!=-1 &&
line->line().length()>5)
{
myPolygonPath->createCorner(line->line().p1(),myCorners);
myPolygonPath->setEndPoint(line->line().p2());
myPolygonPath->updatePosition();
QLineF newLine(line->line().p2(),line->line().p2());
line->setLine(newLine);
myCorners++;
}
case MoveItem:
QGraphicsScene::mousePressEvent(mouseEvent);
break;
default: ;
}
}
void DiagramScene::mouseMoveEvent(QGraphicsSceneMouseEvent *mouseEvent)
{
doSnapToGrid(mouseEvent);
if (myMode == EditPolygon && line != 0 )
{
QLineF newLine(line->line().p1(), mouseEvent->scenePos());
line->setLine(newLine);
}
QGraphicsScene::mouseMoveEvent(mouseEvent);
}
void DiagramScene::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *mouseEvent)
{
doSnapToGrid(mouseEvent);
if (myMode == EditPolygon && line != 0 && myCorners>0)
{
if(myPolygonPath->getStartPoint()!=line->line().p2())
myPolygonPath->createCorner(line->line().p2(),myCorners);
myPolygonPath->setEndPoint(myPolygonPath->getStartPoint());
myPolygonPath->createFirstCorner();
myPolygonPath->updatePosition();
myCorners=0;
removeItem(line);
line = 0;
myMode = MoveItem;
emit textInserted(textItem);//Is the same for all buttons
}
else if (myMode != EditPolygon)
{
QGraphicsScene::mouseDoubleClickEvent(mouseEvent);
}
}
void DiagramScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *mouseEvent)
{
doSnapToGrid(mouseEvent);
if (myMode != EditPolygon && line == 0)
QGraphicsScene::mouseReleaseEvent(mouseEvent);
}
bool DiagramScene::isItemChange(int type)
{
foreach (QGraphicsItem *item, selectedItems()) {
if (item->type() == type)
return true;
}
return false;
}
QDomDocument DiagramScene::toXmlFormat()
{
QDomDocument document;
QDomComment initialComments=document.createComment(
"File for SIE Code Generator. Custmos Blocks");
document.appendChild(initialComments);
QDomElement diagram = document.createElement("CustomItem");
diagram.setAttribute("BlockName",TitleText->toPlainText());
document.appendChild(diagram);
//Lists of items
QList<DiagramTextItem *> Items;
QList<Arrow *> Arrows;
foreach(QGraphicsItem *item, items())
{
if(item->type() == DiagramTextItem::Type)
Items.append(qgraphicsitem_cast<DiagramTextItem *>(item));
else if(item->type() == Arrow::Type)
Arrows.append(qgraphicsitem_cast<Arrow *>(item));
}
if(Arrows.count()>1) {printf("Something is wrong.\n"); fflush(stdout);}
//Create the XML structure
diagram.appendChild(myPolygonPath->toXml(document));
QDomElement element;
if(Items.count()>0)
{
QDomElement textItems = document.createElement("TextItems");
foreach(DiagramTextItem *item, Items)
{
if(item->styleIO() != 0xFFF)
{
element = item->toXml(document);
element.setAttribute("ID",textItemsByID.key(item));
textItems.appendChild(element);
}
}
diagram.appendChild(textItems);
}
return(document);
}
int DiagramScene::fromXmlFormat(QDomDocument document)
{
//Read items TODO: in future... add multi items on same file
QDomNodeList customsItems = document.elementsByTagName("CustomItem");
if(!customsItems.at(0).isElement())
return -1;
//Load the first item in the document
QDomElement customItem = customsItems.at(0).toElement();
if(customItem.attribute("BlockName")=="")
TitleText->setPlainText("Please set Block Name");
else
TitleText->setPlainText(customItem.attribute("BlockName"));
TitleText->updatePosition();
for (QDomNode node = customItem.firstChild() ;
!node.isNull() ;
node = node.nextSibling())
{
QDomElement element = node.toElement();
if(element.tagName()=="Polygon")
{
QList<QPointF> points;
for (QDomNode node = element.firstChild() ;
!node.isNull() ;
node = node.nextSibling())
{
QDomElement point = node.toElement();
if(point.tagName()!="Point")
return -1;
points.append(QPointF((QPointF(point.attribute("x").toFloat(),0)
+QPointF(500,500)).x(),
(QPointF(0,point.attribute("y").toFloat())
+QPointF(500,500)).y()));
}
if(points.count()>0)
{
myPolygonPath = new Arrow(points.at(0),points.at(0),0,this);
for(int i=1; i< points.count();i++)
{
myPolygonPath->createCorner(points.at(i),i-1);
}
myPolygonPath->createFirstCorner();
myPolygonPath->updatePosition();
}
}
else if(element.tagName()=="TextItems")
{
for (QDomNode node = element.firstChild() ;
!node.isNull() ;
node = node.nextSibling())
{
QDomElement textItemE = node.toElement();
if(textItemE.tagName()!="TextItem")
return -1;
int myStyleIO = textItemE.attribute("myStyleIO").toInt();
int myID = textItemE.attribute("ID").toInt();
bool editableItem = textItemE.attribute("editableItem").toInt();
QPointF posOffset=
QPointF((QPointF(textItemE.attribute("posOffset-x")
.toFloat(),0)+QPointF(500,500)).x(),
(-QPointF(0,textItemE.attribute("posOffset-y")
.toFloat())+QPointF(500,500)).y());
QString itemString=textItemE.attribute("text");
if(myStyleIO==0)
{
if(!editableItem)
myStyleIO=256;
else
myStyleIO=257;
}
DiagramTextItem * newTextItem =
new DiagramTextItem(0,0,1,myStyleIO,myID,itemString,posOffset);
newTextItem->setZValue(1000.0);
connect(newTextItem, SIGNAL(lostFocus(DiagramTextItem*)),
this, SLOT(editorLostFocus(DiagramTextItem*)));
addItem(newTextItem);
textItemsByID.insert(myID,newTextItem);
}
}
}
return 1;
}
void DiagramScene::cleanScene()
{
//Lists of items
QList<DiagramTextItem *> Items;
foreach(QGraphicsItem *item, items())
{
if(item->type() == DiagramTextItem::Type)
Items.append(qgraphicsitem_cast<DiagramTextItem *>(item));
}
//Remove Diagram Text Items
foreach(DiagramTextItem *item, Items)
{
if(item->styleIO() != 0xFFF)
{
removeItem(item);
delete(item);
}
}
//Remove Polygon Path
if(items().indexOf(myPolygonPath)!=-1)
{
myPolygonPath->removeLines();
removeItem(myPolygonPath);
delete(myPolygonPath);
}
TitleText->setPlainText("BLOCK NAME HERE (not visible)");
TitleText->updatePosition();
}
int DiagramScene::addTextItem(DiagramTextItem * textItem)
{
for(int i=0; i<255; i++)
{
QHash<int,DiagramTextItem *>::iterator iter= textItemsByID.find(i);
if(iter==textItemsByID.end())
{
textItemsByID.insert(i,textItem);
return 1;
}
}
return 0;
}
void DiagramScene::removeTextItem(DiagramTextItem * textItem)
{
textItemsByID.remove(textItemsByID.key(textItem));
}