TinkerCell Core 1.0
TinkerCell's Core library providing all basic functionalities
MultithreadedSliderWidget.cpp
Go to the documentation of this file.
00001 
00002 /****************************************************************************
00003 
00004 Copyright (c) 2008 Deepak Chandran
00005 Contact: Deepak Chandran (dchandran1@gmail.com)
00006 See COPYRIGHT.TXT
00007 
00008 A slider widget that calls a C function whenver values in the slider are changed.
00009 Uses CThread.
00010 
00011 ****************************************************************************/
00012 
00013 #include <QRegExp>
00014 #include <QHBoxLayout>
00015 #include <QVBoxLayout>
00016 #include <QPushButton>
00017 #include "ConsoleWindow.h"
00018 #include "MainWindow.h"
00019 #include "NetworkHandle.h"
00020 #include "SymbolsTable.h"
00021 #include "MultithreadedSliderWidget.h"
00022 
00023 namespace Tinkercell
00024 {
00025         void MultithreadedSliderWidget::setVisibleSliders(const QString& substring)
00026         {
00027                 QStringList keys, allkeys;
00028                 QRegExp regex(substring);
00029                 for (int j=0; j < labels.size() && j < minline.size() && j < maxline.size() && j < valueline.size(); ++j)
00030                 {
00031                         if (labels[j] && (labels[j]->text().toLower().contains(substring.toLower()) || labels[j]->text().contains(regex)))
00032                                 keys += labels[j]->text();
00033                         allkeys += labels[j]->text();
00034                 }
00035                 if (substring.isEmpty() || keys.isEmpty())
00036                         setVisibleSliders(allkeys);
00037                 else
00038                         setVisibleSliders(keys);
00039         }
00040         
00041         void MultithreadedSliderWidget::setVisibleSliders(const QStringList& options)
00042         {
00043                 QVector<bool> showList(labels.size(),false);
00044                 for (int i=0; i < options.size(); ++i)
00045                 {
00046                         for (int j=0; j < labels.size() && j < minline.size() && j < maxline.size() && j < valueline.size(); ++j)
00047                         {
00048                                 if (labels[j] && options.contains(labels[j]->text()))
00049                                         showList[j] = true;
00050                         }
00051                 }
00052                 
00053                 for (int j=0; j < labels.size() && j < minline.size() && j < maxline.size() && j < valueline.size(); ++j)
00054                         if (!showList[j])
00055                         {
00056                                 labels[j]->hide();
00057                                 minline[j]->hide();
00058                                 maxline[j]->hide();
00059                                 valueline[j]->hide();
00060                                 if (sliderWidgets.contains(labels[j]->text()))
00061                                         sliderWidgets[labels[j]->text()]->hide();
00062                         }
00063                         else
00064                         {
00065                                 labels[j]->show();
00066                                 minline[j]->show();
00067                                 maxline[j]->show();
00068                                 valueline[j]->show();
00069                                 if (sliderWidgets.contains(labels[j]->text()))
00070                                         sliderWidgets[labels[j]->text()]->show();
00071                         }
00072         }
00073 
00074         MultithreadedSliderWidget::MultithreadedSliderWidget(MainWindow * parent, CThread * thread, Qt::Orientation orientation)
00075                 : QWidget(parent), orientation(orientation), mainWindow(parent)
00076         {
00077                 setAttribute(Qt::WA_DeleteOnClose,true);
00078                 cthread = thread;
00079                 setWindowFlags(Qt::Dialog);
00080                 slidersLayout = 0;
00081                 hide();
00082         }
00083 
00084         MultithreadedSliderWidget::MultithreadedSliderWidget(MainWindow * parent, const QString & lib, const QString & functionName, Qt::Orientation orientation)
00085                 : QWidget(parent), orientation(orientation), mainWindow(parent)
00086         {
00087                 setAttribute(Qt::WA_DeleteOnClose,true);
00088                 cthread = new CThread(parent, lib);
00089                 cthread->setMatrixFunction(functionName.toAscii().data());
00090                 setWindowFlags(Qt::Dialog);
00091                 slidersLayout = 0;
00092                 hide();
00093         }
00094 
00095         CThread * MultithreadedSliderWidget::thread() const
00096         {
00097                 return cthread;
00098         }
00099 
00100         void MultithreadedSliderWidget::setThread(CThread * t)
00101         {
00102                 cthread = t;
00103         }
00104         
00105         void MultithreadedSliderWidget::minmaxChanged()
00106         {
00107                 if (sliders.isEmpty()) return;
00108                 
00109                 double range,x;
00110                 bool ok;
00111                 
00112                 for (int i=0; i < sliders.size(); ++i)
00113                         if (sliders[i])
00114                                 disconnect(sliders[i],SIGNAL(valueChanged(int)),this,SLOT(sliderChanged(int)));
00115                 
00116                 for (int i=0; i < sliders.size() && i < max.size() && i < min.size(); ++i)
00117                         if (sliders[i])
00118                         {
00119                                 x = minline[i]->text().toDouble(&ok);
00120                                 if (ok)                         
00121                                         min[i] = x;
00122                                 else
00123                                         minline[i]->setText(QString::number(min[i]));
00124                                         
00125                                 x = maxline[i]->text().toDouble(&ok);
00126                                 if (ok)                         
00127                                         max[i] = x;
00128                                 else
00129                                         maxline[i]->setText(QString::number(max[i]));
00130                                         
00131                                 range = (max[i]-min[i]);
00132                                 sliders[i]->setValue((int)((values.value(i,0) - min[i]) * 100.0/range));
00133                         }
00134                 for (int i=0; i < sliders.size(); ++i)
00135                         if (sliders[i])
00136                                 connect(sliders[i],SIGNAL(valueChanged(int)),this,SLOT(sliderChanged(int)));
00137         }
00138         
00139         void MultithreadedSliderWidget::valueChanged()
00140         {
00141                 if (sliders.isEmpty()) return;
00142 
00143                 double range,x;
00144                 bool ok;
00145                 
00146                 for (int i=0; i < sliders.size(); ++i)
00147                         if (sliders[i])
00148                                 disconnect(sliders[i],SIGNAL(valueChanged(int)),this,SLOT(sliderChanged(int)));
00149                 
00150                 for (int i=0; i < valueline.size() && i < sliders.size() && i < max.size() && i < min.size(); ++i)
00151                         if (sliders[i])
00152                         {
00153                                 x = valueline[i]->text().toDouble(&ok);
00154                                 if (ok)
00155                                 {
00156                                         if (x > max[i])
00157                                         {
00158                                                 max[i] = x;
00159                                                 maxline[i]->setText(QString::number(max[i]));
00160                                         }
00161                                         if (x < min[i])
00162                                         {
00163                                                 min[i] = x;
00164                                                 minline[i]->setText(QString::number(min[i]));
00165                                         }
00166                                         range = (max[i]-min[i]);
00167                                         values.value(i,0) = x;
00168                                         sliders[i]->setValue((int)((x - min[i]) * 100.0/range));
00169                                 }
00170                                 else
00171                                 {
00172                                         valueline[i]->setText(QString::number(values.value(i,0)));
00173                                 }
00174                         }
00175                 
00176                 for (int i=0; i < sliders.size(); ++i)
00177                         if (sliders[i])
00178                                 connect(sliders[i],SIGNAL(valueChanged(int)),this,SLOT(sliderChanged(int)));
00179                 
00180                 emit valuesChanged(values);
00181 
00182                 if (cthread)
00183                 {
00184                         cthread->setArg(values);
00185                 
00186                         if (cthread->isRunning())
00187                         {
00188                                 if (mainWindow && mainWindow->console())
00189                                         mainWindow->console()->message(tr("Previous run has not finished yet"));
00190                                 return;
00191                                 //cthread->terminate();
00192                         }
00193                         cthread->start();
00194                 }
00195         }
00196 
00197         void MultithreadedSliderWidget::sliderChanged(int)
00198         {
00199                 if (sliders.isEmpty()) return;
00200                 
00201                 double range;
00202                 
00203                 for (int i=0; i < valueline.size() && i < sliders.size() && i < max.size() && i < min.size(); ++i)
00204                         if (sliders[i])
00205                         {
00206                                 range = (max[i]-min[i]);
00207                                 values.value(i,0) = min[i] + (range * sliders[i]->value())/100.0;
00208                                 valueline[i]->setText(QString::number(values.value(i,0)).left(6));
00209                         }
00210                 valueChanged();
00211         }
00212         
00213         void MultithreadedSliderWidget::setSliders(const QStringList& options, const QList<double>& minValues, const QList<double>& maxValues)
00214         {
00215                 QSlider * slider;
00216                 QLabel * label;
00217                 QLineEdit * line;
00218 
00219                 sliders.clear();
00220                 labels.clear();
00221                 min.clear();
00222                 max.clear();
00223                 minline.clear();
00224                 maxline.clear();
00225                 valueline.clear();
00226                 values.resize(options.size(),1);
00227                 //values.setRowNames(options);
00228                 values.setColumnNames(QStringList() << "value");
00229                 
00230                 if (this->layout())
00231                         delete (layout());
00232 
00233                 //create tab widget if names contain "::"
00234                 bool createTabs = false;
00235                 for (int i=0; i < options.size(); ++i)
00236                         if (options[i].contains("::"))
00237                         {
00238                                 createTabs = true;
00239                                 break;
00240                         }
00241 
00242                 QHBoxLayout* layout = 0;
00243                 QVBoxLayout * slidersLayout = 0;
00244 
00245                 QHash< QString, QVBoxLayout * > slidersLayoutsHash; //only if using multiple tabs
00246 
00247                 if (createTabs)
00248                 {
00249                         for (int i=0; i < options.size(); ++i)
00250                         {
00251                                 QString tabname;
00252                                 if (options[i].contains("::"))
00253                                 {
00254                                         QStringList words = options[i].split("::");
00255                                         tabname = words[0];
00256                                 }
00257                                 if (tabname.isNull() || tabname.isEmpty())
00258                                         tabname = tr("misc.");
00259                                 if (!slidersLayoutsHash.contains(tabname))
00260                                 {
00261                                         layout = new QHBoxLayout;
00262                                         layout->addWidget(new QLabel(tr("name")));
00263                                         layout->addWidget(new QLabel(tr("")));
00264                                         layout->addWidget(new QLabel(tr("value")));
00265                                         layout->addWidget(new QLabel(tr("min")));
00266                                         layout->addWidget(new QLabel(tr("max")));
00267 
00268                                         slidersLayout = new QVBoxLayout;
00269                                         QWidget * widget = new QWidget;
00270                                         widget->setLayout(layout);
00271                                         slidersLayout->addWidget(widget);
00272                                         slidersLayoutsHash[ tabname ] = slidersLayout; 
00273                                 }
00274                         }
00275                 }
00276                 else
00277                 {
00278                         layout = new QHBoxLayout;
00279                         layout->addWidget(new QLabel(tr("name")));
00280                         layout->addWidget(new QLabel(tr("")));
00281                         layout->addWidget(new QLabel(tr("value")));
00282                         layout->addWidget(new QLabel(tr("min")));
00283                         layout->addWidget(new QLabel(tr("max")));
00284 
00285                         slidersLayout = new QVBoxLayout;
00286                         QWidget * widget = new QWidget;
00287                         widget->setLayout(layout);
00288                         slidersLayout->addWidget(widget);
00289                 }
00290 
00291                 for (int i=0; i < options.size() && i < minValues.size() && i < maxValues.size(); ++i)
00292                 {
00293                         QString tabname, labelname;
00294                         if (createTabs)
00295                         {
00296                                 if (options[i].contains("::"))
00297                                 {
00298                                         QStringList words = options[i].split("::");
00299                                         tabname = words[0];
00300                                         labelname = words[1];
00301                                 }
00302                                 if (tabname.isNull() || tabname.isEmpty())
00303                                         tabname = tr("misc.");
00304                                 slidersLayout = slidersLayoutsHash[ tabname ];
00305                         }
00306                         else
00307                         {
00308                                 labelname = options[i];
00309                         }
00310 
00311                         values.setRowName(i, labelname);
00312                         layout = new QHBoxLayout;
00313                         label = new QLabel(labelname);
00314                         //label->setMaximumWidth(options[i].size() * 3);
00315                         layout->addWidget(label);
00316                         labels << label;
00317 
00318                         slider = new QSlider;
00319                         slider->setOrientation(orientation);
00320                         slider->setRange(0,100);
00321                         slider->setValue(50);
00322                         slider->setMinimumWidth(100);
00323                         layout->addWidget(slider,5);
00324                         sliders << slider;
00325                         slider->setTracking(false);
00326                         connect(slider,SIGNAL(valueChanged(int)),this,SLOT(sliderChanged(int)));
00327 
00328                         values.value(i,0) = (maxValues[i] + minValues[i])/2.0;
00329                         
00330                         line = new QLineEdit;
00331                         line->setText(QString::number(values.value(i,0) ));
00332                         line->setMaximumWidth(80);
00333                         layout->addWidget(line);
00334                         valueline << line;
00335                         connect(line,SIGNAL(editingFinished()),this,SLOT(valueChanged()));
00336 
00337                         line = new QLineEdit;
00338                         line->setText(QString::number(minValues[i]));
00339                         line->setMaximumWidth(80);
00340                         layout->addWidget(line);
00341                         minline << line;
00342                         min << minValues[i];
00343                         connect(line,SIGNAL(editingFinished()),this,SLOT(minmaxChanged()));
00344 
00345                         line = new QLineEdit;
00346                         line->setMaximumWidth(80);
00347                         layout->addWidget(line);
00348                         maxline << line;
00349                         if (maxValues[i] == minValues[i])
00350                         {
00351                                 if (minValues[i] == 0)
00352                                 {
00353                                         line->setText(QString::number(maxValues[i]+1.0));
00354                                         max << maxValues[i] + 1.0;
00355                                 }
00356                                 else
00357                                 {
00358                                         line->setText(QString::number(maxValues[i]*2));
00359                                         max << maxValues[i]*2;
00360                                 }
00361                         }
00362                         else
00363                         {
00364                                 line->setText(QString::number(maxValues[i]));
00365                                 max << maxValues[i];
00366                         }
00367                         connect(line,SIGNAL(editingFinished()),this,SLOT(minmaxChanged()));
00368                         
00369                         QWidget * widget = new QWidget;
00370                         widget->setLayout(layout);
00371                         slidersLayout->addWidget(widget);
00372                         sliderWidgets[ labelname ] = widget;
00373                 }
00374 
00375                 QWidget * centralWidget = 0;
00376                 
00377                 if (createTabs)
00378                 {
00379                         QTabWidget * tabWidget = new QTabWidget;
00380                         QStringList keys = slidersLayoutsHash.keys();
00381                         for (int i=0; i < keys.size(); ++i)
00382                         {
00383                                 slidersLayout = slidersLayoutsHash[ keys[i] ];
00384                                 QWidget * slidersWidget = new QWidget;
00385                                 slidersWidget->setLayout(slidersLayout);
00386                                 QScrollArea * scrollArea = new QScrollArea;
00387                                 scrollArea->setWidget(slidersWidget);
00388                                 scrollArea->setWidgetResizable(true);
00389                                 tabWidget->addTab(scrollArea, keys[i]);
00390                         }
00391                         centralWidget = tabWidget;
00392                 }
00393                 else
00394                 {
00395                         QWidget * slidersWidget = new QWidget;
00396                         slidersWidget->setLayout(slidersLayout);
00397                         QScrollArea * scrollArea = new QScrollArea;
00398                         scrollArea->setWidget(slidersWidget);
00399                         scrollArea->setWidgetResizable(true);
00400                         centralWidget = scrollArea;
00401                 }
00402 
00403                 QVBoxLayout * mainlayout = new QVBoxLayout;
00404                 //search box
00405                 QHBoxLayout * searchLayout = new QHBoxLayout;
00406                 QLineEdit * searchLine = new QLineEdit;
00407                 searchLine->setText(tr(""));
00408                 searchLayout->addStretch(2);
00409                 searchLayout->addWidget(new QLabel(tr("Search")), 0);
00410                 searchLayout->addWidget(searchLine, 1);
00411                 connect(searchLine,SIGNAL(textEdited ( const QString &)),this,SLOT(setVisibleSliders(const QString&)));
00412                 
00413                 //cancel and save buttons
00414                 QHBoxLayout * buttonLayout = new QHBoxLayout;   
00415                 QPushButton * closeButton = new QPushButton(tr("&Close"));
00416                 QPushButton * saveValues = new QPushButton(tr("&Save values"));
00417                 buttonLayout->addStretch(1);
00418                 buttonLayout->addWidget(saveValues);
00419                 buttonLayout->addWidget(closeButton);
00420                 buttonLayout->addStretch(1);
00421                 
00422                 //main layout
00423                 mainlayout->addLayout(searchLayout,0);
00424                 mainlayout->addWidget(centralWidget,1);
00425                 mainlayout->addLayout(buttonLayout,0);
00426                 connect(closeButton,SIGNAL(pressed()),this,SLOT(close()));
00427                 connect(saveValues,SIGNAL(pressed()),this,SLOT(saveValues()));
00428                 setLayout(mainlayout);
00429                 
00430                 valueChanged();
00431         }
00432         
00433         DataTable<qreal> MultithreadedSliderWidget::data() const
00434         {
00435                 return values;
00436         }
00437 
00438         void MultithreadedSliderWidget::setDefaultDataTable(const QString& s)
00439         {
00440                 defaultDataTable = s;
00441         }
00442 
00443         void MultithreadedSliderWidget::saveValues()
00444         {
00445                 NetworkHandle * network = mainWindow->currentNetwork();
00446                 if (!network) 
00447                 {
00448                         mainWindow->statusBar()->showMessage(tr("No model to update"));
00449                         return;
00450                 }
00451                 
00452                 SymbolsTable & symbols = network->symbolsTable;
00453                 QString s;
00454                 qreal d;
00455                 bool ok;
00456                 QList<NumericalDataTable*> newTables, oldTables;
00457                 NumericalDataTable * newTable, * oldTable;
00458                 QPair<ItemHandle*,QString> pair;
00459                 int k;
00460                 for (int i=0; i < labels.size() && i < valueline.size(); ++i)
00461                         if (labels[i] && valueline[i])
00462                         {
00463                                 s = labels[i]->text();
00464                                 d = valueline[i]->text().toDouble(&ok);
00465                                 
00466                                 if (!ok) continue;
00467                                 
00468                                 if (symbols.uniqueDataWithDot.contains(s))
00469                                 {
00470                                         pair = symbols.uniqueDataWithDot.value(s);
00471                                         if (pair.first && pair.first->hasNumericalData(pair.second))
00472                                         {
00473                                                 oldTable = &(pair.first->numericalDataTable(pair.second));
00474                                                 s.remove(pair.first->fullName() + tr("."));
00475                                                 if (oldTable->hasRow(s) && oldTable->value(s,0) != d)
00476                                                 {
00477                                                         k = oldTables.indexOf(oldTable);
00478                                                         if (k > -1)                                                     
00479                                                                 newTable = newTables[k];
00480                                                         else
00481                                                         {
00482                                                                 newTable = new NumericalDataTable(*oldTable);
00483                                                                 oldTables << oldTable;
00484                                                                 newTables << newTable;
00485                                                         }
00486                                                         newTable->value(s,0) = d;
00487                                                 }
00488                                         }
00489                                 }
00490                                 else
00491                                 {
00492                                         s.replace(tr("."),tr("_"));
00493                                         if (symbols.uniqueDataWithUnderscore.contains(s))
00494                                         {
00495                                                 pair = symbols.uniqueDataWithUnderscore.value(s);
00496                                                 if (pair.first && pair.first->hasNumericalData(pair.second))
00497                                                 {
00498                                                         oldTable = &(pair.first->numericalDataTable(pair.second));
00499                                                         s.remove(pair.first->fullName(tr("_")) + tr("_"));
00500                                                         if (oldTable->hasRow(s) && oldTable->value(s,0) != d)
00501                                                         {
00502                                                                 k = oldTables.indexOf(oldTable);
00503                                                                 if (k > -1)                                                     
00504                                                                         newTable = newTables[k];
00505                                                                 else
00506                                                                 {
00507                                                                         newTable = new NumericalDataTable(*oldTable);
00508                                                                         oldTables << oldTable;
00509                                                                         newTables << newTable;
00510                                                                 }
00511                                                                 newTable->value(s,0) = d;
00512                                                         }
00513                                                 }
00514                                         }
00515                                         else
00516                                         if (!defaultDataTable.isNull() &&
00517                                                         !defaultDataTable.isEmpty() &&  
00518                                                         symbols.uniqueHandlesWithUnderscore.contains(s))
00519                                         {
00520                                                 ItemHandle * h = symbols.uniqueHandlesWithUnderscore[s];
00521                                                 if (h->hasNumericalData(defaultDataTable))
00522                                                 {
00523                                                         oldTable = &(h->numericalDataTable(defaultDataTable));
00524                                                         if (oldTable->value(0,0) != d)
00525                                                         {
00526                                                                 k = oldTables.indexOf(oldTable);
00527                                                                 if (k > -1)                                                     
00528                                                                         newTable = newTables[k];
00529                                                                 else
00530                                                                 {
00531                                                                         newTable = new NumericalDataTable(*oldTable);
00532                                                                         oldTables << oldTable;
00533                                                                         newTables << newTable;
00534                                                                 }
00535                                                                 newTable->value(0,0) = d;
00536                                                         }
00537                                                 }
00538                                         }
00539                                 }
00540                 }
00541                 
00542                 if (!newTables.isEmpty())
00543                 {
00544                         network->push(new ChangeNumericalDataCommand(tr("Updated from slider"), oldTables, newTables));
00545                         for (int i=0; i < newTables.size(); ++i)
00546                                 delete newTables[i];
00547                 }
00548         }
00549 }
00550 
00551 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines