00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "TargetModels.h"
00022 #include <QtDebug>
00023 #include <QtGui>
00024
00025 #include <TargetModels.moc>
00026
00027 namespace Aseba
00028 {
00031
00032 VariableListener::VariableListener(TargetVariablesModel* variablesModel) :
00033 variablesModel(variablesModel)
00034 {
00035
00036 }
00037
00038 VariableListener::~VariableListener()
00039 {
00040 if (variablesModel)
00041 variablesModel->unsubscribeViewPlugin(this);
00042 }
00043
00044 bool VariableListener::subscribeToVariableOfInterest(const QString& name)
00045 {
00046 return variablesModel->subscribeToVariableOfInterest(this, name);
00047 }
00048
00049 void VariableListener::unsubscribeToVariableOfInterest(const QString& name)
00050 {
00051 variablesModel->unsubscribeToVariableOfInterest(this, name);
00052 }
00053
00054 void VariableListener::unsubscribeToVariablesOfInterest()
00055 {
00056 variablesModel->unsubscribeToVariablesOfInterest(this);
00057 }
00058
00059 void VariableListener::invalidateVariableModel()
00060 {
00061 variablesModel = 0;
00062 }
00063
00064
00065 TargetVariablesModel::~TargetVariablesModel()
00066 {
00067 for (VariableListenersNameMap::iterator it = variableListenersMap.begin(); it != variableListenersMap.end(); ++it)
00068 {
00069 it.key()->invalidateVariableModel();
00070 }
00071 }
00072
00073 int TargetVariablesModel::rowCount(const QModelIndex &parent) const
00074 {
00075 if (parent.isValid())
00076 {
00077 if (parent.parent().isValid() || (variables.at(parent.row()).value.size() == 1))
00078 return 0;
00079 else
00080 return variables.at(parent.row()).value.size();
00081 }
00082 else
00083 return variables.size();
00084 }
00085
00086 int TargetVariablesModel::columnCount(const QModelIndex & parent) const
00087 {
00088 return 2;
00089 }
00090
00091 QModelIndex TargetVariablesModel::index(int row, int column, const QModelIndex &parent) const
00092 {
00093 if (parent.isValid())
00094 return createIndex(row, column, parent.row());
00095 else
00096 {
00097
00098 if (row < 0 || row >= variables.length())
00099 return QModelIndex();
00100 else
00101 return createIndex(row, column, -1);
00102 }
00103 }
00104
00105 QModelIndex TargetVariablesModel::parent(const QModelIndex &index) const
00106 {
00107 if (index.isValid() && (index.internalId() != -1))
00108 return createIndex(index.internalId(), 0, -1);
00109 else
00110 return QModelIndex();
00111 }
00112
00113 QVariant TargetVariablesModel::data(const QModelIndex &index, int role) const
00114 {
00115 if (index.parent().isValid())
00116 {
00117 if (role != Qt::DisplayRole)
00118 return QVariant();
00119
00120 if (index.column() == 0)
00121 return index.row();
00122 else
00123 return variables.at(index.parent().row()).value[index.row()];
00124 }
00125 else
00126 {
00127 QString name = variables.at(index.row()).name;
00128
00129 if (name.left(1) == "_")
00130 {
00131 if (role == Qt::ForegroundRole)
00132 return QApplication::palette().color(QPalette::Disabled, QPalette::Text);
00133 else if (role == Qt::FontRole)
00134 {
00135 QFont font;
00136 font.setItalic(true);
00137 return font;
00138 }
00139 }
00140 if (index.column() == 0)
00141 {
00142 if (role == Qt::DisplayRole)
00143 return name;
00144 return QVariant();
00145 }
00146 else
00147 {
00148 if (role == Qt::DisplayRole)
00149 {
00150 if (variables.at(index.row()).value.size() == 1)
00151 return variables.at(index.row()).value[0];
00152 else
00153 return QString("(%0)").arg(variables.at(index.row()).value.size());
00154 }
00155 else if (role == Qt::ForegroundRole)
00156 {
00157 if (variables.at(index.row()).value.size() == 1)
00158 return QVariant();
00159 else
00160 return QApplication::palette().color(QPalette::Disabled, QPalette::Text);
00161 }
00162 else
00163 return QVariant();
00164 }
00165 }
00166 }
00167
00168 QVariant TargetVariablesModel::headerData(int section, Qt::Orientation orientation, int role) const
00169 {
00170
00171 Q_UNUSED(orientation)
00172 Q_UNUSED(role)
00173 if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
00174 {
00175 if (section == 0)
00176 return tr("names");
00177 else
00178 return tr("values");
00179 }
00180 return QVariant();
00181 }
00182
00183 Qt::ItemFlags TargetVariablesModel::flags(const QModelIndex &index) const
00184 {
00185 if (!index.isValid())
00186 return 0;
00187
00188 if (index.column() == 1)
00189 {
00190 if (index.parent().isValid())
00191 return Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable;
00192 else if (variables.at(index.row()).value.size() == 1)
00193 return Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable;
00194 else
00195 return 0;
00196 }
00197 else
00198 {
00199 if (index.parent().isValid())
00200 return Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsSelectable;
00201 else
00202 return Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsSelectable;
00203 }
00204 }
00205
00206 bool TargetVariablesModel::setData(const QModelIndex &index, const QVariant &value, int role)
00207 {
00208 if (index.isValid() && role == Qt::EditRole)
00209 {
00210 if (index.parent().isValid())
00211 {
00212 int variableValue;
00213 bool ok;
00214 variableValue = value.toInt(&ok);
00215 Q_ASSERT(ok);
00216
00217 variables[index.parent().row()].value[index.row()] = variableValue;
00218 emit variableValuesChanged(variables[index.parent().row()].pos + index.row(), VariablesDataVector(1, variableValue));
00219
00220 return true;
00221 }
00222 else if (variables.at(index.row()).value.size() == 1)
00223 {
00224 int variableValue;
00225 bool ok;
00226 variableValue = value.toInt(&ok);
00227 Q_ASSERT(ok);
00228
00229 variables[index.row()].value[0] = variableValue;
00230 emit variableValuesChanged(variables[index.row()].pos, VariablesDataVector(1, variableValue));
00231
00232 return true;
00233 }
00234 }
00235 return false;
00236 }
00237
00238 QStringList TargetVariablesModel::mimeTypes () const
00239 {
00240 QStringList types;
00241 types << "text/plain";
00242 return types;
00243 }
00244
00245 QMimeData * TargetVariablesModel::mimeData ( const QModelIndexList & indexes ) const
00246 {
00247 QString texts;
00248 foreach (QModelIndex index, indexes)
00249 {
00250 if (index.isValid())
00251 {
00252 const QString text = data(index, Qt::DisplayRole).toString();
00253 if (index.parent().isValid())
00254 {
00255 const QString varName = data(index.parent(), Qt::DisplayRole).toString();
00256 texts += varName + "[" + text + "]";
00257 }
00258 else
00259 texts += text;
00260 }
00261 }
00262
00263 QMimeData *mimeData = new QMimeData();
00264 mimeData->setText(texts);
00265 return mimeData;
00266 }
00267
00268 unsigned TargetVariablesModel::getVariablePos(const QString& name) const
00269 {
00270 for (int i = 0; i < variables.size(); ++i)
00271 {
00272 const Variable& variable(variables[i]);
00273 if (variable.name == name)
00274 return variable.pos;
00275 }
00276 return 0;
00277 }
00278
00279 unsigned TargetVariablesModel::getVariableSize(const QString& name) const
00280 {
00281 for (int i = 0; i < variables.size(); ++i)
00282 {
00283 const Variable& variable(variables[i]);
00284 if (variable.name == name)
00285 return variable.value.size();
00286 }
00287 return 0;
00288 }
00289
00290 VariablesDataVector TargetVariablesModel::getVariableValue(const QString& name) const
00291 {
00292 for (int i = 0; i < variables.size(); ++i)
00293 {
00294 const Variable& variable(variables[i]);
00295 if (variable.name == name)
00296 return variable.value;
00297 }
00298 return VariablesDataVector();
00299 }
00300
00301 void TargetVariablesModel::updateVariablesStructure(const Compiler::VariablesMap *variablesMap)
00302 {
00303
00304 QList<Variable> newVariables;
00305 for (Compiler::VariablesMap::const_iterator it = variablesMap->begin(); it != variablesMap->end(); ++it)
00306 {
00307
00308 Variable var;
00309 var.name = QString::fromStdWString(it->first);
00310 var.pos = it->second.first;
00311 var.value.resize(it->second.second);
00312
00313
00314 int i;
00315 for (i = 0; i < newVariables.size(); ++i)
00316 {
00317 if (var.pos < newVariables[i].pos)
00318 break;
00319 }
00320 newVariables.insert(i, var);
00321 }
00322
00323
00324 int i(0);
00325 int count(std::min(variables.length(), newVariables.length()));
00326 while (
00327 i < count &&
00328 variables[i].name == newVariables[i].name &&
00329 variables[i].pos == newVariables[i].pos &&
00330 variables[i].value.size() == newVariables[i].value.size()
00331 )
00332 ++i;
00333
00334
00335
00336 if (i != variables.length())
00337 {
00338 beginRemoveRows(QModelIndex(), i, variables.length()-1);
00339 int removeCount(variables.length() - i);
00340 for (int j = 0; j < removeCount; ++j)
00341 variables.removeLast();
00342 endRemoveRows();
00343 }
00344
00345
00346
00347 if (i != newVariables.length())
00348 {
00349 beginInsertRows(QModelIndex(), i, newVariables.length()-1);
00350 for (int j = i; j < newVariables.length(); ++j)
00351 variables.append(newVariables[j]);
00352 endInsertRows();
00353 }
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375 }
00376
00377 void TargetVariablesModel::setVariablesData(unsigned start, const VariablesDataVector &data)
00378 {
00379 size_t dataLength = data.size();
00380 for (int i = 0; i < variables.size(); ++i)
00381 {
00382 Variable &var = variables[i];
00383 int varLen = (int)var.value.size();
00384 int varStart = (int)start - (int)var.pos;
00385 int copyLen = (int)dataLength;
00386 int copyStart = 0;
00387
00388 if (varStart < 0)
00389 {
00390 copyLen += varStart;
00391 copyStart -= varStart;
00392 varStart = 0;
00393 }
00394
00395 if (copyLen <= 0)
00396 continue;
00397
00398 if (varStart + copyLen > varLen)
00399 {
00400 copyLen = varLen - varStart;
00401 }
00402
00403 if (copyLen <= 0)
00404 continue;
00405
00406
00407 copy(data.begin() + copyStart, data.begin() + copyStart + copyLen, var.value.begin() + varStart);
00408
00409
00410 QModelIndex parentIndex = index(i, 0);
00411 emit dataChanged(index(varStart, 0, parentIndex), index(varStart + copyLen, 0, parentIndex));
00412
00413
00414 for (VariableListenersNameMap::iterator it = variableListenersMap.begin(); it != variableListenersMap.end(); ++it)
00415 {
00416 QStringList &list = it.value();
00417 for (int v = 0; v < list.size(); v++)
00418 {
00419 if (list[v] == var.name)
00420 it.key()->variableValueUpdated(var.name, var.value);
00421 }
00422 }
00423 }
00424 }
00425
00426 bool TargetVariablesModel::setVariableValues(const QString& name, const VariablesDataVector& values)
00427 {
00428 for (int i = 0; i < variables.size(); ++i)
00429 {
00430 Variable& variable(variables[i]);
00431 if (variable.name == name)
00432 {
00433
00434 emit variableValuesChanged(variable.pos, values);
00435 return true;
00436 }
00437 }
00438 return false;
00439 }
00440
00441 void TargetVariablesModel::unsubscribeViewPlugin(VariableListener* listener)
00442 {
00443 variableListenersMap.remove(listener);
00444 }
00445
00446 bool TargetVariablesModel::subscribeToVariableOfInterest(VariableListener* listener, const QString& name)
00447 {
00448 QStringList &list = variableListenersMap[listener];
00449 list.push_back(name);
00450 for (int i = 0; i < variables.size(); i++)
00451 if (variables[i].name == name)
00452 return true;
00453 return false;
00454 }
00455
00456 void TargetVariablesModel::unsubscribeToVariableOfInterest(VariableListener* listener, const QString& name)
00457 {
00458 QStringList &list = variableListenersMap[listener];
00459 list.removeAll(name);
00460 }
00461
00462 void TargetVariablesModel::unsubscribeToVariablesOfInterest(VariableListener* plugin)
00463 {
00464 if (variableListenersMap.contains(plugin))
00465 variableListenersMap.remove(plugin);
00466 }
00467
00468 struct TargetFunctionsModel::TreeItem
00469 {
00470 TreeItem* parent;
00471 QList<TreeItem*> children;
00472 QString name;
00473 QString toolTip;
00474 bool enabled;
00475 bool draggable;
00476
00477 TreeItem() :
00478 parent(0),
00479 name("root"),
00480 enabled(true),
00481 draggable(false)
00482 { }
00483
00484 TreeItem(TreeItem* parent, const QString& name, bool enabled, bool draggable) :
00485 parent(parent),
00486 name(name),
00487 enabled(enabled),
00488 draggable(draggable)
00489 { }
00490
00491 TreeItem(TreeItem* parent, const QString& name, const QString& toolTip, bool enabled, bool draggable) :
00492 parent(parent),
00493 name(name),
00494 toolTip(toolTip),
00495 enabled(enabled),
00496 draggable(draggable)
00497 { }
00498
00499 ~TreeItem()
00500 {
00501 for (int i = 0; i < children.size(); i++)
00502 delete children[i];
00503 }
00504
00505 TreeItem *getEntry(const QString& name, bool enabled = true)
00506 {
00507 for (int i = 0; i < children.size(); i++)
00508 if (children[i]->name == name)
00509 return children[i];
00510
00511 children.push_back(new TreeItem(this, name, enabled, draggable));
00512 return children.last();
00513 }
00514 };
00515
00516
00517
00518 TargetFunctionsModel::TargetFunctionsModel(const TargetDescription *descriptionRead, QObject *parent) :
00519 QAbstractItemModel(parent),
00520 root(0),
00521 descriptionRead(descriptionRead),
00522 regExp("\\b")
00523 {
00524 Q_ASSERT(descriptionRead);
00525 setSupportedDragActions(Qt::CopyAction);
00526 recreateTreeFromDescription(false);
00527 }
00528
00529 TargetFunctionsModel::~TargetFunctionsModel()
00530 {
00531 delete root;
00532 }
00533
00534 TargetFunctionsModel::TreeItem *TargetFunctionsModel::getItem(const QModelIndex &index) const
00535 {
00536 if (index.isValid())
00537 {
00538 TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
00539 if (item)
00540 return item;
00541 }
00542 return root;
00543 }
00544
00545 QString TargetFunctionsModel::getToolTip(const TargetDescription::NativeFunction& function) const
00546 {
00547
00548 QString text;
00549 QSet<QString> variablesNames;
00550
00551 text += QString("<b>%1</b>(").arg(QString::fromStdWString(function.name));
00552 for (size_t i = 0; i < function.parameters.size(); i++)
00553 {
00554 QString variableName(QString::fromStdWString(function.parameters[i].name));
00555 variablesNames.insert(variableName);
00556 text += variableName;
00557 if (function.parameters[i].size > 1)
00558 text += QString("[%1]").arg(function.parameters[i].size);
00559 else if (function.parameters[i].size < 0)
00560 {
00561 text += QString("[<T%1>]").arg(-function.parameters[i].size);
00562 }
00563
00564 if (i + 1 < function.parameters.size())
00565 text += QString(", ");
00566 }
00567
00568 QString description = QString::fromStdWString(function.description);
00569 QStringList descriptionWords = description.split(regExp);
00570 for (int i = 0; i < descriptionWords.size(); ++i)
00571 if (variablesNames.contains(descriptionWords.at(i)))
00572 descriptionWords[i] = QString("<tt>%1</tt>").arg(descriptionWords[i]);
00573
00574 text += QString(")<br/>") + descriptionWords.join(" ");
00575
00576 return text;
00577 }
00578
00579 int TargetFunctionsModel::rowCount(const QModelIndex & parent) const
00580 {
00581 return getItem(parent)->children.count();
00582 }
00583
00584 int TargetFunctionsModel::columnCount(const QModelIndex & ) const
00585 {
00586 return 1;
00587 }
00588
00589 void TargetFunctionsModel::recreateTreeFromDescription(bool showHidden)
00590 {
00591 if (root)
00592 delete root;
00593 root = new TreeItem;
00594
00595 if (showHidden)
00596 root->getEntry(tr("hidden"), false);
00597
00598 for (size_t i = 0; i < descriptionRead->nativeFunctions.size(); i++)
00599 {
00600
00601 QString name = QString::fromStdWString(descriptionRead->nativeFunctions[i].name);
00602 QStringList splittedName = name.split(".", QString::SkipEmptyParts);
00603
00604
00605 if (splittedName.isEmpty())
00606 continue;
00607
00608
00609 TreeItem* entry = root;
00610 Q_ASSERT(!splittedName[0].isEmpty());
00611 if (name.at(0) == '_' || name.contains(QString("._")))
00612 {
00613 if (!showHidden)
00614 continue;
00615 entry = entry->getEntry(tr("hidden"), false);
00616 }
00617
00618 for (int j = 0; j < splittedName.size() - 1; ++j)
00619 entry = entry->getEntry(splittedName[j], entry->enabled);
00620
00621
00622 entry->children.push_back(new TreeItem(entry, name, getToolTip(descriptionRead->nativeFunctions[i]), entry->enabled, true));
00623 }
00624
00625 reset();
00626 }
00627
00628 QModelIndex TargetFunctionsModel::parent(const QModelIndex &index) const
00629 {
00630 if (!index.isValid())
00631 return QModelIndex();
00632
00633 TreeItem *childItem = getItem(index);
00634 TreeItem *parentItem = childItem->parent;
00635
00636 if (parentItem == root)
00637 return QModelIndex();
00638
00639 if (parentItem->parent)
00640 return createIndex(parentItem->parent->children.indexOf(const_cast<TreeItem*>(parentItem)), 0, parentItem);
00641 else
00642 return createIndex(0, 0, parentItem);
00643 }
00644
00645 QModelIndex TargetFunctionsModel::index(int row, int column, const QModelIndex &parent) const
00646 {
00647 TreeItem *parentItem = getItem(parent);
00648 TreeItem *childItem = parentItem->children.value(row);
00649 Q_ASSERT(childItem);
00650
00651 if (childItem)
00652 return createIndex(row, column, childItem);
00653 else
00654 return QModelIndex();
00655 }
00656
00657 QVariant TargetFunctionsModel::data(const QModelIndex &index, int role) const
00658 {
00659 if (!index.isValid() ||
00660 (role != Qt::DisplayRole && role != Qt::ToolTipRole && role != Qt::WhatsThisRole))
00661 return QVariant();
00662
00663 if (role == Qt::DisplayRole)
00664 {
00665 return getItem(index)->name;
00666 }
00667 else
00668 {
00669 return getItem(index)->toolTip;
00670 }
00671 }
00672
00673 QVariant TargetFunctionsModel::headerData(int section, Qt::Orientation orientation, int role) const
00674 {
00675 Q_UNUSED(section)
00676 Q_UNUSED(orientation)
00677 Q_UNUSED(role)
00678 return QVariant();
00679 }
00680
00681 Qt::ItemFlags TargetFunctionsModel::flags(const QModelIndex & index) const
00682 {
00683 TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
00684 if (item)
00685 {
00686 QFlags<Qt::ItemFlag> flags;
00687 flags |= item->enabled ? Qt::ItemIsEnabled : QFlags<Qt::ItemFlag>();
00688 flags |= item->draggable ? Qt::ItemIsDragEnabled | Qt::ItemIsSelectable : QFlags<Qt::ItemFlag>();
00689 return flags;
00690 }
00691 else
00692 return Qt::ItemIsEnabled;
00693 }
00694
00695 QStringList TargetFunctionsModel::mimeTypes () const
00696 {
00697 QStringList types;
00698 types << "text/plain";
00699 return types;
00700 }
00701
00702 QMimeData * TargetFunctionsModel::mimeData ( const QModelIndexList & indexes ) const
00703 {
00704 QString texts;
00705 foreach (QModelIndex index, indexes)
00706 {
00707 if (index.isValid())
00708 {
00709 QString text = data(index, Qt::DisplayRole).toString();
00710 texts += text;
00711 }
00712 }
00713
00714 QMimeData *mimeData = new QMimeData();
00715 mimeData->setText(texts);
00716 return mimeData;
00717 }
00718
00719
00721 };