1 #include "argumentseditor.h"
3 #include "apitracecall.h"
6 #include <QDoubleSpinBox>
7 #include <QItemEditorFactory>
15 isVariantEditable(const QVariant &var)
17 switch (var.userType()) {
21 case QVariant::LongLong:
22 case QVariant::ULongLong:
23 case QVariant::Double:
31 isVariantStringArray(const QVariant &var)
33 if (var.isNull() || var.userType() != QMetaType::type("ApiArray"))
36 ApiArray array = var.value<ApiArray>();
37 QList<QVariant> origValues = array.values();
38 if (origValues.isEmpty() ||
39 origValues.first().userType() != QVariant::String)
45 ArgumentsItemEditorFactory::ArgumentsItemEditorFactory()
46 : QItemEditorFactory()
50 QWidget * ArgumentsItemEditorFactory::createEditor(QVariant::Type type,
51 QWidget *parent) const
54 case QVariant::Bool: {
55 BooleanComboBox *cb = new BooleanComboBox(parent);
59 case QVariant::UInt: {
60 QSpinBox *sb = new QSpinBox(parent);
62 sb->setMaximum(INT_MAX);
65 QSpinBox *sb = new QSpinBox(parent);
67 sb->setMinimum(INT_MIN);
68 sb->setMaximum(INT_MAX);
71 case QVariant::ULongLong: {
72 QSpinBox *sb = new QSpinBox(parent);
74 sb->setMaximum(INT_MAX);
76 case QVariant::LongLong: {
77 QSpinBox *sb = new QSpinBox(parent);
79 sb->setMinimum(INT_MIN);
80 sb->setMaximum(INT_MAX);
83 case QVariant::Pixmap:
84 return new QLabel(parent);
85 case QVariant::Double: {
86 QDoubleSpinBox *sb = new QDoubleSpinBox(parent);
88 sb->setMinimum(-DBL_MAX);
89 sb->setMaximum(DBL_MAX);
100 ArgumentsItemEditorFactory::valuePropertyName(QVariant::Type type) const
104 return "currentIndex";
107 case QVariant::LongLong:
108 case QVariant::ULongLong:
109 case QVariant::Double:
112 case QVariant::String:
119 BooleanComboBox::BooleanComboBox(QWidget *parent)
122 addItem(tr("False"));
126 void BooleanComboBox::setValue(bool value)
128 setCurrentIndex(value ? 1 : 0);
131 bool BooleanComboBox::value() const
133 return (currentIndex() == 1);
136 ArgumentsEditor::ArgumentsEditor(QWidget *parent)
138 m_model(new QStandardItemModel()),
144 ArgumentsEditor::~ArgumentsEditor()
149 void ArgumentsEditor::setCall(ApiTraceCall *call)
155 ApiTraceCall * ArgumentsEditor::call() const
160 void ArgumentsEditor::init()
164 connect(m_ui.selectStringCB, SIGNAL(currentIndexChanged(int)),
165 SLOT(currentSourceChanged(int)));
166 connect(m_ui.glslEdit, SIGNAL(textChanged()),
167 SLOT(sourceChanged()));
168 connect(m_ui.revertButton, SIGNAL(clicked()),
171 m_ui.argsTree->setModel(m_model);
172 QItemEditorFactory *factory =
173 new ArgumentsItemEditorFactory();
175 QItemEditorFactory::setDefaultFactory(factory);
178 void ArgumentsEditor::setupCall()
183 headers.append(tr("Argument"));
184 headers.append(tr("Value"));
185 m_model->setColumnCount(2);
186 m_model->setHorizontalHeaderLabels(headers);
187 m_ui.argsTabWidget->removeTab(
188 m_ui.argsTabWidget->indexOf(m_ui.shaderTab));
193 m_ui.callLabel->setText(m_call->name());
194 QStandardItem *rootItem = m_model->invisibleRootItem();
195 for (int i = 0; i < m_call->argNames().count(); ++i) {
196 QString argName = m_call->argNames()[i];
197 QVariant val = m_call->arguments()[i];
198 QStandardItem *nameItem = new QStandardItem(argName);
199 nameItem->setFlags(nameItem->flags() ^ Qt::ItemIsEditable);
200 QList<QStandardItem*> topRow;
201 topRow.append(nameItem);
203 if (val.canConvert<ApiArray>()) {
204 ApiArray array = val.value<ApiArray>();
205 QList<QVariant> vals = array.values();
207 QVariant firstVal = vals.value(0);
208 if (firstVal.userType() == QVariant::String) {
209 m_ui.argsTabWidget->addTab(
210 m_ui.shaderTab, argName);
211 setupShaderEditor(vals);
214 } else if (isVariantEditable(firstVal)) {
215 for (int i = 0; i < vals.count(); ++i) {
216 QList<QStandardItem*> row;
218 QStandardItem *idx = new QStandardItem();
219 idx->setFlags(idx->flags() ^ Qt::ItemIsEditable);
220 idx->setText(tr("%1)").arg(i));
222 QStandardItem *col = new QStandardItem();
223 col->setFlags(col->flags() | Qt::ItemIsEditable);
224 col->setData(vals[i], Qt::DisplayRole);
227 nameItem->appendRow(row);
230 qDebug()<<"\tUnsupported array = "<<firstVal;
234 } else if (val.canConvert<ApiPointer>()) {
235 ApiPointer ptr = val.value<ApiPointer>();
236 QStandardItem *item = new QStandardItem();
237 item->setFlags(item->flags() ^ Qt::ItemIsEditable);
238 item->setText(ptr.toString());
239 QIcon icon(":/resources/emblem-locked.png");
241 item->setToolTip(tr("Argument is read-only"));
243 } else if (val.canConvert<ApiEnum>()) {
244 ApiEnum en = val.value<ApiEnum>();
245 QStandardItem *item = new QStandardItem();
246 item->setFlags(item->flags() ^ Qt::ItemIsEditable);
247 item->setText(en.toString());
248 QIcon icon(":/resources/emblem-locked.png");
250 item->setToolTip(tr("Argument is read-only"));
252 } else if (val.canConvert<ApiBitmask>()) {
253 ApiBitmask mask = val.value<ApiBitmask>();
254 QStandardItem *item = new QStandardItem();
255 item->setFlags(item->flags() ^ Qt::ItemIsEditable);
256 item->setText(mask.toString());
257 QIcon icon(":/resources/emblem-locked.png");
259 item->setToolTip(tr("Argument is read-only"));
261 } else if (val.canConvert<ApiStruct>()) {
262 ApiStruct str = val.value<ApiStruct>();
263 QStandardItem *item = new QStandardItem();
264 item->setFlags(item->flags() ^ Qt::ItemIsEditable);
265 item->setText(str.toString());
266 QIcon icon(":/resources/emblem-locked.png");
268 item->setToolTip(tr("Argument is read-only"));
270 } else if (val.userType() == QVariant::ByteArray) {
271 QByteArray ba = val.value<QByteArray>();
272 QStandardItem *item = new QStandardItem();
273 item->setFlags(item->flags() ^ Qt::ItemIsEditable);
275 tr("<binary data, size = %1 bytes>").arg(ba.size()));
276 QIcon icon(":/resources/emblem-locked.png");
278 item->setToolTip(tr("Argument is read-only"));
282 = new QStandardItem();
284 if (isVariantEditable(val)) {
285 item->setFlags(item->flags() | Qt::ItemIsEditable);
287 QIcon icon(":/resources/emblem-locked.png");
289 item->setFlags(item->flags() ^ Qt::ItemIsEditable);
290 item->setToolTip(tr("Argument is read-only"));
292 item->setData(val, Qt::DisplayRole);
295 rootItem->appendRow(topRow);
299 void ArgumentsEditor::setupShaderEditor(const QList<QVariant> &sources)
301 m_ui.selectStringCB->clear();
302 m_ui.glslEdit->clear();
303 for (int i = 0; i < sources.count(); ++i) {
304 m_ui.selectStringCB->addItem(
305 tr("Shader string: %1").arg(i),
308 m_ui.selectStringCB->setCurrentIndex(0);
311 void ArgumentsEditor::currentSourceChanged(int idx)
313 QVariant source = m_ui.selectStringCB->itemData(idx);
314 QString str = source.toString();
315 m_ui.glslEdit->setPlainText(source.toString());
316 m_ui.lengthLabel->setText(
317 tr("%1").arg(str.length()));
320 void ArgumentsEditor::sourceChanged()
322 QString str = m_ui.glslEdit->toPlainText();
323 m_ui.lengthLabel->setText(
324 tr("%1").arg(str.length()));
326 m_ui.selectStringCB->setItemData(
327 m_ui.selectStringCB->currentIndex(),
331 void ArgumentsEditor::accept()
333 QStringList argNames = m_call->argNames();
334 QList<QVariant> originalValues = m_call->arguments();
335 QList<QVariant> newValues;
336 bool changed = false;
337 for (int i = 0; i < argNames.count(); ++i) {
338 bool valChanged = false;
339 QString argName = argNames[i];
340 QVariant argValue = originalValues[i];
341 QVariant editorValue = valueForName(argName, argValue, &valChanged);
342 newValues.append(editorValue);
344 qDebug()<<"Arg = "<<argName;
345 qDebug()<<"\toriginal = "<<argValue;
346 qDebug()<<"\teditor = "<<editorValue;
347 qDebug()<<"\tchanged = "<<valChanged;
353 m_call->setEditedValues(newValues);
357 QVariant ArgumentsEditor::valueForName(const QString &name,
358 const QVariant &originalValue,
365 //Handle string arrays specially
366 if (isVariantStringArray(originalValue)) {
367 ApiArray array = originalValue.value<ApiArray>();
368 return arrayFromEditor(array, changed);
371 for (int topRow = 0; topRow < m_model->rowCount(); ++topRow) {
372 QModelIndex nameIdx = m_model->index(topRow, 0, QModelIndex());
373 QString argName = nameIdx.data().toString();
374 /* we display shaders in a separate widget so
375 * the ordering might be different */
376 if (argName == name) {
377 if (originalValue.userType() == QMetaType::type("ApiArray")) {
378 ApiArray array = originalValue.value<ApiArray>();
379 val = arrayFromIndex(nameIdx, array, changed);
381 QModelIndex valIdx = m_model->index(topRow, 1, QModelIndex());
383 if (val != originalValue)
391 QVariant ArgumentsEditor::arrayFromIndex(const QModelIndex &parentIndex,
392 const ApiArray &origArray,
395 QList<QVariant> origValues = origArray.values();
399 if (origValues.isEmpty())
400 return QVariant::fromValue(ApiArray());
403 for (int i = 0; i < origValues.count(); ++i) {
404 QModelIndex valIdx = m_model->index(i, 1, parentIndex);
405 QVariant var = valIdx.data();
406 QVariant origValue = origValues[i];
407 if (var != origValue)
409 //qDebug()<<"\t\tarray "<<i<<") "<<var;
412 return QVariant::fromValue(ApiArray(lst));
415 QVariant ArgumentsEditor::arrayFromEditor(const ApiArray &origArray,
418 QList<QVariant> vals;
419 QList<QVariant> origValues = origArray.values();
421 Q_ASSERT(isVariantStringArray(QVariant::fromValue(origArray)));
424 for (int i = 0; i < m_ui.selectStringCB->count(); ++i) {
425 QVariant val = m_ui.selectStringCB->itemData(i);
426 QVariant origValue = origValues[i];
427 if (origValue != val)
431 return QVariant::fromValue(ApiArray(vals));
434 void ArgumentsEditor::revert()
440 #include "argumentseditor.moc"