• Main Page
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

C:/CVUT/diplomka/Automata_editor/sources/state.cpp

Go to the documentation of this file.
00001 #include "constants.h"
00002 
00003 #include "state.h"
00004 #include "mainwindow.h"
00005 #include "editor.h"
00006 #include "transition.h"
00007 #include "stringProcessor.h"
00008 #include "transforms.h"
00009 
00010 #include <QPoint> 
00011 #include <QPointF>
00012 #include <QRect>
00013 #include <QRectF>
00014 #include <QGraphicsView>
00015 #include <QGraphicsSceneMouseEvent>
00016 #include <QColor>
00017 
00018 #include <QTextStream>
00019 
00020 // debug
00021 #include <QtDebug>
00022 
00023 //<-- State ------------------------------------------------------------------
00024 
00025 State::State(const QPoint &position, Editor *parent, const QString l,
00026              const QString n, bool dBorder, bool dim)
00027   : editor(parent), name(n), label(l), dimmed(dim), doubleBorder(dBorder), checked(false),
00028     checkedColor(QColor(CheckedColor::r, CheckedColor::g, CheckedColor::b, CheckedColor::a)),
00029     m_marked(false), m_otherMoved(false)
00030 {
00031     this->setZValue(Z_STATE);
00032     this->setPos(position);
00033     setFlag(QGraphicsItem::ItemIsMovable, true);
00034     setFlag(QGraphicsItem::ItemIsSelectable, true);
00035 
00036 // due to undesirable change in Qt 4.6, this flat should be enabled by defaut, but it isn't
00037 #if QT_VERSION >= 0x040600
00038     setFlag(QGraphicsItem::ItemSendsGeometryChanges);
00039     setFlag(QGraphicsItem::ItemSendsScenePositionChanges);
00040 #endif
00041 
00042     // editor's values are determinate
00043     stateLineStyle = editor->stateLineStyle;
00044     stateLineWidth = 1;
00045     stateLineColor = editor->stateLineColor; 
00046     stateLabelColor = editor->stateLabelColor;
00047     stateLabelScale = 1;
00048     stateFillStatus = editor->stateFillStatus;
00049     stateFillColor = editor->stateFillColor;
00050 
00051     // state parametres preset
00052     stateLineDoubleCoef = editor->stateLineDoubleCoef; //DEF_STATE_LINE_DBL_COEF;
00053     stateLineDoubleSep = editor->stateLineDoubleSep; //DEF_STATE_LINE_DBL_SEP;
00054 
00055     // state parametres dimmed
00056     dimStateLineStyle = editor->dimStateLineStyle; //DEF_DIM_LINE_STYLE;
00057     dimStateLineColor = editor->dimStateLineColor; //DEF_DIM_COLOR;
00058     dimStateLineCoef = editor->dimStateLineCoef; //DEF_DIM_STATE_LINE_COEF;
00059     dimStateLabelColor = editor->dimStateLabelColor; //DEF_DIM_COLOR;
00060     dimStateFillColor = editor->dimStateFillColor; //DEF_DIM_FILL_COLOR;    
00061 
00062     stateLabelSize = (int) (STATE_LABEL_SIZE * editor->stateLabelScale * stateLabelScale);
00063     m_lineWidth = editor->stateLineWidth * STATE_LINE_VIEW_COEF;
00064 
00065     if (dimmed)
00066         m_lineWidth *= dimStateLineCoef;
00067     else
00068         m_lineWidth *= stateLineWidth;
00069     
00070     stringProcessor = new StringProcessor(label, stateLabelSize);
00071 }
00072 
00073 State::~State()
00074 {
00075     delete stringProcessor;
00076     deleteTransitions();
00077     DBGLOG("called");
00078 }
00079 
00080 QPolygonF State::getMyPolygon() const
00081 {
00082     return myPolygon;
00083 }
00084 
00085 bool State::getVCParams(QTextStream &out, StatePrevParams &prevParams){
00086     bool stChanged = false;
00087     if (!dimmed)
00088     {
00089         if (stateLineStyle != prevParams.stateLineStyle)
00090         {
00091             prevParams.stateLineStyle = stateLineStyle;
00092             stChanged = true;
00093             if (stateLineStyle != editor->stateLineStyle)
00094             {
00095                 out << endl << "\\ChgStateLineStyle{";
00096                 out << trLineStyle(stateLineStyle);
00097                 out << "}";
00098             }
00099             else
00100             {
00101                 out << endl << "\\RstStateLineStyle";
00102             } 
00103         }
00104 
00105         if (stateLineWidth != prevParams.stateLineWidth)
00106         {
00107             stChanged = true;
00108             prevParams.stateLineWidth = stateLineWidth;
00109             if (stateLineWidth != 1)
00110                 out << endl << "\\ChgStateLineWidth{" << stateLineWidth << "}";
00111             else
00112                 out << endl << "\\RstStateLineWidth";
00113         }
00114     
00115         if (stateLineColor != prevParams.stateLineColor)
00116         {
00117             stChanged = true;
00118             prevParams.stateLineColor = stateLineColor;
00119             if (stateLineColor != editor->stateLineColor)
00120                 out << endl << "\\ChgStateLineColor{" << stateLineColor.toLower() << "}";
00121             else
00122                 out << endl << "\\RstStateLineColor";
00123         }
00124     
00125         if (stateLabelColor != prevParams.stateLabelColor)
00126         {
00127             stChanged = true;
00128             prevParams.stateLabelColor = stateLabelColor;
00129             if (stateLabelColor != editor->stateLabelColor)
00130                 out << endl << "\\ChgStateLabelColor{" << stateLabelColor.toLower() << "}";
00131             else
00132                 out << endl << "\\RstStateLabelColor";
00133         }
00134 
00135         if (stateLabelScale != prevParams.stateLabelScale)
00136         {
00137             stChanged = true;
00138             prevParams.stateLabelScale = stateLabelScale;
00139             if (stateLabelScale != 1)
00140                 out << endl << "\\ChgStateLabelScale{" << stateLabelScale << "}";
00141             else
00142                 out << endl << "\\RstStateLabelScale";
00143         }
00144 
00145         if (stateFillStatus != prevParams.stateFillStatus)
00146         {
00147             stChanged = true;
00148             prevParams.stateFillStatus = stateFillStatus;
00149             if (stateFillStatus != editor->stateFillStatus)
00150                 out << endl << "\\ChgStateFillStatus{" << trFillStatus(stateFillStatus) << "}"; 
00151             else
00152                 out << endl << "\\RstStateFillStatus";
00153         }
00154 
00155         if (stateFillColor != prevParams.stateFillColor)
00156         {
00157             stChanged = true;
00158             prevParams.stateFillColor = stateFillColor;
00159             if (stateFillColor != editor->stateFillColor)
00160                 out << endl << "\\ChgStateFillColor{" << stateFillColor.toLower() << "}"; 
00161             else
00162                 out << endl << "\\RstStateFillColor";
00163         } 
00164     } // if (!dimmed)
00165     else 
00166     {
00167         if (dimStateLineStyle != prevParams.dimStateLineStyle ||
00168             dimStateLineColor != prevParams.dimStateLineColor ||
00169             dimStateLineCoef != prevParams.dimStateLineCoef ||
00170             dimStateLabelColor != prevParams.dimStateLabelColor ||
00171             dimStateFillColor != prevParams.dimStateFillColor)
00172         {
00173             stChanged = true;
00174             prevParams.dimStateLineStyle = dimStateLineStyle;
00175             prevParams.dimStateLineColor = dimStateLineColor;
00176             prevParams.dimStateLineCoef = dimStateLineCoef;
00177             prevParams.dimStateLabelColor = dimStateLabelColor;
00178             prevParams.dimStateFillColor = dimStateFillColor;
00179             out << endl <<"\\FixDimState{" << trLineStyle(dimStateLineStyle) << "}"
00180                                        "{" << dimStateLineColor.toLower() << "}"
00181                                        "{" << dimStateLineCoef << "}"
00182                                        "{" << dimStateLabelColor.toLower() << "}"
00183                                        "{" << dimStateFillColor.toLower() << "}";
00184         }
00185     }
00186   
00187     if (doubleBorder)
00188     {
00189         if (stateLineDoubleCoef != prevParams.stateLineDoubleCoef ||
00190             stateLineDoubleSep != prevParams.stateLineDoubleSep)
00191         {
00192             stChanged = true;
00193             prevParams.stateLineDoubleCoef = stateLineDoubleCoef;
00194             prevParams.stateLineDoubleSep = stateLineDoubleSep;
00195             out << endl << "\\FixStateLineDouble{" << stateLineDoubleCoef << "}"
00196                                                "{" << stateLineDoubleSep << "}";
00197         }
00198     }
00199   
00200     if (stChanged) out << endl;
00201     return stChanged;
00202 }
00203 
00204 QString State::getVCCommand() const
00205 {
00206     QString command = "";
00207 
00208     QPointF s_pos = editor->mapToGrid(pos());
00209     command = "\\" + getTypeName();
00210     if (getLabel() != "") command += "[" + getLabel() + "]";
00211     command += QString("{(%1,%2)}{%3}")
00212                     .arg(s_pos.x())
00213                     .arg(s_pos.y())
00214                     .arg(getName());    
00215 
00216     return command;
00217 }
00218 
00219 void State::addTransition(Transition *transition)
00220 {
00221     if (transitionList.contains(transition))
00222         RELLOG("transition is currently assigned!!!");
00223     else
00224         transitionList << transition;
00225 }
00226 
00227 void State::removeTransition(Transition *transition)
00228 {  
00229     int i = transitionList.indexOf(transition);
00230     if (i != -1) transitionList.removeAt(i);
00231 }
00232 
00233 void State::deleteTransitions()
00234 {
00235     Transition *tr;
00236     while (!transitionList.isEmpty())
00237     {
00238         tr = transitionList.takeFirst();
00239         tr->unassign();
00240         delete tr;
00241     }
00242 }
00243 
00244 void State::setLabel(const QString &l)
00245 {
00246     prepareGeometryChange();
00247     label = l;
00248     stringProcessor->setText(label);
00249 }
00250 
00251 void State::setName(const QString &n)
00252 {
00253     name = n;
00254 }
00255 
00256 void State::setDoubleBorder(bool db)
00257 {
00258     if (doubleBorder == db) return;
00259     
00260     prepareGeometryChange();
00261     
00262     doubleBorder = db;
00263 
00264     updateMyPolygon();
00265 }
00266 
00267 void State::setDimmed(bool dim)
00268 {
00269     if (dimmed == dim) return;
00270 
00271     dimmed = dim;
00272 
00273     if (dimmed)
00274         m_lineWidth = m_lineWidth * dimStateLineCoef/stateLineWidth;
00275     else
00276         m_lineWidth = m_lineWidth * stateLineWidth/dimStateLineCoef;
00277 
00278     updateMyPolygon();
00279 }
00280 
00281 void State::setAutoNammed(bool aN)
00282 {
00283     autoNammed = aN;
00284 }
00285 
00286 QRectF State::boundingRect() const
00287 {
00288     int width = getWidth() > getTextWidth() ? getWidth() : getTextWidth();
00289     int height = getHeight() > getTextHeight() ? getHeight() : getTextHeight();    
00290     
00291     QRectF ellipseRect(-width/2, -height/2, width, height);
00292     float adjust;
00293 
00294     if (doubleBorder)
00295     {
00296         float doubleLineSep = m_lineWidth * stateLineDoubleSep / STATE_LINE_VIEW_COEF; // w/o correction
00297         float doubleLineWidth = m_lineWidth * stateLineDoubleCoef * STATE_DOUBLE_LINE_VIEW_COEF;
00298         adjust = doubleLineSep + doubleLineWidth*1.5 + 2;
00299     }
00300     else
00301     {
00302         adjust = m_lineWidth/2 + 2;
00303     }
00304 
00305     return ellipseRect.adjusted(-adjust, -adjust,
00306                                  adjust,  adjust);
00307 }
00308 
00309 void State::paintSelectionDecoration(QPainter *painter)
00310 {
00311     if (isSelected())
00312     {
00313         const QColor selectedColor(SelectedColor::r,SelectedColor::g,
00314                                    SelectedColor::b, SelectedColor::a);
00315         painter->setPen(QPen(selectedColor,1,Qt::DashLine));
00316         painter->setBrush(Qt::NoBrush);
00317         painter->drawRect(boundingRect().adjusted(2,2,-2,-2));
00318     }
00319 }
00320 
00321 void State::setChecked(bool checked)
00322 {
00323     if (this->checked ==  checked) return;
00324     DBGLOG_ME(DBGPAR(checked));
00325     this->checked = checked;
00326     update();
00327 }
00328 
00329 QVariant State::itemChange(GraphicsItemChange change, const QVariant &value)
00330 {
00331     switch (change) 
00332     {
00333         case ItemPositionHasChanged:  // update transitions
00334             adjustTransitions();
00335             break;
00336         default:
00337             break;
00338     }
00339     
00340     return QGraphicsItem::itemChange(change, value);
00341 }
00342 
00343 void State::adjustTransitions()
00344 {
00345     foreach(Transition *tr, transitionList)
00346     {
00347         tr->adjust();
00348     }
00349 }
00350 
00351 void State::mousePressEvent(QGraphicsSceneMouseEvent *event)
00352 {
00353     DBGLOG_ME("called," <<  "pos=" << event->pos());
00354     m_lastMouseClickType = eMouseNoClick;
00355     setChecked();
00356 
00357     if (editor->getAction() == Editor::eSelection &&
00358         event->button() == Qt::LeftButton)
00359     {
00360         DBGLOG_ME("cursor=ClosedHandCursor");
00361         editor->setCursor(Qt::ClosedHandCursor);
00362     }
00363 
00364     if(event->button() == Qt::RightButton)
00365     {        
00366         m_lastMouseClickType = eMouseRightClick;
00367     }
00368     else if (event->button() == Qt::LeftButton)
00369     {        
00370         m_lastMouseClickType = eMouseLeftClick;
00371         oldPos = pos(); // original position
00372     }    
00373     else if (event->button() == Qt::MidButton)
00374     {
00375         m_lastMouseClickType = eMouseMiddleClick;
00376     }
00377     else
00378         event->ignore();
00379 }
00380 
00381 void State::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
00382 {    
00383     DBGLOG_ME("called");
00384     if (event->button() == Qt::LeftButton && m_lastMouseClickType == eMouseMove)
00385     {           
00386         if (oldPos != pos())
00387         {            
00388             editor->stateMoved(this, oldPos);
00389         }
00390         setChecked(false);
00391     }
00392     else if ((m_lastMouseClickType == eMouseLeftClick && editor->getAction() == Editor::eInsertTransition) ||
00393              (m_lastMouseClickType == eMouseMiddleClick &&
00394                 (editor->getAction() == Editor::eSelection || editor->getAction() == Editor::eInsertState)))
00395     {
00396         editor->setSelectedState(this);
00397         editor->insertTransition();
00398     }
00399     else if (m_lastMouseClickType == eMouseRightClick)
00400     {
00401         editor->showPopup(this);        
00402     }
00403     else if (m_lastMouseClickType == eMouseDoubleClick)
00404     {
00405         editor->editState(this);
00406         setChecked(false);
00407     }    
00408     else
00409     {
00410         setChecked(false);
00411     }
00412 }
00413 
00414 void State::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
00415 {
00416     DBGLOG_ME("called");
00417     if (event->button() == Qt::LeftButton && editor->getAction() == Editor::eSelection)
00418     {
00419         m_lastMouseClickType = eMouseDoubleClick;
00420         setChecked();             
00421     }
00422 }
00423 
00424 void State::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
00425 {
00426     Q_ASSERT(event != NULL);    
00427 
00428     if (editor->getAction() != Editor::eSelection)
00429         return;
00430 
00431     if (m_lastMouseClickType != eMouseLeftClick && m_lastMouseClickType != eMouseMove)
00432         return;
00433 
00434     m_lastMouseClickType = eMouseMove;
00435 
00436     QPointF g_pos = event->scenePos(); 
00437 
00438     QPointF e_pos = mapFromScene(g_pos);
00439 
00440     prepareGeometryChange();
00441 
00442     QPointF movePoint(0,0);
00443 
00444     if (!editor->snapped())
00445     {
00446         movePoint = e_pos;
00447     }
00448     else
00449     {
00450         editor->itemAlignToGrid(this);
00451         
00452         // move only when change is greather than half of grid step
00453         if (e_pos.toPoint().x() > (GRID_STEP / 2))
00454         {
00455             movePoint = QPoint(GRID_STEP, 0);
00456         } 
00457         else if (e_pos.toPoint().x() < (-GRID_STEP / 2))
00458         {
00459             movePoint = QPoint(-GRID_STEP, 0);
00460         }
00461         if(e_pos.toPoint().y() > (GRID_STEP / 2))
00462         {
00463             movePoint = QPoint(0, GRID_STEP);
00464         }
00465         else if(e_pos.toPoint().y() < (-GRID_STEP / 2))
00466         {
00467             movePoint = QPoint(0,-GRID_STEP);
00468         }
00469     }
00470 
00471     moveBy(movePoint.x(), movePoint.y());
00472 }
00473 
00474 void State::setStateLabelScale(float labelScale)
00475 {
00476     if (stateLabelScale == labelScale) return;
00477 
00478     prepareGeometryChange();
00479     stateLabelSize = (int) (stateLabelSize * labelScale/stateLabelScale);
00480     stateLabelScale = labelScale;
00481     stringProcessor->setFontSize(stateLabelSize);
00482     updateMyPolygon();
00483 }
00484 
00485 void State::setStateLineWidth(float lineWidth)
00486 {
00487     if (stateLineWidth == lineWidth) return;
00488 
00489     prepareGeometryChange();
00490     
00491     if (!dimmed)
00492         m_lineWidth = m_lineWidth * lineWidth/stateLineWidth;    
00493     stateLineWidth = lineWidth;
00494     
00495     if (!dimmed)
00496         updateMyPolygon();
00497 }
00498 
00499 void State::setDimStateLineCoef(float lineCoef)
00500 {
00501     if (dimStateLineCoef  == lineCoef) return;
00502 
00503     prepareGeometryChange();
00504     
00505     if (dimmed)
00506         m_lineWidth = m_lineWidth * lineCoef/dimStateLineCoef;
00507     dimStateLineCoef = lineCoef;
00508 
00509     if (dimmed)
00510         updateMyPolygon();
00511 }
00512 
00513 void State::setStateLineDoubleCoef(float lineCoef)
00514 {
00515     if (stateLineDoubleCoef == lineCoef) return;
00516     
00517     prepareGeometryChange();
00518 
00519     stateLineDoubleCoef = lineCoef;
00520 
00521     if (doubleBorder)
00522         updateMyPolygon();
00523 }
00524 
00525 void State::setStateLineDoubleSep(float lineSep)
00526 {
00527     if (stateLineDoubleSep == lineSep) return;
00528 
00529     prepareGeometryChange();
00530 
00531     stateLineDoubleSep = lineSep;
00532 
00533     if (doubleBorder)
00534         updateMyPolygon();
00535 }
00536 
00537 void State::setMarked(bool marked)
00538 {
00539     prepareGeometryChange();
00540     
00541     if (m_marked == marked) return;
00542         
00543     m_marked = marked;
00544         
00545     if (m_marked)
00546     {
00547         if (isDimmed())
00548         {
00549             m_origColor = dimStateFillColor;
00550             dimStateFillColor = toMarkerColor(dimStateFillColor);
00551         }
00552         else
00553         {
00554             m_origColor = stateFillColor;
00555             stateFillColor = toMarkerColor(stateFillColor);
00556         }
00557     }
00558     else
00559     {
00560         if (isDimmed())
00561         {
00562             dimStateFillColor = m_origColor;
00563         }
00564         else
00565         {
00566             stateFillColor = m_origColor;
00567         }
00568     }
00569 }
00570 
00571 bool State::isInitial() const
00572 {
00573     foreach(const Transition *tr, transitionList)
00574     {
00575         if (tr->getTypeName() == "Initial")
00576         {
00577             return true;
00578         }
00579     }
00580 
00581     return false;
00582 }
00583 
00584 bool State::isFinal() const
00585 {
00586     if (doubleBorder) return true;
00587 
00588     foreach(const Transition *tr, transitionList)
00589     {
00590         if (tr->getTypeName() == "Final")
00591         {
00592             return true;
00593         }
00594     }
00595 
00596     return false;
00597 }
00598 
00599 QList<Transition*> State::getOutgoingTransitions() const
00600 {
00601     QList<Transition*> transitions;
00602 
00603     foreach(Transition *tr, transitionList)
00604     {
00605         if (tr->getStartState() == this &&
00606             tr->getTypeName() != "Initial" && tr->getTypeName() != "Final")
00607         {
00608             transitions << tr;
00609         }
00610     }
00611 
00612     return transitions;
00613 }
00614 
00615 //! only for BFS - finding automata, so orientation of transition is skipped
00616 QList<State*> State::getAccessibleStates() const
00617 {
00618     QList<State*> accessibleStates;
00619 
00620     foreach(Transition *tr, transitionList)
00621     {
00622         if (tr->getStartState() == this && tr->getEndState() != NULL)
00623         {
00624             accessibleStates << tr->getEndState();
00625         }        
00626         else
00627         {
00628             accessibleStates << tr->getStartState(); // ever ok
00629         }
00630     }
00631 
00632     return accessibleStates;
00633 }
00634 
00635 //------------------------------------------------------------------ State -->

Generated on Tue Jan 4 2011 03:03:23 for Autoamata editor by  doxygen 1.7.0