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 QMetaType::Float:
32 case QVariant::Double:
40 isVariantStringArray(const QVariant &var)
42 if (var.isNull() || var.userType() != QMetaType::type("ApiArray"))
45 ApiArray array = var.value<ApiArray>();
46 QVector<QVariant> origValues = array.values();
47 if (origValues.isEmpty() ||
48 origValues.first().userType() != QVariant::String)
54 ArgumentsItemEditorFactory::ArgumentsItemEditorFactory()
55 : QItemEditorFactory()
59 QWidget * ArgumentsItemEditorFactory::createEditor(QMetaType::Type type,
60 QWidget *parent) const
63 case QVariant::Bool: {
64 BooleanComboBox *cb = new BooleanComboBox(parent);
68 case QVariant::UInt: {
69 QSpinBox *sb = new QSpinBox(parent);
71 sb->setMaximum(INT_MAX);
74 QSpinBox *sb = new QSpinBox(parent);
76 sb->setMinimum(INT_MIN);
77 sb->setMaximum(INT_MAX);
80 case QVariant::ULongLong: {
81 QSpinBox *sb = new QSpinBox(parent);
83 sb->setMaximum(INT_MAX);
85 case QVariant::LongLong: {
86 QSpinBox *sb = new QSpinBox(parent);
88 sb->setMinimum(INT_MIN);
89 sb->setMaximum(INT_MAX);
92 case QVariant::Pixmap:
93 return new QLabel(parent);
94 case QMetaType::Float: {
95 QDoubleSpinBox *sb = new QDoubleSpinBox(parent);
97 sb->setMinimum(-FLT_MAX);
98 sb->setMaximum(FLT_MAX);
102 case QVariant::Double: {
103 QDoubleSpinBox *sb = new QDoubleSpinBox(parent);
105 sb->setMinimum(-DBL_MAX);
106 sb->setMaximum(DBL_MAX);
117 ArgumentsItemEditorFactory::valuePropertyName(QMetaType::Type type) const
121 return "currentIndex";
124 case QVariant::LongLong:
125 case QVariant::ULongLong:
126 case QMetaType::Float:
127 case QVariant::Double:
130 case QVariant::String:
137 BooleanComboBox::BooleanComboBox(QWidget *parent)
140 addItem(tr("False"));
144 void BooleanComboBox::setValue(bool value)
146 setCurrentIndex(value ? 1 : 0);
149 bool BooleanComboBox::value() const
151 return (currentIndex() == 1);
154 ArgumentsEditor::ArgumentsEditor(QWidget *parent)
156 m_model(new QStandardItemModel()),
162 ArgumentsEditor::~ArgumentsEditor()
167 void ArgumentsEditor::setCall(ApiTraceCall *call)
173 ApiTraceCall * ArgumentsEditor::call() const
178 void ArgumentsEditor::init()
182 connect(m_ui.selectStringCB, SIGNAL(currentIndexChanged(int)),
183 SLOT(currentSourceChanged(int)));
184 connect(m_ui.glslEdit, SIGNAL(textChanged()),
185 SLOT(sourceChanged()));
186 connect(m_ui.revertButton, SIGNAL(clicked()),
189 m_ui.argsTree->setModel(m_model);
190 QItemEditorFactory *factory =
191 new ArgumentsItemEditorFactory();
193 QItemEditorFactory::setDefaultFactory(factory);
196 void ArgumentsEditor::setupCall()
201 headers.append(tr("Argument"));
202 headers.append(tr("Value"));
203 m_model->setColumnCount(2);
204 m_model->setHorizontalHeaderLabels(headers);
205 m_ui.argsTabWidget->removeTab(
206 m_ui.argsTabWidget->indexOf(m_ui.shaderTab));
211 m_ui.callLabel->setText(m_call->name());
212 QStandardItem *rootItem = m_model->invisibleRootItem();
213 for (int i = 0; i < m_call->argNames().count(); ++i) {
214 QString argName = m_call->argNames()[i];
215 QVariant val = m_call->arguments()[i];
216 QStandardItem *nameItem = new QStandardItem(argName);
217 nameItem->setFlags(nameItem->flags() ^ Qt::ItemIsEditable);
218 QList<QStandardItem*> topRow;
219 topRow.append(nameItem);
221 if (val.canConvert<ApiArray>()) {
222 ApiArray array = val.value<ApiArray>();
223 QVector<QVariant> vals = array.values();
225 QVariant firstVal = vals.value(0);
226 if (firstVal.userType() == QVariant::String) {
227 m_ui.argsTabWidget->addTab(
228 m_ui.shaderTab, argName);
229 setupShaderEditor(vals);
232 } else if (isVariantEditable(firstVal)) {
233 for (int i = 0; i < vals.count(); ++i) {
234 QList<QStandardItem*> row;
236 QStandardItem *idx = new QStandardItem();
237 idx->setFlags(idx->flags() ^ Qt::ItemIsEditable);
238 idx->setText(tr("%1)").arg(i));
240 QStandardItem *col = new QStandardItem();
241 col->setFlags(col->flags() | Qt::ItemIsEditable);
242 col->setData(vals[i], Qt::DisplayRole);
245 nameItem->appendRow(row);
248 qDebug()<<"\tUnsupported array = "<<firstVal;
252 } else if (val.canConvert<ApiPointer>()) {
253 ApiPointer ptr = val.value<ApiPointer>();
254 QStandardItem *item = new QStandardItem();
255 item->setFlags(item->flags() ^ Qt::ItemIsEditable);
256 item->setText(ptr.toString());
257 QIcon icon(":/resources/emblem-locked.png");
259 item->setToolTip(tr("Argument is read-only"));
261 } else if (val.canConvert<ApiEnum>()) {
262 ApiEnum en = val.value<ApiEnum>();
263 QStandardItem *item = new QStandardItem();
264 item->setFlags(item->flags() ^ Qt::ItemIsEditable);
265 item->setText(en.toString());
266 QIcon icon(":/resources/emblem-locked.png");
268 item->setToolTip(tr("Argument is read-only"));
270 } else if (val.canConvert<ApiBitmask>()) {
271 ApiBitmask mask = val.value<ApiBitmask>();
272 QStandardItem *item = new QStandardItem();
273 item->setFlags(item->flags() ^ Qt::ItemIsEditable);
274 item->setText(mask.toString());
275 QIcon icon(":/resources/emblem-locked.png");
277 item->setToolTip(tr("Argument is read-only"));
279 } else if (val.canConvert<ApiStruct>()) {
280 ApiStruct str = val.value<ApiStruct>();
281 QStandardItem *item = new QStandardItem();
282 item->setFlags(item->flags() ^ Qt::ItemIsEditable);
283 item->setText(str.toString());
284 QIcon icon(":/resources/emblem-locked.png");
286 item->setToolTip(tr("Argument is read-only"));
288 } else if (val.userType() == QVariant::ByteArray) {
289 QByteArray ba = val.value<QByteArray>();
290 QStandardItem *item = new QStandardItem();
291 item->setFlags(item->flags() ^ Qt::ItemIsEditable);
293 tr("<binary data, size = %1 bytes>").arg(ba.size()));
294 QIcon icon(":/resources/emblem-locked.png");
296 item->setToolTip(tr("Argument is read-only"));
300 = new QStandardItem();
302 if (isVariantEditable(val)) {
303 item->setFlags(item->flags() | Qt::ItemIsEditable);
305 QIcon icon(":/resources/emblem-locked.png");
307 item->setFlags(item->flags() ^ Qt::ItemIsEditable);
308 item->setToolTip(tr("Argument is read-only"));
310 item->setData(val, Qt::DisplayRole);
313 rootItem->appendRow(topRow);
317 void ArgumentsEditor::setupShaderEditor(const QVector<QVariant> &sources)
319 m_ui.selectStringCB->clear();
320 m_ui.glslEdit->clear();
321 for (int i = 0; i < sources.count(); ++i) {
322 m_ui.selectStringCB->addItem(
323 tr("Shader string: %1").arg(i),
326 m_ui.selectStringCB->setCurrentIndex(0);
329 void ArgumentsEditor::currentSourceChanged(int idx)
331 QVariant source = m_ui.selectStringCB->itemData(idx);
332 QString str = source.toString();
333 m_ui.glslEdit->setPlainText(source.toString());
334 m_ui.lengthLabel->setText(
335 tr("%1").arg(str.length()));
338 void ArgumentsEditor::sourceChanged()
340 QString str = m_ui.glslEdit->toPlainText();
341 m_ui.lengthLabel->setText(
342 tr("%1").arg(str.length()));
344 m_ui.selectStringCB->setItemData(
345 m_ui.selectStringCB->currentIndex(),
349 void ArgumentsEditor::accept()
351 QStringList argNames = m_call->argNames();
352 QVector<QVariant> originalValues = m_call->arguments();
353 QVector<QVariant> newValues;
354 bool changed = false;
355 for (int i = 0; i < argNames.count(); ++i) {
356 bool valChanged = false;
357 QString argName = argNames[i];
358 QVariant argValue = originalValues[i];
359 QVariant editorValue = valueForName(argName, argValue, &valChanged);
361 newValues.append(editorValue);
363 qDebug()<<"Arg = "<<argName;
364 qDebug()<<"\toriginal = "<<argValue;
365 qDebug()<<"\teditor = "<<editorValue;
366 qDebug()<<"\tchanged = "<<valChanged;
372 m_call->setEditedValues(newValues);
376 QVariant ArgumentsEditor::valueForName(const QString &name,
377 const QVariant &originalValue,
384 //Handle string arrays specially
385 if (isVariantStringArray(originalValue)) {
386 ApiArray array = originalValue.value<ApiArray>();
387 return arrayFromEditor(array, changed);
390 if (!isVariantEditable(originalValue)) {
391 return originalValue;
394 for (int topRow = 0; topRow < m_model->rowCount(); ++topRow) {
395 QModelIndex nameIdx = m_model->index(topRow, 0, QModelIndex());
396 QString argName = nameIdx.data().toString();
397 /* we display shaders in a separate widget so
398 * the ordering might be different */
399 if (argName == name) {
400 if (originalValue.userType() == QMetaType::type("ApiArray")) {
401 ApiArray array = originalValue.value<ApiArray>();
402 val = arrayFromIndex(nameIdx, array, changed);
404 QModelIndex valIdx = m_model->index(topRow, 1, QModelIndex());
406 if (val != originalValue)
414 QVariant ArgumentsEditor::arrayFromIndex(const QModelIndex &parentIndex,
415 const ApiArray &origArray,
418 QVector<QVariant> origValues = origArray.values();
422 if (origValues.isEmpty())
423 return QVariant::fromValue(ApiArray());
425 QVector<QVariant> lst;
426 for (int i = 0; i < origValues.count(); ++i) {
427 QModelIndex valIdx = m_model->index(i, 1, parentIndex);
428 QVariant var = valIdx.data();
429 QVariant origValue = origValues[i];
430 if (var != origValue)
432 //qDebug()<<"\t\tarray "<<i<<") "<<var;
435 return QVariant::fromValue(ApiArray(lst));
438 QVariant ArgumentsEditor::arrayFromEditor(const ApiArray &origArray,
441 QVector<QVariant> vals;
442 QVector<QVariant> origValues = origArray.values();
444 Q_ASSERT(isVariantStringArray(QVariant::fromValue(origArray)));
447 for (int i = 0; i < m_ui.selectStringCB->count(); ++i) {
448 QVariant val = m_ui.selectStringCB->itemData(i);
449 QVariant origValue = origValues[i];
450 if (origValue != val)
454 return QVariant::fromValue(ApiArray(vals));
457 void ArgumentsEditor::revert()
463 #include "argumentseditor.moc"