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