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

ConnectionWidget.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 "ConnectionWidget.h"
00025 #include "ConnectionPropertiesDialog.h"
00026 #include "NetworkViewer.h"
00027 #include "Debug.h"
00028 #include "Utilities.h"
00029 #include "ConnectionTableItem.h"
00030 #include "ConnectionCheckTableItem.h"
00031 #include "SpikeStreamMainWindow.h"
00032 #include "ConnectionParameterViewer.h"
00033 
00034 //Qt includes
00035 #include <qpushbutton.h>
00036 #include <qmessagebox.h>
00037 #include <qaccel.h>
00038 #include <qlayout.h>
00039 #include <qfile.h>
00040 
00041 //Other includes
00042 #include <iostream>
00043 #include <vector>
00044 #include <mysql++.h>
00045 using namespace std;
00046 using namespace mysqlpp;
00047 
00048 
00049 /*! Constructor. */
00050 ConnectionWidget::ConnectionWidget(QWidget *parent, DBInterface *netDBInter, DBInterface* devDBInter) : QWidget(parent, "Connection Widget"){
00051         //Keep reference to database interface
00052         networkDBInterface = netDBInter;
00053         deviceDBInterface = devDBInter;
00054 
00055         //Create dialog to show when deleting connections
00056         busyDialog = new BusyDialog(SpikeStreamMainWindow::spikeStrMainWin, "Editing Connections");
00057 
00058         //Create a ConnectionManager to manage the neurons
00059         connectionManager = new ConnectionManager(networkDBInterface, deviceDBInterface);
00060         
00061         //Set up pixmaps to control showing and hiding connections and parameters
00062         showPixmap = new QPixmap(SpikeStreamMainWindow::workingDirectory + "/images/view.xpm");
00063         hidePixmap = new QPixmap(SpikeStreamMainWindow::workingDirectory + "/images/hide.xpm");
00064         paramPixmap = new QPixmap(SpikeStreamMainWindow::workingDirectory + "/images/view_parameters.xpm");
00065         
00066         //Set up widget
00067         //Create vertical layout to arrange panel
00068         QVBoxLayout *verticalBox = new QVBoxLayout(this, 5, 10, "vertical");
00069 
00070         //Set up buttons
00071         QHBoxLayout *buttonBox = new QHBoxLayout();
00072         newConnButt = new QPushButton("Add Connections", this, "NewConnection");
00073         newConnButt->setBaseSize(120, 30);
00074         newConnButt->setMaximumSize(120,30);
00075         newConnButt->setAccel(QKeySequence(CTRL + Key_N));
00076         connect (newConnButt, SIGNAL(clicked()), this, SLOT(newConnectionsButtonPressed()));
00077         buttonBox->addWidget(newConnButt);
00078         
00079         deleteConnButt = new QPushButton("Delete", this, "Delete Conns");
00080         deleteConnButt->setBaseSize(100, 30);
00081         deleteConnButt->setMaximumSize(100,30);
00082         deleteConnButt->setAccel(QKeySequence(Key_Delete));
00083         connect (deleteConnButt, SIGNAL(clicked()), this, SLOT(deleteConnections()));
00084         buttonBox->addWidget(deleteConnButt);
00085         buttonBox->addStretch(5);
00086 
00087         verticalBox->addLayout(buttonBox);      
00088         
00089         //Set up table
00090         connTable = new QTable(0, 8, this);
00091         connTable->setShowGrid(false);
00092         connTable->setSorting(false);
00093         connTable->setSelectionMode(QTable::NoSelection);
00094         connTable->verticalHeader()->hide();
00095         connTable->setLeftMargin(0);
00096         QHeader * connTableHeader = connTable->horizontalHeader();
00097         connTableHeader->setLabel( 0, "" );
00098         connTable->setColumnWidth( 0, 16);      
00099         connTableHeader->setLabel( 1, "From Layer" );
00100         connTable->setColumnWidth( 1, 150);
00101         connTableHeader->setLabel( 2, "To Layer");
00102         connTable->setColumnWidth( 2, 150);
00103         connTableHeader->setLabel( 3, "Connection Type");
00104         connTable->setColumnWidth( 3, 200);
00105         connTableHeader->setLabel( 4, "Synapse Type");
00106         connTable->setColumnWidth( 4, 200);
00107         connTableHeader->setLabel( 5, "Size");
00108         connTable->setColumnWidth( 5, 50);
00109         connGrpIDColumn = 6;
00110         connTableHeader->setLabel(connGrpIDColumn, "ID");
00111         connTable->setColumnWidth(connGrpIDColumn, 50);
00112         paramCol = 7;
00113         connTableHeader->setLabel(paramCol, "Parameters");
00114         connTable->setColumnWidth(connGrpIDColumn, 50);
00115         
00116         verticalBox->addWidget(connTable);
00117         
00118         //Connect header with table header clicked to enable selecting/ deselecting all layers
00119         connect (connTableHeader, SIGNAL(clicked(int)), this, SLOT(tableHeaderClicked(int)));
00120         
00121         //Need to set up table so that clicks on view pixmaps are reflected in 3D display
00122         connect (connTable, SIGNAL(clicked(int, int, int, const QPoint &)), this, SLOT(tableClicked(int, int, int, const QPoint &)));
00123         
00124         //Now load the list of connections from the database
00125         loadAllConnections();
00126 } 
00127 
00128 
00129 /*! Destructor. */
00130 ConnectionWidget::~ConnectionWidget(){
00131         #ifdef MEMORY_DEBUG
00132                 cout<<"DELETING CONNECTION WIDGET"<<endl;
00133         #endif//MEMORY_DEBUG
00134         
00135         delete showPixmap;
00136         delete hidePixmap;
00137         delete connectionManager;
00138 }
00139 
00140 //---------------------------------------------------------------------------------------------
00141 //------------------------------- PUBLIC METHODS ----------------------------------------------
00142 //---------------------------------------------------------------------------------------------
00143 
00144 /*! Creates connections. This method can be called from outside or internally when the
00145         new connections button is pressed. */
00146 void ConnectionWidget::createConnections(unsigned int fromNeurGrpID, unsigned int toNeurGrpID, unsigned int componentID, bool deviceIsFrom){
00147         try{
00148                 /* Set up connections properties dialog differently depending on whethe
00149                         this method has been called by the user or the layer manager */
00150                 ConnectionPropertiesDialog *connPropDlg;
00151                 bool simnosComponentConns = false;
00152                 if(fromNeurGrpID == 0  && toNeurGrpID == 0 && componentID == 0)
00153                         connPropDlg = new ConnectionPropertiesDialog(this, "Conn Properties", networkDBInterface);
00154                 else{
00155                         connPropDlg = new ConnectionPropertiesDialog(this, "Conn Properties", networkDBInterface, fromNeurGrpID, toNeurGrpID, ConnectionType::SIMNOSComponent);
00156                         simnosComponentConns = true;
00157                 }
00158 
00159         connPropDlg->setCaption( "Connection Properties" );
00160         if ( connPropDlg->exec() == QDialog::Accepted ) {
00161                         //Create new set of connections
00162                         //Extract parameters for connections from dialog
00163                         ConnectionHolder connHolder = connPropDlg->getConnectionHolder();
00164 
00165                         //Add component ID if applicable
00166                         if(simnosComponentConns)
00167                                 connHolder.componentID = componentID;
00168 
00169                         //Set whether the device group is from or to
00170                         connHolder.deviceIsFrom = deviceIsFrom;
00171 
00172                         //Create the connections
00173                         int newConnGrpID = connectionManager->createConnections(connHolder);
00174                         if(newConnGrpID < 0){//Method has not created any connections probably due to conflict with existing connections
00175                                 QMessageBox::warning(this, "Connections Conflict!", "Connections have not been created, perhaps due to conflict with existing connections");
00176                         }
00177                         else{//Connections have been successfully created
00178                                 /* With the simnos connections, the network viewer has not loaded up the new
00179                                         neuron group yet, so this needs to be done before loading the connection 
00180                                         group. */
00181                                 if(simnosComponentConns){
00182                                         if(connHolder.deviceIsFrom)//New layer is to neuron grp id
00183                                                 SpikeStreamMainWindow::spikeStrMainWin->getNetworkViewer()->loadNeuronGroup(connHolder.toLayerID, true);
00184                                         else
00185                                                 SpikeStreamMainWindow::spikeStrMainWin->getNetworkViewer()->loadNeuronGroup(connHolder.fromLayerID, true);
00186                                 }
00187 
00188                                 //Load new connection group into network viewer and table
00189                                 SpikeStreamMainWindow::spikeStrMainWin->getNetworkViewer()->loadConnectionGroup(newConnGrpID, true);
00190                                 loadConnection(newConnGrpID);
00191 
00192                                 //Reload the connections in the rest of the application
00193                                 SpikeStreamMainWindow::spikeStrMainWin->reloadConnections();
00194                         }
00195         }
00196         delete connPropDlg;
00197         }
00198     catch (const BadQuery& er) {// Handle any query errors
00199                 cerr<<"ConnectionWidget: MYSQL QUERY EXCEPTION \""<<er.what()<<"\""<<endl;
00200                 QString errorString = "Bad query creating connections: \"";
00201                 errorString += er.what();
00202                 errorString += "\"";
00203                 QMessageBox::critical( 0, "Connection Error", errorString);
00204     }
00205     catch (const Exception& er) {// Catch-all for any other MySQL++ exceptions
00206         cerr<<"ConnectionWidget: MYSQL EXCEPTION \""<<er.what()<<"\""<<endl;
00207                 QString errorString = "Exception thrown creating connections: \"";
00208                 errorString += er.what();
00209                 errorString += "\"";
00210                 QMessageBox::critical( 0, "Connection Error", errorString);
00211     }
00212         catch(std::exception& er){// Catch-all for std exceptions
00213                 cerr<<"ConnectionWidget: STD EXCEPTION \""<<er.what()<<"\""<<endl;
00214                 QString errorString = "Exception thrown creating connections: \"";
00215                 errorString += er.what();
00216                 errorString += "\"";
00217                 QMessageBox::critical( 0, "Connection Error", errorString);
00218         }
00219 }
00220 
00221 
00222 /*! Deletes all connections to and from layer
00223         This method is usually called by the layerWidget when deleting a layer so that all the 
00224         connections to the layer can be deleted. */
00225 void ConnectionWidget::deleteLayerConnections(unsigned int layerID){
00226         try{
00227                 Query query = networkDBInterface->getQuery();
00228                 
00229                 //First remove data structures from Network Viewer and delete connections
00230                 query.reset();
00231                 query<<"SELECT ConnGrpID FROM ConnectionGroups WHERE FromNeuronGrpID = "<<layerID<<" OR ToNeuronGrpID = "<<layerID;
00232                 Result connGrpRes = query.store();
00233                 for(mysqlpp::Result::iterator connGrpIter = connGrpRes.begin(); connGrpIter != connGrpRes.end(); connGrpIter++){
00234                         Row connGrpRow(*connGrpIter);
00235                         unsigned int connGrpID = Utilities::getUInt((std::string)connGrpRow["ConnGrpID"]);
00236                         SpikeStreamMainWindow::spikeStrMainWin->getNetworkViewer()->deleteConnectionGroup(connGrpID);
00237                         removeConnectionFromTable(connGrpID);
00238                         
00239                         //Remove connections from database
00240                         query.reset();
00241                         query<<"DELETE FROM Connections WHERE ConnGrpID = "<<connGrpID;
00242                         query.execute();
00243         
00244                         /*Delete synapse parameters for this connection group
00245                                 Simpler just to delete connection group from all parameter tables than to query the
00246                                 id and then delete it from the appropriate table */
00247                         query.reset();
00248                         query<<"SELECT ParameterTableName FROM SynapseTypes";
00249                         Result tableNameRes = query.store();
00250                         for(Result::iterator paramTableIter = tableNameRes.begin(); paramTableIter != tableNameRes.end(); ++paramTableIter){
00251                                 Row tableNameRow (*paramTableIter);
00252                                 query<<"DELETE FROM "<<(std::string)tableNameRow["ParameterTableName"]<<" WHERE ConnGrpID= "<<connGrpID;
00253                                 query.execute();
00254                         }
00255                 }
00256                 
00257                 //Now delete all connection groups that involve this layer from the database
00258                 query.reset();
00259                 query<<"DELETE FROM ConnectionGroups WHERE FromNeuronGrpID = "<<layerID<<" OR ToNeuronGrpID = "<<layerID;
00260                 query.execute();
00261         }
00262     catch (const BadQuery& er) {// Handle any query errors
00263                 cerr<<"ConnectionWidget: MYSQL QUERY EXCEPTION \""<<er.what()<<"\""<<endl;
00264                 QString errorString = "Bad query when deleting layer connections: \"";
00265                 errorString += er.what();
00266                 errorString += "\"";
00267                 QMessageBox::critical( 0, "Connection Error", errorString);
00268                 return;
00269     }
00270     catch (const Exception& er) {// Catch-all for any other MySQL++ exceptions
00271         cerr<<"ConnectionWidget: MYSQL EXCEPTION \""<<er.what()<<"\""<<endl;
00272                 QString errorString = "Exception thrown when deleting layer connections: \"";
00273                 errorString += er.what();
00274                 errorString += "\"";
00275                 QMessageBox::critical( 0, "Connection Error", errorString);
00276                 return;
00277     }
00278 }
00279 
00280 
00281 /*! Returns the vector containing a list of visible connection group IDs. */
00282 vector<unsigned int> ConnectionWidget::getConnectionViewVector(){
00283         return viewVector;
00284 }
00285 
00286 
00287 /*! Reloads connections when changes have been made to them or to the neuron groups. */
00288 void ConnectionWidget::reloadConnections(){
00289         loadAllConnections();
00290 }
00291 
00292 
00293 /*! Enables editing after simulation has been destroyed. */
00294 void ConnectionWidget::simulationDestroyed(){
00295         newConnButt->setEnabled(true);
00296         deleteConnButt->setEnabled(true);
00297 }
00298 
00299 
00300 /*! Disables editing when simulation is initialised. */
00301 void ConnectionWidget::simulationInitialised(){
00302         newConnButt->setEnabled(false);
00303         deleteConnButt->setEnabled(false);
00304 }
00305 
00306 
00307 //-----------------------------------------------------------------------------------
00308 //--------------------------------- SLOTS -------------------------------------------
00309 //-----------------------------------------------------------------------------------
00310 
00311 /*! Deletes all selected connections
00312         Shows message box to confirm delete. */
00313 void ConnectionWidget::deleteConnections(){
00314         try{
00315                 QString confirmDeleteStr = "Do you want to delete the following connections:\n";
00316                 vector<ConnectionHolder> deleteConnectionVector;
00317                 for(int i=0; i<connTable->numRows(); i++){
00318                         QCheckTableItem * item = (QCheckTableItem*)connTable->item(i, 1);
00319                         if(item->isChecked()){
00320                                 //Declare a temporary connection holder to contain variables
00321                                 ConnectionHolder tempConnHolder;
00322                                 
00323                                 //Fill connection holder with parameters
00324                                 tempConnHolder.connectionGrpID = Utilities::getUInt(connTable->item(i, connGrpIDColumn)->text().ascii());
00325                                 tempConnHolder.fromLayerID = Utilities::getNeuronGrpID(connTable->item(i, 1)->text());
00326                                 tempConnHolder.toLayerID = Utilities::getNeuronGrpID(connTable->item(i, 2)->text());
00327                                 QString connectionTypeStr = connTable->item(i, 3)->text();
00328                                 tempConnHolder.connectionType = ConnectionType::getType(connectionTypeStr.ascii());
00329                                 deleteConnectionVector.push_back(tempConnHolder);
00330                                 
00331                                 //Add variables to string for confirmation dialog
00332                                 confirmDeleteStr += "   From: ";
00333                                 confirmDeleteStr += QString::number(tempConnHolder.fromLayerID) += " To: ";
00334                                 confirmDeleteStr += QString::number(tempConnHolder.toLayerID) += "; Type: ";
00335                                 confirmDeleteStr += connTable->item(i, 3)->text() += "\n";
00336                         }
00337                 }
00338                 //Check that user really wants to delete these connections
00339                 if(deleteConnectionVector.size() > 0){
00340                         if(!( QMessageBox::warning( this, "Confirm Delete Connections", confirmDeleteStr, "Yes", "No", 0, 0, 1 ))) {
00341         
00342                                 //Show dialog to inform user that deletion is in progress
00343                                 //FIXME THE TEXT ON THIS DIALOG IS ONLY VISIBLE SOMETIMES - SOMETHING TO DO WITH UPDATES
00344                                 busyDialog->setModal(true);
00345                                 busyDialog->showDialog("Deleting connections, please wait.");
00346                                 SpikeStreamMainWindow::spikeStreamApplication->processEvents();
00347         
00348                                 //Instruct connection manager to delete connections
00349                                 connectionManager->deleteConnections(deleteConnectionVector);
00350         
00351                                 //Remove data structures from network viewer
00352                                 for(unsigned int i=0; i<deleteConnectionVector.size(); i++){
00353                                         unsigned int connGrpID = deleteConnectionVector[i].connectionGrpID;
00354                                         
00355                                         //Remove connection from network viewer
00356                                         SpikeStreamMainWindow::spikeStrMainWin->getNetworkViewer()->deleteConnectionGroup(connGrpID);
00357         
00358                                         //Remove connection from table
00359                                         removeConnectionFromTable(connGrpID);
00360                                 }
00361         
00362                                 //Reload the connections in the rest of the application
00363                                 SpikeStreamMainWindow::spikeStrMainWin->reloadConnections();
00364                                 busyDialog->hide();
00365                         }
00366                 }
00367         }
00368         catch (const BadQuery& er) {// Handle any query errors
00369                 cerr<<"ConnectionWidget: MYSQL QUERY EXCEPTION \""<<er.what()<<"\""<<endl;
00370                 QString errorString = "Bad query when deleting connections: \"";
00371                 errorString += er.what();
00372                 errorString += "\"";
00373                 QMessageBox::critical( 0, "Connection Error", errorString);
00374         }
00375         catch (const Exception& er) {// Catch-all for any other MySQL++ exceptions
00376                 cerr<<"ConnectionWidget: MYSQL EXCEPTION \""<<er.what()<<"\""<<endl;
00377                 QString errorString = "Exception thrown when deleting connections: \"";
00378                 errorString += er.what();
00379                 errorString += "\"";
00380                 QMessageBox::critical( 0, "Connection Error", errorString);
00381         }
00382         catch(std::exception& er){// Catch-all for std exceptions
00383                 cerr<<"ConnectionWidget: STD EXCEPTION \""<<er.what()<<"\""<<endl;
00384                 QString errorString = "Exception thrown deleting connections: \"";
00385                 errorString += er.what();
00386                 errorString += "\"";
00387                 QMessageBox::critical( 0, "Connection Error", errorString);
00388         }
00389 }
00390 
00391 
00392 /*! Creates new connections using the connection properties dialog. */
00393 void ConnectionWidget::newConnectionsButtonPressed(){
00394         createConnections(0, 0, 0, false);
00395 }
00396 
00397 
00398 /*! Adjusts the 3D view by making connection groups visible or invisible. */
00399 void ConnectionWidget::tableClicked(int row, int col, int, const QPoint &){
00400         if(col == 0){//Want a list of ConnectionGrpIDs to send to the NetworkViewer
00401                 //Get Connection Group ID
00402                 unsigned int connGrpID = 0;
00403                 try{
00404                         connGrpID= Utilities::getUInt(connTable->item(row, connGrpIDColumn)->text().ascii());
00405                 }
00406                 catch(std::exception& er){// Catch-all for std exceptions
00407                         cerr<<"ConnectionWidget: STD EXCEPTION \""<<er.what()<<"\""<<endl;
00408                         QString errorString = "Exception thrown converting string to unsigned int: \"";
00409                         errorString += er.what();
00410                         errorString += "\"";
00411                         QMessageBox::critical( 0, "Connection Group ID Error", errorString);
00412                         return;
00413                 }
00414 
00415                 //Find out if it is already part of the viewVector
00416                 bool connGrpIDFound = false;
00417                 for(vector<unsigned int>::iterator iter = viewVector.begin(); iter != viewVector.end(); iter++){
00418                         if(*iter == connGrpID){//Connection was already visible, so need to make it invisible
00419                                 connGrpIDFound = true;
00420                                 viewVector.erase(iter);
00421                                 connTable->setPixmap(row, 0, *hidePixmap);
00422                                 SpikeStreamMainWindow::spikeStrMainWin->getNetworkViewer()->setConnectionView(viewVector);
00423                                 break;
00424                         }
00425                 }
00426                 if(!connGrpIDFound){//Not already showing, so show connection
00427                         //Only change pixmap if it is not a virtual connection, which cannot be shown.
00428                         if(connTable->text(row, 3) != "Virtual")
00429                                 connTable->setPixmap(row, 0, *showPixmap);
00430                         viewVector.push_back(connGrpID);
00431                         SpikeStreamMainWindow::spikeStrMainWin->getNetworkViewer()->setConnectionView(viewVector);
00432                 }
00433         }
00434         else if (col == paramCol){
00435                 //Get Connection Group ID
00436                 unsigned int connGrpID = 0;
00437                 try{
00438                         connGrpID= Utilities::getUInt(connTable->item(row, connGrpIDColumn)->text().ascii());
00439                 }
00440                 catch(std::exception& er){// Catch-all for std exceptions
00441                         cerr<<"ConnectionWidget: STD EXCEPTION \""<<er.what()<<"\""<<endl;
00442                         QString errorString = "Exception thrown converting string to unsigned int: \"";
00443                         errorString += er.what();
00444                         errorString += "\"";
00445                         QMessageBox::critical( 0, "Connection Group ID Error", errorString);
00446                         return;
00447                 }
00448                 
00449                 //Launch a dialog to view the connection parameters
00450                 ConnectionParameterViewer* connParamViewer = new ConnectionParameterViewer(this, networkDBInterface, connGrpID);
00451                 if(!connParamViewer->loadError())
00452                         connParamViewer->show();
00453         }
00454 }
00455 
00456 
00457 /*! Makes all connection groups visible / invisible or selects/deselects all layers. */
00458 void ConnectionWidget::tableHeaderClicked(int colNumber){
00459         if(colNumber == 0){//View header has been clicked
00460                 //All rows are already selected, so deselect
00461                 if(viewVector.size() == (unsigned int)connTable->numRows()){
00462                         viewVector.clear();
00463                         SpikeStreamMainWindow::spikeStrMainWin->getNetworkViewer()->setConnectionView(viewVector);
00464                         
00465                         //Change pixmaps to hide
00466                         for(int i=0; i<connTable->numRows(); i++){
00467                                 connTable->setPixmap(i, 0, *hidePixmap);
00468                         }
00469                 }
00470                 //Not all rows selected, so select all
00471                 else{
00472                         viewVector.clear();
00473                         for(int i=0; i<connTable->numRows(); i++){
00474                                 unsigned int tempConnGrpID = connTable->item(i, connGrpIDColumn)->text().toUInt();
00475                                 viewVector.push_back(tempConnGrpID);
00476                                 connTable->setPixmap(i, 0, *showPixmap);
00477                         }
00478                         SpikeStreamMainWindow::spikeStrMainWin->getNetworkViewer()->setConnectionView(viewVector);
00479                 }
00480         }
00481         else if(colNumber ==1){//Header above check boxes has been clicked
00482                 //First count the number of selected rows
00483                 int selectedRowCount = 0;
00484                 for(int i=0; i<connTable->numRows(); i++){
00485                         QCheckTableItem * item = (QCheckTableItem*)connTable->item(i, 1);
00486                         if(item->isChecked())
00487                                 selectedRowCount++;
00488                 }
00489                 //If all rows are selected want to deselect rows
00490                 if(selectedRowCount == connTable->numRows()){
00491                         for(int i=0; i<connTable->numRows(); i++){//Deselect all rows
00492                                 QCheckTableItem * item = (QCheckTableItem*)connTable->item(i, 1);
00493                                 item->setChecked(false);
00494                         }
00495                 }
00496                 else{//Select all rows
00497                         for(int i=0; i<connTable->numRows(); i++){
00498                                 QCheckTableItem * item = (QCheckTableItem*)connTable->item(i, 1);
00499                                 item->setChecked(true);
00500                         }
00501                 }
00502         }
00503 }
00504 
00505 
00506 //---------------------------------------------------------------------------------------------
00507 //------------------------------ PRIVATE METHODS ----------------------------------------------
00508 //---------------------------------------------------------------------------------------------
00509 
00510 /*! Gets the description of a particular synapse type from the synapse types database. */
00511 string ConnectionWidget::getSynapseTypeDescription(unsigned short synapseTypeID){
00512         string descStr("Unknown");
00513         try{
00514                 Query query = networkDBInterface->getQuery();
00515                 query.reset();
00516                 query<<"SELECT Description FROM SynapseTypes WHERE TypeID = "<<synapseTypeID;
00517                 Result result = query.store();
00518                 if(result.size() != 1){
00519                         return string("Unknown");
00520                 }
00521                 Row row(*result.begin());//TypeID is unique
00522                 descStr = (std::string)row["Description"];
00523         }
00524     catch (const BadQuery& er) {// Handle any query errors
00525                 cerr<<"ConnectionWidget: MYSQL QUERY EXCEPTION \""<<er.what()<<"\""<<endl;
00526                 QString errorString = "Bad query when getting synapse type description: \"";
00527                 errorString += er.what();
00528                 errorString += "\"";
00529                 QMessageBox::critical( 0, "Synapse Type Error", errorString);
00530     }
00531     catch (const Exception& er) {// Catch-all for any other MySQL++ exceptions
00532         cerr<<"ConnectionWidget: MYSQL EXCEPTION \""<<er.what()<<"\""<<endl;
00533                 QString errorString = "Exception thrown when getting synapse type description: \"";
00534                 errorString += er.what();
00535                 errorString += "\"";
00536                 QMessageBox::critical( 0, "Synapse Type Error", errorString);
00537     }
00538         return descStr;
00539 }
00540 
00541 
00542 /*! Loads all of the connection groups in the database into the table. */
00543 void ConnectionWidget::loadAllConnections(){
00544         //Initialise view vector and remove all rows from table
00545         connTable->setNumRows(0);
00546         viewVector.clear();
00547         
00548         //Load all connection groups, filtering out temporary virtual connections
00549         try{
00550                 Query query = networkDBInterface->getQuery();
00551                 query.reset();
00552                 query << "SELECT ConnGrpID FROM ConnectionGroups WHERE ConnType != "<<ConnectionType::TempVirtual;
00553                 Result connResult = query.store();
00554                 Result::iterator resIter;
00555                 for(resIter = connResult.begin(); resIter != connResult.end(); resIter++){
00556                         Row row(*resIter);
00557                         unsigned int connectionID = Utilities::getUInt((std::string)row["ConnGrpID"]);
00558                         loadConnection(connectionID);
00559                 }
00560         }
00561     catch (const BadQuery& er) {// Handle any query errors
00562                 cerr<<"ConnectionWidget: MYSQL QUERY EXCEPTION \""<<er.what()<<"\""<<endl;
00563                 QString errorString = "Bad query when loading connections: \"";
00564                 errorString += er.what();
00565                 errorString += "\"";
00566                 QMessageBox::critical( 0, "Connections Error", errorString);
00567                 exit(1);//Critical error
00568     }
00569     catch (const Exception& er) {// Catch-all for any other MySQL++ exceptions
00570         cerr<<"ConnectionWidget: MYSQL EXCEPTION \""<<er.what()<<"\""<<endl;
00571                 QString errorString = "Exception thrown when loading connections: \"";
00572                 errorString += er.what();
00573                 errorString += "\"";
00574                 QMessageBox::critical( 0, "Connections Error", errorString);
00575                 exit(1);//Critical error
00576     }
00577 }
00578 
00579 
00580 /*! Loads a single connection group from the database
00581         Default is that connections are hidden by default so do not add to viewVector 
00582         and use hide icon.      Will not load temporary virtual connections. */
00583 void ConnectionWidget::loadConnection(unsigned int connectionGroupID){
00584         Query query = networkDBInterface->getQuery();
00585     query.reset();
00586     query << "SELECT FromNeuronGrpID, ToNeuronGrpID, ConnType, SynapseType FROM ConnectionGroups WHERE ConnGrpID = "<<connectionGroupID<<" AND ConnType != "<<ConnectionType::TempVirtual;
00587     Result connResult = query.store();
00588         Row connRow(*connResult.begin());//Should only be one result
00589         
00590         //Add new row to the table
00591         int currentRowNumber = connTable->numRows();
00592         connTable->insertRows(currentRowNumber, 1);
00593         
00594         //Need to extract the name of the from and to layers to make the table easier to read
00595         unsigned short cType = (unsigned short)connRow["ConnType"];
00596         int fromLayerID = (int)connRow["FromNeuronGrpID"];
00597         int toLayerID = (int)connRow["ToNeuronGrpID"];
00598 
00599         query.reset();
00600         query<<"SELECT Name FROM NeuronGroups WHERE NeuronGrpID = "<<fromLayerID;
00601         Result tempResult = query.store();
00602         Row tempFromRow(*tempResult.begin());
00603         QString fromLayerName = (std::string)tempFromRow.at(0) + " [";
00604         fromLayerName += QString::number(fromLayerID) + "]";
00605         query.reset();
00606         query<<"SELECT Name FROM NeuronGroups WHERE NeuronGrpID = "<<toLayerID;
00607         tempResult = query.store();
00608         mysqlpp::Row tempToRow(*tempResult.begin());
00609         QString toLayerName = (std::string)tempToRow.at(0) + " [";
00610         toLayerName += QString::number(toLayerID) + "]";
00611         
00612         //Fill Rows
00613         connTable->setPixmap(currentRowNumber, 0, *hidePixmap);
00614         
00615         connTable->setItem(currentRowNumber, 1, 
00616                 new ConnectionCheckTableItem( connTable, fromLayerName));//From layer
00617                 
00618         connTable->setItem(currentRowNumber, 2, 
00619                 new ConnectionTableItem(connTable, QTableItem::Never, toLayerName));//To layer
00620                 
00621         connTable->setItem(currentRowNumber, 3, 
00622                 new ConnectionTableItem(connTable, QTableItem::Never, ConnectionType::getDescription(cType)));//Connection Type
00623 
00624         connTable->setItem(currentRowNumber, 4, 
00625                 new ConnectionTableItem(connTable, QTableItem::Never, getSynapseTypeDescription(Utilities::getUShort((std::string)connRow["SynapseType"]))));//Synapse Type
00626 
00627         //Need to get size using neuron and connection tables
00628         //First do the query to get the size
00629         query.reset();
00630         query<<"SELECT COUNT(*) FROM Connections WHERE ConnGrpID = "<<connectionGroupID;
00631         Result connectionResult = query.store();//Execute the query
00632         Row connSizeRow(*connectionResult.begin());//Only one result since selecting count
00633         connTable->setItem(currentRowNumber, 5,
00634                 new ConnectionTableItem(connTable, QTableItem::Never, (std::string)connSizeRow.at(0)));//Number of connections in this connection group
00635         
00636         //Set ID
00637         connTable->setItem(currentRowNumber, connGrpIDColumn, 
00638                 new ConnectionTableItem(connTable, QTableItem::Never, QString::number(connectionGroupID)));
00639 
00640         //Set pixmap that user clicks on to view the parameters of the connection.
00641         connTable->setPixmap(currentRowNumber, paramCol, *paramPixmap);
00642 }
00643 
00644 
00645 /*! Removes the indicated connection group from the table. */
00646 void ConnectionWidget::removeConnectionFromTable(unsigned int connectionGrpID){
00647         //Remove from table
00648         for(int i=0; i<connTable->numRows(); i++){
00649                 unsigned int tempID = connTable->item(i, connGrpIDColumn)->text().toUInt();
00650                 if(tempID == connectionGrpID){
00651                         connTable->removeRow(i);
00652                         break;
00653                 }
00654         }
00655         //Remove from view vector
00656         for(vector<unsigned int>::iterator iter = viewVector.begin(); iter != viewVector.end(); iter++){
00657                 if(*iter == connectionGrpID){
00658                         viewVector.erase(iter);
00659                         break;
00660                 }
00661         }
00662 }
00663 
00664 

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