1 #include "argumentseditor.h"
3 #include "apitracecall.h"
6 #include <QDoubleSpinBox>
7 #include <QItemEditorFactory>
15 isVariantEditable(const QVariant &var)
17 if (var.canConvert<ApiArray>()) {
18 ApiArray array = var.value<ApiArray>();
19 QVector<QVariant> vals = array.values();
23 return isVariantEditable(vals.first());
25 switch (var.userType()) {
29 case QVariant::LongLong:
30 case QVariant::ULongLong:
31 case QVariant::Double:
39 isVariantStringArray(const QVariant &var)
41 if (var.isNull() || var.userType() != QMetaType::type("ApiArray"))
44 ApiArray array = var.value<ApiArray>();
45 QVector<QVariant> origValues = array.values();
46 if (origValues.isEmpty() ||
47 origValues.first().userType() != QVariant::String)
53 ArgumentsItemEditorFactory::ArgumentsItemEditorFactory()
54 : QItemEditorFactory()
58 QWidget * ArgumentsItemEditorFactory::createEditor(QVariant::Type type,
59 QWidget *parent) const
62 case QVariant::Bool: {
63 BooleanComboBox *cb = new BooleanComboBox(parent);
67 case QVariant::UInt: {
68 QSpinBox *sb = new QSpinBox(parent);
70 sb->setMaximum(INT_MAX);
73 QSpinBox *sb = new QSpinBox(parent);
75 sb->setMinimum(INT_MIN);
76 sb->setMaximum(INT_MAX);
79 case QVariant::ULongLong: {
80 QSpinBox *sb = new QSpinBox(parent);
82 sb->setMaximum(INT_MAX);
84 case QVariant::LongLong: {
85 QSpinBox *sb = new QSpinBox(parent);
87 sb->setMinimum(INT_MIN);
88 sb->setMaximum(INT_MAX);
91 case QVariant::Pixmap:
92 return new QLabel(parent);
93 case QVariant::Double: {
94 QDoubleSpinBox *sb = new QDoubleSpinBox(parent);
96 sb->setMinimum(-DBL_MAX);
97 sb->setMaximum(DBL_MAX);
108 ArgumentsItemEditorFactory::valuePropertyName(QVariant::Type type) const
112 return "currentIndex";
115 case QVariant::LongLong:
116 case QVariant::ULongLong:
117 case QVariant::Double:
120 case QVariant::String:
127 BooleanComboBox::BooleanComboBox(QWidget *parent)
130 addItem(tr("False"));
134 void BooleanComboBox::setValue(bool value)
136 setCurrentIndex(value ? 1 : 0);
139 bool BooleanComboBox::value() const
141 return (currentIndex() == 1);
144 ArgumentsEditor::ArgumentsEditor(QWidget *parent)
146 m_model(new QStandardItemModel()),
152 ArgumentsEditor::~ArgumentsEditor()
157 void ArgumentsEditor::setCall(ApiTraceCall *call)
163 ApiTraceCall * ArgumentsEditor::call() const
168 void ArgumentsEditor::init()
172 connect(m_ui.selectStringCB, SIGNAL(currentIndexChanged(int)),
173 SLOT(currentSourceChanged(int)));
174 connect(m_ui.glslEdit, SIGNAL(textChanged()),
175 SLOT(sourceChanged()));
176 connect(m_ui.revertButton, SIGNAL(clicked()),
179 m_ui.argsTree->setModel(m_model);
180 QItemEditorFactory *factory =
181 new ArgumentsItemEditorFactory();
183 QItemEditorFactory::setDefaultFactory(factory);
186 void ArgumentsEditor::setupCall()
191 headers.append(tr("Argument"));
192 headers.append(tr("Value"));
193 m_model->setColumnCount(2);
194 m_model->setHorizontalHeaderLabels(headers);
195 m_ui.argsTabWidget->removeTab(
196 m_ui.argsTabWidget->indexOf(m_ui.shaderTab));
201 m_ui.callLabel->setText(m_call->name());
202 QStandardItem *rootItem = m_model->invisibleRootItem();
203 for (int i = 0; i < m_call->argNames().count(); ++i) {
204 QString argName = m_call->argNames()[i];
205 QVariant val = m_call->arguments()[i];
206 QStandardItem *nameItem = new QStandardItem(argName);
207 nameItem->setFlags(nameItem->flags() ^ Qt::ItemIsEditable);
208 QList<QStandardItem*> topRow;
209 topRow.append(nameItem);
211 if (val.canConvert<ApiArray>()) {
212 ApiArray array = val.value<ApiArray>();
213 QVector<QVariant> vals = array.values();
215 QVariant firstVal = vals.value(0);
216 if (firstVal.userType() == QVariant::String) {
217 m_ui.argsTabWidget->addTab(
218 m_ui.shaderTab, argName);
219 setupShaderEditor(vals);
222 } else if (isVariantEditable(firstVal)) {
223 for (int i = 0; i < vals.count(); ++i) {
224 QList<QStandardItem*> row;
226 QStandardItem *idx = new QStandardItem();
227 idx->setFlags(idx->flags() ^ Qt::ItemIsEditable);
228 idx->setText(tr("%1)").arg(i));
230 QStandardItem *col = new QStandardItem();
231 col->setFlags(col->flags() | Qt::ItemIsEditable);
232 col->setData(vals[i], Qt::DisplayRole);
235 nameItem->appendRow(row);
238 qDebug()<<"\tUnsupported array = "<<firstVal;
242 } else if (val.canConvert<ApiPointer>()) {
243 ApiPointer ptr = val.value<ApiPointer>();
244 QStandardItem *item = new QStandardItem();
245 item->setFlags(item->flags() ^ Qt::ItemIsEditable);
246 item->setText(ptr.toString());
247 QIcon icon(":/resources/emblem-locked.png");
249 item->setToolTip(tr("Argument is read-only"));
251 } else if (val.canConvert<ApiEnum>()) {
252 ApiEnum en = val.value<ApiEnum>();
253 QStandardItem *item = new QStandardItem();
254 item->setFlags(item->flags() ^ Qt::ItemIsEditable);
255 item->setText(en.toString());
256 QIcon icon(":/resources/emblem-locked.png");
258 item->setToolTip(tr("Argument is read-only"));
260 } else if (val.canConvert<ApiBitmask>()) {
261 ApiBitmask mask = val.value<ApiBitmask>();
262 QStandardItem *item = new QStandardItem();
263 item->setFlags(item->flags() ^ Qt::ItemIsEditable);
264 item->setText(mask.toString());
265 QIcon icon(":/resources/emblem-locked.png");
267 item->setToolTip(tr("Argument is read-only"));
269 } else if (val.canConvert<ApiStruct>()) {
270 ApiStruct str = val.value<ApiStruct>();
271 QStandardItem *item = new QStandardItem();
272 item->setFlags(item->flags() ^ Qt::ItemIsEditable);
273 item->setText(str.toString());
274 QIcon icon(":/resources/emblem-locked.png");
276 item->setToolTip(tr("Argument is read-only"));
278 } else if (val.userType() == QVariant::ByteArray) {
279 QByteArray ba = val.value<QByteArray>();
280 QStandardItem *item = new QStandardItem();
281 item->setFlags(item->flags() ^ Qt::ItemIsEditable);
283 tr("<binary data, size = %1 bytes>").arg(ba.size()));
284 QIcon icon(":/resources/emblem-locked.png");
286 item->setToolTip(tr("Argument is read-only"));
290 = new QStandardItem();
292 if (isVariantEditable(val)) {
293 item->setFlags(item->flags() | Qt::ItemIsEditable);
295 QIcon icon(":/resources/emblem-locked.png");
297 item->setFlags(item->flags() ^ Qt::ItemIsEditable);
298 item->setToolTip(tr("Argument is read-only"));
300 item->setData(val, Qt::DisplayRole);
303 rootItem->appendRow(topRow);
307 void ArgumentsEditor::setupShaderEditor(const QVector<QVariant> &sources)
309 m_ui.selectStringCB->clear();
310 m_ui.glslEdit->clear();
311 for (int i = 0; i < sources.count(); ++i) {
312 m_ui.selectStringCB->addItem(
313 tr("Shader string: %1").arg(i),
316 m_ui.selectStringCB->setCurrentIndex(0);
319 void ArgumentsEditor::currentSourceChanged(int idx)
321 QVariant source = m_ui.selectStringCB->itemData(idx);
322 QString str = source.toString();
323 m_ui.glslEdit->setPlainText(source.toString());
324 m_ui.lengthLabel->setText(
325 tr("%1").arg(str.length()));
328 void ArgumentsEditor::sourceChanged()
330 QString str = m_ui.glslEdit->toPlainText();
331 m_ui.lengthLabel->setText(
332 tr("%1").arg(str.length()));
334 m_ui.selectStringCB->setItemData(
335 m_ui.selectStringCB->currentIndex(),
339 void ArgumentsEditor::accept()
341 QStringList argNames = m_call->argNames();
342 QVector<QVariant> originalValues = m_call->arguments();
343 QVector<QVariant> newValues;
344 bool changed = false;
345 for (int i = 0; i < argNames.count(); ++i) {
346 bool valChanged = false;
347 QString argName = argNames[i];
348 QVariant argValue = originalValues[i];
349 QVariant editorValue = valueForName(argName, argValue, &valChanged);
351 newValues.append(editorValue);
353 qDebug()<<"Arg = "<<argName;
354 qDebug()<<"\toriginal = "<<argValue;
355 qDebug()<<"\teditor = "<<editorValue;
356 qDebug()<<"\tchanged = "<<valChanged;
362 m_call->setEditedValues(newValues);
366 QVariant ArgumentsEditor::valueForName(const QString &name,
367 const QVariant &originalValue,
374 //Handle string arrays specially
375 if (isVariantStringArray(originalValue)) {
376 ApiArray array = originalValue.value<ApiArray>();
377 return arrayFromEditor(array, changed);
380 if (!isVariantEditable(originalValue)) {
381 return originalValue;
384 for (int topRow = 0; topRow < m_model->rowCount(); ++topRow) {
385 QModelIndex nameIdx = m_model->index(topRow, 0, QModelIndex());
386 QString argName = nameIdx.data().toString();
387 /* we display shaders in a separate widget so
388 * the ordering might be different */
389 if (argName == name) {
390 if (originalValue.userType() == QMetaType::type("ApiArray")) {
391 ApiArray array = originalValue.value<ApiArray>();
392 val = arrayFromIndex(nameIdx, array, changed);
394 QModelIndex valIdx = m_model->index(topRow, 1, QModelIndex());
396 if (val != originalValue)
404 QVariant ArgumentsEditor::arrayFromIndex(const QModelIndex &parentIndex,
405 const ApiArray &origArray,
408 QVector<QVariant> origValues = origArray.values();
412 if (origValues.isEmpty())
413 return QVariant::fromValue(ApiArray());
415 QVector<QVariant> lst;
416 for (int i = 0; i < origValues.count(); ++i) {
417 QModelIndex valIdx = m_model->index(i, 1, parentIndex);
418 QVariant var = valIdx.data();
419 QVariant origValue = origValues[i];
420 if (var != origValue)
422 //qDebug()<<"\t\tarray "<<i<<") "<<var;
425 return QVariant::fromValue(ApiArray(lst));
428 QVariant ArgumentsEditor::arrayFromEditor(const ApiArray &origArray,
431 QVector<QVariant> vals;
432 QVector<QVariant> origValues = origArray.values();
434 Q_ASSERT(isVariantStringArray(QVariant::fromValue(origArray)));
437 for (int i = 0; i < m_ui.selectStringCB->count(); ++i) {
438 QVariant val = m_ui.selectStringCB->itemData(i);
439 QVariant origValue = origValues[i];
440 if (origValue != val)
444 return QVariant::fromValue(ApiArray(vals));
447 void ArgumentsEditor::revert()
453 #include "argumentseditor.moc"