nodeeditor_doxy
src/Impl/nodeitem.cpp
Go to the documentation of this file.
00001 //dw 
00002 //#include <QtGui>
00003 
00004 #include "NodeItem.h"
00005 //#include "arrow.h"
00006 //dw
00007 //#include "nodeconnector.h"
00008 
00009 
00010 /*//dw FIXME:only proxified
00011 void NodeItem::hide() {
00012         this->widget()->close();
00013 }
00014 //dw slot
00015 void NodeItem::deleted() {
00016         this->widget()->close();
00017         //delete this;
00018 }
00019 void NodeItem::deleted(int result) {
00020         this->widget()->close();
00021 }
00022 */
00023 
00024 NodeItem::~NodeItem() {
00025         removeWigetFromConnectors();
00026         //deleteConnections();
00027         //dw new 
00028         if (scene() != NULL) {
00029                 this->scene()->removeItem(this);
00030         }
00031 }
00032 
00034 NodeItem::NodeItem(QMenu *contextMenu,
00035                                          QGraphicsItem *parent, /*//dw can we really assume our scene type*/ QGraphicsScene /*DiagramScene*/ *scene, Qt::WindowFlags wFlags)
00036                          : /*QGraphicsPolygonItem(parent, scene) //dw*/ /*QFrame(parent->parentWidget(), 0)*/
00037 QGraphicsObject(parent/*, /* //dw668: did this cause decorations now in 4.7 but no in 4.5.2?: Qt::Window*/ /*//dw FIXME:only proxifiedwFlags*/), mMaxRadius(1)
00038 {
00039         //dw new4: is this a problem? check it
00040     setCacheMode(DeviceCoordinateCache);
00041 
00042     mContextMenu = contextMenu;
00043         isMoving = false;
00044 
00045         //dw new:
00046         setZValue(1);
00047         //param
00048         mNoResize = true;
00049         if (mNoResize) {
00050                 mControlResizeHandles = true;
00051         }
00052         else {
00053                 //param
00054                 mControlResizeHandles = false;
00055         }
00056 
00057 
00058 /*
00059     QPainterPath path;
00060 
00061          //dw
00062          //QGroupBox *groupBox = new QGroupBox("GrBox");
00063          //QLabel *numberLabel = new QLabel("Telephone number");
00064          //QLineEdit *numberEdit = new QLineEdit;
00065          //QFormLayout *layout = new QFormLayout;
00066          //layout->addRow(numberLabel, numberEdit);
00067          //groupBox->setLayout(layout);
00068          QFormLayout *layout2 = new QFormLayout;
00069          //layout2->addRow(groupBox);
00070 
00071          QLabel* out0 = new QLabel("out0");
00072          out0->setAlignment(Qt::AlignRight);
00073          QLabel* in0 = new QLabel("in0");
00074          layout2->addRow(in0, out0);
00075          QLabel* in1 = new QLabel("in1");
00076          layout2->addRow(in1);
00077          QLabel* in2 = new QLabel("in2");
00078          layout2->addRow(in2);
00079          QLabel* inout0 = new QLabel("inOut0");
00080          inout0->setAlignment(Qt::AlignRight);
00081          layout2->addRow(inout0);
00082 
00083          //QSpinBox ( int minValue, int maxValue, int step = 1, QWidget * parent = 0, const char * name = 0 )
00084          QSpinBox* spinBox = new QSpinBox();
00085          spinBox->setMinimum(0);
00086          spinBox->setMaximum(9);
00087          layout2->addRow(spinBox);
00088 
00089          QDialog *dialog1 = new QDialog();
00090          //QFrame *dialog1 = new QFrame();
00091          //QGroupBox* dialog1 = new QGroupBox("A QGroupBox");
00092          dialog1->setLayout(layout2);
00093          //dialog1->setLayout(groupBox);
00094          //this->setWidget(groupBox);
00095          //dw will this fix deletion not called on close?
00096          dialog1->setAttribute(Qt::WA_DeleteOnClose);
00097          this->setWidget(dialog1);
00098 
00099          addConnector(new NodeConnector(this, scene, out0, NodeConnector::Out, true));
00100          addConnector(new NodeConnector(this, scene, in0, NodeConnector::In));
00101          addConnector(new NodeConnector(this, scene, in1, NodeConnector::In));
00102          addConnector(new NodeConnector(this, scene, in2, NodeConnector::In));
00103          addConnector(new NodeConnector(this, scene, inout0, NodeConnector::InOut, true));
00104 
00105          addConnector(new NodeConnector(this, scene, spinBox, NodeConnector::InOut));
00106          
00107          //QGraphicsScene scene;
00108          //QGraphicsObject *proxy = scene->addWidget(groupBox);
00109          //QGraphicsView view(&scene);
00110          //view.show();
00111 */
00112 
00113 /*    setPolygon(mPolygon);*/
00114          setFlag(QGraphicsObject::ItemIsMovable, true);
00115          setFlag(QGraphicsObject::ItemIsSelectable, true);
00116          setFlag(QGraphicsObject::ItemIsFocusable, true);
00117 
00118 
00119          //dw why is that needed
00120          //dialog1->setWindowFlags(Qt::WindowMov);
00121          //widget()->setWindowFlags(Qt::WindowFlags);
00122 
00123          //dw new
00124          if (scene != NULL){
00125                 scene->addItem(this);
00126          }
00127          
00128 
00129 /*
00130 QDialog signals:
00131 void    accepted ()
00132 void    finished ( int result )
00133 void    rejected ()
00134 */
00135          /*
00136          connect(dialog1, SIGNAL(accepted()), this, SLOT(deleted()));
00137          connect(dialog1, SIGNAL(finished(int)), this, SLOT(deleted(int)));
00138          connect(dialog1, SIGNAL(rejected()), this, SLOT(deleted()));
00139          */
00140 
00141 /*
00142 QWidget signals:
00143 void    customContextMenuRequested ( const QPoint & pos )
00144 */
00145 /*
00146 QObject signals:
00147 void    destroyed ( QObject * obj = 0 )
00148 */
00149 
00150         //dw big problem: we do not have dialog1 here with new design, but when to do it? ==> override setWidget()
00151         //connect(dialog1, SIGNAL(destroyed()), this, SLOT(deleted()));
00152 }
00154 
00155 
00156 QRectF NodeItem::boundingRect() const
00157 {
00158         /*
00159     qreal adjust = 5;
00160     return QRectF(-radius - adjust, -radius - adjust,
00161                   2*(radius + adjust), 2*(radius + adjust));
00162                                   */
00163 
00164         //dw new
00165         QRectF rec(QGraphicsObject::boundingRect());
00166         //order matters!!!
00167         //rec.setX(rec.x() - 2 * (mMaxRadius));
00168         //rec.setWidth(rec.width() + 2 * (mMaxRadius));
00169         qreal extra = 3;//2 * (mMaxRadius) ;
00170         rec = rec.normalized().adjusted(-extra, 0, extra, 0);
00171 
00172         //rec.setWidth(rec.width() - 2 * (mMaxRadius + 1));
00173         //rec.setX(rec.x() + (mMaxRadius + 1));
00174         //rec.setWidth(rec.width() - 4);
00175         //rec.setX(rec.x() + 2);
00176         return rec;
00177 }
00178 
00179 QPainterPath NodeItem::shape() const {
00180 
00181         QPainterPath p;// = QGraphicsObject::shape();
00182         QRectF rec(QGraphicsObject::boundingRect());
00183         //rec.setWidth(rec.width() - 2 * (mMaxRadius + 1));
00184         //rec.setX(rec.x() + (mMaxRadius + 1));
00185         p.addRect(rec);
00186         
00187         /*//exclude children
00188         foreach (NodeConnector *c, connectors) {
00189                 //dw problem: label already deleted but connector tries to enable it?
00190         //c->deleteConnections();
00191                 p = p.subtracted(c->shape());
00192     }*/
00193 
00194         /*//add children
00195         foreach (NodeConnector *c, connectors) {
00196                 p.addPath(this->mapFromItem(c, c->shape()));
00197     }*/
00198 
00199         return p;
00200 }
00201 
00202 
00203 /* //
00204 void NodeItem::setWidget(QWidget *widget) {
00205         //does this work for all possible wiget types
00206         QGraphicsObject::setWidget(widget);
00207         connect(widget, SIGNAL(destroyed()), this, SLOT(deleted()));
00208 }*/
00209 
00210 void NodeItem::addConnector(NodeConnector* nc) {
00211         connectors.append(nc);
00212         if (nc->mRadius > mMaxRadius) {
00213                 mMaxRadius = nc->mRadius;
00214         }
00215 
00216         updateConnectorsPos();
00217         prepareGeometryChange();
00218 }
00219 
00220 
00222 void NodeItem::deleteConnections()
00223 {
00224     foreach (NodeConnector *c, connectors) {
00225                 //dw problem: label already deleted but connector tries to enable it?
00226         c->deleteConnections();
00227     }
00228 
00229         //dw good location?, needed?
00230         //this->scene()->removeItem(this);
00231 }
00233 
00234 void NodeItem::removeWigetFromConnectors() {
00235         foreach (NodeConnector *c, connectors) {
00236                 //dw problem: label already deleted but connector tries to enable it?
00237         c->removeWidget();
00238     }
00239 }
00240 
00242 void NodeItem::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
00243 {
00244     scene()->clearSelection();
00245     setSelected(true);
00246         //dw new3
00247     //mContextMenu->exec(event->screenPos());
00248         if (mContextMenu != NULL) {
00249                 mContextMenu->exec(event->screenPos());
00250         }
00251 }
00253 
00255 QVariant NodeItem::itemChange(GraphicsItemChange change, //dw FIXME: needs much cleanup
00256                      const QVariant &value)
00257 {
00258 
00259         //dw now in paint, check if this is a good idea (e.g. when is it called)
00260         //dw667 backmerge: was commented, but is shotgun approach!!!
00261         if (change == QGraphicsObject::ItemPositionChange) {
00262                 updateConnectorsPos();
00263         }
00264    //does this create loop on selection?
00265    
00266 
00267    /*//dw FIXME:only proxified
00268    //dw if visibilty changes to false, kill wiget (TODO: make configurable, usfull for Dialogs and such)
00269    if (change == QGraphicsObject::ItemVisibleHasChanged && !value.value<bool>()) {
00270            deleted();
00271            return value;
00272    }
00273    */
00274 
00275 
00276 
00277    /*
00278    //dw 669: turn back on resize handle controlling
00279    //dw new3: do not allow cursor changes, better only over connector!
00280    */
00281    if (mControlResizeHandles && change == QGraphicsObject::ItemCursorChange) {
00282            QCursor cur = qVariantValue<QCursor>(value);
00283            //FIXME: do we really have to do this by hand?
00284            //suppress all resizes
00285            if (cur.shape() == Qt::SizeVerCursor || cur.shape() == Qt::SizeHorCursor || cur.shape() == Qt::SizeBDiagCursor || cur.shape() == Qt::SizeFDiagCursor) {
00286                    if (mNoResize) {
00287                            return Qt::ArrowCursor;
00288                    }
00289                    else {
00290                                 foreach (NodeConnector *con, connectors) {
00291                                         if (con->isUnderMouse()) {
00292                                                 return Qt::ArrowCursor;
00293                                         }
00294                                 }
00295                    }
00296            }
00297    }
00298 
00299    
00300    //dw 669: turn back on resize handle controlling
00301    //dw ugly hack, find better way
00302    //dw deselecting proxy item dialog will cause error sometimes, has size of bounding rect, will not redraw connections 
00303    if (change == QGraphicsObject::ItemSelectedChange || change == QGraphicsObject::ItemTransformChange || change == QGraphicsObject::ItemScaleChange
00304            || change == QGraphicsObject::ItemSendsGeometryChanges || change == QGraphicsObject::ItemMatrixChange) {
00305            /*
00306                 foreach (NodeConnector *con, connectors) {
00307                         con->updatePositionGeometry();
00308                 }
00309                 */
00310            updateConnectorsPos();
00311    }
00312    if (change == QGraphicsObject::ItemPositionHasChanged || change == QGraphicsObject::ItemSelectedChange) {
00313            /*
00314                 foreach (NodeConnector *con, connectors) {
00315                         con->updatePositionGeometry();
00316                 }
00317                 */
00318            updateConnectorsPos();
00319    }
00320 
00321    
00322    /*//dw debug help
00323    if (change == QGraphicsObject::ItemSelectedChange || change == QGraphicsObject::ItemEnabledChange || change == QGraphicsObject::ItemVisibleHasChanged || change == QGraphicsObject::ItemPositionChange
00324            || change == QGraphicsObject::ItemZValueChange || change == QGraphicsObject::ItemZValueHasChanged) {
00325             //scene()->clearSelection();
00326                 //setSelected(true);
00327                 //return true;
00328                 return QGraphicsObject::itemChange(change, value);
00329         }*/
00330 
00331 
00332         return QGraphicsObject::itemChange(change, value);
00333     //return value;
00334 }
00336 
00337 /*//dw FIXME:only proxified
00338 //dw669: new, fixes connector position on resizing, why can it not be done in itemChange?
00339         void NodeItem::resizeEvent ( QGraphicsSceneResizeEvent * event ) {
00340                 QGraphicsObject::resizeEvent(event);
00341                 updateConnectorsPos();
00342         }
00343 */
00344 
00345 //dw new4: remove again
00346 void NodeItem::hoverMoveEvent ( QGraphicsSceneHoverEvent * event )  {
00347         event->ignore();
00348         return;
00349 }
00350 
00351 void NodeItem::updateConnectorsPos() {
00352         foreach (NodeConnector *con, connectors) {
00353                 //dw667 backmerge: was active
00354         //con->updatePositionGeometry();
00355                 //dw new
00356                 con->updatePosition();
00357     }
00358         //dw667: was active
00359         //update();
00360 }
00361 
00362 
00363 void NodeItem::debugPaint(QPainter *painter) {
00364         //dw debug
00365         static int i = 0, j=0, k=0;
00366         painter->fillRect(boundingRect(), /*Qt::green*/ QColor(i=(i+19)%256 , j=(j+51)%256, k=(k+11)%256)); // to see item.
00367         //painter->fillPath(shape(), QColor(i=(i+19)%256 , j=(j+51)%256, k=(k+11)%256));
00368 }
00369 
00370 
00371 //dw
00372 void NodeItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *w)
00373 {
00374         if (static_cast<DiagramScene*>(scene())->isDebugDraw()) {
00375                 debugPaint(painter);
00376         }
00377         //dw new
00378         //dw667: was active
00379         //updateConnectorsPos();
00380 
00381         QGraphicsObject::paint(painter, option, w);
00382         //dw new2
00383         //QGraphicsObject::paint(painter, option, w);
00384 
00385         //dw new3: why do we have to call paint of children???
00386         //dw667: was active
00387         /*
00388         foreach (NodeConnector *c, connectors) {
00389                 //dw problem: label already deleted but connector tries to enable it?
00390         c->paint(painter, option, w);
00391                 c->update();
00392     }
00393         */
00394 }
00395 
00396 /*
00397 //dw new3
00398 void NodeItem::update(const QRectF & rect) {
00399         
00400         //dw new3: why do ourself
00401         foreach (NodeConnector *c, connectors) {
00402                 //dw problem: label already deleted but connector tries to enable it?
00403         //c->paint(painter, option, w);
00404                 c->update(rect);
00405     }
00406         
00407         QGraphicsObject::update(rect);
00408 }
00409 */
00410 
00411 
00412 /*//dw FIXME:only proxified
00413 
00414 //dw TODO: move to good visible location, check which types should be included
00415 //const char* NodeItem::shouldNotMoveTypes[] = {"QLineEdit", "foo", "bar"};
00416 const char* NodeItem::shouldMoveOnClickTypes[] = {"QDialog", "QFrame", "QGroupBox"};
00417 
00418 bool NodeItem::shouldMoveNode(QGraphicsSceneMouseEvent *mouseEvent) {
00419         QPointF pos = mouseEvent->pos();
00420         QPointer<QWidget> hitWidget = widget()->childAt(pos.toPoint());
00421         if (hitWidget == NULL) {
00422                 return true;
00423         }
00424         //foreach(QString t, shouldNotMoveTypes) {
00425         //      if (alienWidget->inherits(t.toStdString().c_str())) {
00426         const size_t len = sizeof(shouldMoveOnClickTypes) / sizeof(shouldMoveOnClickTypes[0]);
00427         for (size_t i = 0; i < len; ++i) {
00428                 if (hitWidget->inherits(shouldMoveOnClickTypes[i])) {
00429                         return true;
00430                 }
00431         }
00432         return false;
00433 }
00434 
00435 void NodeItem::mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent) {
00436         if (shouldMoveNode(mouseEvent)) {
00437                 QGraphicsObject::mousePressEvent(mouseEvent);
00438                 isMoving = true;
00439                 // what if we have to remove that?
00440                 scene()->clearSelection();
00441                 scene()->clearFocus();
00442                 setSelected(true);
00443         }
00444         else {
00445                 QGraphicsObject::mousePressEvent(mouseEvent);
00446         }
00447 }
00448 
00449 void NodeItem::mouseMoveEvent(QGraphicsSceneMouseEvent *mouseEvent) {
00450         if (isMoving) {
00451                 QGraphicsObject::mouseMoveEvent(mouseEvent);
00452 
00453                 //dw667 backmerge: was active
00454                 /*
00455                 //dw new5
00456                 foreach (NodeConnector *con, connectors) {
00457                         //dw667 backmerge: was active
00458                         //con->updatePositionGeometry();
00459                         //dw667 backmerge: new
00460                         con->updatePosition();
00461                 }
00462                 */
00463 /*
00464         }
00465         else {
00466                 QGraphicsObject::mouseMoveEvent(mouseEvent);
00467         }
00468 
00469         //scene()->clearSelection();
00470         //setSelected(true);
00471 
00472         //dw667 backmerge: was active
00473         //updateConnectorsPos();
00474 }
00475 
00476 void NodeItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *mouseEvent) {
00477         if (isMoving) {
00478                 isMoving = false;
00479         }
00480         //call both always to lose no events and to not have to do the same shit for clicks too
00481         QGraphicsObject::mouseReleaseEvent(mouseEvent);
00482         QGraphicsObject::mouseReleaseEvent(mouseEvent);
00483         scene()->clearSelection();
00484         setSelected(true);
00485 
00486         //updateConnectorsPos();
00487 }
00488 */
00489