#include "argumentseditor.h" #include "apitracecall.h" #include #include #include #include #include #include static bool isVariantEditable(const QVariant &var) { if (var.canConvert()) { ApiArray array = var.value(); QVector vals = array.values(); if (vals.isEmpty()) return false; else return isVariantEditable(vals.first()); } switch (var.userType()) { case QVariant::Bool: case QVariant::Int: case QVariant::UInt: case QVariant::LongLong: case QVariant::ULongLong: case QMetaType::Float: case QVariant::Double: case QVariant::String: return true; default: return false; } } static bool isVariantStringArray(const QVariant &var) { if (var.isNull() || var.userType() != QMetaType::type("ApiArray")) return false; ApiArray array = var.value(); QVector origValues = array.values(); if (origValues.isEmpty() || origValues.first().userType() != QVariant::String) return false; return true; } void setArgumentsItemEditorFactory () { QItemEditorCreatorBase *booleanComboBoxEditorCreator = new QStandardItemEditorCreator(); QItemEditorCreatorBase *uIntEditorCreator = new QStandardItemEditorCreator(); QItemEditorCreatorBase *intEditorCreator = new QStandardItemEditorCreator(); QItemEditorCreatorBase *uLongLongEditorCreator = new QStandardItemEditorCreator(); QItemEditorCreatorBase *longLongEditorCreator = new QStandardItemEditorCreator(); QItemEditorCreatorBase *pixmapEditorCreator = new QStandardItemEditorCreator(); QItemEditorCreatorBase *floatEditorCreator = new QStandardItemEditorCreator(); QItemEditorCreatorBase *doubleEditorCreator = new QStandardItemEditorCreator(); QItemEditorCreatorBase *stringEditorCreator = new QStandardItemEditorCreator(); QItemEditorCreatorBase *invalidEditorCreator = new QStandardItemEditorCreator(); QItemEditorFactory *factory = new QItemEditorFactory(); QVariant::Type typeFloat = static_cast (qMetaTypeId()); factory->registerEditor(QVariant::Bool, booleanComboBoxEditorCreator); factory->registerEditor(QVariant::UInt, uIntEditorCreator); factory->registerEditor(QVariant::Int, intEditorCreator); factory->registerEditor(QVariant::ULongLong, uLongLongEditorCreator); factory->registerEditor(QVariant::LongLong, longLongEditorCreator); factory->registerEditor(QVariant::Pixmap, pixmapEditorCreator); factory->registerEditor(typeFloat, floatEditorCreator); factory->registerEditor(QVariant::Double, doubleEditorCreator); factory->registerEditor(QVariant::String, stringEditorCreator); factory->registerEditor(QVariant::Invalid, invalidEditorCreator); QItemEditorFactory::setDefaultFactory(factory); } BooleanComboBox::BooleanComboBox(QWidget *parent) : QComboBox(parent) { addItem(tr("False")); addItem(tr("True")); } void BooleanComboBox::setValue(bool value) { setCurrentIndex(value ? 1 : 0); } bool BooleanComboBox::value() const { return (currentIndex() == 1); } ArgumentsEditor::ArgumentsEditor(QWidget *parent) : QDialog(parent), m_model(new QStandardItemModel()), m_call(0) { init(); } ArgumentsEditor::~ArgumentsEditor() { delete m_model; } void ArgumentsEditor::setCall(ApiTraceCall *call) { m_call = call; setupCall(); } ApiTraceCall * ArgumentsEditor::call() const { return m_call; } void ArgumentsEditor::init() { m_ui.setupUi(this); connect(m_ui.selectStringCB, SIGNAL(currentIndexChanged(int)), SLOT(currentSourceChanged(int))); connect(m_ui.glslEdit, SIGNAL(textChanged()), SLOT(sourceChanged())); connect(m_ui.revertButton, SIGNAL(clicked()), SLOT(revert())); setArgumentsItemEditorFactory (); m_ui.argsTree->setModel(m_model); } void ArgumentsEditor::setupCall() { m_model->clear(); QStringList headers; headers.append(tr("Argument")); headers.append(tr("Value")); m_model->setColumnCount(2); m_model->setHorizontalHeaderLabels(headers); m_ui.argsTabWidget->removeTab( m_ui.argsTabWidget->indexOf(m_ui.shaderTab)); if (!m_call) return; m_ui.callLabel->setText(m_call->name()); QStandardItem *rootItem = m_model->invisibleRootItem(); for (int i = 0; i < m_call->argNames().count(); ++i) { QString argName = m_call->argNames()[i]; QVariant val = m_call->arguments()[i]; QStandardItem *nameItem = new QStandardItem(argName); nameItem->setFlags(nameItem->flags() ^ Qt::ItemIsEditable); QList topRow; topRow.append(nameItem); if (val.canConvert()) { ApiArray array = val.value(); QVector vals = array.values(); QVariant firstVal = vals.value(0); if (firstVal.userType() == QVariant::String) { m_ui.argsTabWidget->addTab( m_ui.shaderTab, argName); setupShaderEditor(vals); delete nameItem; continue; } else if (isVariantEditable(firstVal)) { for (int i = 0; i < vals.count(); ++i) { QList row; QStandardItem *idx = new QStandardItem(); idx->setFlags(idx->flags() ^ Qt::ItemIsEditable); idx->setText(tr("%1)").arg(i)); QStandardItem *col = new QStandardItem(); col->setFlags(col->flags() | Qt::ItemIsEditable); col->setData(vals[i], Qt::EditRole); row.append(idx); row.append(col); nameItem->appendRow(row); } } else { qDebug()<<"\tUnsupported array = "<()) { ApiPointer ptr = val.value(); QStandardItem *item = new QStandardItem(); item->setFlags(item->flags() ^ Qt::ItemIsEditable); item->setText(ptr.toString()); QIcon icon(":/resources/emblem-locked.png"); item->setIcon(icon); item->setToolTip(tr("Argument is read-only")); topRow.append(item); } else if (val.canConvert()) { ApiEnum en = val.value(); QStandardItem *item = new QStandardItem(); item->setFlags(item->flags() ^ Qt::ItemIsEditable); item->setText(en.toString()); QIcon icon(":/resources/emblem-locked.png"); item->setIcon(icon); item->setToolTip(tr("Argument is read-only")); topRow.append(item); } else if (val.canConvert()) { ApiBitmask mask = val.value(); QStandardItem *item = new QStandardItem(); item->setFlags(item->flags() ^ Qt::ItemIsEditable); item->setText(mask.toString()); QIcon icon(":/resources/emblem-locked.png"); item->setIcon(icon); item->setToolTip(tr("Argument is read-only")); topRow.append(item); } else if (val.canConvert()) { ApiStruct str = val.value(); QStandardItem *item = new QStandardItem(); item->setFlags(item->flags() ^ Qt::ItemIsEditable); item->setText(str.toString()); QIcon icon(":/resources/emblem-locked.png"); item->setIcon(icon); item->setToolTip(tr("Argument is read-only")); topRow.append(item); } else if (val.userType() == QVariant::ByteArray) { QByteArray ba = val.value(); QStandardItem *item = new QStandardItem(); item->setFlags(item->flags() ^ Qt::ItemIsEditable); item->setText( tr("").arg(ba.size())); QIcon icon(":/resources/emblem-locked.png"); item->setIcon(icon); item->setToolTip(tr("Argument is read-only")); topRow.append(item); } else { QStandardItem *item = new QStandardItem(); if (isVariantEditable(val)) { item->setFlags(item->flags() | Qt::ItemIsEditable); } else { QIcon icon(":/resources/emblem-locked.png"); item->setIcon(icon); item->setFlags(item->flags() ^ Qt::ItemIsEditable); item->setToolTip(tr("Argument is read-only")); } item->setData(val, Qt::EditRole); topRow.append(item); } rootItem->appendRow(topRow); } } void ArgumentsEditor::setupShaderEditor(const QVector &sources) { m_ui.selectStringCB->clear(); m_ui.glslEdit->clear(); for (int i = 0; i < sources.count(); ++i) { m_ui.selectStringCB->addItem( tr("Shader string: %1").arg(i), sources[i]); } m_ui.selectStringCB->setCurrentIndex(0); } void ArgumentsEditor::currentSourceChanged(int idx) { QVariant source = m_ui.selectStringCB->itemData(idx); QString str = source.toString(); m_ui.glslEdit->setPlainText(source.toString()); m_ui.lengthLabel->setText( tr("%1").arg(str.length())); } void ArgumentsEditor::sourceChanged() { QString str = m_ui.glslEdit->toPlainText(); m_ui.lengthLabel->setText( tr("%1").arg(str.length())); m_ui.selectStringCB->setItemData( m_ui.selectStringCB->currentIndex(), str); } void ArgumentsEditor::accept() { QStringList argNames = m_call->argNames(); QVector originalValues = m_call->arguments(); QVector newValues; bool changed = false; for (int i = 0; i < argNames.count(); ++i) { bool valChanged = false; QString argName = argNames[i]; QVariant argValue = originalValues[i]; QVariant editorValue = valueForName(argName, argValue, &valChanged); newValues.append(editorValue); #if 0 qDebug()<<"Arg = "<(); val = arrayFromIndex(nameIdx, array, changed); } else { QModelIndex valIdx = m_model->index(topRow, 1, QModelIndex()); val = valIdx.data(); if (val != originalValue) *changed = true; } } } return val; } QVariant ArgumentsEditor::arrayFromIndex(const QModelIndex &parentIndex, const ApiArray &origArray, bool *changed) const { QVector origValues = origArray.values(); *changed = false; if (origValues.isEmpty()) return QVariant::fromValue(ApiArray()); QVector lst; for (int i = 0; i < origValues.count(); ++i) { QModelIndex valIdx = m_model->index(i, 1, parentIndex); QVariant var = valIdx.data(); QVariant origValue = origValues[i]; if (var != origValue) *changed = true; //qDebug()<<"\t\tarray "< vals; QVector origValues = origArray.values(); Q_ASSERT(isVariantStringArray(QVariant::fromValue(origArray))); *changed = false; //shaders for (int i = 0; i < m_ui.selectStringCB->count(); ++i) { QVariant val = m_ui.selectStringCB->itemData(i); QVariant origValue = origValues[i]; if (origValue != val) *changed = true; vals.append(val); } return QVariant::fromValue(ApiArray(vals)); } void ArgumentsEditor::revert() { m_call->revert(); setupCall(); } #include "argumentseditor.moc"