ThymioScene.cpp
Go to the documentation of this file.
00001 #include <QGraphicsSceneMouseEvent>
00002 #include <QDebug>
00003 
00004 #include "ThymioButtons.h"
00005 
00006 #include "ThymioScene.h"
00007 #include "ThymioScene.moc"
00008 
00009 using namespace std;
00010 
00011 namespace Aseba
00012 {               
00013 
00014         ThymioScene::ThymioScene(QObject *parent) : 
00015                 QGraphicsScene(parent),
00016                 prevNewEventButton(false),
00017                 prevNewActionButton(false),
00018                 lastFocus(-1),
00019                 thymioCompiler(),
00020                 eventButtonColor(QColor(0,191,255)),
00021                 actionButtonColor(QColor(218,112,214)),
00022                 sceneModified(false),
00023                 scaleFactor(0.5),
00024                 newRow(false),
00025                 advancedMode(false)
00026         {
00027                 ThymioButtonSet *button = new ThymioButtonSet(0, advancedMode);
00028                 button->setScale(scaleFactor);
00029                 button->setPos(15*scaleFactor, 20*scaleFactor); //advancedMode = false
00030                 buttonSets.push_back(button);
00031                 thymioCompiler.addButtonSet(button->getIRButtonSet());
00032                 
00033                 buttonSetHeight = button->boundingRect().height();
00034                 
00035                 addItem(button);
00036                 connect(button, SIGNAL(buttonUpdated()), this, SLOT(buttonUpdateDetected()));
00037                 connect(this, SIGNAL(selectionChanged()), this, SIGNAL(stateChanged()));
00038         }
00039         
00040         ThymioScene::~ThymioScene()
00041         {       
00042                 clear();
00043         }
00044 
00045         QGraphicsItem *ThymioScene::addAction(ThymioButton *item) 
00046         {       
00047                 ThymioButtonSet *button = 0; 
00048                 prevNewActionButton = false;
00049                 
00050                 if( newRow )
00051                         button = createNewButtonSet();
00052                 else if( prevNewEventButton )
00053                         button = buttonSets.last();
00054                 else 
00055                 {
00056                         if( lastFocus >= 0 )
00057                                 button = buttonSets.at(lastFocus);
00058                         else
00059                                 for(int i=0; i<buttonSets.size(); ++i)
00060                                         if( buttonSets.at(i)->hasFocus() )
00061                                         {
00062                                                 button = buttonSets.at(i);
00063                                                 break;
00064                                         }
00065                         
00066                         if( !button )
00067                         {
00068                                 if(!buttonSets.isEmpty() && !(buttonSets.last()->actionExists()) )
00069                                         button = buttonSets.last();
00070                                 else
00071                                 {
00072                                         button = createNewButtonSet();
00073                                         prevNewActionButton = true;
00074                                 }
00075                         }                               
00076                 }
00077                 
00078                 if( item ) button->addActionButton(item);
00079                 prevNewEventButton = false;
00080                 newRow = false;
00081         
00082                 if( button->eventExists() ) 
00083                 {
00084                         lastFocus = -1;
00085                         setFocusItem(0);
00086                 }
00087 
00088                 setSceneRect(QRectF(0, 0, 1030*scaleFactor, (buttonSets.size()+2)*400*scaleFactor));
00089 
00090                 return button;
00091         }
00092 
00093         QGraphicsItem *ThymioScene::addEvent(ThymioButton *item) 
00094         {       
00095                 ThymioButtonSet *button = 0; 
00096                 prevNewEventButton = false;
00097 
00098                 if( newRow )
00099                         button = createNewButtonSet();          
00100                 else if( prevNewActionButton )          
00101                         button = buttonSets.last();
00102                 else 
00103                 {
00104                         if( lastFocus >= 0 )
00105                                 button = buttonSets.at(lastFocus);
00106                         else
00107                                 for(int i=0; i<buttonSets.size(); ++i)
00108                                         if( buttonSets.at(i)->hasFocus() )
00109                                         {
00110                                                 button = buttonSets.at(i);
00111                                                 break;
00112                                         }
00113                         
00114                         if( !button )
00115                         {
00116                                 if(!buttonSets.isEmpty() && !(buttonSets.last()->eventExists()) )
00117                                         button = buttonSets.last();
00118                                 else
00119                                 {
00120                                         button = createNewButtonSet();
00121                                         prevNewEventButton = true;
00122                                 }
00123                         }
00124 
00125                 }
00126                 
00127                 if( item ) button->addEventButton(item);
00128                 prevNewActionButton = false;
00129                 newRow = false;
00130                                 
00131                 if( button->actionExists() ) 
00132                 {
00133                         lastFocus = -1;
00134                         setFocusItem(0);
00135                 }
00136                 
00137                 setSceneRect(QRectF(0, 0, 1030*scaleFactor, (buttonSets.size()+2)*400*scaleFactor));            
00138 
00139                 return button;
00140         }
00141 
00142         void ThymioScene::addButtonSet(ThymioButton *event, ThymioButton *action)
00143         {
00144                 ThymioButtonSet *button = createNewButtonSet();
00145                 if(event) button->addEventButton(event);
00146                 if(action) button->addActionButton(action);
00147                 lastFocus = -1;
00148                 setFocusItem(0);
00149 
00150                 prevNewEventButton = false;
00151                 prevNewActionButton = false;
00152                 newRow = false;
00153 
00154                 setSceneRect(QRectF(0, 0, 1030*scaleFactor, (buttonSets.size()+2)*400*scaleFactor));
00155         }
00156 
00157         ThymioButtonSet *ThymioScene::createNewButtonSet()
00158         {
00159                 ThymioButtonSet *button = new ThymioButtonSet(buttonSets.size(), advancedMode);
00160                 button->setColorScheme(eventButtonColor, actionButtonColor);
00161                 button->setScale(scaleFactor);
00162                 buttonSets.push_back(button);
00163                 
00164                 addItem(button);
00165 
00166                 connect(button, SIGNAL(buttonUpdated()), this, SLOT(buttonUpdateDetected()));
00167                 thymioCompiler.addButtonSet(button->getIRButtonSet());
00168 
00169                 return button;          
00170         }
00171 
00172         bool ThymioScene::isEmpty() const
00173         {
00174                 if( buttonSets.isEmpty() )
00175                         return true;
00176                         
00177                 if( buttonSets.size() > 1 ||
00178                         buttonSets[0]->actionExists() ||
00179                         buttonSets[0]->eventExists() )
00180                         return false;
00181 
00182                 return true;
00183         }
00184 
00185         void ThymioScene::reset()
00186         {       
00187                 clear();
00188 
00189                 ThymioButtonSet *button = createNewButtonSet();
00190                 button->setPos(15*scaleFactor, 20*scaleFactor); //advancedMode = false
00191                 
00192                 setSceneRect(QRectF(0, 0, 1030*scaleFactor, (buttonSets.size()+2)*400*scaleFactor));
00193         }
00194         
00195         void ThymioScene::clear()
00196         {
00197                 advancedMode = false;
00198                 for(ButtonSetItr itr = buttonsBegin(); itr != buttonsEnd(); ++itr)
00199                         (*itr)->setAdvanced(false);     
00200                 
00201                 for(int i=0; i<buttonSets.size(); i++)
00202                 {
00203                         disconnect(buttonSets.at(i), SIGNAL(buttonUpdated()), this, SLOT(buttonUpdateDetected()));
00204                         removeItem(buttonSets.at(i));
00205                         delete(buttonSets.at(i));
00206                 }
00207                 buttonSets.clear();
00208                 thymioCompiler.clear();
00209                 
00210                 sceneModified = false;
00211                 
00212                 lastFocus = -1;
00213                 prevNewActionButton = false;
00214                 prevNewEventButton = false;     
00215         }
00216         
00217         void ThymioScene::setColorScheme(QColor eventColor, QColor actionColor)
00218         {
00219                 eventButtonColor = eventColor;
00220                 actionButtonColor = actionColor;
00221 
00222                 for(ButtonSetItr itr = buttonsBegin(); itr != buttonsEnd(); ++itr)
00223                         (*itr)->setColorScheme(eventColor, actionColor);                                        
00224 
00225                 update();
00226         
00227                 sceneModified = true;
00228         }
00229 
00230         void ThymioScene::setAdvanced(bool advanced)
00231         {
00232                 advancedMode = advanced;
00233                 for(ButtonSetItr itr = buttonsBegin(); itr != buttonsEnd(); ++itr)
00234                         (*itr)->setAdvanced(advanced);
00235                 
00236                 buttonUpdateDetected();
00237         }
00238 
00239         void ThymioScene::removeButton(int row)
00240         {
00241                 Q_ASSERT( row < buttonSets.size() );
00242                         
00243                 ThymioButtonSet *button = buttonSets[row];
00244                 disconnect(button, SIGNAL(buttonUpdated()), this, SLOT(buttonUpdateDetected()));
00245                 buttonSets.removeAt(row);               
00246                 thymioCompiler.removeButtonSet(row);
00247                                 
00248                 removeItem(button);
00249                 delete(button);
00250                 
00251                 rearrangeButtons(row);
00252 
00253                 if( buttonSets.isEmpty() ) 
00254                 {
00255                         ThymioButtonSet *button = createNewButtonSet();
00256                         button->setPos(advancedMode?5*scaleFactor:15*scaleFactor,20*scaleFactor);               
00257                 }
00258 
00259                 prevNewEventButton = false;
00260                 prevNewActionButton = false;
00261                 lastFocus = -1;
00262         
00263                 sceneModified = true;
00264                 
00265                 setSceneRect(QRectF(0, 0, 1030*scaleFactor, (buttonSets.size()+2)*400*scaleFactor));
00266                 
00267                 buttonUpdateDetected();
00268         }
00269         
00270         void ThymioScene::insertButton(int row) 
00271         {
00272                 Q_ASSERT( row <= buttonSets.size() );
00273 
00274                 ThymioButtonSet *button = new ThymioButtonSet(row, advancedMode);
00275                 button->setColorScheme(eventButtonColor, actionButtonColor);
00276                 button->setScale(scaleFactor);
00277                 buttonSets.insert(row, button);
00278                 addItem(button);
00279                 
00280                 thymioCompiler.insertButtonSet(row, button->getIRButtonSet());
00281                 
00282                 connect(button, SIGNAL(buttonUpdated()), this, SLOT(buttonUpdateDetected()));
00283                         
00284                 setFocusItem(button);
00285                 lastFocus = row;
00286                         
00287                 rearrangeButtons(row+1);
00288 
00289                 prevNewEventButton = false;
00290                 prevNewActionButton = false;
00291         
00292                 sceneModified = true;
00293                 
00294                 setSceneRect(QRectF(0, 0, 1030*scaleFactor, (buttonSets.size()+2)*400*scaleFactor));            
00295 
00296                 buttonUpdateDetected();
00297         }
00298 
00299         void ThymioScene::rearrangeButtons(int row)
00300         {
00301                 for(int i=row; i<buttonSets.size(); ++i) 
00302                         buttonSets.at(i)->setRow(i);
00303         }
00304         
00305         void ThymioScene::setScale(qreal scale) 
00306         { 
00307                 scaleFactor = scale*0.5;
00308                 for( ButtonSetItr itr = buttonsBegin(); itr != buttonsEnd(); ++itr )
00309                         (*itr)->setScale(scaleFactor);
00310                         
00311                 setSceneRect(QRectF(0, 0, 1030*scaleFactor, (buttonSets.size()+2)*400*scaleFactor));                    
00312         }       
00313         
00314         QString ThymioScene::getErrorMessage() const
00315         { 
00316                 switch(thymioCompiler.getErrorCode()) {
00317                 case THYMIO_MISSING_EVENT:
00318                         return tr("Line %0: Missing event").arg(thymioCompiler.getErrorLine());
00319                         break;
00320                 case THYMIO_MISSING_ACTION:
00321                         return tr("Line %0: Missing action").arg(thymioCompiler.getErrorLine());
00322                         break;
00323                 case THYMIO_EVENT_MULTISET:
00324                         return tr("Line %0: Redeclaration of event").arg(thymioCompiler.getErrorLine());
00325                         break;
00326                 case THYMIO_INVALID_CODE:
00327                         return tr("Line %0: Unknown event/action type").arg(thymioCompiler.getErrorLine());
00328                         break;
00329                 case THYMIO_NO_ERROR:
00330                         return tr("Compilation success");
00331                 default:
00332                         return tr("Unknown VPL error");
00333                         break;
00334                 }
00335         }       
00336         
00337         QList<QString> ThymioScene::getCode() const
00338         {
00339                 QList<QString> out;
00340                 
00341                 for(std::vector<std::wstring>::const_iterator itr = thymioCompiler.beginCode();
00342                         itr != thymioCompiler.endCode(); ++itr)
00343                         out.push_back(QString::fromStdWString(*itr));
00344         
00345                 return out;
00346         }
00347 
00348         int ThymioScene::getFocusItemId() const 
00349         { 
00350                 QGraphicsItem *item = focusItem();
00351                 
00352                 while( item != 0 )
00353                 {
00354                         if( item->data(0).toString() == "buttonset" )
00355                                 return thymioCompiler.buttonToCode(item->data(1).toInt());
00356                         else
00357                                 item = item->parentItem();                      
00358                 }
00359 
00360                 return -1;
00361         }
00362         
00363         void ThymioScene::buttonUpdateDetected()
00364         {
00365                 sceneModified = true;
00366                 
00367                 thymioCompiler.compile();
00368                 thymioCompiler.generateCode();
00369                 
00370                 for(int i=0; i<buttonSets.size(); i++)
00371                         buttonSets[i]->setErrorStatus(false);
00372                                                 
00373                 if( !thymioCompiler.isSuccessful() )
00374                         buttonSets[thymioCompiler.getErrorLine()]->setErrorStatus(true);
00375                                 
00376                 emit stateChanged();
00377         }
00378 
00379         void ThymioScene::dragMoveEvent(QGraphicsSceneDragDropEvent *event)
00380         {
00381                 if( event->mimeData()->hasFormat("thymiobutton") && 
00382                         ((event->scenePos().y()-20*scaleFactor)/(buttonSetHeight*scaleFactor)) >= buttonSets.size() ) 
00383                 {
00384                         setFocusItem(0);
00385                         event->accept();
00386                 } 
00387                 else
00388                         QGraphicsScene::dragMoveEvent(event);
00389         }
00390         
00391         void ThymioScene::dropEvent(QGraphicsSceneDragDropEvent *event)
00392         {
00393                 if ( event->mimeData()->hasFormat("thymiobuttonset") )
00394                 {
00395                         QByteArray buttonData = event->mimeData()->data("thymiobuttonset");
00396                         QDataStream dataStream(&buttonData, QIODevice::ReadOnly);
00397 
00398                         int prevRow, currentRow;
00399                         dataStream >> prevRow;
00400                         
00401                         ThymioButtonSet *button = buttonSets.at(prevRow);
00402                         buttonSets.removeAt(prevRow);
00403                         thymioCompiler.removeButtonSet(prevRow);
00404 
00405                         qreal currentYPos = event->scenePos().y();      
00406                         currentRow = (int)((currentYPos-20*scaleFactor)/(buttonSetHeight*scaleFactor));
00407                         currentRow = (currentRow < 0 ? 0 : currentRow > buttonSets.size() ? buttonSets.size() : currentRow);
00408 
00409                         buttonSets.insert(currentRow, button);
00410                         thymioCompiler.insertButtonSet(currentRow, button->getIRButtonSet());
00411 
00412                         rearrangeButtons( prevRow < currentRow ? prevRow : currentRow );
00413                         
00414                         event->setDropAction(Qt::MoveAction);
00415                         event->accept();
00416 
00417                         setFocusItem(button);
00418                         lastFocus = currentRow;
00419                         
00420                         buttonUpdateDetected();
00421                 }
00422                 else if( event->mimeData()->hasFormat("thymiobutton") && 
00423                                 ((event->scenePos().y()-20*scaleFactor)/(buttonSetHeight*scaleFactor)) >= buttonSets.size() )
00424                 {                       
00425                         QByteArray buttonData = event->mimeData()->data("thymiobutton");
00426                         QDataStream dataStream(&buttonData, QIODevice::ReadOnly);
00427                         
00428                         int parentID;           
00429                         dataStream >> parentID;
00430 
00431                         QString buttonName;
00432                         int numButtons;
00433                         dataStream >> buttonName >> numButtons;
00434                         
00435                         ThymioButton *button = 0;
00436 
00437                         if ( buttonName == "button" )
00438                                 button = new ThymioButtonsEvent(0, advancedMode);
00439                         else if ( buttonName == "prox" )
00440                                 button = new ThymioProxEvent(0, advancedMode);
00441                         else if ( buttonName == "proxground" )
00442                                 button = new ThymioProxGroundEvent(0, advancedMode);
00443                         else if ( buttonName == "tap" )
00444                         {
00445                                 button = new ThymioTapEvent(0, advancedMode);
00446                                 QByteArray rendererData = event->mimeData()->data("thymiorenderer");
00447                                 QDataStream rendererStream(&rendererData, QIODevice::ReadOnly);
00448                                 quint64 location;
00449                                 rendererStream >> location;
00450                                 QSvgRenderer *tapSvg;
00451                                 tapSvg = (QSvgRenderer*)location;
00452                                 button->setSharedRenderer(tapSvg);
00453                         }
00454                         else if ( buttonName == "clap" )
00455                         {
00456                                 button = new ThymioClapEvent(0, advancedMode);
00457                                 QByteArray rendererData = event->mimeData()->data("thymiorenderer");
00458                                 QDataStream rendererStream(&rendererData, QIODevice::ReadOnly);
00459                                 quint64 location;
00460                                 rendererStream >> location;
00461                                 QSvgRenderer *clapSvg;
00462                                 clapSvg = (QSvgRenderer*)location;
00463                                 button->setSharedRenderer(clapSvg);
00464                         }
00465                         else if ( buttonName == "move" )
00466                                 button = new ThymioMoveAction();
00467                         else if ( buttonName == "color" )
00468                                 button = new ThymioColorAction();
00469                         else if ( buttonName == "circle" )
00470                                 button = new ThymioCircleAction();
00471                         else if ( buttonName == "sound" )                       
00472                                 button = new ThymioSoundAction();
00473                         else if ( buttonName == "memory" )
00474                                 button = new ThymioMemoryAction();
00475 
00476                         if( button ) 
00477                         {                       
00478                                 event->setDropAction(Qt::MoveAction);
00479                                 event->accept();
00480                                 
00481                                 lastFocus = -1;
00482                                 prevNewActionButton = false;
00483                                 prevNewEventButton = false;
00484                                 newRow = true;
00485                                 
00486                                 if( event->mimeData()->data("thymiotype") == QString("event").toLatin1() )
00487                                         addEvent(button);
00488                                 else if( event->mimeData()->data("thymiotype") == QString("action").toLatin1() )
00489                                         addAction(button);
00490 
00491                                 for( int i=0; i<numButtons; ++i ) 
00492                                 {
00493                                         int status;
00494                                         dataStream >> status;   
00495                                         button->setClicked(i, status);
00496                                 }
00497 
00498                         }
00499                 }
00500                 else
00501                         QGraphicsScene::dropEvent(event);
00502         }
00503 
00504         void ThymioScene::mousePressEvent(QGraphicsSceneMouseEvent *event)
00505         {               
00506                 QGraphicsScene::mousePressEvent(event);
00507         }
00508         
00509         void ThymioScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
00510         {
00511                 QGraphicsScene::mouseReleaseEvent(event);
00512                 
00513                 if( event->button() == Qt::LeftButton ) 
00514                 {
00515                         QGraphicsItem *item = focusItem();
00516                         if( item )
00517                         {
00518                                 if( item->data(0) == "remove" )                                 
00519                                         removeButton((item->parentItem()->data(1)).toInt());
00520                                 else if( item->data(0) == "add" )
00521                                         insertButton((item->parentItem()->data(1)).toInt()+1);
00522 //                              else if( item->data(0) == "buttonset" )
00523 //                                      lastFocus = item->data(1).toInt();
00524                         }
00525                 }
00526                 
00527                 update();
00528         }
00529 
00530 };


aseba
Author(s): Stéphane Magnenat
autogenerated on Thu Jan 2 2014 11:17:17