00001 #include "NeovisionII/NeoAnnotate/DBManager.qt.H" 00002 #include "NeovisionII/NeoAnnotate/MainWindow.qt.H" 00003 #include <Qt/QtCore> 00004 #include <QtSql/QSqlDatabase> 00005 #include <QtSql/QSqlError> 00006 #include <QtSql/QSqlQuery> 00007 #include <Qt3Support/q3urloperator.h> 00008 #include <Qt3Support/q3network.h> 00009 #include "NeovisionII/NeoAnnotate/AnnotationObjectManager.qt.H" 00010 #include "NeovisionII/NeoAnnotate/AnnotationObject.qt.H" 00011 #include <set> 00012 00013 // ###################################################################### 00014 ConnectionDialog::ConnectionDialog(QWidget* parent) 00015 : QDialog(parent) 00016 { 00017 QFormLayout *layout = new QFormLayout; 00018 00019 serverNameEdit = new QLineEdit("isvn.usc.edu"); 00020 layout->addRow(tr("&Server Name"), serverNameEdit); 00021 00022 dbNameEdit = new QLineEdit("neo2annotations"); 00023 layout->addRow(tr("&Database Name"), dbNameEdit); 00024 00025 userNameEdit = new QLineEdit("neo2"); 00026 layout->addRow(tr("&User Name"), userNameEdit); 00027 00028 passwordEdit = new QLineEdit("neo2!"); 00029 passwordEdit->setEchoMode(QLineEdit::Password); 00030 layout->addRow(tr("&Password"), passwordEdit); 00031 00032 QPushButton* cancelButton = new QPushButton("&Cancel", this); 00033 connect(cancelButton, SIGNAL(clicked()), this, SLOT(reject())); 00034 layout->addRow(cancelButton); 00035 00036 QPushButton* connectButton = new QPushButton("&Connect", this); 00037 connect(connectButton, SIGNAL(clicked()), this, SLOT(accept())); 00038 layout->addRow(connectButton); 00039 00040 setLayout(layout); 00041 } 00042 00043 // ###################################################################### 00044 NewDBEntryDialog::NewDBEntryDialog(QWidget* parent, DBManager *mgr, QSqlDatabase* _db) 00045 : QDialog(parent), 00046 itsDBManager(mgr), 00047 db(_db), 00048 itsSceneUid("-1") 00049 { 00050 setMinimumSize(QSize(500, 200)); 00051 QFormLayout *layout = new QFormLayout; 00052 00053 labComboBox = new QComboBox(this); 00054 layout->addRow(tr("Lab"), labComboBox); 00055 connect(labComboBox, SIGNAL(activated(int)), this, SLOT(fillInCameraOperator(int))); 00056 00057 QHBoxLayout* fileChooserLayout = new QHBoxLayout; 00058 fileNameLabel = new QLabel; 00059 QPushButton* fileNameButton = new QPushButton("Browse..."); 00060 connect(fileNameButton, SIGNAL(clicked()), this, SLOT(browse())); 00061 fileChooserLayout->addWidget(fileNameLabel); 00062 fileChooserLayout->addWidget(fileNameButton); 00063 layout->addRow(tr("FileName"), fileChooserLayout); 00064 00065 cameraComboBox = new QComboBox(this); 00066 layout->addRow(tr("Camera"), cameraComboBox); 00067 00068 startDateTimeEdit = new QDateTimeEdit(this); 00069 layout->addRow(tr("Start Time"), startDateTimeEdit); 00070 00071 endDateTimeEdit = new QDateTimeEdit(this); 00072 layout->addRow(tr("End Time"), endDateTimeEdit); 00073 00074 timeZoneBox = new QComboBox(this); 00075 timeZoneBox->addItem("NST Newfoundland Standard Time", "NST"); 00076 timeZoneBox->addItem("NDT Newfoundland Daylight Time", "NDT"); 00077 timeZoneBox->addItem("AST Atlantic Standard Time", "AST"); 00078 timeZoneBox->addItem("ADT Atlantic Daylight Time", "ADT"); 00079 timeZoneBox->addItem("EST Eastern Standard Time", "EST"); 00080 timeZoneBox->addItem("EDT Eastern Daylight Time", "EDT"); 00081 timeZoneBox->addItem("CST Central Standard Time", "CST"); 00082 timeZoneBox->addItem("CDT Central Daylight Time", "CDT"); 00083 timeZoneBox->addItem("MST Mountain Standard Time", "MST"); 00084 timeZoneBox->addItem("MDT Mountain Daylight Time", "MDT"); 00085 timeZoneBox->addItem("PST Pacific Standard Time", "PST"); 00086 timeZoneBox->addItem("PDT Pacific Daylight Time", "PDT"); 00087 timeZoneBox->addItem("AKST Alaska Standard Time", "AKST"); 00088 timeZoneBox->addItem("AKDT Alaska Daylight Time", "AKDT"); 00089 timeZoneBox->addItem("HAST Hawaii-Aleutian Standard Time", "HAST"); 00090 timeZoneBox->addItem("HADT Hawaii-Aleutian Daylight Time", "HADT"); 00091 layout->addRow(tr("Time Zone"), timeZoneBox); 00092 00093 operatorComboBox = new QComboBox(this); 00094 layout->addRow(tr("Operator"), operatorComboBox); 00095 00096 weatherComboBox = new QComboBox(this); 00097 layout->addRow(tr("Weather"), weatherComboBox); 00098 00099 startFrameEdit = new QLineEdit(this); 00100 startFrameEdit->setValidator(new QIntValidator(0, 9999999, this)); 00101 layout->addRow(tr("Start Frame"), startFrameEdit); 00102 00103 numFramesEdit = new QLineEdit(this); 00104 numFramesEdit->setValidator(new QIntValidator(0, 9999999, this)); 00105 layout->addRow(tr("Number of Frames"), numFramesEdit); 00106 00107 frameRateEdit = new QLineEdit(this); 00108 frameRateEdit->setValidator(new QIntValidator(1, 300, this)); 00109 layout->addRow(tr("Frame Rate"), frameRateEdit); 00110 00111 sceneNameEdit = new QLineEdit(this); 00112 layout->addRow(tr("Scene Name"), sceneNameEdit); 00113 00114 QPushButton* createButton = new QPushButton("&Create", this); 00115 connect(createButton, SIGNAL(clicked()), this, SLOT(commitNewScene())); 00116 layout->addRow(createButton); 00117 00118 QPushButton* cancelButton = new QPushButton("&Cancel", this); 00119 connect(cancelButton, SIGNAL(clicked()), this, SLOT(reject())); 00120 layout->addRow(cancelButton); 00121 00122 setLayout(layout); 00123 } 00124 00125 // ###################################################################### 00126 void NewDBEntryDialog::browse() 00127 { 00128 QString fileName = QFileDialog::getOpenFileName(this, 00129 tr("Select Video File"), QString(VIDEO_INCOMING_LOCATION), tr("Video Files (*.MTS *.AVI *.MPG *.MPEG)")); 00130 QFileInfo inputFileInfo(fileName); 00131 QFileInfo mgzJFileInfo(inputFileInfo.dir().path() + "/" + inputFileInfo.baseName() + ".mgzJ"); 00132 if(!mgzJFileInfo.exists()) 00133 { 00134 QMessageBox msgBox(QMessageBox::Critical, "No mgzJ File Found", 00135 "The input file you selected does not have a corresponding .mgzJ file in the same directory.\n" 00136 "Please create a .mgzJ file for this video, and try again.", 00137 QMessageBox::Ok); 00138 msgBox.exec(); 00139 } 00140 else 00141 { 00142 fileNameLabel->setText(fileName); 00143 } 00144 } 00145 00146 // ###################################################################### 00147 void NewDBEntryDialog::commitNewScene() 00148 { 00149 00150 QDateTime startTime = startDateTimeEdit->dateTime(); 00151 QDateTime endTime = endDateTimeEdit->dateTime(); 00152 if(startTime >= endTime) 00153 { 00154 QMessageBox msgBox(QMessageBox::Critical, "Bad Dates!", 00155 "Start date/time cannot be after end date/time!", 00156 QMessageBox::Ok); 00157 msgBox.exec(); 00158 } 00159 else 00160 { 00161 QString timeZone = timeZoneBox->itemData(timeZoneBox->currentIndex()).toString(); 00162 QString startDateTime = startTime.toString("yyyy-MM-dd hh:mm ") + timeZone; 00163 QString endDateTime = endTime.toString("yyyy-MM-dd hh:mm ") + timeZone; 00164 00165 QString sourceFileName = fileNameLabel->text(); 00166 QString fileSuffix = QFileInfo(sourceFileName).suffix(); 00167 00168 QString insertStatement; 00169 insertStatement += "INSERT INTO scene "; 00170 insertStatement += "(starttime, endtime, camera, operator, url, numframes, framerate, weather, startframe, name) "; 00171 insertStatement += "VALUES ("; 00172 insertStatement += "\'" + startDateTime + "\', "; 00173 insertStatement += "\'" + endDateTime + "\', "; 00174 insertStatement += cameraComboBox->itemData(cameraComboBox->currentIndex()).toString() + ", "; 00175 insertStatement += operatorComboBox->itemData(operatorComboBox->currentIndex()).toString() + ", "; 00176 insertStatement += "\'ext://" + fileSuffix + "\', "; 00177 insertStatement += numFramesEdit->text() + ", "; 00178 insertStatement += frameRateEdit->text() + ", "; 00179 insertStatement += weatherComboBox->itemData(weatherComboBox->currentIndex()).toString() + ", "; 00180 insertStatement += startFrameEdit->text() + ", "; 00181 insertStatement += "\'" + sceneNameEdit->text() + "\'"; 00182 insertStatement += ")"; 00183 00184 db->exec(insertStatement); 00185 00186 if(db->lastError().isValid()) 00187 { 00188 QMessageBox msgBox(QMessageBox::Critical, "Database Insert Error", 00189 "Error inserting into database. Reason:\n" + db->lastError().text() + "\n\n" + 00190 "Insert Statement Was:\n"+insertStatement, 00191 QMessageBox::Ok); 00192 msgBox.exec(); 00193 } 00194 else 00195 { 00196 // Get the most recently obtained sequence value for our uid - this should be safe, 00197 // even for multiple users 00198 QSqlQuery query = db->exec("select currval('scene_uid_seq')"); 00199 00200 if(db->lastError().isValid()) 00201 { 00202 QMessageBox msgBox(QMessageBox::Critical, "Database Select Error", 00203 "Error retrieving last insertion UID. Reason:\n" + db->lastError().text(), 00204 QMessageBox::Ok); 00205 msgBox.exec(); 00206 } 00207 else 00208 { 00209 // Copy the file to it's new home in the neo2data/archive directory, renamed to the fetched uid 00210 query.next(); 00211 itsSceneUid = query.value(0).toString(); 00212 00213 { 00214 QString destinationFileName = itsDBManager->itsArchiveLoc + "/" + itsSceneUid + "." + fileSuffix; 00215 QProcess copyProc; 00216 QString execString("/bin/mv " + sourceFileName + " " + destinationFileName); 00217 qDebug() << execString; 00218 QProgressDialog progressDialog(this); 00219 progressDialog.setAutoClose(false); 00220 progressDialog.setAutoReset(false); 00221 progressDialog.setLabel(new QLabel("Copying File, Please Wait...", this)); 00222 progressDialog.setCancelButton(0); 00223 progressDialog.setRange(0, 0); 00224 connect(©Proc, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(copyFinished(int, QProcess::ExitStatus))); 00225 connect(this, SIGNAL(closeProgressDialog()), &progressDialog, SLOT(cancel())); 00226 copyProc.start(execString); 00227 progressDialog.exec(); 00228 copyProc.waitForFinished(-1); 00229 } 00230 { 00231 QFileInfo inputFileInfo(sourceFileName); 00232 QString sourceMgzJFileName = inputFileInfo.dir().path() + "/" + inputFileInfo.baseName() + ".mgzJ"; 00233 itsMgzJFileName = itsDBManager->itsWorkingLoc + "/" + itsSceneUid + ".mgzJ"; 00234 00235 qDebug() << "Setting mgzJ filename: " << itsMgzJFileName; 00236 00237 QProcess copyProc; 00238 QString execString("/bin/mv " + sourceMgzJFileName + " " + itsMgzJFileName); 00239 qDebug() << execString; 00240 QProgressDialog progressDialog(this); 00241 progressDialog.setAutoClose(false); 00242 progressDialog.setAutoReset(false); 00243 progressDialog.setLabel(new QLabel("Copying File, Please Wait...", this)); 00244 progressDialog.setCancelButton(0); 00245 progressDialog.setRange(0, 0); 00246 connect(©Proc, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(copyFinished(int, QProcess::ExitStatus))); 00247 connect(this, SIGNAL(closeProgressDialog()), &progressDialog, SLOT(cancel())); 00248 copyProc.start(execString); 00249 progressDialog.exec(); 00250 copyProc.waitForFinished(-1); 00251 } 00252 accept(); 00253 } 00254 } 00255 } 00256 } 00257 00258 // ###################################################################### 00259 void NewDBEntryDialog::copyFinished(int exitCode, QProcess::ExitStatus exitStatus) 00260 { 00261 emit closeProgressDialog(); 00262 } 00263 00264 // ###################################################################### 00265 void NewDBEntryDialog::showEvent(QShowEvent* event) 00266 { 00267 00268 // Fill in the lab combo box first 00269 labComboBox->clear(); 00270 QSqlQuery labsQuery = db->exec("SELECT uid, name, institution FROM lab"); 00271 while(labsQuery.next()) 00272 { 00273 int uid = labsQuery.value(0).toInt(); 00274 QString name = labsQuery.value(1).toString(); 00275 QString institution = labsQuery.value(2).toString(); 00276 labComboBox->addItem(name + " @ " + institution, uid); 00277 } 00278 00279 QSqlQuery weatherQuery = db->exec("SELECT uid, name FROM weather"); 00280 while(weatherQuery.next()) 00281 { 00282 int uid = weatherQuery.value(0).toInt(); 00283 QString name = weatherQuery.value(1).toString(); 00284 weatherComboBox->addItem(name, uid); 00285 } 00286 00287 fillInCameraOperator(0); 00288 00289 QDialog::showEvent(event); 00290 } 00291 00292 // ###################################################################### 00293 void NewDBEntryDialog::fillInCameraOperator(int labComboBoxRow) 00294 { 00295 int labUID = labComboBox->itemData(labComboBoxRow).toInt(); 00296 cameraComboBox->clear(); 00297 operatorComboBox->clear(); 00298 00299 QSqlQuery cameraQuery = 00300 db->exec("SELECT uid, name, manufacturer, model FROM camera WHERE lab="+QString::number(labUID)); 00301 while(cameraQuery.next()) 00302 { 00303 int uid = cameraQuery.value(0).toInt(); 00304 QString name = cameraQuery.value(1).toString(); 00305 QString manufacturer = cameraQuery.value(2).toString(); 00306 QString model = cameraQuery.value(3).toString(); 00307 cameraComboBox->addItem(name + ": " + manufacturer + " " + model, uid); 00308 } 00309 00310 QSqlQuery operatorQuery = 00311 db->exec("SELECT uid, firstname, lastname, jobtitle FROM operator WHERE lab="+QString::number(labUID)); 00312 while(operatorQuery.next()) 00313 { 00314 int uid = operatorQuery.value(0).toInt(); 00315 QString firstname = operatorQuery.value(1).toString(); 00316 QString lastname = operatorQuery.value(2).toString(); 00317 QString jobtitle = operatorQuery.value(3).toString(); 00318 operatorComboBox->addItem(lastname + ", " + firstname + " : " + jobtitle, uid); 00319 } 00320 qDebug() << "Getting Operator!: " << db->lastError(); 00321 } 00322 00323 // ###################################################################### 00324 SelectAnnotationSourceDialog::SelectAnnotationSourceDialog(QWidget* parent, QSqlDatabase* _db) : 00325 QDialog(parent), 00326 itsSourceUid("-1"), 00327 db(_db) 00328 { 00329 setMinimumSize(QSize(500, 200)); 00330 QVBoxLayout *layout = new QVBoxLayout; 00331 00332 itsSourceTree = new QTreeWidget(this); 00333 QStringList headerList; 00334 headerList << "UID" << "Name" << "Validation Level"; 00335 itsSourceTree->setHeaderLabels(headerList); 00336 00337 layout->addWidget(itsSourceTree); 00338 00339 QPushButton* openButton = new QPushButton("&Select", this); 00340 connect(openButton, SIGNAL(clicked()), this, SLOT(selectSource())); 00341 layout->addWidget(openButton); 00342 00343 QPushButton* cancelButton = new QPushButton("&Cancel", this); 00344 connect(cancelButton, SIGNAL(clicked()), this, SLOT(reject())); 00345 layout->addWidget(cancelButton); 00346 00347 setLayout(layout); 00348 } 00349 00350 void SelectAnnotationSourceDialog::showEvent(QShowEvent* event) 00351 { 00352 itsSourceTree->clear(); 00353 QSqlQuery sourceQuery = 00354 db->exec("SELECT uid, name, validationlevel FROM annotationsource WHERE categ=2"); 00355 while(sourceQuery.next()) 00356 { 00357 QString uid = sourceQuery.value(0).toString(); 00358 QString name = sourceQuery.value(1).toString(); 00359 QString level = sourceQuery.value(2).toString(); 00360 QStringList source; 00361 source << uid << name << level; 00362 itsSourceTree->addTopLevelItem(new QTreeWidgetItem(source)); 00363 } 00364 00365 QDialog::showEvent(event); 00366 } 00367 00368 // ###################################################################### 00369 void SelectAnnotationSourceDialog::selectSource() 00370 { 00371 00372 QTreeWidgetItem* selectedSource = itsSourceTree->currentItem(); 00373 if(selectedSource == NULL) return; 00374 00375 itsSourceUid = selectedSource->text(0); 00376 00377 if(itsSourceUid != "-1") 00378 static_cast<MainWindow*>(parent())->setAnnotatorLabel("Annotating As " + selectedSource->text(1)); 00379 else 00380 static_cast<MainWindow*>(parent())->setAnnotatorLabel("No Annotator Selected"); 00381 00382 accept(); 00383 } 00384 00385 // ###################################################################### 00386 OpenDBEntryDialog::OpenDBEntryDialog(QWidget* parent, DBManager *mgr, QSqlDatabase* _db) : 00387 QDialog(parent), 00388 itsDBManager(mgr), 00389 itsSceneUid("-1"), 00390 db(_db) 00391 { 00392 setMinimumSize(QSize(500, 200)); 00393 QVBoxLayout *layout = new QVBoxLayout; 00394 00395 itsSceneTree = new QTreeWidget(this); 00396 QStringList headerList; 00397 headerList << "UID" << "Name" << "Operator" << "Camera" << "Start Time" << "End Time"; 00398 itsSceneTree->setHeaderLabels(headerList); 00399 layout->addWidget(itsSceneTree); 00400 00401 QPushButton* openButton = new QPushButton("&Open", this); 00402 connect(openButton, SIGNAL(clicked()), this, SLOT(openEntry())); 00403 layout->addWidget(openButton); 00404 00405 QPushButton* cancelButton = new QPushButton("&Cancel", this); 00406 connect(cancelButton, SIGNAL(clicked()), this, SLOT(reject())); 00407 layout->addWidget(cancelButton); 00408 00409 setLayout(layout); 00410 } 00411 00412 void OpenDBEntryDialog::showEvent(QShowEvent* event) 00413 { 00414 itsSceneTree->clear(); 00415 00416 QSqlQuery sceneQuery = 00417 db->exec("SELECT uid, name, operator, camera, starttime, endtime FROM scene ORDER BY name"); 00418 00419 while(sceneQuery.next()) 00420 { 00421 QString uid = sceneQuery.value(0).toString(); 00422 QString name = sceneQuery.value(1).toString(); 00423 QString operatorId = sceneQuery.value(2).toString(); 00424 QString cameraId = sceneQuery.value(3).toString(); 00425 QString startTime = sceneQuery.value(4).toString(); 00426 QString endTime = sceneQuery.value(5).toString(); 00427 00428 QSqlQuery cameraQuery = 00429 db->exec("SELECT name FROM camera WHERE uid="+cameraId); 00430 QString cameraName = ""; 00431 if(cameraQuery.size() > 0) 00432 { 00433 cameraQuery.next(); 00434 cameraName = cameraQuery.value(0).toString(); 00435 } 00436 00437 QSqlQuery operatorQuery = 00438 db->exec("SELECT firstname,lastname FROM operator WHERE uid="+operatorId); 00439 QString operatorName = ""; 00440 if(operatorQuery.size() > 0) 00441 { 00442 operatorQuery.next(); 00443 operatorName = operatorQuery.value(1).toString() + ", " + operatorQuery.value(0).toString(); 00444 } 00445 00446 QStringList sceneItem; 00447 sceneItem << uid << name << operatorName << cameraName << startTime << endTime; 00448 00449 QTreeWidgetItem* newItem = new QTreeWidgetItem(sceneItem); 00450 00451 QString mgzJFileName = itsDBManager->itsWorkingLoc + "/" + uid + ".mgzJ"; 00452 QFileInfo mgzJFileInfo(mgzJFileName); 00453 if(mgzJFileInfo.exists() == false) 00454 newItem->setDisabled(true); 00455 00456 itsSceneTree->addTopLevelItem(newItem); 00457 } 00458 00459 QDialog::showEvent(event); 00460 } 00461 00462 void OpenDBEntryDialog::openEntry() 00463 { 00464 QTreeWidgetItem* selectedScene = itsSceneTree->currentItem(); 00465 if(selectedScene) 00466 { 00467 itsSceneUid = selectedScene->text(0); 00468 00469 QString mgzJFileName = itsDBManager->itsWorkingLoc + "/" + itsSceneUid + ".mgzJ"; 00470 QFileInfo mgzJFileInfo(mgzJFileName); 00471 if(mgzJFileInfo.exists()) 00472 { 00473 itsMgzJFileName = mgzJFileName; 00474 accept(); 00475 } 00476 else 00477 { 00478 QMessageBox msgBox(QMessageBox::Warning, "Could Not Open MgzJ File", 00479 "No .mgzJ file found for this scene.\n\n" 00480 "You must ensure that the cached .mgzJ file (" + mgzJFileName + ") " 00481 "exists before trying to reopen an annotation.\n\n" 00482 "**** This error should not have occured! Please file a bug report with the following info:\n" 00483 "File: " + QString(__FILE__) + " Line: " + QString(__LINE__), 00484 QMessageBox::Ok); 00485 msgBox.exec(); 00486 } 00487 } 00488 else 00489 { 00490 QMessageBox msgBox(QMessageBox::Warning, "No Scene Selected", 00491 "You did not select a scene!\n\n" 00492 "If all scenes are greyed out, then you must reconvert some original " 00493 "footage into the .mgzJ format. Please see Dr. Itti or Rand for " 00494 "instructions on doing this.", 00495 QMessageBox::Ok); 00496 msgBox.exec(); 00497 } 00498 } 00499 00500 // ###################################################################### 00501 00502 // ###################################################################### 00503 void DBManager::connectToDb() 00504 { 00505 if(itsConnDialog.exec()) 00506 { 00507 db = QSqlDatabase::addDatabase("QPSQL"); 00508 db.setHostName(itsConnDialog.serverNameEdit->text()); 00509 db.setDatabaseName(itsConnDialog.dbNameEdit->text()); 00510 db.setUserName(itsConnDialog.userNameEdit->text()); 00511 db.setPassword(itsConnDialog.passwordEdit->text()); 00512 00513 connected = db.open(); 00514 00515 00516 if(!connected) 00517 { 00518 QMessageBox msgBox(QMessageBox::Warning, "Could Not Connect", 00519 "Could Not Connect To The Database.\nReason:" + db.lastError().text(), 00520 QMessageBox::Ok); 00521 msgBox.exec(); 00522 } 00523 } 00524 00525 00526 if(connected) 00527 { 00528 static_cast<MainWindow*>(parent())->setDBStatusLabel("Connected To " + db.hostName()); 00529 chooseAnnotationSource(); 00530 } 00531 else 00532 static_cast<MainWindow*>(parent())->setDBStatusLabel("Not Connected To DB"); 00533 } 00534 00535 void DBManager::chooseAnnotationSource() 00536 { 00537 while(!connected) connectToDb(); 00538 00539 while(!itsSelectAnnotationSourceDialog.exec()) 00540 { 00541 QMessageBox msgBox(QMessageBox::Warning, "No Annotation Source Selected", 00542 "You must select yourself as an annotation source to save or load any work.", 00543 QMessageBox::Ok); 00544 msgBox.exec(); 00545 } 00546 } 00547 00548 // ###################################################################### 00549 namespace 00550 { 00551 struct PolygonKeyframe 00552 { 00553 int scene; 00554 std::vector<QPointF> vertices; 00555 std::vector<bool> verticesVisible; 00556 std::vector<bool> verticesKeyframe; 00557 int annotationSource; 00558 int object; 00559 QPointF pos; 00560 bool visible; 00561 bool keyframe; 00562 }; 00563 } 00564 void DBManager::saveAnnotation() 00565 { 00566 // Make sure we have a valid annotation source, and are connected to the database 00567 if(!connected) connectToDb(); 00568 if(!connected) 00569 { 00570 QMessageBox msgBox(QMessageBox::Warning, "Not connected to a database", 00571 "Your work has not been saved!\n\n" 00572 "You must connect to a database before saving your work.", 00573 QMessageBox::Ok); 00574 msgBox.exec(); 00575 return; 00576 } 00577 00578 QString sourceUid = itsSelectAnnotationSourceDialog.getSourceUid(); 00579 if(sourceUid == "-1") 00580 { 00581 QMessageBox msgBox(QMessageBox::Warning, "No source selected!", 00582 "Your work has not been saved!\n\n" 00583 "You must choose yourself as an annotation source before you can save your work.", 00584 QMessageBox::Ok); 00585 msgBox.exec(); 00586 return; 00587 } 00588 00589 // Make sure we have a valid scene to save to 00590 if(itsSceneUid == "-1") 00591 { 00592 QMessageBox msgBox(QMessageBox::Warning, "Work not saved!", 00593 "Your work has not been saved!\n\n" 00594 "You must choose a valid scene in order to save your work.", 00595 QMessageBox::Ok); 00596 msgBox.exec(); 00597 return; 00598 } 00599 00600 // Clear out all entries from this annotator for this scene 00601 db.exec("DELETE from Polygon WHERE scene="+itsSceneUid+" AND annotationSource="+sourceUid); 00602 db.exec("DELETE from PolygonKeyframe WHERE scene="+itsSceneUid+" AND annotationSource="+sourceUid); 00603 00604 AnnotationObjectManager* mgr = static_cast<MainWindow*>(parent())->getObjectManager(); 00605 00606 // Write the keyframes to the database 00607 std::map<int, QString> objIdMap; // A mapping from GUI ids to database ids 00608 QList<AnnotationObject *> objects = mgr->getAnnotationObjects(); 00609 QList<AnnotationObject *>::iterator objIt; 00610 for(objIt = objects.begin(); objIt != objects.end(); ++objIt) 00611 { 00612 AnnotationObject* obj = *objIt; 00613 ObjectAnimation* mainAnimation = obj->getAnimation(); 00614 QList<AnnotationObjectVertex*> vertices = *(obj->getVertices()); 00615 00616 00617 std::map<int, PolygonKeyframe> keyframes; 00618 00619 00620 size_t numVertices = obj->getVertices()->size(); 00621 00622 QMap<int, ObjectAnimation::FrameState> keyFrames = mainAnimation->getKeyFrames(); 00623 00624 // First, insert the main polygon's keyframes 00625 QMap<int, ObjectAnimation::FrameState>::iterator keyIt; 00626 for(keyIt = mainAnimation->getKeyFrames().begin(); keyIt != mainAnimation->getKeyFrames().end(); ++keyIt) 00627 { 00628 int frameNum = keyIt.key(); 00629 ObjectAnimation::FrameState frameState = keyIt.value(); 00630 00631 keyframes[frameNum].keyframe = true; 00632 keyframes[frameNum].visible = frameState.visible; 00633 keyframes[frameNum].pos = frameState.pos; 00634 00635 keyframes[frameNum].vertices.resize(numVertices); 00636 keyframes[frameNum].verticesVisible.resize(numVertices); 00637 keyframes[frameNum].verticesKeyframe.resize(numVertices); 00638 00639 } 00640 00641 // Next, insert each of the vertices keyframes 00642 for(int vertIdx=0; vertIdx < vertices.size(); ++vertIdx) 00643 { 00644 AnnotationObjectVertex* vertex = vertices[vertIdx]; 00645 for(keyIt=vertex->getAnimation()->getKeyFrames().begin(); keyIt!=vertex->getAnimation()->getKeyFrames().end(); ++keyIt) 00646 { 00647 int frameNum = keyIt.key(); 00648 ObjectAnimation::FrameState frameState = keyIt.value(); 00649 00650 00651 if(keyframes[frameNum].vertices.size() != numVertices) 00652 { 00653 keyframes[frameNum].vertices.resize(numVertices); 00654 keyframes[frameNum].verticesVisible.resize(numVertices); 00655 keyframes[frameNum].verticesKeyframe.resize(numVertices); 00656 } 00657 00658 keyframes[frameNum].vertices[vertIdx] = frameState.pos; 00659 keyframes[frameNum].verticesVisible[vertIdx] = frameState.visible; 00660 keyframes[frameNum].verticesKeyframe[vertIdx] = true; 00661 } 00662 } // for vertex 00663 00664 //Create a db entry for this object 00665 db.exec("INSERT into Object (category) VALUES ("+QString::number(obj->getType())+")"); 00666 00667 // Get the most recently obtained object uid - this should be safe, 00668 // even for multiple users 00669 QSqlQuery query = db.exec("select currval('object_uid_seq')"); 00670 query.next(); 00671 QString objDbId = query.value(0).toString(); 00672 objIdMap[obj->getId()] = objDbId; 00673 00674 //Insert the object description 00675 QSqlQuery descPropUidQuery = db.exec("SELECT uid FROM objectproptype WHERE name='Description'"); 00676 descPropUidQuery.next(); 00677 QString descPropUid = descPropUidQuery.value(0).toString(); 00678 QSqlQuery insertDescQuery = db.exec("INSERT into objectproperties (object, type, value) VALUES (" 00679 +objDbId+", " 00680 +descPropUid+", " 00681 + "'" + obj->getDescription()+"')" 00682 ); 00683 00684 //Now, insert the whole keyframe structure into the database 00685 std::map<int, PolygonKeyframe>::iterator keyframeIt; 00686 for(keyframeIt=keyframes.begin();keyframeIt!=keyframes.end(); ++keyframeIt) 00687 { 00688 int frameNum = keyframeIt->first; 00689 PolygonKeyframe polyData = keyframeIt->second; 00690 00691 QString queryString = "INSERT into PolygonKeyframe "; 00692 queryString += "(scene, frame, vertices, verticesVisible, verticesKeyframe, " 00693 "annotationSource, object, pos, visible, keyframe, time)"; 00694 queryString += " VALUES ("; 00695 queryString += itsSceneUid + ", "; 00696 queryString += QString::number(frameNum) + ", "; 00697 queryString += "'("; 00698 for(size_t i=0; i<polyData.vertices.size(); ++i) 00699 { 00700 queryString += "(" + QString::number(polyData.vertices[i].x()) + "," + QString::number(polyData.vertices[i].y()) + ")"; 00701 if(i < polyData.vertices.size()-1) queryString += ","; 00702 } 00703 queryString += ")', "; 00704 queryString += "'{"; 00705 for(size_t i=0; i<polyData.verticesVisible.size(); ++i) 00706 { 00707 queryString += polyData.verticesVisible[i] ? "t" : "f"; 00708 if(i < polyData.vertices.size()-1) queryString += ","; 00709 } 00710 queryString += "}', "; 00711 queryString += "'{"; 00712 for(size_t i=0; i<polyData.verticesKeyframe.size(); ++i) 00713 { 00714 queryString += polyData.verticesKeyframe[i] ? "t" : "f"; 00715 if(i < polyData.vertices.size()-1) queryString += ","; 00716 } 00717 queryString += "}', "; 00718 queryString += sourceUid + ", "; 00719 queryString += objDbId + ", "; 00720 queryString += "'(" + QString::number(polyData.pos.x()) + "," + QString::number(polyData.pos.y()) + ")', "; 00721 queryString += polyData.visible ? "'t'" : "'f'"; 00722 queryString += ", "; 00723 queryString += polyData.keyframe ? "'t'" : "'f'"; 00724 queryString += ", "; 00725 queryString += "NOW()"; 00726 queryString += ")"; 00727 00728 db.exec(queryString); 00729 } 00730 } // for object 00731 00732 ////////////////////////////////////////////////////////////////////// 00733 //Dump the rendered animation 00734 std::set<int> insertedObjects; 00735 std::map<int, std::map<int,AnnotationObjectFrame> > animation = mgr->renderAnimations(); 00736 std::map<int, std::map<int,AnnotationObjectFrame> >::iterator animIt = animation.begin(); 00737 for(;animIt!=animation.end(); ++animIt) 00738 { 00739 int frameNum = animIt->first; 00740 std::map<int,AnnotationObjectFrame>::iterator objectIt = animIt->second.begin(); 00741 for(;objectIt!=animIt->second.end(); ++objectIt) 00742 { 00743 QString objId = objIdMap[objectIt->first]; //All objects already in db 00744 AnnotationObjectFrame objFrame = objectIt->second; 00745 ObjectAnimation::FrameState objFrameState = objFrame.ObjectFrameState; 00746 if(objFrameState.visible) 00747 { 00748 //Construct the string of vertices 00749 QPointF center(0, 0); int numVisVert = 0; 00750 QString verticesString = "("; 00751 std::map<int, ObjectAnimation::FrameState>::iterator vertIt = objFrame.VertexFrames.begin(); 00752 for(; vertIt!=objFrame.VertexFrames.end(); ++vertIt) 00753 { 00754 ObjectAnimation::FrameState vertState = vertIt->second; 00755 if(vertState.visible) 00756 { 00757 QPointF pos = vertState.pos;//+objFrameState.pos; 00758 center += pos; numVisVert++; 00759 verticesString += "("+QString::number(pos.x())+","+QString::number(pos.y())+"),"; 00760 } 00761 } 00762 verticesString.chop(1); //Remove last comma 00763 verticesString+=")"; 00764 if(numVisVert == 0) continue; 00765 00766 //Construct Center string (don't insert it for now) 00767 center/=numVisVert; 00768 QString centerString = "("+QString::number(center.x())+","+QString::number(center.y())+")"; 00769 00770 QString queryString = "INSERT INTO polygon (scene, frame, vertices, annotationsource, object, time) VALUES ("; 00771 queryString += itsSceneUid + ", "; 00772 queryString += QString::number(frameNum) + ", "; 00773 queryString += "'" + verticesString + "', "; 00774 queryString += sourceUid + ", "; 00775 queryString += objId + ", "; 00776 queryString += "NOW()"; 00777 queryString += ")"; 00778 db.exec(queryString); 00779 } //objFrameState.visible 00780 00781 } 00782 } 00783 00784 } 00785 00786 00787 void DBManager::openAnnotation() 00788 { 00789 if(!connected) connectToDb(); 00790 if(!connected) 00791 { 00792 return; 00793 } 00794 00795 QString sourceUid = itsSelectAnnotationSourceDialog.getSourceUid(); 00796 while(sourceUid == "-1") 00797 { 00798 chooseAnnotationSource(); 00799 sourceUid = itsSelectAnnotationSourceDialog.getSourceUid(); 00800 } 00801 00802 if(!itsOpenDBEntryDialog.exec()) return; 00803 itsSceneUid = itsOpenDBEntryDialog.getSceneUid(); 00804 if(itsSceneUid == "-1") return; 00805 00806 // Open the video file 00807 emit openVideo(itsOpenDBEntryDialog.getMgzJFileName()); 00808 00809 MainWindow* mw = static_cast<MainWindow*>(parent()); 00810 AnnotationObjectManager* mgr = mw->getObjectManager(); 00811 00812 //Delete all existing objects 00813 mgr->clear(); 00814 00815 FrameRange frameRange = mw->getFrameRange(); 00816 00817 QSqlQuery objectQuery = 00818 db.exec("SELECT DISTINCT object from PolygonKeyframe WHERE scene="+itsSceneUid+" and annotationsource="+sourceUid); 00819 while(objectQuery.next()) 00820 { 00821 QString objId = objectQuery.value(0).toString(); 00822 QString keyframeQueryString = "SELECT frame, vertices, verticesVisible, verticesKeyFrame, pos, visible, keyframe " + 00823 QString("from PolygonKeyframe WHERE scene=")+itsSceneUid+ 00824 " and object="+objId+ 00825 " order by frame"; 00826 QSqlQuery keyframeQuery = db.exec(keyframeQueryString); 00827 if(keyframeQuery.size() == 0) continue; 00828 00829 AnnotationObject* obj = NULL; // new AnnotationObject(keyframeQuery.value(0).toString(), frameRange, ); 00830 00831 while(keyframeQuery.next()) 00832 { 00833 //Get the frame number 00834 int frame = keyframeQuery.value(0).toInt(); 00835 00836 //Get the list of vertices 00837 std::vector<QPointF> vertices; 00838 QString verticesString = keyframeQuery.value(1).toString().mid(1, keyframeQuery.value(1).toString().size()-2); 00839 int stringpos = verticesString.indexOf("(")+1; 00840 int stringendpos; 00841 while((stringendpos = verticesString.indexOf(")", stringpos)) != -1) 00842 { 00843 QString vertexString = verticesString.mid(stringpos, stringendpos-stringpos); 00844 stringpos = verticesString.indexOf("(",stringendpos)+1; 00845 00846 QStringList coordStrings = vertexString.split(","); 00847 QPointF vPos(coordStrings[0].toFloat(), coordStrings[1].toFloat()); 00848 vertices.push_back(vPos); 00849 00850 if(stringpos == 0) break; 00851 } 00852 00853 //Get the vertices visible list 00854 QStringList verticesVisible = 00855 keyframeQuery.value(2).toString().mid(1, keyframeQuery.value(2).toString().size()-2).split(","); 00856 00857 //Get the vertices keyframe list 00858 QStringList verticesKeyframe = 00859 keyframeQuery.value(3).toString().mid(1, keyframeQuery.value(3).toString().size()-2).split(","); 00860 00861 //Get the position 00862 QStringList posStringCoords = 00863 keyframeQuery.value(4).toString().mid(1, keyframeQuery.value(4).toString().size()-2).split(","); 00864 QPointF pos(posStringCoords[0].toFloat(), posStringCoords[1].toFloat()); 00865 00866 //Get the visibility 00867 QString visible = keyframeQuery.value(5).toString(); 00868 00869 //Get the visibility 00870 QString keyframe = keyframeQuery.value(6).toString(); 00871 00872 //Create the new object if it is not yet made 00873 if(obj == NULL) 00874 { 00875 //Find the object's category 00876 QSqlQuery objInfoQuery = db.exec("SELECT category FROM object WHERE uid="+objId); 00877 objInfoQuery.next(); 00878 int category = objInfoQuery.value(0).toInt(); 00879 00880 QSqlQuery descPropUidQuery = db.exec("SELECT uid FROM objectproptype WHERE name='Description'"); 00881 descPropUidQuery.next(); 00882 QString descPropUid = descPropUidQuery.value(0).toString(); 00883 QSqlQuery descQuery = db.exec("SELECT value FROM objectproperties WHERE object="+objId+" and type="+descPropUid); 00884 descQuery.next(); 00885 QString description = descQuery.value(0).toString(); 00886 00887 00888 //TODO: FIXME object name 00889 obj = new AnnotationObject(frame, frameRange, pos, description, category); 00890 00891 //Delete the auto-created vertices 00892 for(int vIdx=0; vIdx < obj->getVertices()->size(); ++vIdx) 00893 delete obj->getVertices()->at(vIdx); 00894 obj->getVertices()->clear(); 00895 00896 //Add in the vertices 00897 for(size_t vIdx=0; vIdx<vertices.size(); ++vIdx) 00898 { 00899 AnnotationObjectVertex* vert = new AnnotationObjectVertex(obj, frame, frameRange, vertices[vIdx]); 00900 //if(verticesVisible[vIdx] == "f") vert->setKeyframe(frame, vertices[vIdx], false); 00901 obj->addVertex(vIdx, vert); 00902 } 00903 } 00904 00905 if(keyframe[0] == 't') 00906 obj->setKeyframe(frame, pos, (visible[0] == 't')); 00907 00908 for(size_t vIdx=0; vIdx<vertices.size(); ++vIdx) 00909 if(verticesKeyframe[vIdx][0] == 't') 00910 obj->getVertexById(vIdx)->setKeyframe(frame, vertices[vIdx], (verticesVisible[vIdx][0] == 't')); 00911 } 00912 00913 //Add the object to our manager 00914 mgr->addObject(obj); 00915 mw->getMainDisplay()->addObject(obj); 00916 connect(mw->getTimeline(), SIGNAL(frameChanged(int)), obj, SLOT(frameChanged(int))); 00917 } 00918 mw->getTimeline()->setCurrentTime(0); 00919 } 00920 00921 QMap<int, QString> DBManager::getObjCategories() 00922 { 00923 00924 QSqlQuery catQuery = 00925 db.exec("SELECT uid, name FROM objectcategory"); 00926 00927 QMap<int, QString> categories; 00928 while(catQuery.next()) 00929 categories[catQuery.value(0).toInt()] = catQuery.value(1).toString(); 00930 00931 return categories; 00932 } 00933 00934 void DBManager::updateSettings(QSettings *settings) 00935 { 00936 qDebug() << "Loading Settings:"; 00937 if(settings->contains("archiveLoc")) 00938 { 00939 itsArchiveLoc = settings->value("archiveLoc").toString(); 00940 qDebug() << " itsArchiveLoc " << itsArchiveLoc; 00941 } 00942 if(settings->contains("workingLoc")) 00943 { 00944 itsWorkingLoc = settings->value("workingLoc").toString(); 00945 qDebug() << " itsWorkingLoc " << itsWorkingLoc; 00946 } 00947 if(settings->contains("incomingLoc")) 00948 { 00949 itsIncomingLoc = settings->value("incomingLoc").toString(); 00950 qDebug() << " itsIncomingLoc " << itsIncomingLoc; 00951 } 00952 }