Main Page | Namespace List | Class Hierarchy | Class List | Directories | File List | Class Members | File Members

PatternDialog.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   SpikeStream Application                                               *
00003  *   Copyright (C) 2007 by David Gamez                                     *
00004  *   david@davidgamez.eu                                                   *
00005  *   Version 0.1                                                           *
00006  *                                                                         *
00007  *   This program is free software; you can redistribute it and/or modify  *
00008  *   it under the terms of the GNU General Public License as published by  *
00009  *   the Free Software Foundation; either version 2 of the License, or     *
00010  *   (at your option) any later version.                                   *
00011  *                                                                         *
00012  *   This program is distributed in the hope that it will be useful,       *
00013  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00014  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00015  *   GNU General Public License for more details.                          *
00016  *                                                                         *
00017  *   You should have received a copy of the GNU General Public License     *
00018  *   along with this program; if not, write to the                         *
00019  *   Free Software Foundation, Inc.,                                       *
00020  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
00021  ***************************************************************************/
00022 
00023 //SpikeStream includes
00024 #include "PatternDialog.h"
00025 #include "Utilities.h"
00026 #include "PatternTypes.h"
00027 #include "Debug.h"
00028 #include "BusyDialog.h"
00029 #include "SpikeStreamMainWindow.h"
00030 
00031 //Qt includes
00032 #include <qpushbutton.h>
00033 #include <qlayout.h>
00034 #include <qmessagebox.h>
00035 #include <qfiledialog.h>
00036 using namespace std;
00037 using namespace mysqlpp;
00038 
00039 
00040 /*! Constructor. */
00041 PatternDialog::PatternDialog(QWidget* parent, DBInterface* pattDBInter) : QDialog(parent){
00042         //Store reference to database
00043         patternDBInterface = pattDBInter;
00044 
00045         //Create manager to load and delete patterns
00046         patternManager = new PatternManager(patternDBInterface);
00047 
00048         //Set caption
00049         this->setCaption("Pattern Manager");
00050 
00051         //Create box to hold layout
00052         QVBoxLayout *verticalBox = new QVBoxLayout(this, 10, 10, "verticalBox");
00053 
00054         //Set up buttons to add and delete patterns
00055         QHBoxLayout *buttonBox = new QHBoxLayout();
00056         QPushButton* addPatternButt = new QPushButton("Add Pattern(s)", this, "AddPattern");
00057         addPatternButt->setBaseSize(130, 30);
00058         addPatternButt->setMaximumSize(130,30);
00059         addPatternButt->setAccel(QKeySequence(CTRL + Key_A));
00060         connect (addPatternButt, SIGNAL(clicked()), this, SLOT(addPattern()));
00061         buttonBox->addWidget(addPatternButt);
00062         
00063         QPushButton* deletePatternButt = new QPushButton("Delete Pattern(s)", this, "DeletePattern");
00064         deletePatternButt->setBaseSize(130, 30);
00065         deletePatternButt->setMaximumSize(130,30);
00066         deletePatternButt->setAccel(QKeySequence(Key_Delete));
00067         connect (deletePatternButt, SIGNAL(clicked()), this, SLOT(deletePattern()));
00068         buttonBox->addWidget(deletePatternButt);
00069         buttonBox->addStretch(5);
00070         
00071         verticalBox->addLayout(buttonBox);
00072 
00073         //Set up table to hold pattern information
00074         patternTable = new QTable(0, 8, this);
00075         patternTable->setShowGrid(false);
00076         patternTable->setSorting(false);
00077         patternTable->setSelectionMode(QTable::NoSelection);
00078         patternTable->verticalHeader()->hide();
00079         patternTable->setLeftMargin(0);
00080         QHeader * patternTableHeader = patternTable->horizontalHeader();
00081         selectionCol = 0;//Remember to update this when changing the table
00082         patternTableHeader->setLabel(selectionCol, "");
00083         patternTable->setColumnWidth(selectionCol, 20);
00084 
00085         patternIDCol = 1;//Remember to update this when changing the table
00086         patternTableHeader->setLabel(patternIDCol, "ID");
00087         patternTable->setColumnWidth(patternIDCol, 20);
00088         
00089         descriptionCol = 2;
00090         patternTableHeader->setLabel(descriptionCol, "Description");
00091         patternTable->setColumnWidth(descriptionCol, 200);
00092 
00093         patternTableHeader->setLabel(3, "Type");
00094         patternTable->setColumnWidth(3, 80);
00095         patternTableHeader->setLabel( 4, "Width" );
00096         patternTable->setColumnWidth( 4, 50);
00097         patternTableHeader->setLabel( 5, "Length" );
00098         patternTable->setColumnWidth( 5, 50);
00099         patternTableHeader->setLabel( 6, "Size" );
00100         patternTable->setColumnWidth( 6, 50);
00101         patternTableHeader->setLabel( 7, "File" );
00102         patternTable->setColumnWidth( 7, 200);
00103 
00104         //Connect layer table header clicked() slot to select all
00105         connect (patternTableHeader, SIGNAL(clicked(int)), this, SLOT(tableHeaderClicked(int)));
00106 
00107         loadPatternTable();
00108 
00109         verticalBox->addWidget(patternTable);
00110 
00111         //Set up ok and cancel buttons
00112         QHBoxLayout *okCancelBox = new QHBoxLayout();
00113         QPushButton *okPushButton = new QPushButton("Ok", this, "okButton");
00114         QPushButton *cancelPushButton = new QPushButton("Cancel", this, "cancelButton");        
00115         okCancelBox->addWidget(okPushButton);
00116         okCancelBox->addWidget(cancelPushButton);
00117         verticalBox->addLayout(okCancelBox);
00118         
00119         connect (okPushButton, SIGNAL(clicked()), this, SLOT(accept()));
00120         connect (cancelPushButton, SIGNAL(clicked()), this, SLOT(reject()));
00121 
00122         this->setMinimumSize(700, 150);
00123 
00124 }
00125 
00126 
00127 /*! Destructor. */
00128 PatternDialog::~PatternDialog(){
00129         #ifdef MEMORY_DEBUG
00130                 cout<<"DELETING PATTERN DIALOG!"<<endl;
00131         #endif//MEMORY_DEBUG
00132 
00133         delete patternManager;
00134 }
00135 
00136 
00137 //----------------------------------------------------------------------------------------------
00138 //-------------------------------------- PRIVATE SLOTS -----------------------------------------
00139 //----------------------------------------------------------------------------------------------
00140 
00141 /*! Adds a pattern selected by the user using a file dialog. */
00142 void PatternDialog::addPattern(){
00143         //Set up default file location
00144         QString defaultFileLocation = SpikeStreamMainWindow::workingDirectory;
00145         defaultFileLocation += "/patterns";
00146 
00147         QStringList fileNames = QFileDialog::getOpenFileNames("Pattern (*.pat)", defaultFileLocation, this, "Add pattern dialog", "Choose pattern(s) to add to database");
00148         if(fileNames.size() == 0)
00149                 return;
00150 
00151         try{
00152                 for(unsigned int i=0; i<fileNames.size(); ++i){
00153                         if(!patternManager->addPattern(fileNames[i])){
00154                                 QString errorString = "Error adding pattern to database. Check the format of the input file:\n";
00155                                 errorString += fileNames[i];
00156                                 QMessageBox::critical( 0, "Pattern Manager", errorString);
00157                                 break;
00158                         }
00159                 }
00160         }
00161         catch (const BadQuery& er) {// Handle any query errors
00162                 cerr<<"PatternDialog: MYSQL QUERY EXCEPTION \""<<er.what()<<"\""<<endl;
00163                 QString errorString = "Bad query when adding patterns: \"";
00164                 errorString += er.what();
00165                 errorString += "\"";
00166                 QMessageBox::critical( 0, "Pattern Error", errorString);
00167         }
00168         catch (const Exception& er) {// Catch-all for any other MySQL++ exceptions
00169                 cerr<<"PatternDialog: MYSQL EXCEPTION \""<<er.what()<<"\""<<endl;
00170                 QString errorString = "Exception thrown adding patterns: \"";
00171                 errorString += er.what();
00172                 errorString += "\"";
00173                 QMessageBox::critical( 0, "Pattern Error", errorString);
00174         }
00175         catch(std::exception& er){// Catch-all for any other exceptions
00176                 cerr<<"PatternDialog: STD EXCEPTION \""<<er.what()<<"\""<<endl;
00177                 QString errorString = "Exception thrown adding patterns: \"";
00178                 errorString += er.what();
00179                 errorString += "\"";
00180                 QMessageBox::critical( 0, "Pattern Error", errorString);
00181         }
00182 
00183         //Reload patterns
00184         loadPatternTable();
00185         SpikeStreamMainWindow::spikeStrMainWin->reloadPatterns();
00186 }
00187 
00188 
00189 /*! Deletes a pattern. */
00190 void PatternDialog::deletePattern(){
00191         QString confirmDeleteStr = "Do you want to delete the following pattern(s)?\n";
00192         vector<unsigned int> deleteLayerIDs;
00193 
00194         //First get the layer id(s) for the layer(s) to be deleted
00195         for(int i=0; i<patternTable->numRows(); i++){
00196                 QCheckTableItem * item = (QCheckTableItem*)patternTable->item(i, selectionCol);
00197                 if(item->isChecked()){
00198                         unsigned int tempInt = patternTable->item(i, patternIDCol)->text().toUInt();
00199                         deleteLayerIDs.push_back(tempInt);
00200                         confirmDeleteStr += "   ";
00201                         confirmDeleteStr += patternTable->item(i, descriptionCol)->text()+= " (ID: ";
00202                         confirmDeleteStr += patternTable->item(i, patternIDCol)->text() += ")\n";
00203                 }
00204         }
00205 
00206         //Check that user really wants to delete these layers
00207         if(deleteLayerIDs.size() > 0){
00208                 if(!( QMessageBox::warning( this, "Confirm Delete of Pattern(s)", confirmDeleteStr, "Yes", "No", 0, 0, 1 ))) {
00209                         //Show dialog to inform user that deletion is in progress
00210                         BusyDialog* busyDialog = new BusyDialog(this, "Deleting Patterns");
00211                         busyDialog->setModal(true);
00212                         busyDialog->showDialog("Deleting patterns, please wait.");
00213                         SpikeStreamMainWindow::spikeStreamApplication->processEvents();
00214 
00215                         //Delete patterns from database and table
00216                         try{
00217                                 vector<unsigned int>::iterator deleteIDsIter;
00218                                 for(deleteIDsIter = deleteLayerIDs.begin(); deleteIDsIter != deleteLayerIDs.end(); deleteIDsIter++){
00219                                         if(!patternManager->deletePattern(*deleteIDsIter)){
00220                                                 QString errorString = "Error deleting pattern from database.\nPattern ID: ";
00221                                                 errorString += QString::number(*deleteIDsIter);
00222                                                 QMessageBox::critical( 0, "Pattern Manager", errorString);
00223                                                 return;
00224                                         }
00225                                         removePatternFromTable(*deleteIDsIter);
00226                                 }
00227                         }
00228                         catch (const BadQuery& er) {// Handle any query errors
00229                                 cerr<<"PatternDialog: MYSQL QUERY EXCEPTION \""<<er.what()<<"\""<<endl;
00230                                 QString errorString = "Bad query when deleting patterns: \"";
00231                                 errorString += er.what();
00232                                 errorString += "\"";
00233                                 QMessageBox::critical( 0, "Pattern Error", errorString);
00234                         }
00235                         catch (const Exception& er) {// Catch-all for any other MySQL++ exceptions
00236                                 cerr<<"PatternDialog: MYSQL EXCEPTION \""<<er.what()<<"\""<<endl;
00237                                 QString errorString = "Exception thrown deleting patterns: \"";
00238                                 errorString += er.what();
00239                                 errorString += "\"";
00240                                 QMessageBox::critical( 0, "Pattern Error", errorString);
00241                         }
00242                         catch(std::exception& er){// Catch-all for any other exceptions
00243                                 cerr<<"PatternDialog: STD EXCEPTION \""<<er.what()<<"\""<<endl;
00244                                 QString errorString = "Exception thrown deleting patterns: \"";
00245                                 errorString += er.what();
00246                                 errorString += "\"";
00247                                 QMessageBox::critical( 0, "Pattern Error", errorString);
00248                         }
00249                         busyDialog->hide();
00250                 }
00251         }
00252         SpikeStreamMainWindow::spikeStrMainWin->reloadPatterns();
00253 }
00254 
00255 
00256 /*! Called when the table header is clicked and selects or deselects all patterns. */
00257 void PatternDialog::tableHeaderClicked(int colNumber){
00258         if(colNumber == selectionCol){//Header above check boxes has been clicked
00259                 //First count the number of selected rows
00260                 int selectedRowCount = 0;
00261                 for(int i=0; i<patternTable->numRows(); i++){
00262                         QCheckTableItem * item = (QCheckTableItem*)patternTable->item(i, selectionCol);
00263                         if(item->isChecked())
00264                                 selectedRowCount++;
00265                 }
00266                 //If all rows are selected want to deselect rows
00267                 if(selectedRowCount == patternTable->numRows()){
00268                         for(int i=0; i<patternTable->numRows(); i++){//Deselect all rows
00269                                 QCheckTableItem * item = (QCheckTableItem*)patternTable->item(i, selectionCol);
00270                                 item->setChecked(false);
00271                         }
00272                 }
00273                 else{//Select all rows
00274                         for(int i=0; i<patternTable->numRows(); i++){
00275                                 QCheckTableItem * item = (QCheckTableItem*)patternTable->item(i, selectionCol);
00276                                 item->setChecked(true);
00277                         }
00278                 }
00279         }
00280 }
00281 
00282 
00283 //----------------------------------------------------------------------------------------------
00284 //------------------------------------ PRIVATE METHODS -----------------------------------------
00285 //----------------------------------------------------------------------------------------------
00286 
00287 /*! Loads a table with all the available patterns. 
00288         Enables a pattern to be assigned to a suitable neuron group before the simulation starts. */
00289 void PatternDialog::loadPatternTable(){
00290         //Empty pattern table
00291         patternTable->setNumRows(0);
00292         
00293         //Load up a row for each pattern in the database
00294         try{
00295                 Query patternQuery = patternDBInterface->getQuery();
00296                 patternQuery.reset();
00297                 patternQuery<<"SELECT PatternGrpID, Description, PatternType, Width, Length, NumberOfPatterns, File FROM PatternDescriptions";
00298                 Result result = patternQuery.store();
00299                 for(Result::iterator iter = result.begin(); iter != result.end(); ++iter){
00300                         Row row(*iter);
00301                         //Add new row to the table
00302                         int currentRow = patternTable->numRows();
00303                         patternTable->insertRows(currentRow, 1);
00304                 
00305                         //Populate row with pattern information
00306                         QCheckTableItem *checkTableItem = new QCheckTableItem( patternTable, "");
00307                         patternTable->setItem( currentRow, 0, checkTableItem);
00308         
00309                         patternTable->setItem(currentRow, 1,
00310                                 new QTableItem(patternTable, QTableItem::Never, (std::string)row["PatternGrpID"]));//PatternGrpID
00311         
00312                         patternTable->setItem(currentRow, 2,
00313                                 new QTableItem(patternTable, QTableItem::Never, (std::string)row["Description"]));//Description
00314                 
00315                         unsigned int patternType = Utilities::getUInt((std::string)row["PatternType"]);
00316                         patternTable->setItem(currentRow, 3,
00317                                 new QTableItem(patternTable, QTableItem::Never, PatternTypes::getDescription(patternType)));//Pattern Type
00318                 
00319                         patternTable->setItem(currentRow, 4,
00320                                 new QTableItem(patternTable, QTableItem::Never, (std::string)row["Width"]));//Width
00321                 
00322                         patternTable->setItem(currentRow, 5,
00323                                 new QTableItem(patternTable, QTableItem::Never, (std::string)row["Length"]));//Length
00324                 
00325                         patternTable->setItem(currentRow, 6,
00326                                 new QTableItem(patternTable, QTableItem::Never, (std::string)row["NumberOfPatterns"]));//Width
00327         
00328                         patternTable->setItem(currentRow, 7,
00329                                 new QTableItem(patternTable, QTableItem::Never, (std::string)row["File"]));//Width
00330                 }
00331         }
00332         catch (const BadQuery& er) {// Handle any query errors
00333                 cerr<<"PatternDialog: MYSQL QUERY EXCEPTION \""<<er.what()<<"\""<<endl;
00334                 QString errorString = "Bad query when loading patterns: \"";
00335                 errorString += er.what();
00336                 errorString += "\"";
00337                 QMessageBox::critical( 0, "Pattern Error", errorString);
00338         }
00339         catch (const Exception& er) {// Catch-all for any other MySQL++ exceptions
00340                 cerr<<"PatternDialog: MYSQL EXCEPTION \""<<er.what()<<"\""<<endl;
00341                 QString errorString = "Exception thrown loading patterns: \"";
00342                 errorString += er.what();
00343                 errorString += "\"";
00344                 QMessageBox::critical( 0, "Pattern Error", errorString);
00345         }
00346         catch(std::exception& er){// Catch-all for any other exceptions
00347                 cerr<<"PatternDialog: STD EXCEPTION \""<<er.what()<<"\""<<endl;
00348                 QString errorString = "Exception thrown loading patterns: \"";
00349                 errorString += er.what();
00350                 errorString += "\"";
00351                 QMessageBox::critical( 0, "Pattern Error", errorString);
00352         }
00353 }
00354 
00355 
00356 /*! Removes the indicated pattern from the table. */
00357 void PatternDialog::removePatternFromTable(unsigned int patternID){
00358         //Remove from table
00359         for(int i=0; i<patternTable->numRows(); i++){
00360                 unsigned int tempID = patternTable->item(i, patternIDCol)->text().toUInt();
00361                 if(tempID == patternID){
00362                         patternTable->removeRow(i);
00363                         break;
00364                 }
00365         }
00366 }
00367 
00368 

Generated on Mon Sep 3 22:29:04 2007 for SpikeStream Application by  doxygen 1.4.4