$search
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 };