![]() |
TinkerCell Core 1.0
TinkerCell's Core library providing all basic functionalities
|
00001 /**************************************************************************** 00002 00003 Copyright (c) 2008 Deepak Chandran 00004 Contact: Deepak Chandran (dchandran1@gmail.com) 00005 See COPYRIGHT.TXT 00006 00007 This file defines an abstract class that is used to create interfaces for C functions. 00008 LPSolveInputWindow is a good example. 00009 00010 ****************************************************************************/ 00011 #include "ConsoleWindow.h" 00012 #include "AbstractInputWindow.h" 00013 #include "CThread.h" 00014 00015 namespace Tinkercell 00016 { 00017 00018 AbstractInputWindow::AbstractInputWindow(const QString& name, CThread * thread) 00019 : Tool(name), cthread(thread), dockWidget(0), targetFunction(0) 00020 { 00021 if (mainWindow && cthread) 00022 disconnect(mainWindow,SIGNAL(historyChanged()),cthread,SLOT(update())); 00023 00024 if (cthread) 00025 connect(this,SIGNAL(updateThread()),cthread,SLOT(update())); 00026 00027 setWindowFlags(Qt::Dialog); 00028 } 00029 00030 void AbstractInputWindow::setThread(CThread * thread) 00031 { 00032 if (cthread != thread) 00033 { 00034 cthread = thread; 00035 if (cthread) 00036 connect(this,SIGNAL(updateThread()),cthread,SLOT(update())); 00037 00038 if (mainWindow && cthread) 00039 disconnect(mainWindow,SIGNAL(historyChanged()),cthread,SLOT(update())); 00040 } 00041 } 00042 00043 CThread * AbstractInputWindow::thread() const 00044 { 00045 return cthread; 00046 } 00047 00048 void AbstractInputWindow::loadAPI(Tool*) 00049 { 00050 /*if (mainWindow && cthread && cthread->library()) 00051 { 00052 QSemaphore * s = new QSemaphore(1); 00053 s->acquire(); 00054 mainWindow->setupNewThread(s,cthread->library()); 00055 s->acquire(); 00056 s->release(); 00057 }*/ 00058 } 00059 00060 void AbstractInputWindow::setInput(const DataTable<qreal>& dat) 00061 { 00062 if (cthread) 00063 cthread->setArg(dat); 00064 } 00065 00066 bool AbstractInputWindow::setMainWindow(MainWindow * main) 00067 { 00068 Tool::setMainWindow(main); 00069 if (mainWindow) 00070 { 00071 QSize sz = mainWindow->size(); 00072 QPoint pos = mainWindow->pos(); 00073 move(pos + QPoint(sz.width()-100, sz.height()-100)/2 ); 00074 00075 if (cthread) 00076 disconnect(mainWindow,SIGNAL(historyChanged()),cthread,SLOT(update())); 00077 00078 if (mainWindow->console()) 00079 connect(this,SIGNAL(evalScript(const QString&)), mainWindow->console(), SLOT(eval(const QString&))); 00080 00081 connect(mainWindow,SIGNAL(escapeSignal(const QWidget*)),this,SLOT(escapeSignal(const QWidget*))); 00082 00083 setWindowTitle(name); 00084 setWindowIcon(QIcon(tr(":/images/play.png"))); 00085 dockWidget = mainWindow->addToolWindow(this,MainWindow::DockWidget,Qt::BottomDockWidgetArea,Qt::RightDockWidgetArea | Qt::BottomDockWidgetArea,false); 00086 if (dockWidget) 00087 { 00088 //dockWidget->setAttribute(Qt::WA_ContentsPropagated); 00089 dockWidget->hide(); 00090 dockWidget->setFloating(true); 00091 //dockWidget->setWindowOpacity(0.8); 00092 } 00093 } 00094 return true; 00095 } 00096 00097 void AbstractInputWindow::escapeSignal(const QWidget*) 00098 { 00099 if (dockWidget) 00100 dockWidget->hide(); 00101 else 00102 this->hide(); 00103 } 00104 00105 void AbstractInputWindow::exec() 00106 { 00107 if (cthread) 00108 { 00109 if (targetFunction) 00110 cthread->setFunction(targetFunction); 00111 cthread->start(); 00112 } 00113 } 00114 00115 void AbstractInputWindow::enterEvent ( QEvent * ) 00116 { 00117 emit updateThread(); 00118 } 00119 00120 /****************************** 00121 SIMPLE INPUT WINDOW 00122 *******************************/ 00123 00124 QHash<QString,SimpleInputWindow*> SimpleInputWindow::inputWindows; 00125 00126 SimpleInputWindow::SimpleInputWindow(MainWindow * main, const QString& title, const QString& lib, const QString& funcName, const DataTable<qreal>& data) 00127 : AbstractInputWindow(title) 00128 { 00129 CThread * thread = new CThread(main, lib); 00130 thread->setMatrixFunction(funcName.toAscii().data()); 00131 this->dataTable = data; 00132 00133 setThread(thread); 00134 00135 QPushButton * runButton = new QPushButton(this); 00136 runButton->setIcon(QIcon(":/images/play.png")); 00137 connect(runButton,SIGNAL(released()),this,SLOT(exec())); 00138 00139 /*QToolButton * addButton = new QToolButton(this); 00140 addButton->setIcon(QIcon(":/images/plus.png")); 00141 connect(addButton,SIGNAL(released()),this,SLOT(addRow())); 00142 00143 QToolButton * removeButton = new QToolButton(this); 00144 removeButton->setIcon(QIcon(":/images/minus.png")); 00145 connect(removeButton,SIGNAL(released()),this,SLOT(removeRow()));*/ 00146 00147 QVBoxLayout * layout = new QVBoxLayout; 00148 layout->addWidget(&tableWidget,1); 00149 00150 QHBoxLayout * hlayout = new QHBoxLayout; 00151 hlayout->addWidget(runButton,3); 00152 hlayout->addStretch(6); 00153 //hlayout->addWidget(addButton,0); 00154 //hlayout->addWidget(removeButton,0); 00155 layout->addLayout(hlayout,0); 00156 00157 setLayout(layout); 00158 00159 tableWidget.setAlternatingRowColors(true); 00160 tableWidget.setItemDelegate(&delegate); 00161 tableWidget.setEditTriggers ( QAbstractItemView::CurrentChanged | QAbstractItemView::DoubleClicked | QAbstractItemView::SelectedClicked | QAbstractItemView::EditKeyPressed ); 00162 00163 setupDisplay(data); 00164 00165 inputWindows[title.toLower()] = this; 00166 setMainWindow(main); 00167 } 00168 00169 void SimpleInputWindow::exec() 00170 { 00171 if (cthread) 00172 { 00173 if (targetFunction) 00174 cthread->setFunction(targetFunction); 00175 int rows = tableWidget.rowCount(), cols = tableWidget.columnCount(); 00176 00177 for (int i=0; i < rows; ++i) 00178 for (int j=0; j < cols; ++j) 00179 dataChanged(i,j); 00180 cthread->setArg(dataTable); 00181 cthread->start(); 00182 } 00183 00184 if (console() && !scriptCommand.isNull() && !scriptCommand.isEmpty()) 00185 { 00186 QStringList args; 00187 for (int i=0; i < tableWidget.rowCount(); ++i) 00188 for (int j=0; j < tableWidget.columnCount(); ++j) 00189 if (delegate.options(i,j).size() > 0) 00190 args << (tr("\"") + tableWidget.item(i,j)->text() + tr("\"")); 00191 else 00192 args << tableWidget.item(i,j)->text(); 00193 emit evalScript(scriptCommand + tr("(") + args.join(tr(",")) + tr(")")); 00194 } 00195 } 00196 00197 SimpleInputWindow::SimpleInputWindow(MainWindow * main, const QString& title, const DataTable<qreal>& data) 00198 : AbstractInputWindow(title) 00199 { 00200 this->dataTable = data; 00201 00202 QPushButton * runButton = new QPushButton(this); 00203 runButton->setIcon(QIcon(":/images/play.png")); 00204 connect(runButton,SIGNAL(released()),this,SLOT(exec())); 00205 00206 QVBoxLayout * layout = new QVBoxLayout; 00207 layout->addWidget(&tableWidget,1); 00208 00209 QHBoxLayout * hlayout = new QHBoxLayout; 00210 hlayout->addWidget(runButton,3); 00211 hlayout->addStretch(6); 00212 layout->addLayout(hlayout,0); 00213 00214 setLayout(layout); 00215 00216 tableWidget.setAlternatingRowColors(true); 00217 tableWidget.setItemDelegate(&delegate); 00218 tableWidget.setEditTriggers ( QAbstractItemView::CurrentChanged | QAbstractItemView::DoubleClicked | QAbstractItemView::SelectedClicked | QAbstractItemView::EditKeyPressed ); 00219 00220 setupDisplay(data); 00221 00222 inputWindows[title.toLower()] = this; 00223 setMainWindow(main); 00224 } 00225 00226 SimpleInputWindow::SimpleInputWindow(CThread * thread, const QString& title, void (*f)(tc_matrix), const DataTable<qreal>& data) 00227 : AbstractInputWindow(title) 00228 { 00229 QPushButton * runButton = new QPushButton(this); 00230 runButton->setIcon(QIcon(":/images/play.png")); 00231 connect(runButton,SIGNAL(released()),this,SLOT(exec())); 00232 00233 QToolButton * addButton = new QToolButton(this); 00234 addButton->setIcon(QIcon(":/images/plus.png")); 00235 connect(addButton,SIGNAL(released()),this,SLOT(addRow())); 00236 00237 QToolButton * removeButton = new QToolButton(this); 00238 removeButton->setIcon(QIcon(":/images/minus.png")); 00239 connect(removeButton,SIGNAL(released()),this,SLOT(removeRow())); 00240 00241 QVBoxLayout * layout = new QVBoxLayout; 00242 layout->addWidget(&tableWidget,1); 00243 00244 QHBoxLayout * hlayout = new QHBoxLayout; 00245 hlayout->addWidget(runButton,3); 00246 hlayout->addStretch(6); 00247 hlayout->addWidget(addButton,0); 00248 hlayout->addWidget(removeButton,0); 00249 layout->addLayout(hlayout,0); 00250 00251 setLayout(layout); 00252 00253 tableWidget.setAlternatingRowColors(true); 00254 tableWidget.setItemDelegate(&delegate); 00255 tableWidget.setEditTriggers ( QAbstractItemView::CurrentChanged | QAbstractItemView::DoubleClicked | QAbstractItemView::SelectedClicked | QAbstractItemView::EditKeyPressed ); 00256 00257 if (thread) 00258 { 00259 targetFunction = f; 00260 setThread(thread); 00261 setMainWindow(cthread->mainWindow); 00262 } 00263 00264 this->dataTable = data; 00265 setupDisplay(data); 00266 inputWindows[title.toLower()] = this; 00267 } 00268 00269 void SimpleInputWindow::AddOptions(const QString& title, int i, int j, const QStringList& options0) 00270 { 00271 if (inputWindows.contains(title.toLower())) 00272 { 00273 SimpleInputWindow * win = inputWindows[title.toLower()]; 00274 AddOptions(win,i,j,options0); 00275 } 00276 } 00277 00278 void SimpleInputWindow::AddOptions(SimpleInputWindow * win, int i, int j, const QStringList& options0) 00279 { 00280 if (!win) return; 00281 00282 QStringList options = options0; 00283 00284 //for (int k=0; k < options.size(); ++k) 00285 // options[k].replace(tr("_"),tr(".")); 00286 00287 win->delegate.options.value(i,j) = options; 00288 00289 if (win->dataTable.value(i,j) >= options.size() || win->dataTable.value(i,j) < 0) 00290 win->dataTable.value(i,j) = -1; 00291 else 00292 if (win->tableWidget.item(i,j) && !options.contains(win->tableWidget.item(i,j)->text())) 00293 win->tableWidget.item(i,j)->setText(options[ (int)(win->dataTable.value(i,j)) ]); 00294 } 00295 00296 SimpleInputWindow::SimpleInputWindow() : AbstractInputWindow() { } 00297 00298 SimpleInputWindow::SimpleInputWindow(const SimpleInputWindow&) : AbstractInputWindow() { } 00299 00300 SimpleInputWindow * SimpleInputWindow::CreateWindow(MainWindow * main, const QString& title, const QString& lib, const QString& funcName, const DataTable<qreal>& data) 00301 { 00302 if (!main || lib.isEmpty() || funcName.isEmpty()) return 0; 00303 00304 SimpleInputWindow * inputWindow = 0; 00305 if (SimpleInputWindow::inputWindows.contains(title.toLower())) 00306 { 00307 inputWindow = SimpleInputWindow::inputWindows.value(title.toLower()); 00308 if (data.rowNames() != inputWindow->dataTable.rowNames() || 00309 data.columnNames() != inputWindow->dataTable.columnNames()) 00310 { 00311 inputWindow = 0; 00312 } 00313 } 00314 00315 if (!inputWindow) 00316 { 00317 inputWindow = new SimpleInputWindow(main,title,lib,funcName,data); 00318 } 00319 if (inputWindow) 00320 { 00321 if (inputWindow->dockWidget) 00322 inputWindow->dockWidget->show(); 00323 else 00324 inputWindow->show(); 00325 } 00326 return inputWindow; 00327 } 00328 00329 SimpleInputWindow * SimpleInputWindow::CreateWindow(CThread * thread, const QString& title, void (*f)(tc_matrix), const DataTable<qreal>& data) 00330 { 00331 if (!thread || title.isEmpty() || !f) return 0; 00332 00333 SimpleInputWindow * inputWindow = 0; 00334 if (SimpleInputWindow::inputWindows.contains(title.toLower())) 00335 { 00336 inputWindow = SimpleInputWindow::inputWindows.value(title.toLower()); 00337 if (data.rowNames() != inputWindow->dataTable.rowNames() || 00338 data.columnNames() != inputWindow->dataTable.columnNames()) 00339 { 00340 inputWindow = 0; 00341 } 00342 } 00343 00344 if (!inputWindow) 00345 { 00346 inputWindow = new SimpleInputWindow(thread,title,f,data); 00347 } 00348 if (inputWindow) 00349 { 00350 if (inputWindow->dockWidget) 00351 inputWindow->dockWidget->show(); 00352 else 00353 inputWindow->show(); 00354 } 00355 return inputWindow; 00356 } 00357 00358 SimpleInputWindow * SimpleInputWindow::CreateWindow(MainWindow * main, const QString& title, const QString& script, const DataTable<qreal>& data) 00359 { 00360 if (script.isNull() || script.isEmpty() || title.isEmpty()) return 0; 00361 00362 SimpleInputWindow * inputWindow = 0; 00363 if (SimpleInputWindow::inputWindows.contains(title.toLower())) 00364 { 00365 inputWindow = SimpleInputWindow::inputWindows.value(title.toLower()); 00366 if (data.rowNames() != inputWindow->dataTable.rowNames() || 00367 data.columnNames() != inputWindow->dataTable.columnNames()) 00368 { 00369 inputWindow = 0; 00370 } 00371 } 00372 00373 if (!inputWindow) 00374 { 00375 inputWindow = new SimpleInputWindow(main,title,data); 00376 inputWindow->scriptCommand = script; 00377 } 00378 if (inputWindow) 00379 { 00380 if (inputWindow->dockWidget) 00381 inputWindow->dockWidget->show(); 00382 else 00383 inputWindow->show(); 00384 } 00385 return inputWindow; 00386 } 00387 00388 void SimpleInputWindow::addRow() 00389 { 00390 int r = tableWidget.rowCount(); 00391 tableWidget.setRowCount(r+1); 00392 00393 int n = r; 00394 QString name = tr("row") + QString::number(n); 00395 00396 if (dataTable.rows() > 0) 00397 { 00398 name = dataTable.rowName( dataTable.rows()-1 ); 00399 if (name.at( name.length()-1 ).isNumber()) 00400 { 00401 name.chop(1); 00402 name = name + QString::number(n); 00403 } 00404 else 00405 { 00406 name = tr("row") + QString::number(n); 00407 } 00408 } 00409 QStringList names = dataTable.rowNames(); 00410 00411 while (names.contains(name)) //find a unique row name 00412 { 00413 ++n; 00414 name.chop(1); 00415 name = name + QString::number(n); 00416 } 00417 00418 tableWidget.setVerticalHeaderItem ( r, new QTableWidgetItem(name) ); 00419 dataTable.insertRow(r,name); 00420 00421 for (int i=0; i < tableWidget.columnCount(); ++i) 00422 { 00423 if (r > 0) 00424 { 00425 if (tableWidget.item(r-1,i)) 00426 tableWidget.setItem(r,i,new QTableWidgetItem( tableWidget.item(r-1,i)->text() )); 00427 dataTable.value(r,i) = dataTable.value(r-1,i); 00428 delegate.options.value(r,i) = delegate.options.value(r-1,i); 00429 } 00430 else 00431 { 00432 tableWidget.setItem(r,i,new QTableWidgetItem("0.0")); 00433 dataTable.value(r,i) = 0.0; 00434 delegate.options.value(r,i) = QStringList(); 00435 } 00436 } 00437 } 00438 00439 void SimpleInputWindow::removeRow() 00440 { 00441 int r = tableWidget.rowCount()-1; 00442 tableWidget.removeRow(r); 00443 dataTable.removeRow(r); 00444 } 00445 00446 void SimpleInputWindow::dataChanged(int i,int j) 00447 { 00448 QString s = tableWidget.item(i,j)->text(); 00449 00450 QStringList options = delegate.options.value(i,j); 00451 00452 if (options.size() > 1 && options.contains(s)) 00453 { 00454 dataTable.value(i,j) = delegate.options.value(i,j).indexOf(s); 00455 return; 00456 } 00457 00458 if (options.size() == 1) 00459 { 00460 if (s.toLower() == QObject::tr("yes") || s.toLower() == QObject::tr("true")) 00461 dataTable.value(i,j) = 1.0; 00462 else 00463 dataTable.value(i,j) = 0.0; 00464 return; 00465 } 00466 00467 bool ok; 00468 00469 double d = s.toDouble(&ok); 00470 00471 if (ok) 00472 dataTable.value(i,j) = d; 00473 } 00474 00475 void SimpleInputWindow::setupDisplay(const DataTable<qreal>& table) 00476 { 00477 tableWidget.disconnect(); 00478 00479 dataTable = table; 00480 comboBoxes.clear(); 00481 int r = dataTable.rows(); 00482 int c = dataTable.columns(); 00483 tableWidget.clear(); 00484 tableWidget.setColumnCount(c); 00485 tableWidget.setRowCount(r); 00486 tableWidget.setVerticalHeaderLabels(dataTable.rowNames()); 00487 tableWidget.setHorizontalHeaderLabels(dataTable.columnNames()); 00488 00489 for (int i=0; i < dataTable.rows(); ++i) 00490 for (int j=0; j < dataTable.columns(); ++j) 00491 { 00492 tableWidget.setItem(i,j,new QTableWidgetItem(QString::number(dataTable.at(i,j)))); 00493 delegate.options.value(i,j) = QStringList(); 00494 } 00495 00496 connect(&tableWidget, SIGNAL(cellChanged(int,int)), this, SLOT(dataChanged(int,int))); 00497 } 00498 00499 void SimpleInputWindow::comboBoxChanged(int) 00500 { 00501 } 00502 00503 void SimpleInputWindow::enterEvent ( QEvent * event ) 00504 { 00505 AbstractInputWindow::enterEvent(event); 00506 } 00507 00508 void SimpleInputWindow::leaveEvent ( QEvent * event ) 00509 { 00510 //if (dockWidget) 00511 //dockWidget->setWindowOpacity(0.8); 00512 } 00513 00514 /************************************ 00515 ITEM DELEGATE FOR THE INPUT TABLE 00516 *************************************/ 00517 00518 PopupListWidgetDelegate::PopupListWidgetDelegate(QObject *parent) : QItemDelegate(parent) 00519 { 00520 dialogOpen = false; 00521 } 00522 00523 QString PopupListWidgetDelegate::displayListWidget(const QStringList& list, const QString& current, bool * dialogOpen) 00524 { 00525 PopupListWidgetDelegateDialog * dialog = new PopupListWidgetDelegateDialog; 00526 QListWidget * listWidget = new QListWidget; 00527 QVBoxLayout * layout = new QVBoxLayout; 00528 layout->addWidget(listWidget,1); 00529 QPushButton * okButton = new QPushButton("&Select"); 00530 connect(okButton,SIGNAL(clicked()),dialog,SLOT(accept())); 00531 connect(listWidget,SIGNAL(itemActivated(QListWidgetItem*)),dialog,SLOT(acceptListWidget(QListWidgetItem*))); 00532 layout->addWidget(okButton,0,Qt::AlignCenter); 00533 layout->setContentsMargins(0,0,0,0); 00534 dialog->setLayout(layout); 00535 00536 listWidget->addItems(list); 00537 int k = 0; 00538 if (!current.isEmpty()) 00539 { 00540 k = list.indexOf(current); 00541 if (k > -1) 00542 listWidget->setCurrentRow(k); 00543 } 00544 00545 if (dialogOpen) 00546 (*dialogOpen) = true; 00547 dialog->exec(); 00548 if (dialogOpen) 00549 (*dialogOpen) = false; 00550 QString s; 00551 00552 if (dialog->result() == QDialog::Accepted) 00553 { 00554 k = listWidget->currentRow(); 00555 if (k > -1 && k < list.size()) 00556 s = list[k]; 00557 } 00558 00559 delete dialog; 00560 return s; 00561 } 00562 00563 QWidget * PopupListWidgetDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &/* option */, const QModelIndex & index) const 00564 { 00565 QStringList strings = options.at(index.row(),index.column()); 00566 if (strings.size() > 0) 00567 { 00568 QLabel * label = new QLabel(parent); 00569 return label; 00570 } 00571 else 00572 { 00573 QLineEdit *editor = new QLineEdit(parent); 00574 return editor; 00575 } 00576 } 00577 00578 void PopupListWidgetDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const 00579 { 00580 QStringList strings = options.at(index.row(),index.column()); 00581 if (strings.size() > 0) 00582 { 00583 QLabel * label = static_cast<QLabel*>(editor); 00584 label->setText(index.model()->data(index, Qt::EditRole).toString()); 00585 } 00586 else 00587 { 00588 double value = index.model()->data(index, Qt::EditRole).toDouble(); 00589 QLineEdit * lineEdit = static_cast<QLineEdit*>(editor); 00590 lineEdit->setText(QString::number(value)); 00591 } 00592 } 00593 00594 void PopupListWidgetDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const 00595 { 00596 QStringList strings = options.at(index.row(),index.column()); 00597 if (strings.size() > 0) 00598 { 00599 QLabel * label = static_cast<QLabel*>(editor); 00600 label->setText(model->data(index).toString()); 00601 } 00602 else 00603 { 00604 QLineEdit * lineEdit = static_cast<QLineEdit*>(editor); 00605 00606 bool ok; 00607 double value = lineEdit->text().toDouble(&ok); 00608 if (ok) 00609 { 00610 model->setData(index, value, Qt::EditRole); 00611 } 00612 } 00613 } 00614 00615 bool PopupListWidgetDelegate::editorEvent ( QEvent * event, QAbstractItemModel * model, const QStyleOptionViewItem & option, const QModelIndex & index ) 00616 { 00617 QStringList strings = options.at(index.row(),index.column()); 00618 if (strings.size() > 0) 00619 { 00620 if (!dialogOpen) 00621 { 00622 QString value = displayListWidget(strings, QString(), &dialogOpen); 00623 model->setData(index, value, Qt::EditRole); 00624 } 00625 return true; 00626 } 00627 QItemDelegate::editorEvent(event, model, option, index ); 00628 } 00629 00630 void PopupListWidgetDelegate::updateEditorGeometry(QWidget *editor,const QStyleOptionViewItem &option, const QModelIndex &/* index */) const 00631 { 00632 editor->setGeometry(option.rect); 00633 } 00634 00635 }; 00636 00637