]> git.cworth.org Git - apitrace/blob - gui/argumentseditor.cpp
Display shaders in the shader editor.
[apitrace] / gui / argumentseditor.cpp
1 #include "argumentseditor.h"
2
3 #include "apitracecall.h"
4
5 #include <QDebug>
6 #include <QDoubleSpinBox>
7 #include <QItemEditorFactory>
8 #include <QSpinBox>
9
10 #include <limits.h>
11 #include <float.h>
12
13
14 static bool
15 isVariantEditable(const QVariant &var)
16 {
17     switch (var.userType()) {
18     case QVariant::Bool:
19     case QVariant::Int:
20     case QVariant::UInt:
21     case QVariant::LongLong:
22     case QVariant::ULongLong:
23     case QVariant::Double:
24         return true;
25     default:
26         return false;
27     }
28 }
29
30
31 ArgumentsItemEditorFactory::ArgumentsItemEditorFactory()
32     : QItemEditorFactory()
33 {
34 }
35
36 QWidget * ArgumentsItemEditorFactory::createEditor(QVariant::Type type,
37                                                    QWidget *parent) const
38 {
39     switch (type) {
40     case QVariant::Bool: {
41         BooleanComboBox *cb = new BooleanComboBox(parent);
42         cb->setFrame(false);
43         return cb;
44     }
45     case QVariant::UInt: {
46         QSpinBox *sb = new QSpinBox(parent);
47         sb->setFrame(false);
48         sb->setMaximum(INT_MAX);
49         return sb; }
50     case QVariant::Int: {
51         QSpinBox *sb = new QSpinBox(parent);
52         sb->setFrame(false);
53         sb->setMinimum(INT_MIN);
54         sb->setMaximum(INT_MAX);
55         return sb;
56     }
57     case QVariant::ULongLong: {
58         QSpinBox *sb = new QSpinBox(parent);
59         sb->setFrame(false);
60         sb->setMaximum(INT_MAX);
61         return sb; }
62     case QVariant::LongLong: {
63         QSpinBox *sb = new QSpinBox(parent);
64         sb->setFrame(false);
65         sb->setMinimum(INT_MIN);
66         sb->setMaximum(INT_MAX);
67         return sb;
68     }
69     case QVariant::Pixmap:
70         return new QLabel(parent);
71     case QVariant::Double: {
72         QDoubleSpinBox *sb = new QDoubleSpinBox(parent);
73         sb->setFrame(false);
74         sb->setMinimum(-DBL_MAX);
75         sb->setMaximum(DBL_MAX);
76         sb->setDecimals(8);
77         return sb;
78     }
79     default:
80         break;
81     }
82     return 0;
83 }
84
85 QByteArray
86 ArgumentsItemEditorFactory::valuePropertyName(QVariant::Type type) const
87 {
88     switch (type) {
89     case QVariant::Bool:
90         return "currentIndex";
91     case QVariant::UInt:
92     case QVariant::Int:
93     case QVariant::LongLong:
94     case QVariant::ULongLong:
95     case QVariant::Double:
96         return "value";
97 #if 0
98     case QVariant::String:
99 #endif
100     default:
101         return "text";
102     }
103 }
104
105 BooleanComboBox::BooleanComboBox(QWidget *parent)
106     : QComboBox(parent)
107 {
108     addItem(tr("False"));
109     addItem(tr("True"));
110 }
111
112 void BooleanComboBox::setValue(bool value)
113 {
114     setCurrentIndex(value ? 1 : 0);
115 }
116
117 bool BooleanComboBox::value() const
118 {
119     return (currentIndex() == 1);
120 }
121
122 ArgumentsEditor::ArgumentsEditor(QWidget *parent)
123     : QWidget(parent),
124       m_model(new QStandardItemModel()),
125       m_call(0)
126 {
127     init();
128 }
129
130 ArgumentsEditor::~ArgumentsEditor()
131 {
132 }
133
134 void ArgumentsEditor::setCall(ApiTraceCall *call)
135 {
136     if (m_call != call) {
137         m_call = call;
138         setupCall();
139     }
140 }
141
142 ApiTraceCall * ArgumentsEditor::call() const
143 {
144     return m_call;
145 }
146
147 void ArgumentsEditor::init()
148 {
149     m_ui.setupUi(this);
150
151     connect(m_ui.selectStringCB, SIGNAL(currentIndexChanged(int)),
152             SLOT(currentSourceChanged(int)));
153     connect(m_ui.glslEdit, SIGNAL(textChanged()),
154             SLOT(sourceChanged()));
155
156     m_ui.argsTree->setModel(m_model);
157     QItemEditorFactory *factory =
158         new ArgumentsItemEditorFactory();
159
160     QItemEditorFactory::setDefaultFactory(factory);
161 }
162
163 void ArgumentsEditor::setupCall()
164 {
165     m_model->clear();
166
167     QStringList headers;
168     headers.append(tr("Argument"));
169     headers.append(tr("Value"));
170     m_model->setColumnCount(2);
171     m_model->setHorizontalHeaderLabels(headers);
172     m_ui.argsTabWidget->removeTab(
173         m_ui.argsTabWidget->indexOf(m_ui.shaderTab));
174
175     if (!m_call)
176         return;
177
178     m_ui.callLabel->setText(m_call->name);
179     QStandardItem *rootItem = m_model->invisibleRootItem();
180     for (int i = 0; i < m_call->argNames.count(); ++i) {
181         QString argName = m_call->argNames[i];
182         QVariant val = m_call->argValues[i];
183         QStandardItem *nameItem = new QStandardItem(argName);
184         nameItem->setFlags(nameItem->flags() ^ Qt::ItemIsEditable);
185         QList<QStandardItem*> topRow;
186         topRow.append(nameItem);
187         qDebug()<<"arg "<<argName<<", val = "<<val;
188
189         if (val.canConvert<ApiArray>()) {
190             ApiArray array = val.value<ApiArray>();
191             QList<QVariant> vals = array.values();
192
193             QVariant firstVal = vals.value(0);
194             if (firstVal.userType() == QVariant::String) {
195                 m_ui.argsTabWidget->addTab(
196                     m_ui.shaderTab, argName);
197                 setupShaderEditor(vals);
198                 delete nameItem;
199                 continue;
200             } else if (isVariantEditable(firstVal)) {
201                 for (int i = 0; i < vals.count(); ++i) {
202                     QList<QStandardItem*> row;
203
204                     QStandardItem *idx = new QStandardItem();
205                     idx->setFlags(idx->flags() ^ Qt::ItemIsEditable);
206                     idx->setText(tr("%1)").arg(i));
207
208                     QStandardItem *col = new QStandardItem();
209                     col->setFlags(col->flags() | Qt::ItemIsEditable);
210                     col->setData(vals[i], Qt::DisplayRole);
211                     row.append(idx);
212                     row.append(col);
213                     nameItem->appendRow(row);
214                 }
215             } else {
216                 qDebug()<<"\tUnsupported array = "<<firstVal;
217                 delete nameItem;
218                 continue;
219             }
220         } else  if (val.canConvert<ApiPointer>()) {
221             ApiPointer ptr = val.value<ApiPointer>();
222             QStandardItem *item = new QStandardItem();
223             item->setFlags(item->flags() ^ Qt::ItemIsEditable);
224             item->setText(ptr.toString());
225             QIcon icon(":/resources/emblem-locked.png");
226             item->setIcon(icon);
227             item->setToolTip(tr("Argument is read-only"));
228             topRow.append(item);
229         } else if (val.canConvert<ApiBitmask>()) {
230             ApiBitmask mask = val.value<ApiBitmask>();
231             QStandardItem *item = new QStandardItem();
232             item->setFlags(item->flags() ^ Qt::ItemIsEditable);
233             item->setText(mask.toString());
234             QIcon icon(":/resources/emblem-locked.png");
235             item->setIcon(icon);
236             item->setToolTip(tr("Argument is read-only"));
237             topRow.append(item);
238         } else if (val.canConvert<ApiStruct>()) {
239             ApiStruct str = val.value<ApiStruct>();
240             QStandardItem *item = new QStandardItem();
241             item->setFlags(item->flags() ^ Qt::ItemIsEditable);
242             item->setText(str.toString());
243             QIcon icon(":/resources/emblem-locked.png");
244             item->setIcon(icon);
245             item->setToolTip(tr("Argument is read-only"));
246             topRow.append(item);
247         } else if (val.userType() == QVariant::ByteArray) {
248             QByteArray ba = val.value<QByteArray>();
249             QStandardItem *item = new QStandardItem();
250             item->setFlags(item->flags() ^ Qt::ItemIsEditable);
251             item->setText(
252                 tr("<binary data, size = %1 bytes>").arg(ba.size()));
253             QIcon icon(":/resources/emblem-locked.png");
254             item->setIcon(icon);
255             item->setToolTip(tr("Argument is read-only"));
256             topRow.append(item);
257         } else {
258             QStandardItem *item
259                 = new QStandardItem();
260
261             if (isVariantEditable(val)) {
262                 item->setFlags(item->flags() | Qt::ItemIsEditable);
263             } else {
264                 QIcon icon(":/resources/emblem-locked.png");
265                 item->setIcon(icon);
266                 item->setFlags(item->flags() ^ Qt::ItemIsEditable);
267                 item->setToolTip(tr("Argument is read-only"));
268             }
269             item->setData(val, Qt::DisplayRole);
270             topRow.append(item);
271         }
272         rootItem->appendRow(topRow);
273     }
274 }
275
276 void ArgumentsEditor::setupShaderEditor(const QList<QVariant> &sources)
277 {
278     m_ui.selectStringCB->clear();
279     m_ui.glslEdit->clear();
280     for (int i = 0; i < sources.count(); ++i) {
281         m_ui.selectStringCB->addItem(
282             tr("Shader string: %1").arg(i),
283             sources[i]);
284     }
285     m_ui.selectStringCB->setCurrentIndex(0);
286 }
287
288 void ArgumentsEditor::currentSourceChanged(int idx)
289 {
290     QVariant source = m_ui.selectStringCB->itemData(idx);
291     QString str = source.toString();
292     m_ui.glslEdit->setPlainText(source.toString());
293     m_ui.lengthLabel->setText(
294         tr("%1").arg(str.length()));
295 }
296
297 void ArgumentsEditor::sourceChanged()
298 {
299     QString str = m_ui.glslEdit->toPlainText();
300     m_ui.lengthLabel->setText(
301         tr("%1").arg(str.length()));
302 }
303
304 #include "argumentseditor.moc"