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

LayerWidget.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 "LayerWidget.h"
00025 #include "NetworkViewer.h"
00026 #include "LayerPropertiesDialog.h"
00027 #include "Debug.h"
00028 #include "Utilities.h"
00029 #include "SpikeStreamMainWindow.h"
00030 #include "NeuronGroup.h"
00031 
00032 //Qt includes
00033 #include <qpushbutton.h>
00034 #include <qmessagebox.h>
00035 #include <qaccel.h>
00036 #include <qlayout.h>
00037 #include <qfile.h>
00038 #include <qcursor.h>
00039 
00040 //Other includes
00041 #include <iostream>
00042 #include <vector>
00043 #include "mysql++.h"
00044 using namespace std;
00045 using namespace mysqlpp;
00046 
00047 
00048 /*! Constructor. */
00049 LayerWidget::LayerWidget(QWidget *parent, DBInterface *netDBInter, DBInterface* devDBInter) : QWidget(parent, "Layer Widget"){
00050         //Keep reference to database interfaces 
00051         networkDBInterface = netDBInter;
00052         deviceDBInterface = devDBInter;
00053         
00054         //Create a layerManager to manage the neurons
00055         layerManager = new LayerManager(networkDBInterface, deviceDBInterface);
00056         
00057         //Set up pixmaps to control zoom
00058         showPixmap = new QPixmap(SpikeStreamMainWindow::workingDirectory + "/images/view.xpm");
00059         hidePixmap = new QPixmap(SpikeStreamMainWindow::workingDirectory + "/images/hide.xpm");
00060         zoomToPixmap = new QPixmap(SpikeStreamMainWindow::workingDirectory + "/images/zoom_to_small.xpm");
00061         zoomToPixmapHighlight = new QPixmap(SpikeStreamMainWindow::workingDirectory + "/images/zoom_to_highlight.xpm");
00062         zoomAbovePixmapHighlight = new QPixmap(SpikeStreamMainWindow::workingDirectory + "/images/zoom_above_highlight.xpm");
00063         
00064         //Set zoom layer row to -1 and click count to zero
00065         zoomLayerRow = -1;
00066         zoomClickCount = 0;
00067         
00068         //Create vertical layout to organise widget
00069         QVBoxLayout *verticalBox = new QVBoxLayout(this, 5, 10, "vertical");
00070 
00071         //Set up buttons
00072         QHBoxLayout *buttonBox = new QHBoxLayout();
00073         newLayerButt = new QPushButton("Add Neurons", this, "NewNeuronGrp");
00074         newLayerButt->setBaseSize(100, 30);
00075         newLayerButt->setMaximumSize(100,30);
00076         newLayerButt->setAccel(QKeySequence(CTRL + Key_N));
00077         connect (newLayerButt, SIGNAL(clicked()), this, SLOT(newLayer()));
00078         buttonBox->addWidget(newLayerButt);
00079         
00080         deleteButt = new QPushButton("Delete", this, "Delete");
00081         deleteButt->setBaseSize(100, 30);
00082         deleteButt->setMaximumSize(100,30);
00083         deleteButt->setAccel(QKeySequence(Key_Delete));
00084         connect (deleteButt, SIGNAL(clicked()), this, SLOT(deleteLayer()));
00085         buttonBox->addWidget(deleteButt);
00086         buttonBox->addStretch(5);
00087         
00088         verticalBox->addLayout(buttonBox);
00089         
00090         //Set up table
00091         layerTable = new QTable(0, 10, this);
00092         layerTable->setColumnReadOnly(0, true);
00093         layerTable->setColumnReadOnly(1, true);
00094         layerTable->setShowGrid(false);
00095         layerTable->setSorting(false);
00096         layerTable->setSelectionMode(QTable::NoSelection);
00097         layerTable->verticalHeader()->hide();
00098         layerTable->setLeftMargin(0);
00099         QHeader * layerTableHeader = layerTable->horizontalHeader();
00100         layerTableHeader->setLabel(0, "");
00101         layerTable->setColumnWidth(0, 16);
00102         layerTableHeader->setLabel(1, "");
00103         layerTable->setColumnWidth(1, 16);
00104         layerTableHeader->setLabel( 2, "Name" );
00105         layerTable->setColumnWidth( 2, 200);
00106         layerTableHeader->setLabel( 3, "ID");
00107         layerTable->setColumnWidth( 3, 50);
00108         layerTableHeader->setLabel( 4, "Neuron Type");
00109         layerTable->setColumnWidth( 4, 200);
00110         layerTableHeader->setLabel( 5, "Width");
00111         layerTable->setColumnWidth( 5, 50);
00112         layerTableHeader->setLabel( 6, "Length");
00113         layerTable->setColumnWidth( 6, 50);
00114         layerTableHeader->setLabel( 7, "Size" );
00115         layerTable->setColumnWidth( 7, 50);
00116         layerTableHeader->setLabel( 8, "Position" );
00117         layerTable->setColumnWidth( 8, 100);
00118         layerTableHeader->setLabel( 9, "Task ID" );
00119         layerTable->setColumnWidth( 9, 100);
00120         
00121         //Connect layer table header clicked() slot to select all
00122         connect (layerTableHeader, SIGNAL(clicked(int)), this, SLOT(tableHeaderClicked(int)));
00123         
00124         //Need to set up table so that change in selection is reflected in 3D display
00125         connect (layerTable, SIGNAL(clicked(int, int, int, const QPoint &)), this, SLOT (tableClicked(int, int, int, const QPoint &)));
00126         
00127         //Now load the list of layers from the database
00128         addAllLayersToTable();
00129 
00130         verticalBox->addWidget(layerTable);
00131         
00132         //Set up popup menu to enable the user to edit a layer using a right mouse click
00133         layerPropertiesPopup = new QPopupMenu(this);
00134         layerPropertiesPopup->insertItem("Edit layer properties", this, SLOT(editLayerProperties()));
00135 }
00136 
00137 
00138 /*! Destructor. */
00139 LayerWidget::~LayerWidget(){
00140         #ifdef MEMORY_DEBUG
00141                 cout<<"DELETING LAYER WIDGET!"<<endl;
00142         #endif//MEMORY_DEBUG
00143         
00144         delete layerManager;
00145         delete showPixmap;
00146         delete hidePixmap;
00147         delete zoomToPixmap;
00148         delete zoomToPixmapHighlight;
00149         delete zoomAbovePixmapHighlight;
00150 }
00151 
00152 
00153 //--------------------------------------------------------------------------
00154 //--------------------- PUBLIC METHODS -------------------------------------
00155 //--------------------------------------------------------------------------
00156 
00157 /*! Reloads neuron groups when database has changed. */
00158 void LayerWidget::reloadNeuronGroups(){
00159         addAllLayersToTable();
00160 }
00161 
00162 
00163 /*! Need communication between layer widget and connection widget to enable layer widget
00164         to delete connections to layers that are being deleted. */
00165 void LayerWidget::setConnectionWidget(ConnectionWidget* connWidg){
00166         connectionWidget = connWidg;
00167         layerManager->setConnectionWidget(connWidg);
00168 }
00169 
00170 
00171 /*! Called when simulation is initialised to disable editing. */
00172 void LayerWidget::simulationDestroyed(){
00173         newLayerButt->setEnabled(true);
00174         deleteButt->setEnabled(true);
00175 }
00176 
00177 
00178 /*! Called when simulation is destroyed to enable editing. */
00179 void LayerWidget::simulationInitialised(){
00180         newLayerButt->setEnabled(false);
00181         deleteButt->setEnabled(false);
00182 }
00183 
00184 
00185 //-----------------------------------------------------------------------
00186 //--------------------------- SLOTS -------------------------------------
00187 //-----------------------------------------------------------------------
00188 
00189 /*! Deletes a layer from the table and instructs connection manager to delete the layer from the
00190         database along with all associated connections. */
00191 void LayerWidget::deleteLayer(){
00192         QString confirmDeleteStr = "Do you want to delete the following neuron groups and their associated connection groups?\n";
00193         vector<unsigned int> deleteLayerIDs;
00194         //First get the layer id(s) for the layer(s) to be deleted
00195         for(int i=0; i<layerTable->numRows(); i++){
00196                 QCheckTableItem * item = (QCheckTableItem*)layerTable->item(i, 2);
00197                 if(item->isChecked()){
00198                         unsigned int tempInt = layerTable->item(i, 3)->text().toUInt();
00199                         deleteLayerIDs.push_back(tempInt);
00200                         confirmDeleteStr += "   ";
00201                         confirmDeleteStr += layerTable->item(i, 2)->text()+= " (ID: ";
00202                         confirmDeleteStr += layerTable->item(i, 3)->text() += ")\n";
00203                 }
00204         }
00205         //Check that user really wants to delete these layers
00206         if(deleteLayerIDs.size() > 0){
00207                 if(!( QMessageBox::warning( this, "Confirm Delete Neuron Groups", confirmDeleteStr, "Yes", "No", 0, 0, 1 ))) {
00208                         
00209                         //Show dialog to inform user that deletion is in progress
00210                         BusyDialog* busyDialog = new BusyDialog(SpikeStreamMainWindow::spikeStrMainWin, "Editing Neuron Groups");
00211                         busyDialog->setModal(true);
00212                         busyDialog->showDialog("Deleting neuron groups, please wait.");
00213                         SpikeStreamMainWindow::spikeStreamApplication->processEvents();
00214 
00215                         //Delete the layers
00216                         try{
00217                         layerManager->deleteLayers(deleteLayerIDs);
00218 
00219                                 //Delete layer data from NetworkViewer
00220                                 vector<unsigned int>::iterator deleteIDsIter;
00221                                 for(deleteIDsIter = deleteLayerIDs.begin(); deleteIDsIter != deleteLayerIDs.end(); deleteIDsIter++){
00222                                         SpikeStreamMainWindow::spikeStrMainWin->getNetworkViewer()->deleteNeuronGroup(*deleteIDsIter);
00223                                         connectionWidget->deleteLayerConnections(*deleteIDsIter);
00224                                         removeLayerFromTable(*deleteIDsIter);
00225                                 }
00226                                 //Reset default clipping volume so that remaining neuron groups fit within it
00227                                 SpikeStreamMainWindow::spikeStrMainWin->getNetworkViewer()->loadDefaultClippingVolume();
00228                                 SpikeStreamMainWindow::spikeStrMainWin->getNetworkViewer()->resetView();
00229                                 
00230                                 //Reload neuron groups and connection groups
00231                                 SpikeStreamMainWindow::spikeStrMainWin->reloadNeuronGroups();
00232                                 SpikeStreamMainWindow::spikeStrMainWin->reloadConnections();
00233                         }
00234                         catch (const BadQuery& er) {// Handle any query errors
00235                                 cerr<<"LayerWidget: MYSQL QUERY EXCEPTION \""<<er.what()<<"\""<<endl;
00236                                 QString errorString = "Bad query when deleting layers: \"";
00237                                 errorString += er.what();
00238                                 errorString += "\"";
00239                                 QMessageBox::critical( 0, "Delete Layer Error", errorString);
00240                         }
00241                         catch (const Exception& er) {// Catch-all for any other MySQL++ exceptions
00242                                 cerr<<"LayerWidget: MYSQL EXCEPTION \""<<er.what()<<"\""<<endl;
00243                                 QString errorString = "Exception thrown deleting layers: \"";
00244                                 errorString += er.what();
00245                                 errorString += "\"";
00246                                 QMessageBox::critical( 0, "Delete Layer Error", errorString);
00247                         }
00248                         catch(std::exception& er){// Catch-all for std exceptions
00249                                 cerr<<"LayerWidget: STD EXCEPTION \""<<er.what()<<"\""<<endl;
00250                                 QString errorString = "Exception thrown deleting layers: \"";
00251                                 errorString += er.what();
00252                                 errorString += "\"";
00253                                 QMessageBox::critical( 0, "Delete Layer Error", errorString);
00254                         }
00255 
00256                         //Delete busy dialog
00257                         delete busyDialog;
00258         }
00259         }
00260 }
00261 
00262 
00263 /*! Used to change the properties of a layer, except the width and length. */
00264 void LayerWidget::editLayerProperties(){
00265         NeuronGroup origNeurGrpProps;
00266         
00267         //Double check that the activeRow is a sensible number
00268         if(layerTable->numRows() <= 0 || activeRow > (unsigned int)layerTable->numRows()){
00269                 QMessageBox::critical( 0, "Edit Layer Error", "Active row is out of range.");
00270                 return;
00271         }
00272 
00273         unsigned int neuronGrpID = 0;
00274         try{
00275                 //Extract neuronGrpID from table
00276                 neuronGrpID = Utilities::getUInt(layerTable->text(activeRow, 3).ascii());
00277 
00278                 //Get all information from database
00279                 Query query = networkDBInterface->getQuery();
00280                 query.reset();
00281                 query<<"SELECT Name, NeuronType, X, Y, Z, Width, Length, Spacing FROM NeuronGroups WHERE NeuronGrpID = "<<neuronGrpID; //Write query string
00282                 Result layerResult = query.store();
00283                 Row row(*layerResult.begin());//Neuron group ids are unique
00284         
00285                 //Fill neuron group holder
00286                 origNeurGrpProps.name = (std::string)row["Name"];
00287                 origNeurGrpProps.neuronType = Utilities::getUInt((std::string)row["NeuronType"]);
00288                 origNeurGrpProps.width = Utilities::getUInt((std::string)row["Width"]);;
00289                 origNeurGrpProps.length = Utilities::getUInt((std::string)row["Length"]);
00290                 origNeurGrpProps.spacing =Utilities::getUInt((std::string)row["Spacing"]);
00291                 origNeurGrpProps.xPos = Utilities::getUInt((std::string)row["X"]);
00292                 origNeurGrpProps.yPos = Utilities::getUInt((std::string)row["Y"]);
00293                 origNeurGrpProps.zPos = Utilities::getUInt((std::string)row["Z"]);
00294         }
00295     catch (const BadQuery& er) {// Handle any query errors
00296                 cerr<<"LayerWidget: MYSQL QUERY EXCEPTION \""<<er.what()<<"\""<<endl;
00297                 QString errorString = "Bad query when editing layer properties: \"";
00298                 errorString += er.what();
00299                 errorString += "\"";
00300                 QMessageBox::critical( 0, "Edit Layer Error", errorString);
00301                 return;
00302     }
00303     catch (const Exception& er) {// Catch-all for any other MySQL++ exceptions
00304         cerr<<"LayerWidget: MYSQL EXCEPTION \""<<er.what()<<"\""<<endl;
00305                 QString errorString = "Exception thrown editing layer properties: \"";
00306                 errorString += er.what();
00307                 errorString += "\"";
00308                 QMessageBox::critical( 0, "Edit Layer Error", errorString);
00309                 return;
00310     }
00311         catch(std::exception& er){// Catch-all for std exceptions
00312         cerr<<"LayerWidget: STD EXCEPTION \""<<er.what()<<"\""<<endl;
00313                 QString errorString = "Exception thrown editing layer properties: \"";
00314                 errorString += er.what();
00315                 errorString += "\"";
00316                 QMessageBox::critical( 0, "Edit Layer Error", errorString);
00317                 return;
00318         }
00319 
00320         //Show dialog with information
00321         LayerPropertiesDialog *layPropDlg = new LayerPropertiesDialog(this, "Neuron Group Properties", true, origNeurGrpProps, networkDBInterface, deviceDBInterface);
00322         layPropDlg->setCaption( "Neuron Group Properties" );
00323         if ( layPropDlg->exec() == QDialog::Accepted ) {//Adjust layer properties
00324         
00325                 //Get data from dialog
00326                 NeuronGroup newNeurGrpProps = layPropDlg->getNeuronGroup();
00327                 
00328                 //Create bool to record any changes
00329                 bool neuronGrpChanged = false;
00330                 bool neuronGrpNameChanged = false;
00331                 
00332                 //Work through all the neuron properties and change all those which have been altered
00333                 try{
00334                         if(newNeurGrpProps.name != origNeurGrpProps.name){
00335                                 layerManager->setNeuronGrpName(neuronGrpID, newNeurGrpProps.name);
00336                                 neuronGrpNameChanged = true;
00337                         }
00338                                 
00339                         if(newNeurGrpProps.neuronType != origNeurGrpProps.neuronType){
00340                                 layerManager->setNeuronGrpType(neuronGrpID, newNeurGrpProps.neuronType);
00341                                 neuronGrpChanged = true;
00342                         }
00343                         
00344                         //The next two changes need to be checked for conflicts with existing layers.
00345                         QString errorString = "";
00346                         if((newNeurGrpProps.spacing != origNeurGrpProps.spacing) || (newNeurGrpProps.xPos != origNeurGrpProps.xPos || newNeurGrpProps.yPos != origNeurGrpProps.yPos || newNeurGrpProps.zPos != origNeurGrpProps.zPos)){
00347                                 bool neurSpacingPositionChanged = layerManager->setNeuronGrpSpacingPosition(neuronGrpID, origNeurGrpProps, newNeurGrpProps);
00348                                 if(!neurSpacingPositionChanged)
00349                                         errorString += "New neuron spacing and/or position causes overlap with other layers.\n Left at original value.\n";
00350                                 else
00351                                         neuronGrpChanged = true;
00352                         }
00353                         //Show message dialog about any errors
00354                         if(errorString != "")
00355                                 QMessageBox::warning(this, "Neuron Group Properties Conflict!", errorString);
00356 
00357 
00358                         //Reload altered neuron group in network viewer and any affected connection groups
00359                         if(neuronGrpChanged){
00360                                 //Reload neuron group
00361                                 SpikeStreamMainWindow::spikeStrMainWin->getNetworkViewer()->deleteNeuronGroup(neuronGrpID);
00362                                 SpikeStreamMainWindow::spikeStrMainWin->getNetworkViewer()->loadNeuronGroup(neuronGrpID, true);
00363                                 
00364                                 //Load default clipping volume so that remaining neuron groups fit within it
00365                                 SpikeStreamMainWindow::spikeStrMainWin->getNetworkViewer()->loadDefaultClippingVolume();
00366                                 SpikeStreamMainWindow::spikeStrMainWin->getNetworkViewer()->resetView();
00367                                 
00368                                 //Set the view vector so the same neuron groups are visible as before
00369                                 SpikeStreamMainWindow::spikeStrMainWin->getNetworkViewer()->setLayerView(viewVector);
00370                                 
00371                                 //Reload connection groups that connect to this neuron group
00372                                 SpikeStreamMainWindow::spikeStrMainWin->getNetworkViewer()->setConnectionView(connectionWidget->getConnectionViewVector());
00373                         }
00374                         if(neuronGrpChanged || neuronGrpNameChanged){
00375                                 //Reload layer data into table
00376                                 removeLayerFromTable(neuronGrpID);
00377                                 addLayerToTable(neuronGrpID);
00378                                 
00379                                 //Update list of neuron groups in the rest of the application
00380                                 SpikeStreamMainWindow::spikeStrMainWin->reloadNeuronGroups();
00381                         }
00382                 }
00383                 catch (const BadQuery& er) {// Handle any query errors
00384                         cerr<<"LayerWidget: MYSQL QUERY EXCEPTION \""<<er.what()<<"\""<<endl;
00385                         QString errorString = "Bad query when editing layer properties: \"";
00386                         errorString += er.what();
00387                         errorString += "\"";
00388                         QMessageBox::critical( 0, "Edit Layer Error", errorString);
00389                         return;
00390                 }
00391                 catch (const Exception& er) {// Catch-all for any other MySQL++ exceptions
00392                         cerr<<"LayerWidget: MYSQL EXCEPTION \""<<er.what()<<"\""<<endl;
00393                         QString errorString = "Exception thrown editing layer properties: \"";
00394                         errorString += er.what();
00395                         errorString += "\"";
00396                         QMessageBox::critical( 0, "Edit Layer Error", errorString);
00397                         return;
00398                 }
00399                 catch(std::exception& er){// Catch-all for any other exceptions
00400                         cerr<<"LayerWidget: STD EXCEPTION \""<<er.what()<<"\""<<endl;
00401                         QString errorString = "Exception thrown editing layer properties: \"";
00402                         errorString += er.what();
00403                         errorString += "\"";
00404                         QMessageBox::critical( 0, "Edit Layer Error", errorString);
00405                         return;
00406                 }
00407         }
00408         //Clean up dialog
00409         delete layPropDlg;
00410 }
00411 
00412 
00413 /*! Creates a new layer. */
00414 void LayerWidget::newLayer(){
00415         NeuronGroup neuronGrp; //Empty neuron group holder to reduce double coding in layer properties dialog to accommodate edit mode.
00416         LayerPropertiesDialog *layPropDlg = new LayerPropertiesDialog(this, "Neuron Group Properties", false, neuronGrp, networkDBInterface, deviceDBInterface);
00417         layPropDlg->setCaption( "Neuron Group Properties" );
00418         if ( layPropDlg->exec() == QDialog::Accepted ) {//Create new layer
00419         
00420                 //Get neuronGrpHolder with layer details
00421                 NeuronGroup neuronGrp = layPropDlg->getNeuronGroup();
00422 
00423                 //Instruct layer manager to create layer
00424                 int layerID = -1;
00425                 try{
00426                         layerID = layerManager->createLayer(neuronGrp);
00427 
00428                         if(layerID < 0){//Method has returned a negative number or exception thrown, indicating that no layer has been created, probably due to conflict with existing layer
00429                                 QMessageBox::warning(this, "Layer Error!", "Layer has not been created due to an error or conflict with existing layers.");
00430                         }
00431                         else{//Layer has been created successfully
00432                                 SpikeStreamMainWindow::spikeStrMainWin->getNetworkViewer()->loadNeuronGroup(layerID, true);
00433                                 SpikeStreamMainWindow::spikeStrMainWin->getNetworkViewer()->loadDefaultClippingVolume();
00434                                 SpikeStreamMainWindow::spikeStrMainWin->getNetworkViewer()->resetView();
00435                                 
00436                                 //Update list of neuron groups in the rest of the application
00437                                 SpikeStreamMainWindow::spikeStrMainWin->reloadNeuronGroups();
00438                                 
00439                                 //Add layer to layer table
00440                                 addLayerToTable(layerID);
00441                         }
00442                 }
00443                 catch (const BadQuery& er) {// Handle any query errors
00444                         cerr<<"LayerWidget: MYSQL QUERY EXCEPTION \""<<er.what()<<"\""<<endl;
00445                         QString errorString = "Bad query creating layer: \"";
00446                         errorString += er.what();
00447                         errorString += "\"";
00448                         QMessageBox::critical( 0, "Create Layer Error", errorString);
00449                 }
00450                 catch (const Exception& er) {// Catch-all for any other MySQL++ exceptions
00451                         cerr<<"LayerWidget: MYSQL EXCEPTION \""<<er.what()<<"\""<<endl;
00452                         QString errorString = "Exception thrown creating layer: \"";
00453                         errorString += er.what();
00454                         errorString += "\"";
00455                         QMessageBox::critical( 0, "Create Layer Error", errorString);
00456                 }
00457                 catch(std::exception& er){// Catch-all for std exceptions
00458                         cerr<<"LayerWidget: STD EXCEPTION \""<<er.what()<<"\""<<endl;
00459                         QString errorString = "Exception thrown creating layer: \"";
00460                         errorString += er.what();
00461                         errorString += "\"";
00462                         QMessageBox::critical( 0, "Create Layer Error", errorString);
00463                 }
00464         }
00465 
00466         //Clean up dialog
00467         delete layPropDlg;
00468 }
00469 
00470 
00471 /*! Displays the popup menu if the right mouse button has been clicked.
00472         Otherwise controls the zoom and viewing of the layer. */
00473 void LayerWidget::tableClicked(int row, int col, int button, const QPoint &){
00474         //Show editing popup menu if it is the right button
00475         if(button == Qt::RightButton){
00476                 //First store active row so that information about the layer that is being edited can be accessed
00477                 activeRow = row;
00478         
00479                 //Show popup menu 
00480                 layerPropertiesPopup->exec(QCursor::pos());
00481         }
00482 
00483         //Otherwise check to see if the view changing pixmaps have been clicked
00484         else if(button == Qt::LeftButton){
00485                 if(col == 0){//View pixmap has been clicked
00486                         //Get layerID
00487                         unsigned int layerID = 0;
00488                         try{
00489                                 layerID = Utilities::getUInt(layerTable->item(row, 3)->text().ascii());
00490                         }
00491                         catch(std::exception& er){// Catch-all for any other exceptions
00492                                 cerr<<"LayerWidget: STD EXCEPTION \""<<er.what()<<"\""<<endl;
00493                                 QString errorString = "Exception thrown extracting neuron group ID: \"";
00494                                 errorString += er.what();
00495                                 errorString += "\"";
00496                                 QMessageBox::critical( 0, "Neuron Group ID Error", errorString);
00497                                 return;
00498                         }
00499                                         
00500                         //Find out if it is already part of the viewLayerIDVector
00501                         bool layerIDFound = false;
00502                         for(vector<unsigned int>::iterator iter = viewVector.begin(); iter != viewVector.end(); iter++){
00503                                 if(*iter == layerID){//Layer was already visible, so need to make it invisible
00504                                         layerIDFound = true;
00505                                         viewVector.erase(iter);
00506                                         layerTable->setPixmap(row, 0, *hidePixmap);
00507                                         SpikeStreamMainWindow::spikeStrMainWin->getNetworkViewer()->setLayerView(viewVector);
00508                                         break;
00509                                 }
00510                         }
00511                         if(!layerIDFound){//Not already showing, so show layer
00512                                 layerTable->setPixmap(row, 0, *showPixmap);
00513                                 viewVector.push_back(layerID);
00514                                 SpikeStreamMainWindow::spikeStrMainWin->getNetworkViewer()->setLayerView(viewVector);
00515                         }
00516                 }
00517                 else if(col == 1){//Zoom pixmap has been clicked
00518                         if(row == zoomLayerRow && zoomClickCount == 1){//Second click on the same row. Want to zoom above layer
00519                                 unsigned int layerID = layerTable->item(row, 3)->text().toUInt();
00520                                 SpikeStreamMainWindow::spikeStrMainWin->getNetworkViewer()->zoomAboveLayer(layerID);
00521                                 layerTable->setPixmap(row, 1, *zoomAbovePixmapHighlight);
00522                                 zoomClickCount++;
00523                         }
00524                         else if(row == zoomLayerRow && zoomClickCount == 2){//Third click on same row. Want to reset view and zoom to all layers
00525                                 SpikeStreamMainWindow::spikeStrMainWin->getNetworkViewer()->zoomToLayer(0);
00526                                 layerTable->setPixmap(row, 1, *zoomToPixmap);
00527                                 zoomClickCount = 0;
00528                                 zoomLayerRow = -1;
00529                         }
00530                         else{//Different row has been clicked
00531                                 unsigned int layerID = layerTable->item(row, 3)->text().toUInt();
00532                                 SpikeStreamMainWindow::spikeStrMainWin->getNetworkViewer()->zoomToLayer(layerID);
00533                                 
00534                                 //Change pixmap to hightlighted pixmap
00535                                 for(int i=0; i<layerTable->numRows(); i++){
00536                                         if(i==row)
00537                                                 layerTable->setPixmap(i, 1, *zoomToPixmapHighlight);
00538                                         else
00539                                                 layerTable->setPixmap(i, 1, *zoomToPixmap);
00540                                 }
00541                                 
00542                                 //Record which layer is selected
00543                                 zoomLayerRow = row;
00544                                 zoomClickCount = 1;
00545                         }
00546                 }
00547         }
00548 }
00549 
00550 
00551 /*! Used to select all layers or deselect all layers for deletion or zooming. */
00552 void LayerWidget::tableHeaderClicked(int colNumber){
00553         if(colNumber == 0){//View header has been clicked
00554                 //All rows are already selected, so deselect
00555                 if(viewVector.size() == (unsigned int)layerTable->numRows()){
00556                         viewVector.clear();
00557                         SpikeStreamMainWindow::spikeStrMainWin->getNetworkViewer()->setLayerView(viewVector);
00558                         
00559                         //Change pixmaps to hide
00560                         for(int i=0; i<layerTable->numRows(); i++){
00561                                 layerTable->setPixmap(i, 0, *hidePixmap);
00562                         }
00563                 }
00564                 //Not all rows selected, so select all
00565                 else{
00566                         viewVector.clear();
00567                         for(int i=0; i<layerTable->numRows(); i++){
00568                                 unsigned int tempLayerID = layerTable->item(i, 3)->text().toUInt();
00569                                 viewVector.push_back(tempLayerID);
00570                                 layerTable->setPixmap(i, 0, *showPixmap);
00571                         }
00572                         SpikeStreamMainWindow::spikeStrMainWin->getNetworkViewer()->setLayerView(viewVector);
00573                 }
00574         }
00575         else if(colNumber ==2){//Header above check boxes has been clicked
00576                 //First count the number of selected rows
00577                 int selectedRowCount = 0;
00578                 for(int i=0; i<layerTable->numRows(); i++){
00579                         QCheckTableItem * item = (QCheckTableItem*)layerTable->item(i, 2);
00580                         if(item->isChecked())
00581                                 selectedRowCount++;
00582                 }
00583                 //If all rows are selected want to deselect rows
00584                 if(selectedRowCount == layerTable->numRows()){
00585                         for(int i=0; i<layerTable->numRows(); i++){//Deselect all rows
00586                                 QCheckTableItem * item = (QCheckTableItem*)layerTable->item(i, 2);
00587                                 item->setChecked(false);
00588                         }
00589                 }
00590                 else{//Select all rows
00591                         for(int i=0; i<layerTable->numRows(); i++){
00592                                 QCheckTableItem * item = (QCheckTableItem*)layerTable->item(i, 2);
00593                                 item->setChecked(true);
00594                         }
00595                 }
00596         }
00597 }
00598 
00599 
00600 //--------------------------------------------------------------------------
00601 //-------------------------- PRIVATE METHODS -------------------------------
00602 //--------------------------------------------------------------------------
00603 
00604 /*! Works through all the layers and adds them to the table. */
00605 void LayerWidget::addAllLayersToTable(){
00606         //First clear the table
00607         clearTable();
00608         try{
00609                 Query query = networkDBInterface->getQuery();   //Get query object
00610                 query.reset();// Reset the query object just in case it has already been used
00611                 query<<"SELECT NeuronGrpID FROM NeuronGroups";
00612                 Result layerResult = query.store();
00613                 Result::iterator resIter;
00614                 for (resIter = layerResult.begin(); resIter != layerResult.end(); ++resIter) {
00615                         Row row(*resIter);
00616                         unsigned int neuronGrpID = Utilities::getUInt((std::string)row.at(0));
00617                         addLayerToTable(neuronGrpID);
00618                 }
00619         }
00620         catch (const BadQuery& er) {// Handle any query errors
00621                 cerr<<"LayerWidget: MYSQL QUERY EXCEPTION \""<<er.what()<<"\""<<endl;
00622                 QString errorString = "Bad query adding layer to table: \"";
00623                 errorString += er.what();
00624                 errorString += "\"";
00625                 QMessageBox::critical( 0, "Add Layer Error", errorString);
00626         }
00627         catch (const Exception& er) {// Catch-all for any other MySQL++ exceptions
00628                 cerr<<"LayerWidget: MYSQL EXCEPTION \""<<er.what()<<"\""<<endl;
00629                 QString errorString = "Exception thrown adding layer to table: \"";
00630                 errorString += er.what();
00631                 errorString += "\"";
00632                 QMessageBox::critical( 0, "Add Layer Error", errorString);
00633         }
00634         catch(std::exception& er){// Catch-all for std exceptions
00635                 cerr<<"LayerWidget: STD EXCEPTION \""<<er.what()<<"\""<<endl;
00636                 QString errorString = "Exception thrown adding layer to table: \"";
00637                 errorString += er.what();
00638                 errorString += "\"";
00639                 QMessageBox::critical( 0, "Add Layer Error", errorString);
00640         }
00641 }
00642 
00643 
00644 /*! Adds an individual layer to the table. */
00645 void LayerWidget::addLayerToTable(unsigned int neuronGrpID){
00646         //First add neuronGrpID to view vector. Default is that layers are visible
00647         viewVector.push_back(neuronGrpID);
00648 
00649         try{
00650                 Query query = networkDBInterface->getQuery();
00651                 query.reset();
00652                 query << "SELECT Name, NeuronType, X, Y, Z, Width, Length, Spacing, TaskID FROM NeuronGroups WHERE NeuronGrpID = "<<neuronGrpID; //Write query string
00653                 Result layerResult = query.store();
00654                 Row row(*layerResult.begin());//Neuron group ids are unique
00655                 
00656                 //Add new row to the table
00657                 int currentRow = layerTable->numRows();
00658                 layerTable->insertRows(currentRow, 1);
00659                 
00660                 //Fill Row
00661                 layerTable->setPixmap(currentRow, 0, *showPixmap);
00662                 layerTable->setPixmap(currentRow, 1, *zoomToPixmap);
00663                 
00664                 QCheckTableItem *checkTableItem = new QCheckTableItem( layerTable, (std::string)row["Name"] );
00665                 //checkTableItem->setChecked(true);
00666                 layerTable->setItem( currentRow, 2, checkTableItem);//Name
00667                         
00668                 layerTable->setItem( currentRow, 3, 
00669                         new QTableItem(layerTable, QTableItem::Never, QString::number(neuronGrpID)));//ID
00670                         
00671                 layerTable->setItem(currentRow, 4, 
00672                         new QTableItem(layerTable, QTableItem::Never, getNeuronTypeDescription(Utilities::getUShort((std::string)row["NeuronType"]))));//Type
00673                                         
00674                 layerTable->setItem(currentRow, 5,
00675                         new QTableItem(layerTable, QTableItem::Never, (std::string)row["Width"]));//Width
00676                         
00677                 layerTable->setItem(currentRow, 6, 
00678                         new QTableItem(layerTable, QTableItem::Never, (std::string)row["Length"]));//Length
00679                 
00680                 //Next get size from other Table for id
00681                 query.reset();
00682                 query << "SELECT * from Neurons WHERE NeuronGrpID = \""<<neuronGrpID<<"\"";
00683                 Result neuronResult = query.store();
00684                 layerTable->setItem( currentRow, 7, 
00685                         new QTableItem(layerTable, QTableItem::Never, QString::number(neuronResult.size())));//Size
00686                         
00687                 QString positionString = "(" + (std::string)row["X"] + ", " + (std::string)row["Y"] + ", " + (std::string)row["Z"] + ")";
00688                 layerTable->setItem(currentRow, 8, 
00689                         new QTableItem(layerTable, QTableItem::Never, positionString));//Position
00690                 
00691                 layerTable->setItem( currentRow, 9, 
00692                         new QTableItem(layerTable, QTableItem::Never, (std::string)row["TaskID"]));//Processing ID
00693         }
00694         catch (const BadQuery& er) {// Handle any query errors
00695                 cerr<<"LayerWidget: MYSQL QUERY EXCEPTION \""<<er.what()<<"\""<<endl;
00696                 QString errorString = "Bad query adding layer to table: \"";
00697                 errorString += er.what();
00698                 errorString += "\"";
00699                 QMessageBox::critical( 0, "Add Layer Error", errorString);
00700         }
00701         catch (const Exception& er) {// Catch-all for any other MySQL++ exceptions
00702                 cerr<<"LayerWidget: MYSQL EXCEPTION \""<<er.what()<<"\""<<endl;
00703                 QString errorString = "Exception thrown adding layer to table: \"";
00704                 errorString += er.what();
00705                 errorString += "\"";
00706                 QMessageBox::critical( 0, "Add Layer Error", errorString);
00707         }
00708         catch(std::exception& er){// Catch-all for std exceptions
00709                 cerr<<"LayerWidget: STD EXCEPTION \""<<er.what()<<"\""<<endl;
00710                 QString errorString = "Exception thrown adding layer to table: \"";
00711                 errorString += er.what();
00712                 errorString += "\"";
00713                 QMessageBox::critical( 0, "Add Layer Error", errorString);
00714         }
00715 }
00716 
00717 
00718 /*! Clears the table and resets the appropriate variables. */
00719 void LayerWidget::clearTable(){
00720         layerTable->setNumRows(0);
00721         viewVector.clear();
00722                 
00723         //Reset zoom and click counts
00724         zoomClickCount = 0;
00725         zoomLayerRow = -1;
00726 }
00727 
00728 
00729 /*! Returns the description of a particular neuron type. */
00730 string LayerWidget::getNeuronTypeDescription(unsigned short neuronTypeID){
00731         try {
00732                 Query query = networkDBInterface->getQuery();
00733                 query.reset();
00734                 query<<"SELECT Description FROM NeuronTypes WHERE TypeID = "<<neuronTypeID;
00735                 Result result = query.store();
00736                 if(result.size() != 1){
00737                         return string("Unknown");
00738                 }
00739                 Row row(*result.begin());//TypeID is unique
00740                 return (std::string)row["Description"];
00741         }
00742         catch (const BadQuery& er) {// Handle any query errors
00743                 cerr<<"LayerWidget: MYSQL QUERY EXCEPTION \""<<er.what()<<"\""<<endl;
00744                 QString errorString = "Bad query when getting neuron type description: \"";
00745                 errorString += er.what();
00746                 errorString += "\"";
00747                 QMessageBox::critical( 0, "Neuron Type Error", errorString);
00748                 return string("Unknown");
00749         }
00750         catch (const Exception& er) {// Catch-all for any other MySQL++ exceptions
00751                 cerr<<"LayerWidget: MYSQL EXCEPTION \""<<er.what()<<"\""<<endl;
00752                 QString errorString = "Exception thrown when getting neuron type description: \"";
00753                 errorString += er.what();
00754                 errorString += "\"";
00755                 QMessageBox::critical( 0, "Neuron Type Error", errorString);
00756                 return string("Unknown");
00757         }
00758 }
00759 
00760 
00761 /*! Removes the indicated neuronGrp from the table. */
00762 void LayerWidget::removeLayerFromTable(unsigned int neuronGrpID){
00763         //Remove from table
00764         for(int i=0; i<layerTable->numRows(); i++){
00765                 unsigned int tempID = layerTable->item(i, 3)->text().toUInt();
00766                 if(tempID == neuronGrpID){
00767                         layerTable->removeRow(i);
00768                         break;
00769                 }
00770         }
00771         //Remove from view vector
00772         for(vector<unsigned int>::iterator iter = viewVector.begin(); iter != viewVector.end(); iter++){
00773                 if(*iter == neuronGrpID){
00774                         viewVector.erase(iter);
00775                         break;
00776                 }
00777         }
00778 }
00779 
00780 
00781 

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