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()
148 void ArgumentsEditor::setCall(ApiTraceCall *call)
154 ApiTraceCall * ArgumentsEditor::call() const
159 void ArgumentsEditor::init()
163 connect(m_ui.selectStringCB, SIGNAL(currentIndexChanged(int)),
164 SLOT(currentSourceChanged(int)));
165 connect(m_ui.glslEdit, SIGNAL(textChanged()),
166 SLOT(sourceChanged()));
167 connect(m_ui.revertButton, SIGNAL(clicked()),
170 m_ui.argsTree->setModel(m_model);
171 QItemEditorFactory *factory =
172 new ArgumentsItemEditorFactory();
174 QItemEditorFactory::setDefaultFactory(factory);
177 void ArgumentsEditor::setupCall()
182 headers.append(tr("Argument"));
183 headers.append(tr("Value"));
184 m_model->setColumnCount(2);
185 m_model->setHorizontalHeaderLabels(headers);
186 m_ui.argsTabWidget->removeTab(
187 m_ui.argsTabWidget->indexOf(m_ui.shaderTab));
192 m_ui.callLabel->setText(m_call->name());
193 QStandardItem *rootItem = m_model->invisibleRootItem();
194 for (int i = 0; i < m_call->argNames().count(); ++i) {
195 QString argName = m_call->argNames()[i];
196 QVariant val = m_call->arguments()[i];
197 QStandardItem *nameItem = new QStandardItem(argName);
198 nameItem->setFlags(nameItem->flags() ^ Qt::ItemIsEditable);
199 QList<QStandardItem*> topRow;
200 topRow.append(nameItem);
202 if (val.canConvert<ApiArray>()) {
203 ApiArray array = val.value<ApiArray>();
204 QList<QVariant> vals = array.values();
206 QVariant firstVal = vals.value(0);
207 if (firstVal.userType() == QVariant::String) {
208 m_ui.argsTabWidget->addTab(
209 m_ui.shaderTab, argName);
210 setupShaderEditor(vals);
213 } else if (isVariantEditable(firstVal)) {
214 for (int i = 0; i < vals.count(); ++i) {
215 QList<QStandardItem*> row;
217 QStandardItem *idx = new QStandardItem();
218 idx->setFlags(idx->flags() ^ Qt::ItemIsEditable);
219 idx->setText(tr("%1)").arg(i));
221 QStandardItem *col = new QStandardItem();
222 col->setFlags(col->flags() | Qt::ItemIsEditable);
223 col->setData(vals[i], Qt::DisplayRole);
226 nameItem->appendRow(row);
229 qDebug()<<"\tUnsupported array = "<<firstVal;
233 } else if (val.canConvert<ApiPointer>()) {
234 ApiPointer ptr = val.value<ApiPointer>();
235 QStandardItem *item = new QStandardItem();
236 item->setFlags(item->flags() ^ Qt::ItemIsEditable);
237 item->setText(ptr.toString());
238 QIcon icon(":/resources/emblem-locked.png");
240 item->setToolTip(tr("Argument is read-only"));
242 } else if (val.canConvert<ApiEnum>()) {
243 ApiEnum en = val.value<ApiEnum>();
244 QStandardItem *item = new QStandardItem();
245 item->setFlags(item->flags() ^ Qt::ItemIsEditable);
246 item->setText(en.toString());
247 QIcon icon(":/resources/emblem-locked.png");
249 item->setToolTip(tr("Argument is read-only"));
251 } else if (val.canConvert<ApiBitmask>()) {
252 ApiBitmask mask = val.value<ApiBitmask>();
253 QStandardItem *item = new QStandardItem();
254 item->setFlags(item->flags() ^ Qt::ItemIsEditable);
255 item->setText(mask.toString());
256 QIcon icon(":/resources/emblem-locked.png");
258 item->setToolTip(tr("Argument is read-only"));
260 } else if (val.canConvert<ApiStruct>()) {
261 ApiStruct str = val.value<ApiStruct>();
262 QStandardItem *item = new QStandardItem();
263 item->setFlags(item->flags() ^ Qt::ItemIsEditable);
264 item->setText(str.toString());
265 QIcon icon(":/resources/emblem-locked.png");
267 item->setToolTip(tr("Argument is read-only"));
269 } else if (val.userType() == QVariant::ByteArray) {
270 QByteArray ba = val.value<QByteArray>();
271 QStandardItem *item = new QStandardItem();
272 item->setFlags(item->flags() ^ Qt::ItemIsEditable);
274 tr("<binary data, size = %1 bytes>").arg(ba.size()));
275 QIcon icon(":/resources/emblem-locked.png");
277 item->setToolTip(tr("Argument is read-only"));
281 = new QStandardItem();
283 if (isVariantEditable(val)) {
284 item->setFlags(item->flags() | Qt::ItemIsEditable);
286 QIcon icon(":/resources/emblem-locked.png");
288 item->setFlags(item->flags() ^ Qt::ItemIsEditable);
289 item->setToolTip(tr("Argument is read-only"));
291 item->setData(val, Qt::DisplayRole);
294 rootItem->appendRow(topRow);
298 void ArgumentsEditor::setupShaderEditor(const QList<QVariant> &sources)
300 m_ui.selectStringCB->clear();
301 m_ui.glslEdit->clear();
302 for (int i = 0; i < sources.count(); ++i) {
303 m_ui.selectStringCB->addItem(
304 tr("Shader string: %1").arg(i),
307 m_ui.selectStringCB->setCurrentIndex(0);
310 void ArgumentsEditor::currentSourceChanged(int idx)
312 QVariant source = m_ui.selectStringCB->itemData(idx);
313 QString str = source.toString();
314 m_ui.glslEdit->setPlainText(source.toString());
315 m_ui.lengthLabel->setText(
316 tr("%1").arg(str.length()));
319 void ArgumentsEditor::sourceChanged()
321 QString str = m_ui.glslEdit->toPlainText();
322 m_ui.lengthLabel->setText(
323 tr("%1").arg(str.length()));
325 m_ui.selectStringCB->setItemData(
326 m_ui.selectStringCB->currentIndex(),
330 void ArgumentsEditor::accept()
332 QStringList argNames = m_call->argNames();
333 QList<QVariant> originalValues = m_call->arguments();
334 QList<QVariant> newValues;
335 bool changed = false;
336 for (int i = 0; i < argNames.count(); ++i) {
337 bool valChanged = false;
338 QString argName = argNames[i];
339 QVariant argValue = originalValues[i];
340 QVariant editorValue = valueForName(argName, argValue, &valChanged);
341 newValues.append(editorValue);
343 qDebug()<<"Arg = "<<argName;
344 qDebug()<<"\toriginal = "<<argValue;
345 qDebug()<<"\teditor = "<<editorValue;
346 qDebug()<<"\tchanged = "<<valChanged;
352 m_call->setEditedValues(newValues);
356 QVariant ArgumentsEditor::valueForName(const QString &name,
357 const QVariant &originalValue,
364 //Handle string arrays specially
365 if (isVariantStringArray(originalValue)) {
366 ApiArray array = originalValue.value<ApiArray>();
367 return arrayFromEditor(array, changed);
370 for (int topRow = 0; topRow < m_model->rowCount(); ++topRow) {
371 QModelIndex nameIdx = m_model->index(topRow, 0, QModelIndex());
372 QString argName = nameIdx.data().toString();
373 /* we display shaders in a separate widget so
374 * the ordering might be different */
375 if (argName == name) {
376 if (originalValue.userType() == QMetaType::type("ApiArray")) {
377 ApiArray array = originalValue.value<ApiArray>();
378 val = arrayFromIndex(nameIdx, array, changed);
380 QModelIndex valIdx = m_model->index(topRow, 1, QModelIndex());
382 if (val != originalValue)
390 QVariant ArgumentsEditor::arrayFromIndex(const QModelIndex &parentIndex,
391 const ApiArray &origArray,
394 QList<QVariant> origValues = origArray.values();
398 if (origValues.isEmpty())
399 return QVariant::fromValue(ApiArray());
402 for (int i = 0; i < origValues.count(); ++i) {
403 QModelIndex valIdx = m_model->index(i, 1, parentIndex);
404 QVariant var = valIdx.data();
405 QVariant origValue = origValues[i];
406 if (var != origValue)
408 //qDebug()<<"\t\tarray "<<i<<") "<<var;
411 return QVariant::fromValue(ApiArray(lst));
414 QVariant ArgumentsEditor::arrayFromEditor(const ApiArray &origArray,
417 QList<QVariant> vals;
418 QList<QVariant> origValues = origArray.values();
420 Q_ASSERT(isVariantStringArray(QVariant::fromValue(origArray)));
423 for (int i = 0; i < m_ui.selectStringCB->count(); ++i) {
424 QVariant val = m_ui.selectStringCB->itemData(i);
425 QVariant origValue = origValues[i];
426 if (origValue != val)
430 return QVariant::fromValue(ApiArray(vals));
433 void ArgumentsEditor::revert()
439 #include "argumentseditor.moc"