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<ApiBitmask>()) {
243 ApiBitmask mask = val.value<ApiBitmask>();
244 QStandardItem *item = new QStandardItem();
245 item->setFlags(item->flags() ^ Qt::ItemIsEditable);
246 item->setText(mask.toString());
247 QIcon icon(":/resources/emblem-locked.png");
249 item->setToolTip(tr("Argument is read-only"));
251 } else if (val.canConvert<ApiStruct>()) {
252 ApiStruct str = val.value<ApiStruct>();
253 QStandardItem *item = new QStandardItem();
254 item->setFlags(item->flags() ^ Qt::ItemIsEditable);
255 item->setText(str.toString());
256 QIcon icon(":/resources/emblem-locked.png");
258 item->setToolTip(tr("Argument is read-only"));
260 } else if (val.userType() == QVariant::ByteArray) {
261 QByteArray ba = val.value<QByteArray>();
262 QStandardItem *item = new QStandardItem();
263 item->setFlags(item->flags() ^ Qt::ItemIsEditable);
265 tr("<binary data, size = %1 bytes>").arg(ba.size()));
266 QIcon icon(":/resources/emblem-locked.png");
268 item->setToolTip(tr("Argument is read-only"));
272 = new QStandardItem();
274 if (isVariantEditable(val)) {
275 item->setFlags(item->flags() | Qt::ItemIsEditable);
277 QIcon icon(":/resources/emblem-locked.png");
279 item->setFlags(item->flags() ^ Qt::ItemIsEditable);
280 item->setToolTip(tr("Argument is read-only"));
282 item->setData(val, Qt::DisplayRole);
285 rootItem->appendRow(topRow);
289 void ArgumentsEditor::setupShaderEditor(const QList<QVariant> &sources)
291 m_ui.selectStringCB->clear();
292 m_ui.glslEdit->clear();
293 for (int i = 0; i < sources.count(); ++i) {
294 m_ui.selectStringCB->addItem(
295 tr("Shader string: %1").arg(i),
298 m_ui.selectStringCB->setCurrentIndex(0);
301 void ArgumentsEditor::currentSourceChanged(int idx)
303 QVariant source = m_ui.selectStringCB->itemData(idx);
304 QString str = source.toString();
305 m_ui.glslEdit->setPlainText(source.toString());
306 m_ui.lengthLabel->setText(
307 tr("%1").arg(str.length()));
310 void ArgumentsEditor::sourceChanged()
312 QString str = m_ui.glslEdit->toPlainText();
313 m_ui.lengthLabel->setText(
314 tr("%1").arg(str.length()));
316 m_ui.selectStringCB->setItemData(
317 m_ui.selectStringCB->currentIndex(),
321 void ArgumentsEditor::accept()
323 QStringList argNames = m_call->argNames();
324 QList<QVariant> originalValues = m_call->arguments();
325 QList<QVariant> newValues;
326 bool changed = false;
327 for (int i = 0; i < argNames.count(); ++i) {
328 bool valChanged = false;
329 QString argName = argNames[i];
330 QVariant argValue = originalValues[i];
331 QVariant editorValue = valueForName(argName, argValue, &valChanged);
332 newValues.append(editorValue);
333 qDebug()<<"Arg = "<<argName;
334 qDebug()<<"\toriginal = "<<argValue;
335 qDebug()<<"\teditor = "<<editorValue;
336 qDebug()<<"\tchanged = "<<valChanged;
341 m_call->setEditedValues(newValues);
345 QVariant ArgumentsEditor::valueForName(const QString &name,
346 const QVariant &originalValue,
353 //Handle string arrays specially
354 if (isVariantStringArray(originalValue)) {
355 ApiArray array = originalValue.value<ApiArray>();
356 return arrayFromEditor(array, changed);
359 for (int topRow = 0; topRow < m_model->rowCount(); ++topRow) {
360 QModelIndex nameIdx = m_model->index(topRow, 0, QModelIndex());
361 QString argName = nameIdx.data().toString();
362 /* we display shaders in a separate widget so
363 * the ordering might be different */
364 if (argName == name) {
365 if (originalValue.userType() == QMetaType::type("ApiArray")) {
366 ApiArray array = originalValue.value<ApiArray>();
367 val = arrayFromIndex(nameIdx, array, changed);
369 QModelIndex valIdx = m_model->index(topRow, 1, QModelIndex());
371 if (val != originalValue)
379 QVariant ArgumentsEditor::arrayFromIndex(const QModelIndex &parentIndex,
380 const ApiArray &origArray,
383 QList<QVariant> origValues = origArray.values();
387 if (origValues.isEmpty())
388 return QVariant::fromValue(ApiArray());
391 for (int i = 0; i < origValues.count(); ++i) {
392 QModelIndex valIdx = m_model->index(i, 1, parentIndex);
393 QVariant var = valIdx.data();
394 QVariant origValue = origValues[i];
395 if (var != origValue)
397 //qDebug()<<"\t\tarray "<<i<<") "<<var;
400 return QVariant::fromValue(ApiArray(lst));
403 QVariant ArgumentsEditor::arrayFromEditor(const ApiArray &origArray,
406 QList<QVariant> vals;
407 QList<QVariant> origValues = origArray.values();
409 Q_ASSERT(isVariantStringArray(QVariant::fromValue(origArray)));
412 for (int i = 0; i < m_ui.selectStringCB->count(); ++i) {
413 QVariant val = m_ui.selectStringCB->itemData(i);
414 QVariant origValue = origValues[i];
415 if (origValue != val)
419 return QVariant::fromValue(ApiArray(vals));
422 void ArgumentsEditor::revert()
428 #include "argumentseditor.moc"