DBManager.qt.C

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(&copyProc, 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(&copyProc, 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 }
Generated on Sun May 8 08:41:02 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3