diff options
Diffstat (limited to 'utils/regtools/qeditor')
-rw-r--r-- | utils/regtools/qeditor/analyser.h | 5 | ||||
-rw-r--r-- | utils/regtools/qeditor/aux.cpp | 746 | ||||
-rw-r--r-- | utils/regtools/qeditor/aux.h | 227 | ||||
-rw-r--r-- | utils/regtools/qeditor/backend.cpp | 67 | ||||
-rw-r--r-- | utils/regtools/qeditor/backend.h | 79 | ||||
-rw-r--r-- | utils/regtools/qeditor/mainwindow.cpp | 63 | ||||
-rw-r--r-- | utils/regtools/qeditor/mainwindow.h | 16 | ||||
-rw-r--r-- | utils/regtools/qeditor/qeditor.pro | 6 | ||||
-rw-r--r-- | utils/regtools/qeditor/regdisplaypanel.cpp | 314 | ||||
-rw-r--r-- | utils/regtools/qeditor/regdisplaypanel.h | 77 | ||||
-rw-r--r-- | utils/regtools/qeditor/regedit.cpp | 1324 | ||||
-rw-r--r-- | utils/regtools/qeditor/regedit.h | 282 | ||||
-rw-r--r-- | utils/regtools/qeditor/regtab.cpp | 534 | ||||
-rw-r--r-- | utils/regtools/qeditor/regtab.h | 119 | ||||
-rw-r--r-- | utils/regtools/qeditor/std_analysers.cpp | 9 | ||||
-rw-r--r-- | utils/regtools/qeditor/std_analysers.h | 4 |
16 files changed, 3308 insertions, 564 deletions
diff --git a/utils/regtools/qeditor/analyser.h b/utils/regtools/qeditor/analyser.h index a06652bfb0..4f9830ac4c 100644 --- a/utils/regtools/qeditor/analyser.h +++ b/utils/regtools/qeditor/analyser.h | |||
@@ -5,13 +5,14 @@ | |||
5 | #include <QVector> | 5 | #include <QVector> |
6 | #include <QString> | 6 | #include <QString> |
7 | #include "backend.h" | 7 | #include "backend.h" |
8 | #include "regtab.h" | ||
8 | 9 | ||
9 | class Analyser : public QObject | 10 | class Analyser : public RegTabPanel |
10 | { | 11 | { |
11 | Q_OBJECT | ||
12 | public: | 12 | public: |
13 | Analyser(const SocRef& soc, IoBackend *backend); | 13 | Analyser(const SocRef& soc, IoBackend *backend); |
14 | virtual ~Analyser(); | 14 | virtual ~Analyser(); |
15 | virtual void AllowWrite(bool en) { Q_UNUSED(en); } | ||
15 | virtual QWidget *GetWidget() = 0; | 16 | virtual QWidget *GetWidget() = 0; |
16 | 17 | ||
17 | protected: | 18 | protected: |
diff --git a/utils/regtools/qeditor/aux.cpp b/utils/regtools/qeditor/aux.cpp new file mode 100644 index 0000000000..0614bb57f6 --- /dev/null +++ b/utils/regtools/qeditor/aux.cpp | |||
@@ -0,0 +1,746 @@ | |||
1 | #include "aux.h" | ||
2 | #include <QFontMetrics> | ||
3 | #include <QPainter> | ||
4 | #include <QTextDocument> | ||
5 | #include <QAbstractTextDocumentLayout> | ||
6 | #include <QHeaderView> | ||
7 | #include <QDebug> | ||
8 | #include <QElapsedTimer> | ||
9 | #include <QXmlStreamReader> | ||
10 | #include <QXmlStreamWriter> | ||
11 | #include <QTextBlock> | ||
12 | |||
13 | /** | ||
14 | * SocBitRangeValidator | ||
15 | */ | ||
16 | SocBitRangeValidator::SocBitRangeValidator(QObject *parent) | ||
17 | :QValidator(parent) | ||
18 | { | ||
19 | } | ||
20 | |||
21 | void SocBitRangeValidator::fixup(QString& input) const | ||
22 | { | ||
23 | input = input.trimmed(); | ||
24 | } | ||
25 | |||
26 | QValidator::State SocBitRangeValidator::validate(QString& input, int& pos) const | ||
27 | { | ||
28 | Q_UNUSED(pos); | ||
29 | int first, last; | ||
30 | State state = parse(input, last, first); | ||
31 | return state; | ||
32 | } | ||
33 | |||
34 | QValidator::State SocBitRangeValidator::parse(const QString& input, int& last, int& first) const | ||
35 | { | ||
36 | // the empty string is always intermediate | ||
37 | if(input.size() == 0) | ||
38 | return Intermediate; | ||
39 | // check if there is ':' | ||
40 | int pos = input.indexOf(':'); | ||
41 | if(pos == -1) | ||
42 | pos = input.size(); | ||
43 | // if field start with ':', the last bit is implicit and is 31 | ||
44 | if(pos > 0) | ||
45 | { | ||
46 | // parse last bit and check it's between 0 and 31 | ||
47 | bool ok = false; | ||
48 | last = input.left(pos).toInt(&ok); | ||
49 | if(!ok || last < 0 || last >= 32) | ||
50 | return Invalid; | ||
51 | } | ||
52 | else | ||
53 | last = 31; | ||
54 | // parse first bit | ||
55 | if(pos < input.size() - 1) | ||
56 | { | ||
57 | bool ok = false; | ||
58 | first = input.mid(pos + 1).toInt(&ok); | ||
59 | if(!ok || first < 0 || first > last) | ||
60 | return Invalid; | ||
61 | } | ||
62 | // if input ends with ':', first bit is implicit and is 0 | ||
63 | else if(pos == input.size() - 1) | ||
64 | first = 0; | ||
65 | // if there no ':', first=last | ||
66 | else | ||
67 | first = last; | ||
68 | return Acceptable; | ||
69 | } | ||
70 | |||
71 | /** | ||
72 | * SocFieldValidator | ||
73 | */ | ||
74 | |||
75 | SocFieldValidator::SocFieldValidator(QObject *parent) | ||
76 | :QValidator(parent) | ||
77 | { | ||
78 | m_field.first_bit = 0; | ||
79 | m_field.last_bit = 31; | ||
80 | } | ||
81 | |||
82 | SocFieldValidator::SocFieldValidator(const soc_reg_field_t& field, QObject *parent) | ||
83 | :QValidator(parent), m_field(field) | ||
84 | { | ||
85 | } | ||
86 | |||
87 | void SocFieldValidator::fixup(QString& input) const | ||
88 | { | ||
89 | input = input.trimmed(); | ||
90 | } | ||
91 | |||
92 | QValidator::State SocFieldValidator::validate(QString& input, int& pos) const | ||
93 | { | ||
94 | Q_UNUSED(pos); | ||
95 | soc_word_t val; | ||
96 | State state = parse(input, val); | ||
97 | return state; | ||
98 | } | ||
99 | |||
100 | QValidator::State SocFieldValidator::parse(const QString& input, soc_word_t& val) const | ||
101 | { | ||
102 | // the empty string is always intermediate | ||
103 | if(input.size() == 0) | ||
104 | return Intermediate; | ||
105 | // first check named values | ||
106 | State state = Invalid; | ||
107 | foreach(const soc_reg_field_value_t& value, m_field.value) | ||
108 | { | ||
109 | QString name = QString::fromLocal8Bit(value.name.c_str()); | ||
110 | // cannot be a substring if too long or empty | ||
111 | if(input.size() > name.size()) | ||
112 | continue; | ||
113 | // check equal string | ||
114 | if(input == name) | ||
115 | { | ||
116 | state = Acceptable; | ||
117 | val = value.value; | ||
118 | break; | ||
119 | } | ||
120 | // check substring | ||
121 | if(name.startsWith(input)) | ||
122 | state = Intermediate; | ||
123 | } | ||
124 | // early return for exact match | ||
125 | if(state == Acceptable) | ||
126 | return state; | ||
127 | // do a few special cases for convenience | ||
128 | if(input.compare("0x", Qt::CaseInsensitive) == 0 || | ||
129 | input.compare("0b", Qt::CaseInsensitive) == 0) | ||
130 | return Intermediate; | ||
131 | // try by parsing | ||
132 | unsigned basis, pos; | ||
133 | if(input.size() >= 2 && input.startsWith("0x", Qt::CaseInsensitive)) | ||
134 | { | ||
135 | basis = 16; | ||
136 | pos = 2; | ||
137 | } | ||
138 | else if(input.size() >= 2 && input.startsWith("0b", Qt::CaseInsensitive)) | ||
139 | { | ||
140 | basis = 2; | ||
141 | pos = 2; | ||
142 | } | ||
143 | else if(input.size() >= 2 && input.startsWith("0")) | ||
144 | { | ||
145 | basis = 8; | ||
146 | pos = 1; | ||
147 | } | ||
148 | else | ||
149 | { | ||
150 | basis = 10; | ||
151 | pos = 0; | ||
152 | } | ||
153 | bool ok = false; | ||
154 | unsigned long v = input.mid(pos).toULong(&ok, basis); | ||
155 | // if not ok, return result of name parsing | ||
156 | if(!ok) | ||
157 | return state; | ||
158 | // if ok, check if it fits in the number of bits | ||
159 | unsigned nr_bits = m_field.last_bit - m_field.first_bit + 1; | ||
160 | unsigned long max = nr_bits == 32 ? 0xffffffff : (1 << nr_bits) - 1; | ||
161 | if(v <= max) | ||
162 | { | ||
163 | val = v; | ||
164 | return Acceptable; | ||
165 | } | ||
166 | |||
167 | return state; | ||
168 | } | ||
169 | |||
170 | /** | ||
171 | * RegLineEdit | ||
172 | */ | ||
173 | RegLineEdit::RegLineEdit(QWidget *parent) | ||
174 | :QWidget(parent) | ||
175 | { | ||
176 | m_layout = new QHBoxLayout(this); | ||
177 | m_button = new QToolButton(this); | ||
178 | m_button->setCursor(Qt::ArrowCursor); | ||
179 | m_button->setStyleSheet("QToolButton { font-weight: bold; color: white; background: black; }"); | ||
180 | m_button->setPopupMode(QToolButton::InstantPopup); | ||
181 | m_edit = new QLineEdit(this); | ||
182 | m_layout->addWidget(m_button); | ||
183 | m_layout->addWidget(m_edit); | ||
184 | m_menu = new QMenu(this); | ||
185 | connect(m_menu->addAction("Write"), SIGNAL(triggered()), this, SLOT(OnWriteAct())); | ||
186 | connect(m_menu->addAction("Set"), SIGNAL(triggered()), this, SLOT(OnSetAct())); | ||
187 | connect(m_menu->addAction("Clear"), SIGNAL(triggered()), this, SLOT(OnClearAct())); | ||
188 | connect(m_menu->addAction("Toggle"), SIGNAL(triggered()), this, SLOT(OnToggleAct())); | ||
189 | EnableSCT(false); | ||
190 | SetReadOnly(false); | ||
191 | ShowMode(true); | ||
192 | SetMode(Write); | ||
193 | } | ||
194 | |||
195 | void RegLineEdit::SetReadOnly(bool ro) | ||
196 | { | ||
197 | m_edit->setReadOnly(ro); | ||
198 | m_readonly = ro; | ||
199 | ShowMode(!ro); | ||
200 | } | ||
201 | |||
202 | void RegLineEdit::EnableSCT(bool en) | ||
203 | { | ||
204 | m_has_sct = en; | ||
205 | if(!m_has_sct) | ||
206 | { | ||
207 | m_button->setMenu(0); | ||
208 | SetMode(Write); | ||
209 | } | ||
210 | else | ||
211 | m_button->setMenu(m_menu); | ||
212 | } | ||
213 | |||
214 | RegLineEdit::~RegLineEdit() | ||
215 | { | ||
216 | } | ||
217 | |||
218 | QLineEdit *RegLineEdit::GetLineEdit() | ||
219 | { | ||
220 | return m_edit; | ||
221 | } | ||
222 | |||
223 | void RegLineEdit::ShowMode(bool show) | ||
224 | { | ||
225 | if(show) | ||
226 | m_button->show(); | ||
227 | else | ||
228 | m_button->hide(); | ||
229 | } | ||
230 | |||
231 | void RegLineEdit::OnWriteAct() | ||
232 | { | ||
233 | SetMode(Write); | ||
234 | } | ||
235 | |||
236 | void RegLineEdit::OnSetAct() | ||
237 | { | ||
238 | SetMode(Set); | ||
239 | } | ||
240 | |||
241 | void RegLineEdit::OnClearAct() | ||
242 | { | ||
243 | SetMode(Clear); | ||
244 | } | ||
245 | |||
246 | void RegLineEdit::OnToggleAct() | ||
247 | { | ||
248 | SetMode(Toggle); | ||
249 | } | ||
250 | |||
251 | void RegLineEdit::SetMode(EditMode mode) | ||
252 | { | ||
253 | m_mode = mode; | ||
254 | switch(m_mode) | ||
255 | { | ||
256 | case Write: m_button->setText("WR"); break; | ||
257 | case Set: m_button->setText("SET"); break; | ||
258 | case Clear: m_button->setText("CLR"); break; | ||
259 | case Toggle: m_button->setText("TOG"); break; | ||
260 | default: break; | ||
261 | } | ||
262 | } | ||
263 | |||
264 | RegLineEdit::EditMode RegLineEdit::GetMode() | ||
265 | { | ||
266 | return m_mode; | ||
267 | } | ||
268 | |||
269 | void RegLineEdit::setText(const QString& text) | ||
270 | { | ||
271 | m_edit->setText(text); | ||
272 | } | ||
273 | |||
274 | QString RegLineEdit::text() const | ||
275 | { | ||
276 | return m_edit->text(); | ||
277 | } | ||
278 | |||
279 | /** | ||
280 | * SocFieldItemDelegate | ||
281 | */ | ||
282 | |||
283 | QString SocFieldItemDelegate::displayText(const QVariant& value, const QLocale& locale) const | ||
284 | { | ||
285 | if(value.type() == QVariant::UInt) | ||
286 | return QString("0x%1").arg(value.toUInt(), (m_bitcount + 3) / 4, 16, QChar('0')); | ||
287 | else | ||
288 | return QStyledItemDelegate::displayText(value, locale); | ||
289 | } | ||
290 | |||
291 | /** | ||
292 | * SocFieldEditor | ||
293 | */ | ||
294 | SocFieldEditor::SocFieldEditor(const soc_reg_field_t& field, QWidget *parent) | ||
295 | :QLineEdit(parent), m_reg_field(field) | ||
296 | { | ||
297 | m_validator = new SocFieldValidator(field); | ||
298 | setValidator(m_validator); | ||
299 | } | ||
300 | |||
301 | SocFieldEditor::~SocFieldEditor() | ||
302 | { | ||
303 | delete m_validator; | ||
304 | } | ||
305 | |||
306 | uint SocFieldEditor::field() const | ||
307 | { | ||
308 | soc_word_t v; | ||
309 | /* in case validator fails to parse, return old value */ | ||
310 | if(m_validator->parse(text(), v) == QValidator::Acceptable) | ||
311 | return v; | ||
312 | else | ||
313 | return m_field; | ||
314 | } | ||
315 | |||
316 | void SocFieldEditor::setField(uint field) | ||
317 | { | ||
318 | m_field = field; | ||
319 | int digits = (m_reg_field.last_bit - m_reg_field.first_bit + 4) / 4; | ||
320 | setText(QString("0x%1").arg(field, digits, 16, QChar('0'))); | ||
321 | } | ||
322 | |||
323 | /** | ||
324 | * SocFieldEditorCreator | ||
325 | */ | ||
326 | QWidget *SocFieldEditorCreator::createWidget(QWidget *parent) const | ||
327 | { | ||
328 | return new SocFieldEditor(m_field, parent); | ||
329 | } | ||
330 | |||
331 | QByteArray SocFieldEditorCreator::valuePropertyName() const | ||
332 | { | ||
333 | return QByteArray("field"); | ||
334 | } | ||
335 | |||
336 | /** | ||
337 | * RegSexyDisplay | ||
338 | */ | ||
339 | RegSexyDisplay::RegSexyDisplay(const SocRegRef& reg, QWidget *parent) | ||
340 | :QWidget(parent), m_reg(reg) | ||
341 | { | ||
342 | m_size = QSize(); | ||
343 | } | ||
344 | |||
345 | int RegSexyDisplay::separatorSize() const | ||
346 | { | ||
347 | return 1; | ||
348 | } | ||
349 | |||
350 | int RegSexyDisplay::marginSize() const | ||
351 | { | ||
352 | return fontMetrics().height() / 3; | ||
353 | } | ||
354 | |||
355 | int RegSexyDisplay::textSep() const | ||
356 | { | ||
357 | return marginSize() / 2; | ||
358 | } | ||
359 | |||
360 | int RegSexyDisplay::headerHeight() const | ||
361 | { | ||
362 | return 2 * marginSize() + textSep() + 2 * fontMetrics().height(); | ||
363 | } | ||
364 | |||
365 | int RegSexyDisplay::columnWidth() const | ||
366 | { | ||
367 | return 2 * marginSize() + fontMetrics().height(); | ||
368 | } | ||
369 | |||
370 | int RegSexyDisplay::maxContentHeight() const | ||
371 | { | ||
372 | int max = 0; | ||
373 | QFontMetrics metrics = fontMetrics(); | ||
374 | for(size_t i = 0; i < m_reg.GetReg().field.size(); i++) | ||
375 | { | ||
376 | QString s = QString::fromStdString(m_reg.GetReg().field[i].name); | ||
377 | // add extra spaces arounds | ||
378 | s = " " + s + " "; | ||
379 | max = qMax(max, metrics.boundingRect(s).width()); | ||
380 | } | ||
381 | return 2 * marginSize() + max; | ||
382 | } | ||
383 | |||
384 | int RegSexyDisplay::gapHeight() const | ||
385 | { | ||
386 | return marginSize() / 2; | ||
387 | } | ||
388 | |||
389 | QSize RegSexyDisplay::minimumSizeHint() const | ||
390 | { | ||
391 | /* cache computation because it's expensive */ | ||
392 | if(m_size.isValid()) | ||
393 | return m_size; | ||
394 | /* width: display 32 columns + 33 vertical separators */ | ||
395 | m_size.setWidth(32 * columnWidth() + 33 * separatorSize()); | ||
396 | /* height: one separator + two digits + one separator + margin + separator | ||
397 | * + names + separator */ | ||
398 | m_size.setHeight(4 * separatorSize() + headerHeight() + gapHeight() + maxContentHeight()); | ||
399 | return m_size; | ||
400 | } | ||
401 | |||
402 | QSize RegSexyDisplay::sizeHint() const | ||
403 | { | ||
404 | return minimumSizeHint(); | ||
405 | } | ||
406 | |||
407 | void RegSexyDisplay::paintEvent(QPaintEvent *event) | ||
408 | { | ||
409 | // FIXME could be optimised with QStaticText | ||
410 | Q_UNUSED(event); | ||
411 | int txt_h = fontMetrics().height(); | ||
412 | int sep_sz = separatorSize(); | ||
413 | int w = width(); | ||
414 | int h = height() - 1; | ||
415 | int col_w = (w - 33 * sep_sz) / 32; | ||
416 | int hdr_h = headerHeight(); | ||
417 | int gap_h = gapHeight(); | ||
418 | int tot_w = 33 * sep_sz + 32 * col_w; | ||
419 | int margin = marginSize(); | ||
420 | int txt_sep = textSep(); | ||
421 | int tot_hdr_sz = 2 * sep_sz + hdr_h; | ||
422 | // computer xshift | ||
423 | int x_shift = (w - tot_w) / 2; | ||
424 | #define ith_col_x(i) (x_shift + (i) * (sep_sz + col_w)) | ||
425 | |||
426 | QPainter painter(this); | ||
427 | QBrush back_brush = palette().base(); | ||
428 | QBrush line_brush = palette().dark(); | ||
429 | |||
430 | // fill interesting zone with base | ||
431 | painter.fillRect(x_shift, 0, tot_w, h, back_brush); | ||
432 | |||
433 | // draw top and bottom lines | ||
434 | painter.setPen(QPen(palette().dark(), sep_sz)); | ||
435 | painter.fillRect(x_shift, 0, tot_w, sep_sz, line_brush); | ||
436 | painter.fillRect(x_shift, h - sep_sz, tot_w, sep_sz, line_brush); | ||
437 | // draw intemediate lines | ||
438 | for(int i = 0; i <= 32; i++) | ||
439 | painter.fillRect(ith_col_x(i), 0, sep_sz, 2 * sep_sz + hdr_h, line_brush); | ||
440 | // draw bottom header lines | ||
441 | painter.fillRect(ith_col_x(0), sep_sz + hdr_h, tot_w, sep_sz, line_brush); | ||
442 | painter.fillRect(ith_col_x(0), tot_hdr_sz + gap_h, tot_w, sep_sz, line_brush); | ||
443 | // redraw some lines but wider | ||
444 | for(int i = 4; i < 32; i += 4) | ||
445 | painter.fillRect(ith_col_x(i) - sep_sz, 0, 3 * sep_sz, tot_hdr_sz, line_brush); | ||
446 | // draw numbers in the header | ||
447 | painter.setPen(palette().brush(QPalette::ButtonText).color()); | ||
448 | for(int i = 0; i < 32; i++) | ||
449 | { | ||
450 | QRect r(ith_col_x(i), sep_sz + margin, col_w, txt_h); | ||
451 | painter.drawText(r, Qt::AlignCenter, QString("%1").arg((31 - i) / 10)); | ||
452 | r.translate(0, txt_h + txt_sep); | ||
453 | painter.drawText(r, Qt::AlignCenter, QString("%1").arg((31 - i) % 10)); | ||
454 | } | ||
455 | // display content | ||
456 | for(size_t i = 0; i < m_reg.GetReg().field.size(); i++) | ||
457 | { | ||
458 | const soc_reg_field_t& field = m_reg.GetReg().field[i]; | ||
459 | QRect r(QPoint(ith_col_x(31 - field.last_bit) + sep_sz, tot_hdr_sz), | ||
460 | QPoint(ith_col_x(32 - field.first_bit), h - sep_sz)); | ||
461 | painter.fillRect(r.x() - sep_sz, r.y(), sep_sz, r.height(), line_brush); | ||
462 | painter.fillRect(r.right(), r.y(), sep_sz, r.height(), line_brush); | ||
463 | r.setY(r.y() + gap_h + sep_sz); | ||
464 | // draw rotated text | ||
465 | painter.save(); | ||
466 | painter.translate(r.bottomLeft()); | ||
467 | painter.rotate(-90); | ||
468 | //painter.fillRect(QRect(0, 0, r.height(), r.width()), QBrush(Qt::red)); | ||
469 | QRect r2(0, 0, r.height(), r.width()); | ||
470 | painter.drawText(r2, Qt::AlignCenter, QString::fromStdString(field.name)); | ||
471 | painter.restore(); | ||
472 | } | ||
473 | #undef ith_col_x | ||
474 | } | ||
475 | |||
476 | /** | ||
477 | * GrowingTextEdit | ||
478 | */ | ||
479 | GrowingTextEdit::GrowingTextEdit(QWidget *parent) | ||
480 | :QTextEdit(parent) | ||
481 | { | ||
482 | connect(this, SIGNAL(textChanged()), this, SLOT(TextChanged())); | ||
483 | setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); | ||
484 | setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); | ||
485 | } | ||
486 | |||
487 | void GrowingTextEdit::TextChanged() | ||
488 | { | ||
489 | int content_size = document()->documentLayout()->documentSize().height(); | ||
490 | content_size = qMax(content_size, fontMetrics().height()); | ||
491 | setFixedHeight(content_size + contentsMargins().top() + contentsMargins().bottom()); | ||
492 | } | ||
493 | |||
494 | /** | ||
495 | * GrowingTableWidget | ||
496 | */ | ||
497 | GrowingTableWidget::GrowingTableWidget(QWidget *parent) | ||
498 | :QTableWidget(parent) | ||
499 | { | ||
500 | connect(model(), SIGNAL(dataChanged(const QModelIndex&, const QModelIndex&)), | ||
501 | this, SLOT(DataChanged(const QModelIndex&, const QModelIndex&))); | ||
502 | } | ||
503 | |||
504 | void GrowingTableWidget::DataChanged(const QModelIndex& tl, const QModelIndex& br) | ||
505 | { | ||
506 | Q_UNUSED(tl); | ||
507 | Q_UNUSED(br); | ||
508 | resizeRowsToContents(); | ||
509 | resizeColumnsToContents(); | ||
510 | int h = contentsMargins().top() + contentsMargins().bottom(); | ||
511 | h += horizontalHeader()->height(); | ||
512 | for(int i = 0; i < rowCount(); i++) | ||
513 | h += rowHeight(i); | ||
514 | setMinimumHeight(h); | ||
515 | } | ||
516 | |||
517 | /** | ||
518 | * MyTextEditor | ||
519 | */ | ||
520 | MyTextEditor::MyTextEditor(QWidget *parent) | ||
521 | :QWidget(parent) | ||
522 | { | ||
523 | QVBoxLayout *layout = new QVBoxLayout; | ||
524 | m_toolbar = new QToolBar(this); | ||
525 | m_edit = new QTextEdit(this); | ||
526 | layout->addWidget(m_toolbar, 0); | ||
527 | layout->addWidget(m_edit, 1); | ||
528 | setLayout(layout); | ||
529 | setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); | ||
530 | |||
531 | m_edit->setAcceptRichText(false); | ||
532 | m_edit->setAutoFormatting(QTextEdit::AutoAll); | ||
533 | |||
534 | m_bold_button = new QToolButton(this); | ||
535 | m_bold_button->setIcon(QIcon::fromTheme("format-text-bold")); | ||
536 | m_bold_button->setText("bold"); | ||
537 | m_bold_button->setCheckable(true); | ||
538 | |||
539 | m_italic_button = new QToolButton(this); | ||
540 | m_italic_button->setIcon(QIcon::fromTheme("format-text-italic")); | ||
541 | m_italic_button->setText("italic"); | ||
542 | m_italic_button->setCheckable(true); | ||
543 | |||
544 | m_underline_button = new QToolButton(this); | ||
545 | m_underline_button->setIcon(QIcon::fromTheme("format-text-underline")); | ||
546 | m_underline_button->setText("underline"); | ||
547 | m_underline_button->setCheckable(true); | ||
548 | |||
549 | m_toolbar->addWidget(m_bold_button); | ||
550 | m_toolbar->addWidget(m_italic_button); | ||
551 | m_toolbar->addWidget(m_underline_button); | ||
552 | |||
553 | connect(m_bold_button, SIGNAL(toggled(bool)), this, SLOT(OnTextBold(bool))); | ||
554 | connect(m_italic_button, SIGNAL(toggled(bool)), this, SLOT(OnTextItalic(bool))); | ||
555 | connect(m_underline_button, SIGNAL(toggled(bool)), this, SLOT(OnTextUnderline(bool))); | ||
556 | connect(m_edit, SIGNAL(textChanged()), this, SLOT(OnInternalTextChanged())); | ||
557 | connect(m_edit, SIGNAL(currentCharFormatChanged(const QTextCharFormat&)), | ||
558 | this, SLOT(OnCharFormatChanged(const QTextCharFormat&))); | ||
559 | |||
560 | SetGrowingMode(false); | ||
561 | SetReadOnly(false); | ||
562 | } | ||
563 | |||
564 | void MyTextEditor::SetReadOnly(bool en) | ||
565 | { | ||
566 | m_read_only = en; | ||
567 | if(en) | ||
568 | m_toolbar->hide(); | ||
569 | else | ||
570 | m_toolbar->hide(); | ||
571 | m_edit->setReadOnly(en); | ||
572 | } | ||
573 | |||
574 | void MyTextEditor::SetGrowingMode(bool en) | ||
575 | { | ||
576 | m_growing_mode = en; | ||
577 | if(en) | ||
578 | { | ||
579 | m_edit->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum); | ||
580 | m_edit->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); | ||
581 | OnTextChanged(); | ||
582 | } | ||
583 | else | ||
584 | { | ||
585 | m_edit->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); | ||
586 | m_edit->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); | ||
587 | } | ||
588 | } | ||
589 | |||
590 | void MyTextEditor::OnInternalTextChanged() | ||
591 | { | ||
592 | if(m_growing_mode) | ||
593 | { | ||
594 | int content_size = m_edit->document()->documentLayout()->documentSize().height(); | ||
595 | content_size = qMax(content_size, m_edit->fontMetrics().height()); | ||
596 | m_edit->setMinimumHeight(content_size + m_edit->contentsMargins().top() + | ||
597 | m_edit->contentsMargins().bottom()); | ||
598 | } | ||
599 | emit OnTextChanged(); | ||
600 | } | ||
601 | |||
602 | void MyTextEditor::OnTextBold(bool checked) | ||
603 | { | ||
604 | QTextCursor cursor = m_edit->textCursor(); | ||
605 | QTextCharFormat fmt = cursor.charFormat(); | ||
606 | fmt.setFontWeight(checked ? QFont::Bold : QFont::Normal); | ||
607 | cursor.setCharFormat(fmt); | ||
608 | m_edit->setTextCursor(cursor); | ||
609 | } | ||
610 | |||
611 | void MyTextEditor::OnTextItalic(bool checked) | ||
612 | { | ||
613 | QTextCursor cursor = m_edit->textCursor(); | ||
614 | QTextCharFormat fmt = cursor.charFormat(); | ||
615 | fmt.setFontItalic(checked); | ||
616 | cursor.setCharFormat(fmt); | ||
617 | m_edit->setTextCursor(cursor); | ||
618 | } | ||
619 | |||
620 | void MyTextEditor::OnTextUnderline(bool checked) | ||
621 | { | ||
622 | QTextCursor cursor = m_edit->textCursor(); | ||
623 | QTextCharFormat fmt = cursor.charFormat(); | ||
624 | fmt.setFontUnderline(checked); | ||
625 | cursor.setCharFormat(fmt); | ||
626 | m_edit->setTextCursor(cursor); | ||
627 | } | ||
628 | |||
629 | void MyTextEditor::OnCharFormatChanged(const QTextCharFormat& fmt) | ||
630 | { | ||
631 | /* NOTE: changing the button states programmaticaly doesn't trigger | ||
632 | * the toggled() signals, otherwise it would result in a loop | ||
633 | * between this function and OnText{Bold,Italic,Underline,...} */ | ||
634 | m_bold_button->setChecked(fmt.fontWeight() > QFont::Normal); | ||
635 | m_italic_button->setChecked(fmt.fontItalic()); | ||
636 | m_underline_button->setChecked(fmt.fontUnderline()); | ||
637 | } | ||
638 | |||
639 | void MyTextEditor::SetTextHtml(const QString& text) | ||
640 | { | ||
641 | m_edit->setHtml(text); | ||
642 | } | ||
643 | |||
644 | QString MyTextEditor::GetTextHtml() | ||
645 | { | ||
646 | return m_edit->toPlainText(); | ||
647 | } | ||
648 | |||
649 | bool MyTextEditor::IsModified() | ||
650 | { | ||
651 | return m_edit->document()->isModified(); | ||
652 | } | ||
653 | |||
654 | /** | ||
655 | * MySwitchableTextEditor | ||
656 | */ | ||
657 | MySwitchableTextEditor::MySwitchableTextEditor(QWidget *parent) | ||
658 | :QWidget(parent) | ||
659 | { | ||
660 | QVBoxLayout *layout = new QVBoxLayout(this); | ||
661 | m_edit = new MyTextEditor(this); | ||
662 | m_label = new QLabel(this); | ||
663 | m_label->setTextFormat(Qt::RichText); | ||
664 | m_label->setAlignment(Qt::AlignTop); | ||
665 | m_line = new QLineEdit(this); | ||
666 | |||
667 | layout->addWidget(m_label); | ||
668 | layout->addWidget(m_edit); | ||
669 | layout->addWidget(m_line); | ||
670 | |||
671 | setLayout(layout); | ||
672 | |||
673 | m_editor_mode = false; | ||
674 | m_line_mode = false; | ||
675 | UpdateVisibility(); | ||
676 | } | ||
677 | |||
678 | void MySwitchableTextEditor::SetEditorMode(bool edit) | ||
679 | { | ||
680 | if(edit == m_editor_mode) | ||
681 | return; | ||
682 | QString text = GetTextHtml(); | ||
683 | m_editor_mode = edit; | ||
684 | UpdateVisibility(); | ||
685 | SetTextHtml(text); | ||
686 | } | ||
687 | |||
688 | QString MySwitchableTextEditor::GetTextHtml() | ||
689 | { | ||
690 | if(m_editor_mode) | ||
691 | return m_line_mode ? m_line->text() : m_edit->GetTextHtml(); | ||
692 | else | ||
693 | return m_label->text(); | ||
694 | } | ||
695 | |||
696 | void MySwitchableTextEditor::SetTextHtml(const QString& text) | ||
697 | { | ||
698 | if(m_editor_mode) | ||
699 | { | ||
700 | if(m_line_mode) | ||
701 | m_line->setText(text); | ||
702 | else | ||
703 | m_edit->SetTextHtml(text); | ||
704 | } | ||
705 | else | ||
706 | m_label->setText(text); | ||
707 | } | ||
708 | |||
709 | MyTextEditor *MySwitchableTextEditor::GetEditor() | ||
710 | { | ||
711 | return m_edit; | ||
712 | } | ||
713 | |||
714 | void MySwitchableTextEditor::SetLineMode(bool en) | ||
715 | { | ||
716 | if(m_line_mode == en) | ||
717 | return; | ||
718 | QString text = GetTextHtml(); | ||
719 | m_line_mode = en; | ||
720 | SetTextHtml(text); | ||
721 | UpdateVisibility(); | ||
722 | } | ||
723 | |||
724 | QLineEdit *MySwitchableTextEditor::GetLineEdit() | ||
725 | { | ||
726 | return m_line; | ||
727 | } | ||
728 | |||
729 | void MySwitchableTextEditor::UpdateVisibility() | ||
730 | { | ||
731 | m_label->setVisible(!m_editor_mode); | ||
732 | m_edit->setVisible(m_editor_mode && !m_line_mode); | ||
733 | m_line->setVisible(m_editor_mode && m_line_mode); | ||
734 | } | ||
735 | |||
736 | QLabel *MySwitchableTextEditor::GetLabel() | ||
737 | { | ||
738 | return m_label; | ||
739 | } | ||
740 | |||
741 | bool MySwitchableTextEditor::IsModified() | ||
742 | { | ||
743 | if(!m_editor_mode) | ||
744 | return false; | ||
745 | return m_line_mode ? m_line->isModified() : m_edit->IsModified(); | ||
746 | } | ||
diff --git a/utils/regtools/qeditor/aux.h b/utils/regtools/qeditor/aux.h new file mode 100644 index 0000000000..d6a572826c --- /dev/null +++ b/utils/regtools/qeditor/aux.h | |||
@@ -0,0 +1,227 @@ | |||
1 | #ifndef AUX_H | ||
2 | #define AUX_H | ||
3 | |||
4 | #include <QEvent> | ||
5 | #include <QPaintEvent> | ||
6 | #include <QLineEdit> | ||
7 | #include <QValidator> | ||
8 | #include <QToolButton> | ||
9 | #include <QMenu> | ||
10 | #include <QHBoxLayout> | ||
11 | #include <QTextEdit> | ||
12 | #include <QTableWidget> | ||
13 | #include <QToolBar> | ||
14 | #include <QLabel> | ||
15 | #include <QHBoxLayout> | ||
16 | #include <QItemEditorCreatorBase> | ||
17 | #include <QStyledItemDelegate> | ||
18 | #include "backend.h" | ||
19 | |||
20 | class SocBitRangeValidator : public QValidator | ||
21 | { | ||
22 | Q_OBJECT | ||
23 | public: | ||
24 | SocBitRangeValidator(QObject *parent = 0); | ||
25 | |||
26 | virtual void fixup(QString& input) const; | ||
27 | virtual State validate(QString& input, int& pos) const; | ||
28 | /* validate and return the interpreted value */ | ||
29 | State parse(const QString& input, int& last_bit, int& first_bit) const; | ||
30 | }; | ||
31 | |||
32 | class SocFieldValidator : public QValidator | ||
33 | { | ||
34 | Q_OBJECT | ||
35 | public: | ||
36 | SocFieldValidator(QObject *parent = 0); | ||
37 | SocFieldValidator(const soc_reg_field_t& field, QObject *parent = 0); | ||
38 | |||
39 | virtual void fixup(QString& input) const; | ||
40 | virtual State validate(QString& input, int& pos) const; | ||
41 | /* validate and return the interpreted value */ | ||
42 | State parse(const QString& input, soc_word_t& val) const; | ||
43 | |||
44 | protected: | ||
45 | soc_reg_field_t m_field; | ||
46 | }; | ||
47 | |||
48 | class RegLineEdit : public QWidget | ||
49 | { | ||
50 | Q_OBJECT | ||
51 | public: | ||
52 | enum EditMode | ||
53 | { | ||
54 | Write, Set, Clear, Toggle | ||
55 | }; | ||
56 | |||
57 | RegLineEdit(QWidget *parent = 0); | ||
58 | ~RegLineEdit(); | ||
59 | void SetReadOnly(bool ro); | ||
60 | void EnableSCT(bool en); | ||
61 | void SetMode(EditMode mode); | ||
62 | EditMode GetMode(); | ||
63 | QLineEdit *GetLineEdit(); | ||
64 | void setText(const QString& text); | ||
65 | QString text() const; | ||
66 | |||
67 | Q_PROPERTY(QString text READ text WRITE setText USER true) | ||
68 | |||
69 | protected slots: | ||
70 | void OnWriteAct(); | ||
71 | void OnSetAct(); | ||
72 | void OnClearAct(); | ||
73 | void OnToggleAct(); | ||
74 | protected: | ||
75 | void ShowMode(bool show); | ||
76 | void DoAutoHide(); | ||
77 | |||
78 | QHBoxLayout *m_layout; | ||
79 | QToolButton *m_button; | ||
80 | QLineEdit *m_edit; | ||
81 | EditMode m_mode; | ||
82 | bool m_has_sct; | ||
83 | bool m_readonly; | ||
84 | QMenu *m_menu; | ||
85 | }; | ||
86 | |||
87 | class SocFieldItemDelegate : public QStyledItemDelegate | ||
88 | { | ||
89 | public: | ||
90 | SocFieldItemDelegate(QObject *parent = 0):QStyledItemDelegate(parent), m_bitcount(32) {} | ||
91 | SocFieldItemDelegate(const soc_reg_field_t& field, QObject *parent = 0) | ||
92 | :QStyledItemDelegate(parent), m_bitcount(field.last_bit - field.first_bit + 1) {} | ||
93 | |||
94 | virtual QString displayText(const QVariant& value, const QLocale& locale) const; | ||
95 | protected: | ||
96 | int m_bitcount; | ||
97 | }; | ||
98 | |||
99 | class SocFieldEditor : public QLineEdit | ||
100 | { | ||
101 | Q_OBJECT | ||
102 | Q_PROPERTY(uint field READ field WRITE setField USER true) | ||
103 | public: | ||
104 | SocFieldEditor(const soc_reg_field_t& field, QWidget *parent = 0); | ||
105 | virtual ~SocFieldEditor(); | ||
106 | |||
107 | uint field() const; | ||
108 | void setField(uint field); | ||
109 | |||
110 | protected: | ||
111 | SocFieldValidator *m_validator; | ||
112 | uint m_field; | ||
113 | soc_reg_field_t m_reg_field; | ||
114 | }; | ||
115 | |||
116 | class SocFieldEditorCreator : public QItemEditorCreatorBase | ||
117 | { | ||
118 | public: | ||
119 | SocFieldEditorCreator() { m_field.first_bit = 0; m_field.last_bit = 31; } | ||
120 | SocFieldEditorCreator(const soc_reg_field_t& field):m_field(field) {} | ||
121 | |||
122 | virtual QWidget *createWidget(QWidget *parent) const; | ||
123 | virtual QByteArray valuePropertyName() const; | ||
124 | |||
125 | protected: | ||
126 | soc_reg_field_t m_field; | ||
127 | }; | ||
128 | |||
129 | class RegSexyDisplay : public QWidget | ||
130 | { | ||
131 | Q_OBJECT | ||
132 | public: | ||
133 | RegSexyDisplay(const SocRegRef& reg, QWidget *parent = 0); | ||
134 | |||
135 | QSize minimumSizeHint() const; | ||
136 | QSize sizeHint() const; | ||
137 | |||
138 | protected: | ||
139 | int marginSize() const; | ||
140 | int separatorSize() const; | ||
141 | int columnWidth() const; | ||
142 | int headerHeight() const; | ||
143 | int gapHeight() const; | ||
144 | int maxContentHeight() const; | ||
145 | int textSep() const; | ||
146 | void paintEvent(QPaintEvent *event); | ||
147 | |||
148 | private: | ||
149 | SocRegRef m_reg; | ||
150 | mutable QSize m_size; | ||
151 | }; | ||
152 | |||
153 | class GrowingTextEdit : public QTextEdit | ||
154 | { | ||
155 | Q_OBJECT | ||
156 | public: | ||
157 | GrowingTextEdit(QWidget *parent = 0); | ||
158 | |||
159 | protected slots: | ||
160 | void TextChanged(); | ||
161 | }; | ||
162 | |||
163 | class GrowingTableWidget : public QTableWidget | ||
164 | { | ||
165 | Q_OBJECT | ||
166 | public: | ||
167 | GrowingTableWidget(QWidget *parent = 0); | ||
168 | |||
169 | protected slots: | ||
170 | void DataChanged(const QModelIndex& tl, const QModelIndex& br); | ||
171 | }; | ||
172 | |||
173 | class MyTextEditor : public QWidget | ||
174 | { | ||
175 | Q_OBJECT | ||
176 | public: | ||
177 | MyTextEditor(QWidget *parent = 0); | ||
178 | void SetGrowingMode(bool en); | ||
179 | void SetReadOnly(bool ro); | ||
180 | void SetTextHtml(const QString& text); | ||
181 | QString GetTextHtml(); | ||
182 | bool IsModified(); | ||
183 | signals: | ||
184 | void OnTextChanged(); | ||
185 | |||
186 | protected slots: | ||
187 | void OnInternalTextChanged(); | ||
188 | void OnTextBold(bool checked); | ||
189 | void OnTextItalic(bool checked); | ||
190 | void OnTextUnderline(bool checked); | ||
191 | void OnCharFormatChanged(const QTextCharFormat& fmt); | ||
192 | |||
193 | protected: | ||
194 | bool m_growing_mode; | ||
195 | bool m_read_only; | ||
196 | QToolBar *m_toolbar; | ||
197 | QTextEdit *m_edit; | ||
198 | QToolButton *m_bold_button; | ||
199 | QToolButton *m_italic_button; | ||
200 | QToolButton *m_underline_button; | ||
201 | }; | ||
202 | |||
203 | class MySwitchableTextEditor : public QWidget | ||
204 | { | ||
205 | Q_OBJECT | ||
206 | public: | ||
207 | MySwitchableTextEditor(QWidget *parent = 0); | ||
208 | QString GetTextHtml(); | ||
209 | void SetTextHtml(const QString& text); | ||
210 | void SetEditorMode(bool en); | ||
211 | MyTextEditor *GetEditor(); | ||
212 | QLineEdit *GetLineEdit(); | ||
213 | QLabel *GetLabel(); | ||
214 | void SetLineMode(bool en); | ||
215 | bool IsModified(); | ||
216 | |||
217 | protected: | ||
218 | void UpdateVisibility(); | ||
219 | |||
220 | bool m_editor_mode; | ||
221 | bool m_line_mode; | ||
222 | QLabel *m_label; | ||
223 | MyTextEditor *m_edit; | ||
224 | QLineEdit *m_line; | ||
225 | }; | ||
226 | |||
227 | #endif /* AUX_H */ | ||
diff --git a/utils/regtools/qeditor/backend.cpp b/utils/regtools/qeditor/backend.cpp index eebda31989..204c160054 100644 --- a/utils/regtools/qeditor/backend.cpp +++ b/utils/regtools/qeditor/backend.cpp | |||
@@ -5,6 +5,36 @@ | |||
5 | #include "backend.h" | 5 | #include "backend.h" |
6 | 6 | ||
7 | /** | 7 | /** |
8 | * SocFile | ||
9 | */ | ||
10 | SocFile::SocFile() | ||
11 | :m_valid(false) | ||
12 | { | ||
13 | } | ||
14 | |||
15 | SocFile::SocFile(const QString& filename) | ||
16 | :m_filename(filename) | ||
17 | { | ||
18 | m_valid = soc_desc_parse_xml(filename.toStdString(), m_soc); | ||
19 | soc_desc_normalize(m_soc); | ||
20 | } | ||
21 | |||
22 | bool SocFile::IsValid() | ||
23 | { | ||
24 | return m_valid; | ||
25 | } | ||
26 | |||
27 | SocRef SocFile::GetSocRef() | ||
28 | { | ||
29 | return SocRef(this); | ||
30 | } | ||
31 | |||
32 | QString SocFile::GetFilename() | ||
33 | { | ||
34 | return m_filename; | ||
35 | } | ||
36 | |||
37 | /** | ||
8 | * Backend | 38 | * Backend |
9 | */ | 39 | */ |
10 | 40 | ||
@@ -12,33 +42,31 @@ Backend::Backend() | |||
12 | { | 42 | { |
13 | } | 43 | } |
14 | 44 | ||
15 | QStringList Backend::GetSocNameList() | 45 | |
46 | QList< SocFileRef > Backend::GetSocFileList() | ||
16 | { | 47 | { |
17 | QStringList sl; | 48 | QList< SocFileRef > list; |
18 | foreach(const soc_t& soc, m_socs) | 49 | for(std::list< SocFile >::iterator it = m_socs.begin(); it != m_socs.end(); ++it) |
19 | sl.append(QString(soc.name.c_str())); | 50 | list.append(SocFileRef(&(*it))); |
20 | return sl; | 51 | return list; |
21 | } | 52 | } |
22 | 53 | ||
23 | bool Backend::GetSocByName(const QString& name, SocRef& s) | 54 | QList< SocRef > Backend::GetSocList() |
24 | { | 55 | { |
25 | for(std::list< soc_t >::iterator it = m_socs.begin(); it != m_socs.end(); ++it) | 56 | QList< SocRef > list; |
26 | if(it->name == name.toStdString()) | 57 | for(std::list< SocFile >::iterator it = m_socs.begin(); it != m_socs.end(); ++it) |
27 | { | 58 | list.append(it->GetSocRef()); |
28 | s = SocRef(&(*it)); | 59 | return list; |
29 | return true; | ||
30 | } | ||
31 | return false; | ||
32 | } | 60 | } |
33 | 61 | ||
34 | bool Backend::LoadSocDesc(const QString& filename) | 62 | bool Backend::LoadSocDesc(const QString& filename) |
35 | { | 63 | { |
36 | std::vector< soc_t > new_socs; | 64 | SocFile f(filename); |
37 | bool ret = soc_desc_parse_xml(filename.toStdString(), new_socs); | 65 | if(!f.IsValid()) |
38 | for(size_t i = 0; i < new_socs.size(); i++) | 66 | return false; |
39 | m_socs.push_back(new_socs[i]); | 67 | m_socs.push_back(f); |
40 | emit OnSocListChanged(); | 68 | emit OnSocListChanged(); |
41 | return ret; | 69 | return true; |
42 | } | 70 | } |
43 | 71 | ||
44 | IoBackend *Backend::CreateFileIoBackend(const QString& filename) | 72 | IoBackend *Backend::CreateFileIoBackend(const QString& filename) |
@@ -321,7 +349,7 @@ HWStubBackendHelper::HWStubBackendHelper() | |||
321 | if(m_hotplug) | 349 | if(m_hotplug) |
322 | { | 350 | { |
323 | m_hotplug = LIBUSB_SUCCESS == libusb_hotplug_register_callback( | 351 | m_hotplug = LIBUSB_SUCCESS == libusb_hotplug_register_callback( |
324 | NULL, LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED | LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT, | 352 | NULL, (libusb_hotplug_event)(LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED | LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT), |
325 | LIBUSB_HOTPLUG_ENUMERATE, HWSTUB_USB_VID, HWSTUB_USB_PID, HWSTUB_CLASS, | 353 | LIBUSB_HOTPLUG_ENUMERATE, HWSTUB_USB_VID, HWSTUB_USB_PID, HWSTUB_CLASS, |
326 | &HWStubBackendHelper::HotPlugCallback, reinterpret_cast< void* >(this), &m_hotplug_handle); | 354 | &HWStubBackendHelper::HotPlugCallback, reinterpret_cast< void* >(this), &m_hotplug_handle); |
327 | } | 355 | } |
@@ -364,6 +392,7 @@ void HWStubBackendHelper::OnHotPlug(bool arrived, struct libusb_device *dev) | |||
364 | int HWStubBackendHelper::HotPlugCallback(struct libusb_context *ctx, struct libusb_device *dev, | 392 | int HWStubBackendHelper::HotPlugCallback(struct libusb_context *ctx, struct libusb_device *dev, |
365 | libusb_hotplug_event event, void *user_data) | 393 | libusb_hotplug_event event, void *user_data) |
366 | { | 394 | { |
395 | Q_UNUSED(ctx); | ||
367 | HWStubBackendHelper *helper = reinterpret_cast< HWStubBackendHelper* >(user_data); | 396 | HWStubBackendHelper *helper = reinterpret_cast< HWStubBackendHelper* >(user_data); |
368 | switch(event) | 397 | switch(event) |
369 | { | 398 | { |
diff --git a/utils/regtools/qeditor/backend.h b/utils/regtools/qeditor/backend.h index 939ed9529f..a813f5929f 100644 --- a/utils/regtools/qeditor/backend.h +++ b/utils/regtools/qeditor/backend.h | |||
@@ -5,10 +5,11 @@ | |||
5 | #include <QStringList> | 5 | #include <QStringList> |
6 | #include <QMap> | 6 | #include <QMap> |
7 | #include <QVector> | 7 | #include <QVector> |
8 | #include "soc_desc.hpp" | 8 | #include <QMetaType> |
9 | #ifdef HAVE_HWSTUB | 9 | #ifdef HAVE_HWSTUB |
10 | #include "hwstub.h" | 10 | #include "hwstub.h" |
11 | #endif | 11 | #endif |
12 | #include "soc.h" | ||
12 | 13 | ||
13 | class IoBackend : public QObject | 14 | class IoBackend : public QObject |
14 | { | 15 | { |
@@ -62,18 +63,18 @@ class DummyIoBackend : public IoBackend | |||
62 | public: | 63 | public: |
63 | DummyIoBackend() {} | 64 | DummyIoBackend() {} |
64 | 65 | ||
65 | virtual bool SupportAccess(AccessType type) { (void) type; return false; } | 66 | virtual bool SupportAccess(AccessType type) { Q_UNUSED(type); return false; } |
66 | virtual QString GetSocName() { return ""; } | 67 | virtual QString GetSocName() { return ""; } |
67 | virtual bool ReadRegister(const QString& name, soc_word_t& value) | 68 | virtual bool ReadRegister(const QString& name, soc_word_t& value) |
68 | { (void) name; (void) value; return false; } | 69 | { Q_UNUSED(name); Q_UNUSED(value); return false; } |
69 | virtual bool ReadRegister(soc_addr_t addr, soc_word_t& value) | 70 | virtual bool ReadRegister(soc_addr_t addr, soc_word_t& value) |
70 | { (void) addr; (void) value; return false; } | 71 | { Q_UNUSED(addr); Q_UNUSED(value); return false; } |
71 | virtual bool Reload() { return false; } | 72 | virtual bool Reload() { return false; } |
72 | virtual bool IsReadOnly() { return true; } | 73 | virtual bool IsReadOnly() { return true; } |
73 | virtual bool WriteRegister(const QString& name, soc_word_t value, WriteMode mode) | 74 | virtual bool WriteRegister(const QString& name, soc_word_t value, WriteMode mode) |
74 | { (void) name; (void) value; (void) mode; return false; } | 75 | { Q_UNUSED(name); Q_UNUSED(value); Q_UNUSED(mode); return false; } |
75 | virtual bool WriteRegister(soc_addr_t addr, soc_word_t value, WriteMode mode) | 76 | virtual bool WriteRegister(soc_addr_t addr, soc_word_t value, WriteMode mode) |
76 | { (void) addr; (void) value; (void) mode; return false; } | 77 | { Q_UNUSED(addr); Q_UNUSED(value); Q_UNUSED(mode); return false; } |
77 | virtual bool IsDirty() { return false; } | 78 | virtual bool IsDirty() { return false; } |
78 | virtual bool Commit() { return false; } | 79 | virtual bool Commit() { return false; } |
79 | }; | 80 | }; |
@@ -90,12 +91,12 @@ public: | |||
90 | virtual QString GetSocName(); | 91 | virtual QString GetSocName(); |
91 | virtual bool ReadRegister(const QString& name, soc_word_t& value); | 92 | virtual bool ReadRegister(const QString& name, soc_word_t& value); |
92 | virtual bool ReadRegister(soc_addr_t addr, soc_word_t& value) | 93 | virtual bool ReadRegister(soc_addr_t addr, soc_word_t& value) |
93 | { (void) addr; (void) value; return false; } | 94 | { Q_UNUSED(addr); Q_UNUSED(value); return false; } |
94 | virtual bool Reload(); | 95 | virtual bool Reload(); |
95 | virtual bool IsReadOnly() { return m_readonly; } | 96 | virtual bool IsReadOnly() { return m_readonly; } |
96 | virtual bool WriteRegister(const QString& name, soc_word_t value, WriteMode mode); | 97 | virtual bool WriteRegister(const QString& name, soc_word_t value, WriteMode mode); |
97 | virtual bool WriteRegister(soc_addr_t addr, soc_word_t value, WriteMode mode) | 98 | virtual bool WriteRegister(soc_addr_t addr, soc_word_t value, WriteMode mode) |
98 | { (void) addr; (void) value; (void) mode; return false; } | 99 | { Q_UNUSED(addr); Q_UNUSED(value); Q_UNUSED(mode); return false; } |
99 | virtual bool IsDirty() { return m_dirty; } | 100 | virtual bool IsDirty() { return m_dirty; } |
100 | virtual bool Commit(); | 101 | virtual bool Commit(); |
101 | 102 | ||
@@ -149,12 +150,12 @@ public: | |||
149 | virtual bool SupportAccess(AccessType type) { return type == ByAddress; } | 150 | virtual bool SupportAccess(AccessType type) { return type == ByAddress; } |
150 | virtual QString GetSocName(); | 151 | virtual QString GetSocName(); |
151 | virtual bool ReadRegister(const QString& name, soc_word_t& value) | 152 | virtual bool ReadRegister(const QString& name, soc_word_t& value) |
152 | { (void) name; (void) value; return false; } | 153 | { Q_UNUSED(name); Q_UNUSED(value); return false; } |
153 | virtual bool ReadRegister(soc_addr_t addr, soc_word_t& value); | 154 | virtual bool ReadRegister(soc_addr_t addr, soc_word_t& value); |
154 | virtual bool Reload(); | 155 | virtual bool Reload(); |
155 | virtual bool IsReadOnly() { return false; } | 156 | virtual bool IsReadOnly() { return false; } |
156 | virtual bool WriteRegister(const QString& name, soc_word_t value, WriteMode mode) | 157 | virtual bool WriteRegister(const QString& name, soc_word_t value, WriteMode mode) |
157 | { (void) name; (void) value; (void) mode; return false; } | 158 | { Q_UNUSED(name); Q_UNUSED(value); Q_UNUSED(mode); return false; } |
158 | virtual bool WriteRegister(soc_addr_t addr, soc_word_t value, WriteMode mode); | 159 | virtual bool WriteRegister(soc_addr_t addr, soc_word_t value, WriteMode mode); |
159 | virtual bool IsDirty() { return false; } | 160 | virtual bool IsDirty() { return false; } |
160 | virtual bool Commit() { return true; } | 161 | virtual bool Commit() { return true; } |
@@ -191,16 +192,48 @@ protected: | |||
191 | }; | 192 | }; |
192 | #endif | 193 | #endif |
193 | 194 | ||
194 | class SocRef | 195 | class SocRef; |
196 | |||
197 | class SocFile | ||
198 | { | ||
199 | public: | ||
200 | SocFile(); | ||
201 | SocFile(const QString& filename); | ||
202 | bool IsValid(); | ||
203 | |||
204 | SocRef GetSocRef(); | ||
205 | QString GetFilename(); | ||
206 | soc_t& GetSoc() { return m_soc; } | ||
207 | |||
208 | protected: | ||
209 | bool m_valid; | ||
210 | QString m_filename; | ||
211 | soc_t m_soc; | ||
212 | }; | ||
213 | |||
214 | class SocFileRef | ||
195 | { | 215 | { |
196 | public: | 216 | public: |
197 | SocRef():m_soc(0) {} | 217 | SocFileRef():m_socfile(0) {} |
198 | SocRef(const soc_t *soc):m_soc(soc) {} | 218 | SocFileRef(SocFile *file):m_socfile(file) {} |
199 | const soc_t& GetSoc() const { return *m_soc; } | 219 | SocFile *GetSocFile() const { return m_socfile; } |
220 | |||
200 | protected: | 221 | protected: |
201 | const soc_t *m_soc; | 222 | SocFile *m_socfile; |
202 | }; | 223 | }; |
203 | 224 | ||
225 | Q_DECLARE_METATYPE(SocFileRef) | ||
226 | |||
227 | class SocRef : public SocFileRef | ||
228 | { | ||
229 | public: | ||
230 | SocRef() {} | ||
231 | SocRef(SocFile *file):SocFileRef(file) {} | ||
232 | soc_t& GetSoc() const { return GetSocFile()->GetSoc(); } | ||
233 | }; | ||
234 | |||
235 | Q_DECLARE_METATYPE(SocRef) | ||
236 | |||
204 | class SocDevRef : public SocRef | 237 | class SocDevRef : public SocRef |
205 | { | 238 | { |
206 | public: | 239 | public: |
@@ -208,9 +241,9 @@ public: | |||
208 | SocDevRef(const SocRef& soc, int dev_idx, int dev_addr_idx) | 241 | SocDevRef(const SocRef& soc, int dev_idx, int dev_addr_idx) |
209 | :SocRef(soc), m_dev_idx(dev_idx), m_dev_addr_idx(dev_addr_idx) {} | 242 | :SocRef(soc), m_dev_idx(dev_idx), m_dev_addr_idx(dev_addr_idx) {} |
210 | int GetDevIndex() const { return m_dev_idx; } | 243 | int GetDevIndex() const { return m_dev_idx; } |
211 | const soc_dev_t& GetDev() const { return GetSoc().dev[GetDevIndex()]; } | 244 | soc_dev_t& GetDev() const { return GetSoc().dev[GetDevIndex()]; } |
212 | int GetDevAddrIndex() const { return m_dev_addr_idx; } | 245 | int GetDevAddrIndex() const { return m_dev_addr_idx; } |
213 | const soc_dev_addr_t& GetDevAddr() const { return GetDev().addr[GetDevAddrIndex()]; } | 246 | soc_dev_addr_t& GetDevAddr() const { return GetDev().addr[GetDevAddrIndex()]; } |
214 | protected: | 247 | protected: |
215 | int m_dev_idx, m_dev_addr_idx; | 248 | int m_dev_idx, m_dev_addr_idx; |
216 | }; | 249 | }; |
@@ -222,9 +255,9 @@ public: | |||
222 | SocRegRef(const SocDevRef& dev, int reg_idx, int reg_addr_idx) | 255 | SocRegRef(const SocDevRef& dev, int reg_idx, int reg_addr_idx) |
223 | :SocDevRef(dev), m_reg_idx(reg_idx), m_reg_addr_idx(reg_addr_idx) {} | 256 | :SocDevRef(dev), m_reg_idx(reg_idx), m_reg_addr_idx(reg_addr_idx) {} |
224 | int GetRegIndex() const { return m_reg_idx; } | 257 | int GetRegIndex() const { return m_reg_idx; } |
225 | const soc_reg_t& GetReg() const { return GetDev().reg[GetRegIndex()]; } | 258 | soc_reg_t& GetReg() const { return GetDev().reg[GetRegIndex()]; } |
226 | int GetRegAddrIndex() const { return m_reg_addr_idx; } | 259 | int GetRegAddrIndex() const { return m_reg_addr_idx; } |
227 | const soc_reg_addr_t& GetRegAddr() const { return GetReg().addr[GetRegAddrIndex()]; } | 260 | soc_reg_addr_t& GetRegAddr() const { return GetReg().addr[GetRegAddrIndex()]; } |
228 | protected: | 261 | protected: |
229 | int m_reg_idx, m_reg_addr_idx; | 262 | int m_reg_idx, m_reg_addr_idx; |
230 | }; | 263 | }; |
@@ -236,7 +269,7 @@ public: | |||
236 | SocFieldRef(const SocRegRef& reg, int field_idx) | 269 | SocFieldRef(const SocRegRef& reg, int field_idx) |
237 | :SocRegRef(reg), m_field_idx(field_idx) {} | 270 | :SocRegRef(reg), m_field_idx(field_idx) {} |
238 | int GetFieldIndex() const { return m_field_idx; } | 271 | int GetFieldIndex() const { return m_field_idx; } |
239 | const soc_reg_field_t& GetField() const { return GetReg().field[GetFieldIndex()]; } | 272 | soc_reg_field_t& GetField() const { return GetReg().field[GetFieldIndex()]; } |
240 | protected: | 273 | protected: |
241 | int m_field_idx; | 274 | int m_field_idx; |
242 | }; | 275 | }; |
@@ -247,9 +280,9 @@ class Backend : public QObject | |||
247 | public: | 280 | public: |
248 | Backend(); | 281 | Backend(); |
249 | 282 | ||
250 | QStringList GetSocNameList(); | 283 | QList< SocFileRef > GetSocFileList(); |
284 | QList< SocRef > GetSocList(); | ||
251 | bool LoadSocDesc(const QString& filename); | 285 | bool LoadSocDesc(const QString& filename); |
252 | bool GetSocByName(const QString& name, SocRef& s); | ||
253 | IoBackend *CreateDummyIoBackend(); | 286 | IoBackend *CreateDummyIoBackend(); |
254 | IoBackend *CreateFileIoBackend(const QString& filename); | 287 | IoBackend *CreateFileIoBackend(const QString& filename); |
255 | #ifdef HAVE_HWSTUB | 288 | #ifdef HAVE_HWSTUB |
@@ -259,7 +292,7 @@ public: | |||
259 | signals: | 292 | signals: |
260 | void OnSocListChanged(); | 293 | void OnSocListChanged(); |
261 | private: | 294 | private: |
262 | std::list< soc_t > m_socs; | 295 | std::list< SocFile > m_socs; |
263 | }; | 296 | }; |
264 | 297 | ||
265 | class BackendHelper | 298 | class BackendHelper |
diff --git a/utils/regtools/qeditor/mainwindow.cpp b/utils/regtools/qeditor/mainwindow.cpp index 2ba781b042..cd0926851c 100644 --- a/utils/regtools/qeditor/mainwindow.cpp +++ b/utils/regtools/qeditor/mainwindow.cpp | |||
@@ -12,6 +12,7 @@ | |||
12 | 12 | ||
13 | #include "mainwindow.h" | 13 | #include "mainwindow.h" |
14 | #include "regtab.h" | 14 | #include "regtab.h" |
15 | #include "regedit.h" | ||
15 | 16 | ||
16 | MyTabWidget::MyTabWidget() | 17 | MyTabWidget::MyTabWidget() |
17 | { | 18 | { |
@@ -20,23 +21,37 @@ MyTabWidget::MyTabWidget() | |||
20 | connect(this, SIGNAL(tabCloseRequested(int)), this, SLOT(OnCloseTab(int))); | 21 | connect(this, SIGNAL(tabCloseRequested(int)), this, SLOT(OnCloseTab(int))); |
21 | } | 22 | } |
22 | 23 | ||
23 | void MyTabWidget::OnCloseTab(int index) | 24 | bool MyTabWidget::CloseTab(int index) |
24 | { | 25 | { |
25 | QWidget *w = this->widget(index); | 26 | QWidget *w = this->widget(index); |
26 | removeTab(index); | 27 | DocumentTab *doc = dynamic_cast< DocumentTab* >(w); |
27 | delete w; | 28 | if(doc->Quit()) |
29 | { | ||
30 | removeTab(index); | ||
31 | delete w; | ||
32 | return true; | ||
33 | } | ||
34 | else | ||
35 | return false; | ||
36 | } | ||
37 | |||
38 | void MyTabWidget::OnCloseTab(int index) | ||
39 | { | ||
40 | CloseTab(index); | ||
28 | } | 41 | } |
29 | 42 | ||
30 | MainWindow::MainWindow(Backend *backend) | 43 | MainWindow::MainWindow(Backend *backend) |
31 | :m_backend(backend) | 44 | :m_backend(backend) |
32 | { | 45 | { |
33 | QAction *new_regtab_act = new QAction(QIcon::fromTheme("document-new"), tr("&Register Tab"), this); | 46 | QAction *new_regtab_act = new QAction(QIcon::fromTheme("document-new"), tr("Register &Tab"), this); |
47 | QAction *new_regedit_act = new QAction(QIcon::fromTheme("document-edit"), tr("Register &Editor"), this); | ||
34 | QAction *load_desc_act = new QAction(QIcon::fromTheme("document-open"), tr("&Soc Description"), this); | 48 | QAction *load_desc_act = new QAction(QIcon::fromTheme("document-open"), tr("&Soc Description"), this); |
35 | QAction *quit_act = new QAction(QIcon::fromTheme("application-exit"), tr("&Quit"), this); | 49 | QAction *quit_act = new QAction(QIcon::fromTheme("application-exit"), tr("&Quit"), this); |
36 | QAction *about_act = new QAction(QIcon::fromTheme("help-about"), tr("&About"), this); | 50 | QAction *about_act = new QAction(QIcon::fromTheme("help-about"), tr("&About"), this); |
37 | QAction *about_qt_act = new QAction(QIcon::fromTheme("help-about"), tr("About &Qt"), this); | 51 | QAction *about_qt_act = new QAction(QIcon::fromTheme("help-about"), tr("About &Qt"), this); |
38 | 52 | ||
39 | connect(new_regtab_act, SIGNAL(triggered()), this, SLOT(OnNewRegTab())); | 53 | connect(new_regtab_act, SIGNAL(triggered()), this, SLOT(OnNewRegTab())); |
54 | connect(new_regedit_act, SIGNAL(triggered()), this, SLOT(OnNewRegEdit())); | ||
40 | connect(load_desc_act, SIGNAL(triggered()), this, SLOT(OnLoadDesc())); | 55 | connect(load_desc_act, SIGNAL(triggered()), this, SLOT(OnLoadDesc())); |
41 | connect(quit_act, SIGNAL(triggered()), this, SLOT(OnQuit())); | 56 | connect(quit_act, SIGNAL(triggered()), this, SLOT(OnQuit())); |
42 | connect(about_act, SIGNAL(triggered()), this, SLOT(OnAbout())); | 57 | connect(about_act, SIGNAL(triggered()), this, SLOT(OnAbout())); |
@@ -48,6 +63,7 @@ MainWindow::MainWindow(Backend *backend) | |||
48 | file_menu->addAction(quit_act); | 63 | file_menu->addAction(quit_act); |
49 | 64 | ||
50 | new_submenu->addAction(new_regtab_act); | 65 | new_submenu->addAction(new_regtab_act); |
66 | new_submenu->addAction(new_regedit_act); | ||
51 | 67 | ||
52 | load_submenu->addAction(load_desc_act); | 68 | load_submenu->addAction(load_desc_act); |
53 | 69 | ||
@@ -91,6 +107,8 @@ void MainWindow::OnAboutQt() | |||
91 | 107 | ||
92 | void MainWindow::closeEvent(QCloseEvent *event) | 108 | void MainWindow::closeEvent(QCloseEvent *event) |
93 | { | 109 | { |
110 | if(!Quit()) | ||
111 | return event->ignore(); | ||
94 | WriteSettings(); | 112 | WriteSettings(); |
95 | event->accept(); | 113 | event->accept(); |
96 | } | 114 | } |
@@ -100,7 +118,7 @@ void MainWindow::OnLoadDesc() | |||
100 | QFileDialog *fd = new QFileDialog(this); | 118 | QFileDialog *fd = new QFileDialog(this); |
101 | fd->setFilter("XML files (*.xml);;All files (*)"); | 119 | fd->setFilter("XML files (*.xml);;All files (*)"); |
102 | fd->setFileMode(QFileDialog::ExistingFiles); | 120 | fd->setFileMode(QFileDialog::ExistingFiles); |
103 | fd->setDirectory(Settings::Get()->value("mainwindow/loaddescdir", QDir::currentPath()).toString()); | 121 | fd->setDirectory(Settings::Get()->value("loaddescdir", QDir::currentPath()).toString()); |
104 | if(fd->exec()) | 122 | if(fd->exec()) |
105 | { | 123 | { |
106 | QStringList filenames = fd->selectedFiles(); | 124 | QStringList filenames = fd->selectedFiles(); |
@@ -111,11 +129,42 @@ void MainWindow::OnLoadDesc() | |||
111 | msg.setText(QString("Cannot load ") + filenames[i]); | 129 | msg.setText(QString("Cannot load ") + filenames[i]); |
112 | msg.exec(); | 130 | msg.exec(); |
113 | } | 131 | } |
114 | Settings::Get()->setValue("mainwindow/loaddescdir", fd->directory().absolutePath()); | 132 | Settings::Get()->setValue("loaddescdir", fd->directory().absolutePath()); |
115 | } | 133 | } |
116 | } | 134 | } |
117 | 135 | ||
136 | void MainWindow::OnTabModified(bool modified) | ||
137 | { | ||
138 | QWidget *sender = qobject_cast< QWidget* >(QObject::sender()); | ||
139 | int index = m_tab->indexOf(sender); | ||
140 | if(modified) | ||
141 | m_tab->setTabIcon(index, QIcon::fromTheme("document-save")); | ||
142 | else | ||
143 | m_tab->setTabIcon(index, QIcon()); | ||
144 | } | ||
145 | |||
146 | void MainWindow::AddTab(QWidget *tab, const QString& title) | ||
147 | { | ||
148 | connect(tab, SIGNAL(OnModified(bool)), this, SLOT(OnTabModified(bool))); | ||
149 | m_tab->setCurrentIndex(m_tab->addTab(tab, title)); | ||
150 | } | ||
151 | |||
118 | void MainWindow::OnNewRegTab() | 152 | void MainWindow::OnNewRegTab() |
119 | { | 153 | { |
120 | m_tab->addTab(new RegTab(m_backend), "Register Tab"); | 154 | AddTab(new RegTab(m_backend, this), "Register Tab"); |
155 | } | ||
156 | |||
157 | void MainWindow::OnNewRegEdit() | ||
158 | { | ||
159 | AddTab(new RegEdit(m_backend, this), "Register Editor"); | ||
160 | } | ||
161 | |||
162 | bool MainWindow::Quit() | ||
163 | { | ||
164 | while(m_tab->count() > 0) | ||
165 | { | ||
166 | if(!m_tab->CloseTab(0)) | ||
167 | return false; | ||
168 | } | ||
169 | return true; | ||
121 | } | 170 | } |
diff --git a/utils/regtools/qeditor/mainwindow.h b/utils/regtools/qeditor/mainwindow.h index d7dab3717f..b32b0647f5 100644 --- a/utils/regtools/qeditor/mainwindow.h +++ b/utils/regtools/qeditor/mainwindow.h | |||
@@ -7,11 +7,19 @@ | |||
7 | #include "backend.h" | 7 | #include "backend.h" |
8 | #include "settings.h" | 8 | #include "settings.h" |
9 | 9 | ||
10 | class DocumentTab | ||
11 | { | ||
12 | public: | ||
13 | virtual bool Quit() = 0; | ||
14 | virtual void OnModified(bool modified) = 0; | ||
15 | }; | ||
16 | |||
10 | class MyTabWidget : public QTabWidget | 17 | class MyTabWidget : public QTabWidget |
11 | { | 18 | { |
12 | Q_OBJECT | 19 | Q_OBJECT |
13 | public: | 20 | public: |
14 | MyTabWidget(); | 21 | MyTabWidget(); |
22 | bool CloseTab(int index); | ||
15 | 23 | ||
16 | private slots: | 24 | private slots: |
17 | void OnCloseTab(int index); | 25 | void OnCloseTab(int index); |
@@ -30,15 +38,21 @@ public: | |||
30 | private: | 38 | private: |
31 | void closeEvent(QCloseEvent *event); | 39 | void closeEvent(QCloseEvent *event); |
32 | 40 | ||
41 | protected: | ||
42 | void AddTab(QWidget *tab, const QString& title); | ||
43 | bool Quit(); | ||
44 | |||
33 | private slots: | 45 | private slots: |
34 | void OnQuit(); | 46 | void OnQuit(); |
35 | void OnAbout(); | 47 | void OnAbout(); |
36 | void OnAboutQt(); | 48 | void OnAboutQt(); |
37 | void OnLoadDesc(); | 49 | void OnLoadDesc(); |
38 | void OnNewRegTab(); | 50 | void OnNewRegTab(); |
51 | void OnNewRegEdit(); | ||
52 | void OnTabModified(bool modified); | ||
39 | 53 | ||
40 | private: | 54 | private: |
41 | QTabWidget *m_tab; | 55 | MyTabWidget *m_tab; |
42 | Backend *m_backend; | 56 | Backend *m_backend; |
43 | }; | 57 | }; |
44 | 58 | ||
diff --git a/utils/regtools/qeditor/qeditor.pro b/utils/regtools/qeditor/qeditor.pro index 5604fe9d41..38d7c987bf 100644 --- a/utils/regtools/qeditor/qeditor.pro +++ b/utils/regtools/qeditor/qeditor.pro | |||
@@ -1,7 +1,9 @@ | |||
1 | QT += widgets | 1 | QT += widgets |
2 | 2 | ||
3 | HEADERS += mainwindow.h backend.h regtab.h analyser.h settings.h std_analysers.h | 3 | HEADERS += mainwindow.h backend.h regtab.h analyser.h settings.h \ |
4 | SOURCES += main.cpp mainwindow.cpp regtab.cpp backend.cpp analyser.cpp std_analysers.cpp settings.cpp | 4 | std_analysers.h aux.h regdisplaypanel.h regedit.h |
5 | SOURCES += main.cpp mainwindow.cpp regtab.cpp backend.cpp analyser.cpp \ | ||
6 | std_analysers.cpp settings.cpp aux.cpp regdisplaypanel.cpp regedit.cpp | ||
5 | LIBS += -L../lib/ -lsocdesc -lxml2 | 7 | LIBS += -L../lib/ -lsocdesc -lxml2 |
6 | INCLUDEPATH += ../lib/ ../../hwstub/lib | 8 | INCLUDEPATH += ../lib/ ../../hwstub/lib |
7 | 9 | ||
diff --git a/utils/regtools/qeditor/regdisplaypanel.cpp b/utils/regtools/qeditor/regdisplaypanel.cpp new file mode 100644 index 0000000000..cef5f9807b --- /dev/null +++ b/utils/regtools/qeditor/regdisplaypanel.cpp | |||
@@ -0,0 +1,314 @@ | |||
1 | #include "regdisplaypanel.h" | ||
2 | #include <QHeaderView> | ||
3 | #include <QDebug> | ||
4 | |||
5 | /** | ||
6 | * RegItemEditorCreator | ||
7 | */ | ||
8 | |||
9 | QWidget *RegItemEditorCreator::createWidget(QWidget * parent) const | ||
10 | { | ||
11 | return new RegLineEdit(parent); | ||
12 | } | ||
13 | |||
14 | QByteArray RegItemEditorCreator::valuePropertyName () const | ||
15 | { | ||
16 | return QByteArray("text"); | ||
17 | } | ||
18 | |||
19 | /** | ||
20 | * DevDisplayPanel | ||
21 | */ | ||
22 | DevDisplayPanel::DevDisplayPanel(QWidget *parent, const SocDevRef& dev_ref) | ||
23 | :QGroupBox(parent), m_dev(dev_ref), m_reg_font(font()) | ||
24 | { | ||
25 | QVBoxLayout *right_layout = new QVBoxLayout; | ||
26 | const soc_dev_addr_t& dev_addr = m_dev.GetDevAddr(); | ||
27 | |||
28 | m_reg_font.setWeight(100); | ||
29 | m_reg_font.setKerning(false); | ||
30 | |||
31 | QString dev_name; | ||
32 | dev_name.sprintf("HW_%s_BASE", dev_addr.name.c_str()); | ||
33 | |||
34 | QLabel *label_names = new QLabel("<b>" + dev_name + "</b>"); | ||
35 | label_names->setTextFormat(Qt::RichText); | ||
36 | |||
37 | QLabel *label_addr = new QLabel("<b>" + QString().sprintf("0x%03x", dev_addr.addr) + "</b>"); | ||
38 | label_addr->setTextFormat(Qt::RichText); | ||
39 | |||
40 | QHBoxLayout *top_layout = new QHBoxLayout; | ||
41 | top_layout->addStretch(); | ||
42 | top_layout->addWidget(label_names); | ||
43 | top_layout->addWidget(label_addr); | ||
44 | top_layout->addStretch(); | ||
45 | |||
46 | m_name = new QLabel(this); | ||
47 | m_name->setTextFormat(Qt::RichText); | ||
48 | m_name->setText("<h1>" + QString::fromStdString(m_dev.GetDev().long_name) + "</h1>"); | ||
49 | |||
50 | m_desc = new QLabel(this); | ||
51 | m_name->setTextFormat(Qt::RichText); | ||
52 | m_desc->setText(QString::fromStdString(m_dev.GetDev().desc)); | ||
53 | |||
54 | right_layout->addLayout(top_layout, 0); | ||
55 | right_layout->addWidget(m_name, 0); | ||
56 | right_layout->addWidget(m_desc, 0); | ||
57 | right_layout->addStretch(1); | ||
58 | |||
59 | setTitle("Device Description"); | ||
60 | setLayout(right_layout); | ||
61 | } | ||
62 | |||
63 | void DevDisplayPanel::AllowWrite(bool en) | ||
64 | { | ||
65 | Q_UNUSED(en); | ||
66 | } | ||
67 | |||
68 | QWidget *DevDisplayPanel::GetWidget() | ||
69 | { | ||
70 | return this; | ||
71 | } | ||
72 | |||
73 | /** | ||
74 | * RegDisplayPanel | ||
75 | */ | ||
76 | |||
77 | RegDisplayPanel::RegDisplayPanel(QWidget *parent, IoBackend *io_backend, const SocRegRef& reg_ref) | ||
78 | :QGroupBox(parent), m_io_backend(io_backend), m_reg(reg_ref), m_reg_font(font()) | ||
79 | { | ||
80 | bool read_only = m_io_backend->IsReadOnly(); | ||
81 | |||
82 | QVBoxLayout *right_layout = new QVBoxLayout; | ||
83 | |||
84 | const soc_dev_addr_t& dev_addr = m_reg.GetDevAddr(); | ||
85 | const soc_reg_t& reg = m_reg.GetReg(); | ||
86 | const soc_reg_addr_t& reg_addr = m_reg.GetRegAddr(); | ||
87 | |||
88 | m_reg_font.setWeight(100); | ||
89 | m_reg_font.setKerning(false); | ||
90 | |||
91 | QString reg_name; | ||
92 | reg_name.sprintf("HW_%s_%s", dev_addr.name.c_str(), reg_addr.name.c_str()); | ||
93 | QStringList names; | ||
94 | QVector< soc_addr_t > addresses; | ||
95 | names.append(reg_name); | ||
96 | addresses.append(reg_addr.addr); | ||
97 | if(reg.flags & REG_HAS_SCT) | ||
98 | { | ||
99 | names.append(reg_name + "_SET"); | ||
100 | names.append(reg_name + "_CLR"); | ||
101 | names.append(reg_name + "_TOG"); | ||
102 | addresses.append(reg_addr.addr + 4); | ||
103 | addresses.append(reg_addr.addr + 8); | ||
104 | addresses.append(reg_addr.addr + 12); | ||
105 | } | ||
106 | |||
107 | QString str; | ||
108 | str += "<table align=left>"; | ||
109 | for(int i = 0; i < names.size(); i++) | ||
110 | str += "<tr><td><b>" + names[i] + "</b></td></tr>"; | ||
111 | str += "</table>"; | ||
112 | QLabel *label_names = new QLabel; | ||
113 | label_names->setTextFormat(Qt::RichText); | ||
114 | label_names->setText(str); | ||
115 | |||
116 | QString str_addr; | ||
117 | str_addr += "<table align=left>"; | ||
118 | for(int i = 0; i < names.size(); i++) | ||
119 | str_addr += "<tr><td><b>" + QString().sprintf("0x%03x", addresses[i]) + "</b></td></tr>"; | ||
120 | str_addr += "</table>"; | ||
121 | QLabel *label_addr = new QLabel; | ||
122 | label_addr->setTextFormat(Qt::RichText); | ||
123 | label_addr->setText(str_addr); | ||
124 | |||
125 | QHBoxLayout *top_layout = new QHBoxLayout; | ||
126 | top_layout->addStretch(); | ||
127 | top_layout->addWidget(label_names); | ||
128 | top_layout->addWidget(label_addr); | ||
129 | top_layout->addStretch(); | ||
130 | |||
131 | m_raw_val_name = new QLabel; | ||
132 | m_raw_val_name->setText("Raw value:"); | ||
133 | m_raw_val_edit = new RegLineEdit; | ||
134 | m_raw_val_edit->SetReadOnly(read_only); | ||
135 | m_raw_val_edit->GetLineEdit()->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter); | ||
136 | m_raw_val_edit->GetLineEdit()->setValidator(new SocFieldValidator(m_raw_val_edit)); | ||
137 | m_raw_val_edit->EnableSCT(!!(reg.flags & REG_HAS_SCT)); | ||
138 | m_raw_val_edit->GetLineEdit()->setFont(m_reg_font); | ||
139 | connect(m_raw_val_edit->GetLineEdit(), SIGNAL(returnPressed()), this, SLOT(OnRawRegValueReturnPressed())); | ||
140 | QHBoxLayout *raw_val_layout = new QHBoxLayout; | ||
141 | raw_val_layout->addStretch(); | ||
142 | raw_val_layout->addWidget(m_raw_val_name); | ||
143 | raw_val_layout->addWidget(m_raw_val_edit); | ||
144 | raw_val_layout->addStretch(); | ||
145 | |||
146 | m_value_table = new GrowingTableWidget; | ||
147 | m_value_table->setRowCount(reg.field.size()); | ||
148 | m_value_table->setColumnCount(5); | ||
149 | for(size_t row = 0; row < reg.field.size(); row++) | ||
150 | { | ||
151 | const soc_reg_field_t& field = reg.field[row]; | ||
152 | QString bits_str; | ||
153 | if(field.first_bit == field.last_bit) | ||
154 | bits_str.sprintf("%d", field.first_bit); | ||
155 | else | ||
156 | bits_str.sprintf("%d:%d", field.last_bit, field.first_bit); | ||
157 | QTableWidgetItem *item = new QTableWidgetItem(bits_str); | ||
158 | item->setTextAlignment(Qt::AlignVCenter | Qt::AlignHCenter); | ||
159 | item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); | ||
160 | m_value_table->setItem(row, 0, item); | ||
161 | item = new QTableWidgetItem(QString(field.name.c_str())); | ||
162 | item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); | ||
163 | m_value_table->setItem(row, 1, item); | ||
164 | item = new QTableWidgetItem(QString(field.desc.c_str())); | ||
165 | item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); | ||
166 | m_value_table->setItem(row, 4, item); | ||
167 | } | ||
168 | m_value_table->setHorizontalHeaderItem(0, new QTableWidgetItem("Bits")); | ||
169 | m_value_table->setHorizontalHeaderItem(1, new QTableWidgetItem("Name")); | ||
170 | m_value_table->setHorizontalHeaderItem(2, new QTableWidgetItem("Value")); | ||
171 | m_value_table->setHorizontalHeaderItem(3, new QTableWidgetItem("Meaning")); | ||
172 | m_value_table->setHorizontalHeaderItem(4, new QTableWidgetItem("Description")); | ||
173 | m_value_table->verticalHeader()->setVisible(false); | ||
174 | m_value_table->resizeColumnsToContents(); | ||
175 | m_value_table->horizontalHeader()->setStretchLastSection(true); | ||
176 | m_value_table->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); | ||
177 | |||
178 | m_table_delegate = new QStyledItemDelegate(this); | ||
179 | m_table_edit_factory = new QItemEditorFactory(); | ||
180 | m_regedit_creator = new RegItemEditorCreator(); | ||
181 | m_table_edit_factory->registerEditor(QVariant::String, m_regedit_creator); | ||
182 | m_table_delegate->setItemEditorFactory(m_table_edit_factory); | ||
183 | m_value_table->setItemDelegate(m_table_delegate); | ||
184 | |||
185 | m_sexy_display = new RegSexyDisplay(reg_ref, this); | ||
186 | m_sexy_display->setFont(m_reg_font); | ||
187 | |||
188 | m_desc = new QLabel(this); | ||
189 | m_desc->setTextFormat(Qt::RichText); | ||
190 | m_desc->setText(QString::fromStdString(m_reg.GetReg().desc)); | ||
191 | |||
192 | right_layout->addWidget(m_desc); | ||
193 | right_layout->addLayout(top_layout); | ||
194 | if(raw_val_layout) | ||
195 | right_layout->addLayout(raw_val_layout); | ||
196 | right_layout->addWidget(m_sexy_display); | ||
197 | right_layout->addWidget(m_value_table); | ||
198 | |||
199 | setTitle("Register Description"); | ||
200 | m_viewport = new QWidget; | ||
201 | m_viewport->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); | ||
202 | m_viewport->setLayout(right_layout); | ||
203 | m_scroll = new QScrollArea; | ||
204 | m_scroll->setWidget(m_viewport); | ||
205 | m_scroll->setWidgetResizable(true); | ||
206 | m_scroll->setFrameShape(QFrame::NoFrame); | ||
207 | QHBoxLayout *layout = new QHBoxLayout; | ||
208 | layout->addWidget(m_scroll, 1); | ||
209 | setLayout(layout); | ||
210 | AllowWrite(false); | ||
211 | |||
212 | // load data | ||
213 | Reload(); | ||
214 | } | ||
215 | |||
216 | RegDisplayPanel::~RegDisplayPanel() | ||
217 | { | ||
218 | delete m_table_edit_factory; | ||
219 | } | ||
220 | |||
221 | void RegDisplayPanel::Reload() | ||
222 | { | ||
223 | const soc_dev_addr_t& dev_addr = m_reg.GetDevAddr(); | ||
224 | const soc_reg_t& reg = m_reg.GetReg(); | ||
225 | const soc_reg_addr_t& reg_addr = m_reg.GetRegAddr(); | ||
226 | soc_word_t value; | ||
227 | BackendHelper helper(m_io_backend, m_reg); | ||
228 | bool has_value = helper.ReadRegister(dev_addr.name.c_str(), reg_addr.name.c_str(), value); | ||
229 | |||
230 | if(has_value) | ||
231 | { | ||
232 | m_raw_val_name->show(); | ||
233 | m_raw_val_edit->show(); | ||
234 | m_raw_val_edit->GetLineEdit()->setText(QString().sprintf("0x%08x", value)); | ||
235 | } | ||
236 | else | ||
237 | { | ||
238 | m_raw_val_name->hide(); | ||
239 | m_raw_val_edit->hide(); | ||
240 | } | ||
241 | |||
242 | int row = 0; | ||
243 | foreach(const soc_reg_field_t& field, reg.field) | ||
244 | { | ||
245 | QTableWidgetItem *item = new QTableWidgetItem(); | ||
246 | QTableWidgetItem *desc_item = new QTableWidgetItem(); | ||
247 | if(has_value) | ||
248 | { | ||
249 | soc_word_t v = (value & field.bitmask()) >> field.first_bit; | ||
250 | QString value_name; | ||
251 | foreach(const soc_reg_field_value_t& rval, field.value) | ||
252 | if(v == rval.value) | ||
253 | value_name = rval.name.c_str(); | ||
254 | const char *fmt = "%lu"; | ||
255 | // heuristic | ||
256 | if((field.last_bit - field.first_bit + 1) > 16) | ||
257 | fmt = "0x%lx"; | ||
258 | item->setText(QString().sprintf(fmt, (unsigned long)v)); | ||
259 | item->setTextAlignment(Qt::AlignVCenter | Qt::AlignHCenter); | ||
260 | |||
261 | if(value_name.size() != 0) | ||
262 | { | ||
263 | desc_item->setText(value_name); | ||
264 | desc_item->setTextAlignment(Qt::AlignVCenter | Qt::AlignHCenter); | ||
265 | } | ||
266 | } | ||
267 | item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); | ||
268 | desc_item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); | ||
269 | m_value_table->setItem(row, 2, item); | ||
270 | m_value_table->setItem(row, 3, desc_item); | ||
271 | row++; | ||
272 | } | ||
273 | } | ||
274 | |||
275 | void RegDisplayPanel::AllowWrite(bool en) | ||
276 | { | ||
277 | m_allow_write = en; | ||
278 | if(m_raw_val_edit) | ||
279 | m_raw_val_edit->SetReadOnly(m_io_backend->IsReadOnly() || !m_allow_write); | ||
280 | } | ||
281 | |||
282 | IoBackend::WriteMode RegDisplayPanel::EditModeToWriteMode(RegLineEdit::EditMode mode) | ||
283 | { | ||
284 | switch(mode) | ||
285 | { | ||
286 | case RegLineEdit::Write: return IoBackend::Write; | ||
287 | case RegLineEdit::Set: return IoBackend::Set; | ||
288 | case RegLineEdit::Clear: return IoBackend::Clear; | ||
289 | case RegLineEdit::Toggle: return IoBackend::Toggle; | ||
290 | default: return IoBackend::Write; | ||
291 | } | ||
292 | } | ||
293 | |||
294 | void RegDisplayPanel::OnRawRegValueReturnPressed() | ||
295 | { | ||
296 | soc_word_t val; | ||
297 | QLineEdit *edit = m_raw_val_edit->GetLineEdit(); | ||
298 | const SocFieldValidator *validator = dynamic_cast< const SocFieldValidator *>(edit->validator()); | ||
299 | QValidator::State state = validator->parse(edit->text(), val); | ||
300 | if(state != QValidator::Acceptable) | ||
301 | return; | ||
302 | IoBackend::WriteMode mode = EditModeToWriteMode(m_raw_val_edit->GetMode()); | ||
303 | BackendHelper helper(m_io_backend, m_reg); | ||
304 | helper.WriteRegister(m_reg.GetDevAddr().name.c_str(), m_reg.GetRegAddr().name.c_str(), | ||
305 | val, mode); | ||
306 | // FIXME: we should notify the UI to read value back because it has changed | ||
307 | Reload(); | ||
308 | } | ||
309 | |||
310 | QWidget *RegDisplayPanel::GetWidget() | ||
311 | { | ||
312 | return this; | ||
313 | } | ||
314 | |||
diff --git a/utils/regtools/qeditor/regdisplaypanel.h b/utils/regtools/qeditor/regdisplaypanel.h new file mode 100644 index 0000000000..444f3615f2 --- /dev/null +++ b/utils/regtools/qeditor/regdisplaypanel.h | |||
@@ -0,0 +1,77 @@ | |||
1 | #ifndef REGDISPLAYPANEL_H | ||
2 | #define REGDISPLAYPANEL_H | ||
3 | |||
4 | #include <QVBoxLayout> | ||
5 | #include <QLabel> | ||
6 | #include <QGroupBox> | ||
7 | #include <QTableWidget> | ||
8 | #include <QStyledItemDelegate> | ||
9 | #include <QItemEditorCreatorBase> | ||
10 | #include <QTextEdit> | ||
11 | #include <QScrollArea> | ||
12 | #include <soc_desc.hpp> | ||
13 | #include "backend.h" | ||
14 | #include "settings.h" | ||
15 | #include "aux.h" | ||
16 | #include "regtab.h" | ||
17 | |||
18 | class RegItemEditorCreator : public QItemEditorCreatorBase | ||
19 | { | ||
20 | public: | ||
21 | RegItemEditorCreator() {} | ||
22 | virtual QWidget *createWidget(QWidget * parent) const; | ||
23 | virtual QByteArray valuePropertyName () const; | ||
24 | }; | ||
25 | |||
26 | class DevDisplayPanel : public QGroupBox, public RegTabPanel | ||
27 | { | ||
28 | Q_OBJECT | ||
29 | public: | ||
30 | DevDisplayPanel(QWidget *parent, const SocDevRef& reg); | ||
31 | void Reload(); | ||
32 | void AllowWrite(bool en); | ||
33 | QWidget *GetWidget(); | ||
34 | bool Quit(); | ||
35 | |||
36 | protected: | ||
37 | |||
38 | const SocDevRef& m_dev; | ||
39 | QFont m_reg_font; | ||
40 | QLabel *m_name; | ||
41 | QLabel *m_desc; | ||
42 | }; | ||
43 | |||
44 | class RegDisplayPanel : public QGroupBox, public RegTabPanel | ||
45 | { | ||
46 | Q_OBJECT | ||
47 | public: | ||
48 | RegDisplayPanel(QWidget *parent, IoBackend *io_backend, const SocRegRef& reg); | ||
49 | ~RegDisplayPanel(); | ||
50 | void AllowWrite(bool en); | ||
51 | void Reload(); | ||
52 | QWidget *GetWidget(); | ||
53 | bool Quit(); | ||
54 | |||
55 | protected: | ||
56 | IoBackend::WriteMode EditModeToWriteMode(RegLineEdit::EditMode mode); | ||
57 | |||
58 | IoBackend *m_io_backend; | ||
59 | const SocRegRef& m_reg; | ||
60 | bool m_allow_write; | ||
61 | RegLineEdit *m_raw_val_edit; | ||
62 | RegSexyDisplay *m_sexy_display; | ||
63 | GrowingTableWidget *m_value_table; | ||
64 | QStyledItemDelegate *m_table_delegate; | ||
65 | QItemEditorFactory *m_table_edit_factory; | ||
66 | RegItemEditorCreator *m_regedit_creator; | ||
67 | QLabel *m_raw_val_name; | ||
68 | QFont m_reg_font; | ||
69 | QLabel *m_desc; | ||
70 | QWidget *m_viewport; | ||
71 | QScrollArea *m_scroll; | ||
72 | |||
73 | private slots: | ||
74 | void OnRawRegValueReturnPressed(); | ||
75 | }; | ||
76 | |||
77 | #endif /* REGDISPLAYPANEL_H */ | ||
diff --git a/utils/regtools/qeditor/regedit.cpp b/utils/regtools/qeditor/regedit.cpp new file mode 100644 index 0000000000..5e498ce496 --- /dev/null +++ b/utils/regtools/qeditor/regedit.cpp | |||
@@ -0,0 +1,1324 @@ | |||
1 | #include "regedit.h" | ||
2 | #include <QFileDialog> | ||
3 | #include <QDebug> | ||
4 | #include <QHeaderView> | ||
5 | #include <QMessageBox> | ||
6 | #include <QInputDialog> | ||
7 | |||
8 | /** | ||
9 | * EmptyEditPanel | ||
10 | */ | ||
11 | EmptyEditPanel::EmptyEditPanel(QWidget *parent) | ||
12 | :QWidget(parent) | ||
13 | { | ||
14 | } | ||
15 | |||
16 | /** | ||
17 | * SocEditPanel | ||
18 | */ | ||
19 | SocEditPanel::SocEditPanel(SocRef ref, QWidget *parent) | ||
20 | :QWidget(parent), m_ref(ref) | ||
21 | { | ||
22 | m_name_group = new QGroupBox("Name", this); | ||
23 | m_name_edit = new QLineEdit(this); | ||
24 | m_name_edit->setText(QString::fromStdString(ref.GetSoc().name)); | ||
25 | QVBoxLayout *name_group_layout = new QVBoxLayout; | ||
26 | name_group_layout->addWidget(m_name_edit); | ||
27 | m_name_group->setLayout(name_group_layout); | ||
28 | |||
29 | m_desc_group = new QGroupBox("Description", this); | ||
30 | QHBoxLayout *group_layout = new QHBoxLayout; | ||
31 | m_desc_edit = new MyTextEditor(this); | ||
32 | m_desc_edit->SetTextHtml(QString::fromStdString(ref.GetSoc().desc)); | ||
33 | group_layout->addWidget(m_desc_edit); | ||
34 | m_desc_group->setLayout(group_layout); | ||
35 | |||
36 | QVBoxLayout *layout = new QVBoxLayout; | ||
37 | layout->addWidget(m_name_group); | ||
38 | layout->addWidget(m_desc_group); | ||
39 | layout->addStretch(1); | ||
40 | |||
41 | connect(m_name_edit, SIGNAL(textChanged(const QString&)), this, SLOT(OnNameEdited(const QString&))); | ||
42 | connect(m_desc_edit, SIGNAL(OnTextChanged()), this, SLOT(OnTextEdited())); | ||
43 | |||
44 | setLayout(layout); | ||
45 | } | ||
46 | |||
47 | void SocEditPanel::OnNameEdited(const QString& text) | ||
48 | { | ||
49 | m_ref.GetSoc().name = text.toStdString(); | ||
50 | emit OnModified(m_name_edit->isModified()); | ||
51 | } | ||
52 | |||
53 | void SocEditPanel::OnTextEdited() | ||
54 | { | ||
55 | m_ref.GetSoc().desc = m_desc_edit->GetTextHtml().toStdString(); | ||
56 | emit OnModified(m_desc_edit->IsModified()); | ||
57 | } | ||
58 | |||
59 | /** | ||
60 | * DevEditPanel | ||
61 | */ | ||
62 | DevEditPanel::DevEditPanel(SocDevRef ref, QWidget *parent) | ||
63 | :QWidget(parent), m_ref(ref) | ||
64 | { | ||
65 | m_name_group = new QGroupBox("Name", this); | ||
66 | m_name_edit = new QLineEdit(this); | ||
67 | m_name_edit->setText(QString::fromStdString(ref.GetDev().name)); | ||
68 | QVBoxLayout *name_group_layout = new QVBoxLayout; | ||
69 | name_group_layout->addWidget(m_name_edit); | ||
70 | m_name_group->setLayout(name_group_layout); | ||
71 | |||
72 | m_long_name_group = new QGroupBox("Long Name", this); | ||
73 | m_long_name_edit = new QLineEdit(this); | ||
74 | m_long_name_edit->setText(QString::fromStdString(ref.GetDev().long_name)); | ||
75 | QVBoxLayout *long_name_group_layout = new QVBoxLayout; | ||
76 | long_name_group_layout->addWidget(m_long_name_edit); | ||
77 | m_long_name_group->setLayout(long_name_group_layout); | ||
78 | |||
79 | m_version_group = new QGroupBox("Version", this); | ||
80 | m_version_edit = new QLineEdit(this); | ||
81 | m_version_edit->setText(QString::fromStdString(ref.GetDev().version)); | ||
82 | QVBoxLayout *version_group_layout = new QVBoxLayout; | ||
83 | version_group_layout->addWidget(m_version_edit); | ||
84 | m_version_group->setLayout(version_group_layout); | ||
85 | |||
86 | QVBoxLayout *name_ver_layout = new QVBoxLayout; | ||
87 | name_ver_layout->addWidget(m_name_group); | ||
88 | name_ver_layout->addWidget(m_long_name_group); | ||
89 | name_ver_layout->addWidget(m_version_group); | ||
90 | name_ver_layout->addStretch(); | ||
91 | |||
92 | m_instances_table = new QTableWidget(this); | ||
93 | m_instances_table->setRowCount(ref.GetDev().addr.size() + 1); | ||
94 | m_instances_table->setColumnCount(3); | ||
95 | for(size_t row = 0; row < ref.GetDev().addr.size(); row++) | ||
96 | FillRow(row, ref.GetDev().addr[row]); | ||
97 | CreateNewRow(ref.GetDev().addr.size()); | ||
98 | m_instances_table->setHorizontalHeaderItem(0, new QTableWidgetItem("")); | ||
99 | m_instances_table->setHorizontalHeaderItem(1, new QTableWidgetItem("Name")); | ||
100 | m_instances_table->setHorizontalHeaderItem(2, new QTableWidgetItem("Address")); | ||
101 | m_instances_table->verticalHeader()->setVisible(false); | ||
102 | m_instances_table->resizeColumnsToContents(); | ||
103 | m_instances_table->horizontalHeader()->setStretchLastSection(true); | ||
104 | m_instances_table->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); | ||
105 | m_instances_group = new QGroupBox("Instances", this); | ||
106 | QHBoxLayout *instances_group_layout = new QHBoxLayout; | ||
107 | instances_group_layout->addWidget(m_instances_table); | ||
108 | m_instances_group->setLayout(instances_group_layout); | ||
109 | |||
110 | QHBoxLayout *top_layout = new QHBoxLayout; | ||
111 | top_layout->addWidget(m_instances_group); | ||
112 | top_layout->addLayout(name_ver_layout); | ||
113 | top_layout->addStretch(); | ||
114 | |||
115 | m_desc_group = new QGroupBox("Description", this); | ||
116 | QHBoxLayout *group_layout = new QHBoxLayout; | ||
117 | m_desc_edit = new MyTextEditor(this); | ||
118 | m_desc_edit->SetTextHtml(QString::fromStdString(ref.GetDev().desc)); | ||
119 | group_layout->addWidget(m_desc_edit); | ||
120 | m_desc_group->setLayout(group_layout); | ||
121 | |||
122 | QVBoxLayout *layout = new QVBoxLayout; | ||
123 | layout->addLayout(top_layout, 0); | ||
124 | layout->addWidget(m_desc_group, 1); | ||
125 | |||
126 | setLayout(layout); | ||
127 | |||
128 | SocFieldItemDelegate *m_table_delegate = new SocFieldItemDelegate(this); | ||
129 | QItemEditorFactory *m_table_edit_factory = new QItemEditorFactory(); | ||
130 | SocFieldEditorCreator *m_table_edit_creator = new SocFieldEditorCreator(); | ||
131 | m_table_edit_factory->registerEditor(QVariant::UInt, m_table_edit_creator); | ||
132 | m_table_delegate->setItemEditorFactory(m_table_edit_factory); | ||
133 | m_instances_table->setItemDelegate(m_table_delegate); | ||
134 | |||
135 | connect(m_instances_table, SIGNAL(cellActivated(int,int)), this, SLOT(OnInstActivated(int,int))); | ||
136 | connect(m_instances_table, SIGNAL(cellChanged(int,int)), this, SLOT(OnInstChanged(int,int))); | ||
137 | connect(m_name_edit, SIGNAL(textChanged(const QString&)), this, SLOT(OnNameEdited(const QString&))); | ||
138 | connect(m_long_name_edit, SIGNAL(textChanged(const QString&)), this, SLOT(OnLongNameEdited(const QString&))); | ||
139 | connect(m_version_edit, SIGNAL(textChanged(const QString&)), this, SLOT(OnVersionEdited(const QString&))); | ||
140 | connect(m_desc_edit, SIGNAL(OnTextChanged()), this, SLOT(OnDescEdited())); | ||
141 | } | ||
142 | |||
143 | void DevEditPanel::OnNameEdited(const QString& text) | ||
144 | { | ||
145 | m_ref.GetDev().name = text.toStdString(); | ||
146 | emit OnModified(m_name_edit->isModified()); | ||
147 | } | ||
148 | |||
149 | void DevEditPanel::OnLongNameEdited(const QString& text) | ||
150 | { | ||
151 | m_ref.GetDev().long_name = text.toStdString(); | ||
152 | emit OnModified(m_long_name_edit->isModified()); | ||
153 | } | ||
154 | |||
155 | void DevEditPanel::OnVersionEdited(const QString& text) | ||
156 | { | ||
157 | m_ref.GetDev().version = text.toStdString(); | ||
158 | emit OnModified(m_version_edit->isModified()); | ||
159 | } | ||
160 | |||
161 | void DevEditPanel::OnDescEdited() | ||
162 | { | ||
163 | m_ref.GetDev().desc = m_desc_edit->GetTextHtml().toStdString(); | ||
164 | emit OnModified(m_desc_edit->IsModified()); | ||
165 | } | ||
166 | |||
167 | void DevEditPanel::CreateNewRow(int row) | ||
168 | { | ||
169 | QTableWidgetItem *item = new QTableWidgetItem(QIcon::fromTheme("list-add"), "", DevInstNewType); | ||
170 | item->setToolTip("New?"); | ||
171 | item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); | ||
172 | m_instances_table->setItem(row, DevInstIconColumn, item); | ||
173 | item = new QTableWidgetItem("New instance..."); | ||
174 | QFont font = item->font(); | ||
175 | font.setItalic(true); | ||
176 | item->setFont(font); | ||
177 | item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); | ||
178 | m_instances_table->setItem(row, DevInstNameColumn, item); | ||
179 | item = new QTableWidgetItem(""); | ||
180 | item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); | ||
181 | m_instances_table->setItem(row, DevInstAddrColumn, item); | ||
182 | } | ||
183 | |||
184 | void DevEditPanel::FillRow(int row, const soc_dev_addr_t& addr) | ||
185 | { | ||
186 | QTableWidgetItem *item = new QTableWidgetItem(QString::fromStdString(addr.name)); | ||
187 | item->setTextAlignment(Qt::AlignVCenter | Qt::AlignHCenter); | ||
188 | item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsEditable); | ||
189 | m_instances_table->setItem(row, DevInstNameColumn, item); | ||
190 | item = new QTableWidgetItem(); | ||
191 | item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsEditable); | ||
192 | item->setData(Qt::DisplayRole, QVariant(addr.addr)); | ||
193 | m_instances_table->setItem(row, DevInstAddrColumn, item); | ||
194 | item = new QTableWidgetItem(QIcon::fromTheme("list-remove"), "", DevInstDeleteType); | ||
195 | item->setToolTip("Remove?"); | ||
196 | item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); | ||
197 | m_instances_table->setItem(row, DevInstIconColumn, item); | ||
198 | } | ||
199 | |||
200 | void DevEditPanel::OnInstActivated(int row, int column) | ||
201 | { | ||
202 | if(column != 0) | ||
203 | return; | ||
204 | int type = m_instances_table->item(row, column)->type(); | ||
205 | if(type == DevInstDeleteType) | ||
206 | { | ||
207 | m_ref.GetDev().addr.erase(m_ref.GetDev().addr.begin() + row); | ||
208 | m_instances_table->removeRow(row); | ||
209 | } | ||
210 | else if(type == DevInstNewType) | ||
211 | { | ||
212 | m_instances_table->insertRow(row); | ||
213 | soc_dev_addr_t addr; | ||
214 | addr.name = QString("UNNAMED_%1").arg(row).toStdString(); | ||
215 | addr.addr = 0; | ||
216 | m_ref.GetDev().addr.push_back(addr); | ||
217 | FillRow(row, addr); | ||
218 | } | ||
219 | } | ||
220 | |||
221 | void DevEditPanel::OnInstChanged(int row, int column) | ||
222 | { | ||
223 | /* ignore extra row for addition */ | ||
224 | if(row >= (int)m_ref.GetDev().addr.size()) | ||
225 | return; | ||
226 | QTableWidgetItem *item = m_instances_table->item(row, column); | ||
227 | if(column == DevInstNameColumn) | ||
228 | { | ||
229 | m_ref.GetDev().addr[row].name = item->text().toStdString(); | ||
230 | emit OnModified(true); | ||
231 | } | ||
232 | else if(column == DevInstAddrColumn) | ||
233 | { | ||
234 | m_ref.GetDev().addr[row].addr = item->data(Qt::DisplayRole).toUInt(); | ||
235 | emit OnModified(true); | ||
236 | } | ||
237 | } | ||
238 | |||
239 | /** | ||
240 | * RegEditPanel | ||
241 | */ | ||
242 | |||
243 | RegEditPanel::RegEditPanel(SocRegRef ref, QWidget *parent) | ||
244 | :QWidget(parent), m_ref(ref), m_reg_font(font()) | ||
245 | { | ||
246 | m_reg_font.setWeight(100); | ||
247 | m_reg_font.setKerning(false); | ||
248 | |||
249 | m_name_group = new QGroupBox("Name", this); | ||
250 | m_name_edit = new QLineEdit(this); | ||
251 | m_name_edit->setText(QString::fromStdString(ref.GetReg().name)); | ||
252 | QVBoxLayout *name_group_layout = new QVBoxLayout; | ||
253 | name_group_layout->addWidget(m_name_edit); | ||
254 | m_name_group->setLayout(name_group_layout); | ||
255 | |||
256 | m_instances_table = new QTableWidget(this); | ||
257 | m_instances_table->setRowCount(ref.GetReg().addr.size() + 1); | ||
258 | m_instances_table->setColumnCount(RegInstNrColumns); | ||
259 | for(size_t row = 0; row < ref.GetReg().addr.size(); row++) | ||
260 | FillRow(row, ref.GetReg().addr[row]); | ||
261 | CreateNewAddrRow(ref.GetReg().addr.size()); | ||
262 | m_instances_table->setHorizontalHeaderItem(RegInstIconColumn, new QTableWidgetItem("")); | ||
263 | m_instances_table->setHorizontalHeaderItem(RegInstNameColumn, new QTableWidgetItem("Name")); | ||
264 | m_instances_table->setHorizontalHeaderItem(RegInstAddrColumn, new QTableWidgetItem("Address")); | ||
265 | m_instances_table->verticalHeader()->setVisible(false); | ||
266 | m_instances_table->resizeColumnsToContents(); | ||
267 | m_instances_table->horizontalHeader()->setStretchLastSection(true); | ||
268 | m_instances_table->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); | ||
269 | m_instances_group = new QGroupBox("Instances", this); | ||
270 | QHBoxLayout *instances_group_layout = new QHBoxLayout; | ||
271 | instances_group_layout->addWidget(m_instances_table); | ||
272 | m_instances_group->setLayout(instances_group_layout); | ||
273 | |||
274 | m_desc_group = new QGroupBox("Description", this); | ||
275 | QHBoxLayout *group_layout = new QHBoxLayout; | ||
276 | m_desc_edit = new MyTextEditor(this); | ||
277 | m_desc_edit->SetTextHtml(QString::fromStdString(ref.GetReg().desc)); | ||
278 | group_layout->addWidget(m_desc_edit); | ||
279 | m_desc_group->setLayout(group_layout); | ||
280 | |||
281 | bool has_sct = m_ref.GetReg().flags & REG_HAS_SCT; | ||
282 | m_sct_check = new QCheckBox("Set/Clear/Toggle", this); | ||
283 | m_sct_check->setCheckState(has_sct ? Qt::Checked : Qt::Unchecked); | ||
284 | QHBoxLayout *flags_layout = new QHBoxLayout; | ||
285 | flags_layout->addWidget(m_sct_check); | ||
286 | flags_layout->addStretch(); | ||
287 | m_flags_group = new QGroupBox("Flags", this); | ||
288 | m_flags_group->setLayout(flags_layout); | ||
289 | |||
290 | m_formula_combo = new QComboBox(this); | ||
291 | m_formula_combo->addItem("None", QVariant(REG_FORMULA_NONE)); | ||
292 | m_formula_combo->addItem("String", QVariant(REG_FORMULA_STRING)); | ||
293 | m_formula_combo->setCurrentIndex(m_formula_combo->findData(QVariant(m_ref.GetReg().formula.type))); | ||
294 | m_formula_type_label = new QLabel("Type:", this); | ||
295 | QHBoxLayout *formula_top_layout = new QHBoxLayout; | ||
296 | formula_top_layout->addWidget(m_formula_type_label); | ||
297 | formula_top_layout->addWidget(m_formula_combo); | ||
298 | m_formula_string_edit = new QLineEdit(QString::fromStdString(ref.GetReg().formula.string), this); | ||
299 | QVBoxLayout *formula_layout = new QVBoxLayout; | ||
300 | formula_layout->addLayout(formula_top_layout); | ||
301 | formula_layout->addWidget(m_formula_string_edit); | ||
302 | m_formula_string_gen = new QPushButton("Generate", this); | ||
303 | formula_layout->addWidget(m_formula_string_gen); | ||
304 | m_formula_group = new QGroupBox("Formula", this); | ||
305 | m_formula_group->setLayout(formula_layout); | ||
306 | |||
307 | QVBoxLayout *name_layout = new QVBoxLayout; | ||
308 | name_layout->addWidget(m_name_group); | ||
309 | name_layout->addWidget(m_flags_group); | ||
310 | name_layout->addWidget(m_formula_group); | ||
311 | name_layout->addStretch(); | ||
312 | |||
313 | QHBoxLayout *top_layout = new QHBoxLayout; | ||
314 | top_layout->addWidget(m_instances_group); | ||
315 | top_layout->addLayout(name_layout); | ||
316 | top_layout->addWidget(m_desc_group, 1); | ||
317 | |||
318 | m_sexy_display = new RegSexyDisplay(m_ref, this); | ||
319 | m_sexy_display->setFont(m_reg_font); | ||
320 | |||
321 | m_field_table = new QTableWidget; | ||
322 | m_field_table->setRowCount(m_ref.GetReg().field.size()); | ||
323 | m_field_table->setColumnCount(4); | ||
324 | for(size_t row = 0; row < m_ref.GetReg().field.size(); row++) | ||
325 | { | ||
326 | const soc_reg_field_t& field = m_ref.GetReg().field[row]; | ||
327 | QString bits_str; | ||
328 | if(field.first_bit == field.last_bit) | ||
329 | bits_str.sprintf("%d", field.first_bit); | ||
330 | else | ||
331 | bits_str.sprintf("%d:%d", field.last_bit, field.first_bit); | ||
332 | QTableWidgetItem *item = new QTableWidgetItem(bits_str); | ||
333 | item->setTextAlignment(Qt::AlignVCenter | Qt::AlignHCenter); | ||
334 | item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); | ||
335 | m_field_table->setItem(row, 1, item); | ||
336 | item = new QTableWidgetItem(QString(field.name.c_str())); | ||
337 | item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); | ||
338 | m_field_table->setItem(row, 2, item); | ||
339 | item = new QTableWidgetItem(QString(field.desc.c_str())); | ||
340 | item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); | ||
341 | m_field_table->setItem(row, 3, item); | ||
342 | UpdateWarning(row); | ||
343 | } | ||
344 | m_field_table->setHorizontalHeaderItem(0, new QTableWidgetItem("")); | ||
345 | m_field_table->setHorizontalHeaderItem(1, new QTableWidgetItem("Bits")); | ||
346 | m_field_table->setHorizontalHeaderItem(2, new QTableWidgetItem("Name")); | ||
347 | m_field_table->setHorizontalHeaderItem(3, new QTableWidgetItem("Description")); | ||
348 | m_field_table->verticalHeader()->setVisible(false); | ||
349 | m_field_table->resizeColumnsToContents(); | ||
350 | m_field_table->horizontalHeader()->setStretchLastSection(true); | ||
351 | QHBoxLayout *field_layout = new QHBoxLayout; | ||
352 | field_layout->addWidget(m_field_table); | ||
353 | m_field_group = new QGroupBox("Flags", this); | ||
354 | m_field_group->setLayout(field_layout); | ||
355 | |||
356 | QVBoxLayout *layout = new QVBoxLayout; | ||
357 | layout->addLayout(top_layout, 0); | ||
358 | layout->addWidget(m_sexy_display, 0); | ||
359 | layout->addWidget(m_field_group); | ||
360 | |||
361 | UpdateFormula(); | ||
362 | |||
363 | setLayout(layout); | ||
364 | |||
365 | SocFieldItemDelegate *m_table_delegate = new SocFieldItemDelegate(this); | ||
366 | QItemEditorFactory *m_table_edit_factory = new QItemEditorFactory(); | ||
367 | SocFieldEditorCreator *m_table_edit_creator = new SocFieldEditorCreator(); | ||
368 | m_table_edit_factory->registerEditor(QVariant::UInt, m_table_edit_creator); | ||
369 | m_table_delegate->setItemEditorFactory(m_table_edit_factory); | ||
370 | m_instances_table->setItemDelegate(m_table_delegate); | ||
371 | |||
372 | connect(m_instances_table, SIGNAL(cellActivated(int,int)), this, SLOT(OnInstActivated(int,int))); | ||
373 | connect(m_instances_table, SIGNAL(cellChanged(int,int)), this, SLOT(OnInstChanged(int,int))); | ||
374 | connect(m_name_edit, SIGNAL(textChanged(const QString&)), this, SLOT(OnNameEdited(const QString&))); | ||
375 | connect(m_desc_edit, SIGNAL(OnTextChanged()), this, SLOT(OnDescEdited())); | ||
376 | connect(m_sct_check, SIGNAL(stateChanged(int)), this, SLOT(OnSctEdited(int))); | ||
377 | connect(m_formula_combo, SIGNAL(currentIndexChanged(int)), this, SLOT(OnFormulaChanged(int))); | ||
378 | connect(m_formula_string_edit, SIGNAL(textChanged(const QString&)), this, | ||
379 | SLOT(OnFormulaStringChanged(const QString&))); | ||
380 | connect(m_formula_string_gen, SIGNAL(clicked(bool)), this, SLOT(OnFormulaGenerate(bool))); | ||
381 | } | ||
382 | |||
383 | void RegEditPanel::UpdateWarning(int row) | ||
384 | { | ||
385 | Q_UNUSED(row); | ||
386 | } | ||
387 | |||
388 | void RegEditPanel::OnFormulaStringChanged(const QString& text) | ||
389 | { | ||
390 | m_ref.GetReg().formula.string = text.toStdString(); | ||
391 | emit OnModified(true); | ||
392 | } | ||
393 | |||
394 | void RegEditPanel::OnFormulaGenerate(bool checked) | ||
395 | { | ||
396 | Q_UNUSED(checked); | ||
397 | bool ok; | ||
398 | int count = QInputDialog::getInt(this, "Instance generator", "Number of instances", | ||
399 | 0, 0, 100, 1, &ok); | ||
400 | if(!ok) | ||
401 | return; | ||
402 | std::string name(m_ref.GetReg().name); | ||
403 | size_t pos = name.find('n'); | ||
404 | if(pos == std::string::npos) | ||
405 | { | ||
406 | name.push_back('n'); | ||
407 | pos = name.size() - 1; | ||
408 | } | ||
409 | std::map< std::string, soc_word_t > map; | ||
410 | std::vector< std::pair< std::string, soc_word_t > > list; | ||
411 | std::string formula = m_ref.GetReg().formula.string; | ||
412 | for(int n = 0; n < count; n++) | ||
413 | { | ||
414 | map["n"] = n; | ||
415 | std::string err; | ||
416 | soc_word_t res; | ||
417 | if(!soc_desc_evaluate_formula(formula, map, res, err)) | ||
418 | { | ||
419 | qDebug() << "Cannot evaluator " << QString::fromStdString(formula) | ||
420 | << "for n=" << n << ": " << QString::fromStdString(err); | ||
421 | return; | ||
422 | } | ||
423 | std::string regname = name; | ||
424 | std::string strn = QString("%1").arg(n).toStdString(); | ||
425 | regname.replace(pos, 1, strn); | ||
426 | list.push_back(std::make_pair(regname, res)); | ||
427 | } | ||
428 | // everything went good, commit result | ||
429 | while(m_instances_table->rowCount() > 1) | ||
430 | m_instances_table->removeRow(0); | ||
431 | m_ref.GetReg().addr.resize(list.size()); | ||
432 | for(size_t i = 0; i < list.size(); i++) | ||
433 | { | ||
434 | m_instances_table->insertRow(i); | ||
435 | m_ref.GetReg().addr[i].name = list[i].first; | ||
436 | m_ref.GetReg().addr[i].addr = list[i].second; | ||
437 | FillRow(i, m_ref.GetReg().addr[i]); | ||
438 | } | ||
439 | } | ||
440 | |||
441 | void RegEditPanel::OnFormulaChanged(int index) | ||
442 | { | ||
443 | if(index == -1) | ||
444 | return; | ||
445 | m_ref.GetReg().formula.type = static_cast< soc_reg_formula_type_t >(m_formula_combo->itemData(index).toInt()); | ||
446 | UpdateFormula(); | ||
447 | emit OnModified(true); | ||
448 | } | ||
449 | |||
450 | void RegEditPanel::UpdateFormula() | ||
451 | { | ||
452 | m_formula_string_edit->hide(); | ||
453 | m_formula_string_gen->hide(); | ||
454 | switch(m_ref.GetReg().formula.type) | ||
455 | { | ||
456 | case REG_FORMULA_STRING: | ||
457 | m_formula_string_edit->show(); | ||
458 | m_formula_string_gen->show(); | ||
459 | break; | ||
460 | case REG_FORMULA_NONE: | ||
461 | default: | ||
462 | break; | ||
463 | } | ||
464 | } | ||
465 | |||
466 | void RegEditPanel::OnSctEdited(int state) | ||
467 | { | ||
468 | if(state == Qt::Checked) | ||
469 | m_ref.GetReg().flags |= REG_HAS_SCT; | ||
470 | else | ||
471 | m_ref.GetReg().flags &= ~REG_HAS_SCT; | ||
472 | emit OnModified(true); | ||
473 | } | ||
474 | |||
475 | void RegEditPanel::FillRow(int row, const soc_reg_addr_t& addr) | ||
476 | { | ||
477 | QTableWidgetItem *item = new QTableWidgetItem(QString::fromStdString(addr.name)); | ||
478 | item->setTextAlignment(Qt::AlignVCenter | Qt::AlignHCenter); | ||
479 | item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsEditable); | ||
480 | m_instances_table->setItem(row, RegInstNameColumn, item); | ||
481 | item = new QTableWidgetItem(); | ||
482 | item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsEditable); | ||
483 | item->setData(Qt::DisplayRole, QVariant(addr.addr)); | ||
484 | m_instances_table->setItem(row, RegInstAddrColumn, item); | ||
485 | item = new QTableWidgetItem(QIcon::fromTheme("list-remove"), "", RegInstDeleteType); | ||
486 | item->setToolTip("Remove?"); | ||
487 | item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); | ||
488 | m_instances_table->setItem(row, RegInstIconColumn, item); | ||
489 | } | ||
490 | |||
491 | void RegEditPanel::CreateNewAddrRow(int row) | ||
492 | { | ||
493 | QTableWidgetItem *item = new QTableWidgetItem(QIcon::fromTheme("list-add"), "", RegInstNewType); | ||
494 | item->setToolTip("New?"); | ||
495 | item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); | ||
496 | m_instances_table->setItem(row, RegInstIconColumn, item); | ||
497 | item = new QTableWidgetItem("New instance..."); | ||
498 | QFont font = item->font(); | ||
499 | font.setItalic(true); | ||
500 | item->setFont(font); | ||
501 | item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); | ||
502 | m_instances_table->setItem(row, RegInstNameColumn, item); | ||
503 | item = new QTableWidgetItem(""); | ||
504 | item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); | ||
505 | m_instances_table->setItem(row, RegInstAddrColumn, item); | ||
506 | } | ||
507 | |||
508 | void RegEditPanel::OnNameEdited(const QString& text) | ||
509 | { | ||
510 | m_ref.GetReg().name = text.toStdString(); | ||
511 | emit OnModified(m_name_edit->isModified()); | ||
512 | } | ||
513 | |||
514 | void RegEditPanel::OnDescEdited() | ||
515 | { | ||
516 | m_ref.GetReg().desc = m_desc_edit->GetTextHtml().toStdString(); | ||
517 | emit OnModified(m_desc_edit->IsModified()); | ||
518 | } | ||
519 | |||
520 | void RegEditPanel::OnInstActivated(int row, int column) | ||
521 | { | ||
522 | if(column != 0) | ||
523 | return; | ||
524 | int type = m_instances_table->item(row, column)->type(); | ||
525 | if(type == RegInstDeleteType) | ||
526 | { | ||
527 | m_ref.GetReg().addr.erase(m_ref.GetReg().addr.begin() + row); | ||
528 | m_instances_table->removeRow(row); | ||
529 | } | ||
530 | else if(type == RegInstNewType) | ||
531 | { | ||
532 | m_instances_table->insertRow(row); | ||
533 | soc_reg_addr_t addr; | ||
534 | addr.name = QString("UNNAMED_%1").arg(row).toStdString(); | ||
535 | addr.addr = 0; | ||
536 | m_ref.GetReg().addr.push_back(addr); | ||
537 | FillRow(row, addr); | ||
538 | } | ||
539 | } | ||
540 | |||
541 | void RegEditPanel::OnInstChanged(int row, int column) | ||
542 | { | ||
543 | /* ignore extra row for addition */ | ||
544 | if(row >= (int)m_ref.GetReg().addr.size()) | ||
545 | return; | ||
546 | QTableWidgetItem *item = m_instances_table->item(row, column); | ||
547 | if(column == RegInstNameColumn) | ||
548 | { | ||
549 | m_ref.GetReg().addr[row].name = item->text().toStdString(); | ||
550 | emit OnModified(true); | ||
551 | } | ||
552 | else if(column == RegInstAddrColumn) | ||
553 | { | ||
554 | m_ref.GetReg().addr[row].addr = item->data(Qt::DisplayRole).toUInt(); | ||
555 | emit OnModified(true); | ||
556 | } | ||
557 | } | ||
558 | |||
559 | /** | ||
560 | * FieldEditPanel | ||
561 | */ | ||
562 | FieldEditPanel::FieldEditPanel(SocFieldRef ref, QWidget *parent) | ||
563 | :QWidget(parent), m_ref(ref) | ||
564 | { | ||
565 | m_name_group = new QGroupBox("Name", this); | ||
566 | m_name_edit = new QLineEdit(this); | ||
567 | m_name_edit->setText(QString::fromStdString(ref.GetField().name)); | ||
568 | QVBoxLayout *name_group_layout = new QVBoxLayout; | ||
569 | name_group_layout->addWidget(m_name_edit); | ||
570 | m_name_group->setLayout(name_group_layout); | ||
571 | |||
572 | m_bitrange_group = new QGroupBox("Bit Range", this); | ||
573 | m_bitrange_edit = new QLineEdit(this); | ||
574 | const soc_reg_field_t& field = ref.GetField(); | ||
575 | QString bits_str; | ||
576 | if(field.first_bit == field.last_bit) | ||
577 | bits_str.sprintf("%d", field.first_bit); | ||
578 | else | ||
579 | bits_str.sprintf("%d:%d", field.last_bit, field.first_bit); | ||
580 | m_bitrange_edit->setText(bits_str); | ||
581 | m_bitrange_edit->setValidator(new SocBitRangeValidator(m_bitrange_edit)); | ||
582 | QVBoxLayout *bitrange_group_layout = new QVBoxLayout; | ||
583 | bitrange_group_layout->addWidget(m_bitrange_edit); | ||
584 | m_bitrange_group->setLayout(bitrange_group_layout); | ||
585 | |||
586 | m_desc_group = new QGroupBox("Description", this); | ||
587 | QHBoxLayout *group_layout = new QHBoxLayout; | ||
588 | m_desc_edit = new MyTextEditor(this); | ||
589 | m_desc_edit->SetTextHtml(QString::fromStdString(ref.GetField().desc)); | ||
590 | group_layout->addWidget(m_desc_edit); | ||
591 | m_desc_group->setLayout(group_layout); | ||
592 | |||
593 | m_value_group = new QGroupBox("Values", this); | ||
594 | QHBoxLayout *value_layout = new QHBoxLayout; | ||
595 | m_value_table = new QTableWidget(this); | ||
596 | m_value_table->setRowCount(ref.GetField().value.size() + 1); | ||
597 | m_value_table->setColumnCount(FieldValueNrColumns); | ||
598 | for(size_t row = 0; row < ref.GetField().value.size(); row++) | ||
599 | FillRow(row, ref.GetField().value[row]); | ||
600 | CreateNewRow(ref.GetField().value.size()); | ||
601 | m_value_table->setHorizontalHeaderItem(FieldValueIconColumn, new QTableWidgetItem("")); | ||
602 | m_value_table->setHorizontalHeaderItem(FieldValueNameColumn, new QTableWidgetItem("Name")); | ||
603 | m_value_table->setHorizontalHeaderItem(FieldValueValueColumn, new QTableWidgetItem("Value")); | ||
604 | m_value_table->setHorizontalHeaderItem(FieldValueDescColumn, new QTableWidgetItem("Description")); | ||
605 | m_value_table->verticalHeader()->setVisible(false); | ||
606 | m_value_table->horizontalHeader()->setStretchLastSection(true); | ||
607 | value_layout->addWidget(m_value_table); | ||
608 | m_value_group->setLayout(value_layout); | ||
609 | |||
610 | QHBoxLayout *line_layout = new QHBoxLayout; | ||
611 | line_layout->addWidget(m_name_group); | ||
612 | line_layout->addWidget(m_bitrange_group); | ||
613 | line_layout->addStretch(); | ||
614 | |||
615 | QVBoxLayout *left_layout = new QVBoxLayout; | ||
616 | left_layout->addLayout(line_layout); | ||
617 | left_layout->addWidget(m_desc_group); | ||
618 | left_layout->addWidget(m_value_group, 1); | ||
619 | |||
620 | UpdateDelegates(); | ||
621 | |||
622 | connect(m_name_edit, SIGNAL(textChanged(const QString&)), this, SLOT(OnNameEdited(const QString&))); | ||
623 | connect(m_desc_edit, SIGNAL(OnTextChanged()), this, SLOT(OnDescEdited())); | ||
624 | connect(m_value_table, SIGNAL(cellActivated(int,int)), this, SLOT(OnValueActivated(int,int))); | ||
625 | connect(m_value_table, SIGNAL(cellChanged(int,int)), this, SLOT(OnValueChanged(int,int))); | ||
626 | connect(m_bitrange_edit, SIGNAL(textChanged(const QString&)), this, SLOT(OnBitRangeEdited(const QString&))); | ||
627 | |||
628 | setLayout(left_layout); | ||
629 | } | ||
630 | |||
631 | void FieldEditPanel::UpdateDelegates() | ||
632 | { | ||
633 | SocFieldItemDelegate *m_table_delegate = new SocFieldItemDelegate(m_ref.GetField(), this); | ||
634 | QItemEditorFactory *m_table_edit_factory = new QItemEditorFactory(); | ||
635 | SocFieldEditorCreator *m_table_edit_creator = new SocFieldEditorCreator(m_ref.GetField()); | ||
636 | m_table_edit_factory->registerEditor(QVariant::UInt, m_table_edit_creator); | ||
637 | m_table_delegate->setItemEditorFactory(m_table_edit_factory); | ||
638 | m_value_table->setItemDelegate(m_table_delegate); | ||
639 | m_value_table->resizeColumnsToContents(); | ||
640 | } | ||
641 | |||
642 | void FieldEditPanel::UpdateWarning(int row) | ||
643 | { | ||
644 | soc_word_t val = m_ref.GetField().value[row].value; | ||
645 | soc_word_t max = m_ref.GetField().bitmask() >> m_ref.GetField().first_bit; | ||
646 | QTableWidgetItem *item = m_value_table->item(row, FieldValueValueColumn); | ||
647 | if(val > max) | ||
648 | { | ||
649 | item->setIcon(QIcon::fromTheme("dialog-warning")); | ||
650 | item->setToolTip("Value is too big for the field"); | ||
651 | } | ||
652 | else | ||
653 | { | ||
654 | item->setIcon(QIcon()); | ||
655 | item->setToolTip(""); | ||
656 | } | ||
657 | } | ||
658 | |||
659 | void FieldEditPanel::FillRow(int row, const soc_reg_field_value_t& val) | ||
660 | { | ||
661 | QTableWidgetItem *item = new QTableWidgetItem(QString::fromStdString(val.name)); | ||
662 | item->setTextAlignment(Qt::AlignVCenter | Qt::AlignHCenter); | ||
663 | item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsEditable); | ||
664 | m_value_table->setItem(row, FieldValueNameColumn, item); | ||
665 | item = new QTableWidgetItem(); | ||
666 | item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsEditable); | ||
667 | item->setData(Qt::DisplayRole, QVariant(val.value)); | ||
668 | m_value_table->setItem(row, FieldValueValueColumn, item); | ||
669 | item = new QTableWidgetItem(QString::fromStdString(val.desc)); | ||
670 | item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsEditable); | ||
671 | m_value_table->setItem(row, FieldValueDescColumn, item); | ||
672 | item = new QTableWidgetItem(QIcon::fromTheme("list-remove"), "", FieldValueDeleteType); | ||
673 | item->setToolTip("Remove?"); | ||
674 | item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); | ||
675 | m_value_table->setItem(row, FieldValueIconColumn, item); | ||
676 | UpdateWarning(row); | ||
677 | } | ||
678 | |||
679 | void FieldEditPanel::CreateNewRow(int row) | ||
680 | { | ||
681 | QTableWidgetItem *item = new QTableWidgetItem(QIcon::fromTheme("list-add"), "", FieldValueNewType); | ||
682 | item->setToolTip("New?"); | ||
683 | item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); | ||
684 | m_value_table->setItem(row, FieldValueIconColumn, item); | ||
685 | item = new QTableWidgetItem("New value..."); | ||
686 | QFont font = item->font(); | ||
687 | font.setItalic(true); | ||
688 | item->setFont(font); | ||
689 | item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); | ||
690 | m_value_table->setItem(row, FieldValueNameColumn, item); | ||
691 | } | ||
692 | |||
693 | void FieldEditPanel::OnBitRangeEdited(const QString& input) | ||
694 | { | ||
695 | const SocBitRangeValidator *validator = | ||
696 | dynamic_cast< const SocBitRangeValidator *>(m_bitrange_edit->validator()); | ||
697 | int first, last; | ||
698 | QValidator::State state = validator->parse(input, last, first); | ||
699 | if(state != QValidator::Acceptable) | ||
700 | return; | ||
701 | m_ref.GetField().first_bit = first; | ||
702 | m_ref.GetField().last_bit = last; | ||
703 | // update all warning signs | ||
704 | for(size_t row = 0; row < m_ref.GetField().value.size(); row++) | ||
705 | UpdateWarning(row); | ||
706 | // also updates delegates because they now have the wrong view of the field | ||
707 | UpdateDelegates(); | ||
708 | emit OnModified(true); | ||
709 | } | ||
710 | |||
711 | void FieldEditPanel::OnNameEdited(const QString& text) | ||
712 | { | ||
713 | m_ref.GetField().name = text.toStdString(); | ||
714 | emit OnModified(m_name_edit->isModified()); | ||
715 | } | ||
716 | |||
717 | void FieldEditPanel::OnDescEdited() | ||
718 | { | ||
719 | m_ref.GetField().desc = m_desc_edit->GetTextHtml().toStdString(); | ||
720 | emit OnModified(m_desc_edit->IsModified()); | ||
721 | } | ||
722 | |||
723 | void FieldEditPanel::OnValueActivated(int row, int column) | ||
724 | { | ||
725 | if(column != 0) | ||
726 | return; | ||
727 | int type = m_value_table->item(row, column)->type(); | ||
728 | if(type == FieldValueDeleteType) | ||
729 | { | ||
730 | m_ref.GetField().value.erase(m_ref.GetField().value.begin() + row); | ||
731 | m_value_table->removeRow(row); | ||
732 | } | ||
733 | else if(type == FieldValueNewType) | ||
734 | { | ||
735 | m_value_table->insertRow(row); | ||
736 | soc_reg_field_value_t val; | ||
737 | val.name = QString("UNNAMED_%1").arg(row).toStdString(); | ||
738 | val.value = 0; | ||
739 | m_ref.GetField().value.push_back(val); | ||
740 | FillRow(row, val); | ||
741 | } | ||
742 | } | ||
743 | |||
744 | void FieldEditPanel::OnValueChanged(int row, int column) | ||
745 | { | ||
746 | /* ignore extra row for addition */ | ||
747 | if(row >= (int)m_ref.GetField().value.size()) | ||
748 | return; | ||
749 | QTableWidgetItem *item = m_value_table->item(row, column); | ||
750 | if(column == FieldValueNameColumn) | ||
751 | m_ref.GetField().value[row].name = item->text().toStdString(); | ||
752 | else if(column == FieldValueValueColumn) | ||
753 | { | ||
754 | soc_word_t& fval = m_ref.GetField().value[row].value; | ||
755 | soc_word_t new_val = item->data(Qt::DisplayRole).toUInt(); | ||
756 | /* avoid infinite recursion by calling UpdateWarning() when | ||
757 | * only the icon changes which would trigger this callback again */ | ||
758 | if(fval != new_val) | ||
759 | { | ||
760 | fval = new_val; | ||
761 | UpdateWarning(row); | ||
762 | } | ||
763 | } | ||
764 | else if(column == FieldValueDescColumn) | ||
765 | m_ref.GetField().value[row].desc = item->text().toStdString(); | ||
766 | emit OnModified(true); | ||
767 | } | ||
768 | |||
769 | namespace | ||
770 | { | ||
771 | |||
772 | enum | ||
773 | { | ||
774 | SocTreeSocType = QTreeWidgetItem::UserType, | ||
775 | SocTreeDevType, | ||
776 | SocTreeRegType, | ||
777 | SocTreeFieldType, | ||
778 | SocTreeNewDevType, | ||
779 | SocTreeNewRegType, | ||
780 | SocTreeNewFieldType, | ||
781 | }; | ||
782 | |||
783 | /** | ||
784 | * SocTreeItem | ||
785 | */ | ||
786 | |||
787 | class SocTreeItem : public QTreeWidgetItem | ||
788 | { | ||
789 | public: | ||
790 | SocTreeItem(const QString& string, const SocRef& ref) | ||
791 | :QTreeWidgetItem(QStringList(string), SocTreeSocType), m_ref(ref) {} | ||
792 | |||
793 | const SocRef& GetRef() { return m_ref; } | ||
794 | private: | ||
795 | SocRef m_ref; | ||
796 | }; | ||
797 | |||
798 | /** | ||
799 | * NewDevTreeItem | ||
800 | */ | ||
801 | |||
802 | class NewDevTreeItem : public QTreeWidgetItem | ||
803 | { | ||
804 | public: | ||
805 | NewDevTreeItem(const QString& string, const SocRef& ref) | ||
806 | :QTreeWidgetItem(QStringList(string), SocTreeNewDevType), m_ref(ref) {} | ||
807 | |||
808 | const SocRef& GetRef() { return m_ref; } | ||
809 | private: | ||
810 | SocRef m_ref; | ||
811 | }; | ||
812 | |||
813 | /** | ||
814 | * DevTreeItem | ||
815 | */ | ||
816 | |||
817 | class DevTreeItem : public QTreeWidgetItem | ||
818 | { | ||
819 | public: | ||
820 | DevTreeItem(const QString& string, const SocDevRef& ref) | ||
821 | :QTreeWidgetItem(QStringList(string), SocTreeDevType), m_ref(ref) {} | ||
822 | |||
823 | const SocDevRef& GetRef() { return m_ref; } | ||
824 | private: | ||
825 | SocDevRef m_ref; | ||
826 | }; | ||
827 | |||
828 | /** | ||
829 | * NewRegTreeItem | ||
830 | */ | ||
831 | |||
832 | class NewRegTreeItem : public QTreeWidgetItem | ||
833 | { | ||
834 | public: | ||
835 | NewRegTreeItem(const QString& string, const SocDevRef& ref) | ||
836 | :QTreeWidgetItem(QStringList(string), SocTreeNewRegType), m_ref(ref) {} | ||
837 | |||
838 | const SocDevRef& GetRef() { return m_ref; } | ||
839 | private: | ||
840 | SocDevRef m_ref; | ||
841 | }; | ||
842 | |||
843 | /** | ||
844 | * RegTreeItem | ||
845 | */ | ||
846 | |||
847 | class RegTreeItem : public QTreeWidgetItem | ||
848 | { | ||
849 | public: | ||
850 | RegTreeItem(const QString& string, const SocRegRef& ref) | ||
851 | :QTreeWidgetItem(QStringList(string), SocTreeRegType), m_ref(ref) {} | ||
852 | |||
853 | const SocRegRef& GetRef() { return m_ref; } | ||
854 | private: | ||
855 | SocRegRef m_ref; | ||
856 | }; | ||
857 | |||
858 | /** | ||
859 | * NewFieldTreeItem | ||
860 | */ | ||
861 | |||
862 | class NewFieldTreeItem : public QTreeWidgetItem | ||
863 | { | ||
864 | public: | ||
865 | NewFieldTreeItem(const QString& string, const SocRegRef& ref) | ||
866 | :QTreeWidgetItem(QStringList(string), SocTreeNewFieldType), m_ref(ref) {} | ||
867 | |||
868 | const SocRegRef& GetRef() { return m_ref; } | ||
869 | private: | ||
870 | SocRegRef m_ref; | ||
871 | }; | ||
872 | |||
873 | /** | ||
874 | * FieldTreeItem | ||
875 | */ | ||
876 | |||
877 | class FieldTreeItem : public QTreeWidgetItem | ||
878 | { | ||
879 | public: | ||
880 | FieldTreeItem(const QString& string, const SocFieldRef& ref) | ||
881 | :QTreeWidgetItem(QStringList(string), SocTreeFieldType), m_ref(ref) {} | ||
882 | |||
883 | const SocFieldRef& GetRef() { return m_ref; } | ||
884 | private: | ||
885 | SocFieldRef m_ref; | ||
886 | }; | ||
887 | |||
888 | } | ||
889 | |||
890 | /** | ||
891 | * RegEdit | ||
892 | */ | ||
893 | RegEdit::RegEdit(Backend *backend, QWidget *parent) | ||
894 | :QWidget(parent), m_backend(backend) | ||
895 | { | ||
896 | QVBoxLayout *m_vert_layout = new QVBoxLayout(); | ||
897 | m_file_group = new QGroupBox("File selection", this); | ||
898 | QHBoxLayout *m_file_group_layout = new QHBoxLayout(); | ||
899 | m_file_edit = new QLineEdit(this); | ||
900 | m_file_edit->setReadOnly(true); | ||
901 | m_file_open = new QToolButton(this); | ||
902 | m_file_open->setText("Open"); | ||
903 | m_file_open->setIcon(QIcon::fromTheme("document-open")); | ||
904 | m_file_open->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); | ||
905 | QMenu *file_open_menu = new QMenu(this); | ||
906 | QAction *new_act = file_open_menu->addAction(QIcon::fromTheme("document-new"), "New..."); | ||
907 | m_file_open->setMenu(file_open_menu); | ||
908 | |||
909 | m_file_save = new QToolButton(this); | ||
910 | m_file_save->setText("Save"); | ||
911 | m_file_save->setIcon(QIcon::fromTheme("document-save")); | ||
912 | m_file_save->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); | ||
913 | QMenu *file_save_menu = new QMenu(this); | ||
914 | QAction *saveas_act = file_save_menu->addAction(QIcon::fromTheme("document-save-as"), "Save as..."); | ||
915 | m_file_save->setMenu(file_save_menu); | ||
916 | m_file_group_layout->addWidget(m_file_open); | ||
917 | m_file_group_layout->addWidget(m_file_save); | ||
918 | m_file_group_layout->addWidget(m_file_edit); | ||
919 | |||
920 | m_splitter = new QSplitter(this); | ||
921 | m_soc_tree = new QTreeWidget(this); | ||
922 | m_soc_tree->setColumnCount(1); | ||
923 | m_soc_tree->setHeaderLabel(QString("Name")); | ||
924 | m_splitter->addWidget(m_soc_tree); | ||
925 | m_splitter->setStretchFactor(0, 0); | ||
926 | |||
927 | m_file_group->setLayout(m_file_group_layout); | ||
928 | m_vert_layout->addWidget(m_file_group); | ||
929 | m_vert_layout->addWidget(m_splitter, 1); | ||
930 | |||
931 | setLayout(m_vert_layout); | ||
932 | |||
933 | SetModified(false, false); | ||
934 | m_right_panel = 0; | ||
935 | SetPanel(new EmptyEditPanel(this)); | ||
936 | |||
937 | connect(m_file_open, SIGNAL(clicked()), this, SLOT(OnOpen())); | ||
938 | connect(m_file_save, SIGNAL(clicked()), this, SLOT(OnSave())); | ||
939 | connect(new_act, SIGNAL(triggered()), this, SLOT(OnNew())); | ||
940 | connect(saveas_act, SIGNAL(triggered()), this, SLOT(OnSaveAs())); | ||
941 | connect(m_soc_tree, SIGNAL(currentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*)), | ||
942 | this, SLOT(OnSocItemChanged(QTreeWidgetItem*, QTreeWidgetItem*))); | ||
943 | connect(m_soc_tree, SIGNAL(itemActivated(QTreeWidgetItem*, int)), | ||
944 | this, SLOT(OnSocItemActivated(QTreeWidgetItem*, int))); | ||
945 | } | ||
946 | |||
947 | RegEdit::~RegEdit() | ||
948 | { | ||
949 | } | ||
950 | |||
951 | void RegEdit::OnSave() | ||
952 | { | ||
953 | SaveSoc(); | ||
954 | } | ||
955 | |||
956 | void RegEdit::OnSaveAs() | ||
957 | { | ||
958 | SaveSocAs(); | ||
959 | } | ||
960 | |||
961 | bool RegEdit::CloseSoc() | ||
962 | { | ||
963 | if(!m_modified) | ||
964 | return true; | ||
965 | QMessageBox msgBox; | ||
966 | msgBox.setText("The description has been modified."); | ||
967 | msgBox.setInformativeText("Do you want to save your changes?"); | ||
968 | msgBox.setStandardButtons(QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel); | ||
969 | msgBox.setDefaultButton(QMessageBox::Save); | ||
970 | int ret = msgBox.exec(); | ||
971 | if(ret == QMessageBox::Discard) | ||
972 | return true; | ||
973 | if(ret == QMessageBox::Cancel) | ||
974 | return false; | ||
975 | return SaveSoc(); | ||
976 | } | ||
977 | |||
978 | bool RegEdit::SaveSoc() | ||
979 | { | ||
980 | if(m_file_edit->text().size() == 0) | ||
981 | return SaveSocAs(); | ||
982 | else | ||
983 | return SaveSocFile(m_file_edit->text()); | ||
984 | } | ||
985 | |||
986 | bool RegEdit::GetFilename(QString& filename, bool save) | ||
987 | { | ||
988 | QFileDialog *fd = new QFileDialog(this); | ||
989 | if(save) | ||
990 | fd->setAcceptMode(QFileDialog::AcceptSave); | ||
991 | fd->setFilter("Description files (*.xml);;All files (*)"); | ||
992 | fd->setDirectory(Settings::Get()->value("loaddescdir", QDir::currentPath()).toString()); | ||
993 | if(fd->exec()) | ||
994 | { | ||
995 | QStringList filenames = fd->selectedFiles(); | ||
996 | filename = filenames[0]; | ||
997 | Settings::Get()->setValue("loaddescdir", fd->directory().absolutePath()); | ||
998 | return true; | ||
999 | } | ||
1000 | else | ||
1001 | return false; | ||
1002 | } | ||
1003 | |||
1004 | bool RegEdit::SaveSocAs() | ||
1005 | { | ||
1006 | QString filename; | ||
1007 | if(!GetFilename(filename, true)) | ||
1008 | return false; | ||
1009 | m_file_edit->setText(filename); | ||
1010 | return SaveSocFile(filename); | ||
1011 | } | ||
1012 | |||
1013 | void RegEdit::OnOpen() | ||
1014 | { | ||
1015 | if(!CloseSoc()) | ||
1016 | return; | ||
1017 | QString filename; | ||
1018 | if(!GetFilename(filename, false)) | ||
1019 | return; | ||
1020 | LoadSocFile(filename); | ||
1021 | } | ||
1022 | |||
1023 | void RegEdit::OnNew() | ||
1024 | { | ||
1025 | if(!CloseSoc()) | ||
1026 | return; | ||
1027 | m_cur_socfile = SocFile(); | ||
1028 | m_file_edit->setText(""); | ||
1029 | SetModified(false, false); | ||
1030 | UpdateSocFile(); | ||
1031 | } | ||
1032 | |||
1033 | bool RegEdit::SaveSocFile(const QString& filename) | ||
1034 | { | ||
1035 | soc_desc_normalize(m_cur_socfile.GetSoc()); | ||
1036 | if(!soc_desc_produce_xml(filename.toStdString(), m_cur_socfile.GetSoc())) | ||
1037 | { | ||
1038 | QMessageBox::warning(this, "The description was not saved", | ||
1039 | "There was an error when saving the file"); | ||
1040 | return false; | ||
1041 | } | ||
1042 | m_soc_tree->clear(); | ||
1043 | FillSocTree(); | ||
1044 | SetModified(false, false); | ||
1045 | return true; | ||
1046 | } | ||
1047 | |||
1048 | void RegEdit::LoadSocFile(const QString& filename) | ||
1049 | { | ||
1050 | m_cur_socfile = SocFile(filename); | ||
1051 | if(!m_cur_socfile.IsValid()) | ||
1052 | { | ||
1053 | QMessageBox::warning(this, "The description was not loaded", | ||
1054 | "There was an error when loading the file"); | ||
1055 | return; | ||
1056 | } | ||
1057 | m_file_edit->setText(filename); | ||
1058 | SetModified(false, false); | ||
1059 | UpdateSocFile(); | ||
1060 | } | ||
1061 | |||
1062 | void RegEdit::CreateNewFieldItem(QTreeWidgetItem *_parent) | ||
1063 | { | ||
1064 | RegTreeItem *parent = dynamic_cast< RegTreeItem* >(_parent); | ||
1065 | NewFieldTreeItem *newdev_item = new NewFieldTreeItem("New field...", parent->GetRef()); | ||
1066 | MakeItalic(newdev_item, true); | ||
1067 | newdev_item->setIcon(0, QIcon::fromTheme("list-add")); | ||
1068 | parent->addChild(newdev_item); | ||
1069 | } | ||
1070 | |||
1071 | void RegEdit::FillRegTreeItem(QTreeWidgetItem *_item) | ||
1072 | { | ||
1073 | RegTreeItem *item = dynamic_cast< RegTreeItem* >(_item); | ||
1074 | const soc_reg_t& reg = item->GetRef().GetReg(); | ||
1075 | for(size_t i = 0; i < reg.field.size(); i++) | ||
1076 | { | ||
1077 | const soc_reg_field_t& field = reg.field[i]; | ||
1078 | FieldTreeItem *field_item = new FieldTreeItem(QString::fromStdString(field.name), | ||
1079 | SocFieldRef(item->GetRef(), i)); | ||
1080 | FixupEmptyItem(field_item); | ||
1081 | item->addChild(field_item); | ||
1082 | } | ||
1083 | CreateNewFieldItem(item); | ||
1084 | } | ||
1085 | |||
1086 | void RegEdit::CreateNewRegisterItem(QTreeWidgetItem *_parent) | ||
1087 | { | ||
1088 | DevTreeItem *parent = dynamic_cast< DevTreeItem* >(_parent); | ||
1089 | NewRegTreeItem *newdev_item = new NewRegTreeItem("New register...", parent->GetRef()); | ||
1090 | MakeItalic(newdev_item, true); | ||
1091 | newdev_item->setIcon(0, QIcon::fromTheme("list-add")); | ||
1092 | parent->addChild(newdev_item); | ||
1093 | } | ||
1094 | |||
1095 | void RegEdit::FillDevTreeItem(QTreeWidgetItem *_item) | ||
1096 | { | ||
1097 | DevTreeItem *item = dynamic_cast< DevTreeItem* >(_item); | ||
1098 | const soc_dev_t& dev = item->GetRef().GetDev(); | ||
1099 | for(size_t i = 0; i < dev.reg.size(); i++) | ||
1100 | { | ||
1101 | const soc_reg_t& reg = dev.reg[i]; | ||
1102 | RegTreeItem *reg_item = new RegTreeItem(QString::fromStdString(reg.name), | ||
1103 | SocRegRef(item->GetRef(), i, -1)); | ||
1104 | FixupEmptyItem(reg_item); | ||
1105 | FillRegTreeItem(reg_item); | ||
1106 | item->addChild(reg_item); | ||
1107 | } | ||
1108 | CreateNewRegisterItem(item); | ||
1109 | } | ||
1110 | |||
1111 | void RegEdit::CreateNewDeviceItem(QTreeWidgetItem *_parent) | ||
1112 | { | ||
1113 | SocTreeItem *parent = dynamic_cast< SocTreeItem* >(_parent); | ||
1114 | NewDevTreeItem *newdev_item = new NewDevTreeItem("New device...", parent->GetRef()); | ||
1115 | MakeItalic(newdev_item, true); | ||
1116 | newdev_item->setIcon(0, QIcon::fromTheme("list-add")); | ||
1117 | parent->addChild(newdev_item); | ||
1118 | } | ||
1119 | |||
1120 | void RegEdit::FillSocTreeItem(QTreeWidgetItem *_item) | ||
1121 | { | ||
1122 | SocTreeItem *item = dynamic_cast< SocTreeItem* >(_item); | ||
1123 | const soc_t& soc = item->GetRef().GetSoc(); | ||
1124 | for(size_t i = 0; i < soc.dev.size(); i++) | ||
1125 | { | ||
1126 | const soc_dev_t& reg = soc.dev[i]; | ||
1127 | DevTreeItem *dev_item = new DevTreeItem(QString::fromStdString(reg.name), | ||
1128 | SocDevRef(item->GetRef(), i, -1)); | ||
1129 | FixupEmptyItem(dev_item); | ||
1130 | FillDevTreeItem(dev_item); | ||
1131 | item->addChild(dev_item); | ||
1132 | } | ||
1133 | CreateNewDeviceItem(item); | ||
1134 | } | ||
1135 | |||
1136 | void RegEdit::FillSocTree() | ||
1137 | { | ||
1138 | SocRef ref = m_cur_socfile.GetSocRef(); | ||
1139 | SocTreeItem *soc_item = new SocTreeItem( | ||
1140 | QString::fromStdString(ref.GetSoc().name), ref); | ||
1141 | FixupEmptyItem(soc_item); | ||
1142 | FillSocTreeItem(soc_item); | ||
1143 | m_soc_tree->addTopLevelItem(soc_item); | ||
1144 | soc_item->setExpanded(true); | ||
1145 | } | ||
1146 | |||
1147 | void RegEdit::MakeItalic(QTreeWidgetItem *item, bool it) | ||
1148 | { | ||
1149 | QFont font = item->font(0); | ||
1150 | font.setItalic(it); | ||
1151 | item->setFont(0, font); | ||
1152 | } | ||
1153 | |||
1154 | void RegEdit::FixupEmptyItem(QTreeWidgetItem *item) | ||
1155 | { | ||
1156 | if(item->text(0).size() == 0) | ||
1157 | { | ||
1158 | item->setIcon(0, QIcon::fromTheme("dialog-error")); | ||
1159 | MakeItalic(item, true); | ||
1160 | item->setText(0, "Unnamed"); | ||
1161 | } | ||
1162 | else | ||
1163 | { | ||
1164 | item->setIcon(0, QIcon::fromTheme("cpu")); | ||
1165 | MakeItalic(item, false); | ||
1166 | } | ||
1167 | } | ||
1168 | |||
1169 | void RegEdit::UpdateSocFile() | ||
1170 | { | ||
1171 | m_soc_tree->clear(); | ||
1172 | FillSocTree(); | ||
1173 | SetPanel(new EmptyEditPanel(this)); | ||
1174 | } | ||
1175 | |||
1176 | void RegEdit::SetPanel(QWidget *panel) | ||
1177 | { | ||
1178 | delete m_right_panel; | ||
1179 | m_right_panel = panel; | ||
1180 | connect(m_right_panel, SIGNAL(OnModified(bool)), this, SLOT(OnSocModified(bool))); | ||
1181 | m_splitter->addWidget(m_right_panel); | ||
1182 | m_splitter->setStretchFactor(1, 2); | ||
1183 | } | ||
1184 | |||
1185 | void RegEdit::SetModified(bool add, bool mod) | ||
1186 | { | ||
1187 | m_modified = add ? (m_modified || mod) : mod; | ||
1188 | emit OnModified(mod); | ||
1189 | } | ||
1190 | |||
1191 | void RegEdit::OnSocModified(bool modified) | ||
1192 | { | ||
1193 | // we might need to update the name in the tree | ||
1194 | UpdateName(m_soc_tree->currentItem()); | ||
1195 | if(modified) | ||
1196 | SetModified(true, true); | ||
1197 | } | ||
1198 | |||
1199 | void RegEdit::DisplaySoc(SocRef ref) | ||
1200 | { | ||
1201 | SetPanel(new SocEditPanel(ref, this)); | ||
1202 | } | ||
1203 | |||
1204 | void RegEdit::DisplayDev(SocDevRef ref) | ||
1205 | { | ||
1206 | SetPanel(new DevEditPanel(ref, this)); | ||
1207 | } | ||
1208 | |||
1209 | void RegEdit::DisplayReg(SocRegRef ref) | ||
1210 | { | ||
1211 | SetPanel(new RegEditPanel(ref, this)); | ||
1212 | } | ||
1213 | |||
1214 | void RegEdit::DisplayField(SocFieldRef ref) | ||
1215 | { | ||
1216 | SetPanel(new FieldEditPanel(ref, this)); | ||
1217 | } | ||
1218 | |||
1219 | void RegEdit::UpdateName(QTreeWidgetItem *current) | ||
1220 | { | ||
1221 | if(current == 0) | ||
1222 | return; | ||
1223 | if(current->type() == SocTreeSocType) | ||
1224 | { | ||
1225 | SocTreeItem *item = dynamic_cast< SocTreeItem * >(current); | ||
1226 | item->setText(0, QString::fromStdString(item->GetRef().GetSoc().name)); | ||
1227 | } | ||
1228 | else if(current->type() == SocTreeDevType) | ||
1229 | { | ||
1230 | DevTreeItem *item = dynamic_cast< DevTreeItem * >(current); | ||
1231 | item->setText(0, QString::fromStdString(item->GetRef().GetDev().name)); | ||
1232 | } | ||
1233 | else if(current->type() == SocTreeRegType) | ||
1234 | { | ||
1235 | RegTreeItem *item = dynamic_cast< RegTreeItem * >(current); | ||
1236 | item->setText(0, QString::fromStdString(item->GetRef().GetReg().name)); | ||
1237 | } | ||
1238 | else if(current->type() == SocTreeFieldType) | ||
1239 | { | ||
1240 | FieldTreeItem *item = dynamic_cast< FieldTreeItem * >(current); | ||
1241 | item->setText(0, QString::fromStdString(item->GetRef().GetField().name)); | ||
1242 | } | ||
1243 | FixupEmptyItem(current); | ||
1244 | } | ||
1245 | |||
1246 | void RegEdit::OnSocItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous) | ||
1247 | { | ||
1248 | Q_UNUSED(previous); | ||
1249 | if(current == 0) | ||
1250 | return; | ||
1251 | if(current->type() == SocTreeSocType) | ||
1252 | { | ||
1253 | SocTreeItem *item = dynamic_cast< SocTreeItem * >(current); | ||
1254 | DisplaySoc(item->GetRef()); | ||
1255 | } | ||
1256 | else if(current->type() == SocTreeDevType) | ||
1257 | { | ||
1258 | DevTreeItem *item = dynamic_cast< DevTreeItem * >(current); | ||
1259 | DisplayDev(item->GetRef()); | ||
1260 | } | ||
1261 | else if(current->type() == SocTreeRegType) | ||
1262 | { | ||
1263 | RegTreeItem *item = dynamic_cast< RegTreeItem * >(current); | ||
1264 | DisplayReg(item->GetRef()); | ||
1265 | } | ||
1266 | else if(current->type() == SocTreeFieldType) | ||
1267 | { | ||
1268 | FieldTreeItem *item = dynamic_cast< FieldTreeItem * >(current); | ||
1269 | DisplayField(item->GetRef()); | ||
1270 | } | ||
1271 | } | ||
1272 | |||
1273 | void RegEdit::OnSocItemActivated(QTreeWidgetItem *current, int column) | ||
1274 | { | ||
1275 | Q_UNUSED(column); | ||
1276 | if(current == 0) | ||
1277 | return; | ||
1278 | if(current->type() == SocTreeNewDevType) | ||
1279 | AddDevice(current); | ||
1280 | else if(current->type() == SocTreeNewRegType) | ||
1281 | AddRegister(current); | ||
1282 | else if(current->type() == SocTreeNewFieldType) | ||
1283 | AddField(current); | ||
1284 | } | ||
1285 | |||
1286 | void RegEdit::AddDevice(QTreeWidgetItem *_item) | ||
1287 | { | ||
1288 | NewDevTreeItem *item = dynamic_cast< NewDevTreeItem * >(_item); | ||
1289 | item->GetRef().GetSoc().dev.push_back(soc_dev_t()); | ||
1290 | DevTreeItem *dev_item = new DevTreeItem("", | ||
1291 | SocDevRef(item->GetRef(), item->GetRef().GetSoc().dev.size() - 1, -1)); | ||
1292 | FixupEmptyItem(dev_item); | ||
1293 | item->parent()->insertChild(item->parent()->indexOfChild(item), dev_item); | ||
1294 | CreateNewRegisterItem(dev_item); | ||
1295 | m_soc_tree->setCurrentItem(dev_item); | ||
1296 | } | ||
1297 | |||
1298 | void RegEdit::AddRegister(QTreeWidgetItem *_item) | ||
1299 | { | ||
1300 | NewRegTreeItem *item = dynamic_cast< NewRegTreeItem * >(_item); | ||
1301 | item->GetRef().GetDev().reg.push_back(soc_reg_t()); | ||
1302 | RegTreeItem *reg_item = new RegTreeItem("", | ||
1303 | SocRegRef(item->GetRef(), item->GetRef().GetDev().reg.size() - 1, -1)); | ||
1304 | FixupEmptyItem(reg_item); | ||
1305 | item->parent()->insertChild(item->parent()->indexOfChild(item), reg_item); | ||
1306 | CreateNewFieldItem(reg_item); | ||
1307 | m_soc_tree->setCurrentItem(reg_item); | ||
1308 | } | ||
1309 | |||
1310 | void RegEdit::AddField(QTreeWidgetItem *_item) | ||
1311 | { | ||
1312 | NewFieldTreeItem *item = dynamic_cast< NewFieldTreeItem * >(_item); | ||
1313 | item->GetRef().GetReg().field.push_back(soc_reg_field_t()); | ||
1314 | FieldTreeItem *field_item = new FieldTreeItem("", | ||
1315 | SocFieldRef(item->GetRef(), item->GetRef().GetReg().field.size() - 1)); | ||
1316 | FixupEmptyItem(field_item); | ||
1317 | item->parent()->insertChild(item->parent()->indexOfChild(item), field_item); | ||
1318 | m_soc_tree->setCurrentItem(field_item); | ||
1319 | } | ||
1320 | |||
1321 | bool RegEdit::Quit() | ||
1322 | { | ||
1323 | return CloseSoc(); | ||
1324 | } \ No newline at end of file | ||
diff --git a/utils/regtools/qeditor/regedit.h b/utils/regtools/qeditor/regedit.h new file mode 100644 index 0000000000..8615816783 --- /dev/null +++ b/utils/regtools/qeditor/regedit.h | |||
@@ -0,0 +1,282 @@ | |||
1 | #ifndef REGEDIT_H | ||
2 | #define REGEDIT_H | ||
3 | |||
4 | #include <QComboBox> | ||
5 | #include <QTreeWidget> | ||
6 | #include <QVBoxLayout> | ||
7 | #include <QTabWidget> | ||
8 | #include <QSplitter> | ||
9 | #include <QLineEdit> | ||
10 | #include <QPushButton> | ||
11 | #include <QLabel> | ||
12 | #include <QListWidget> | ||
13 | #include <QGroupBox> | ||
14 | #include <QToolButton> | ||
15 | #include <QMenu> | ||
16 | #include <QCheckBox> | ||
17 | #include <QRadioButton> | ||
18 | #include <QButtonGroup> | ||
19 | #include <QDebug> | ||
20 | #include <QScrollArea> | ||
21 | #include "backend.h" | ||
22 | #include "settings.h" | ||
23 | #include "mainwindow.h" | ||
24 | #include "aux.h" | ||
25 | |||
26 | class AbstractRegEditPanel | ||
27 | { | ||
28 | public: | ||
29 | AbstractRegEditPanel() {} | ||
30 | virtual ~AbstractRegEditPanel() {} | ||
31 | virtual void OnModified(bool mod) = 0; | ||
32 | }; | ||
33 | |||
34 | class EmptyEditPanel : public QWidget, public AbstractRegEditPanel | ||
35 | { | ||
36 | Q_OBJECT | ||
37 | public: | ||
38 | EmptyEditPanel(QWidget *parent); | ||
39 | |||
40 | signals: | ||
41 | void OnModified(bool mod); | ||
42 | |||
43 | protected: | ||
44 | }; | ||
45 | |||
46 | class SocEditPanel : public QWidget, public AbstractRegEditPanel | ||
47 | { | ||
48 | Q_OBJECT | ||
49 | public: | ||
50 | SocEditPanel(SocRef ref, QWidget *parent = 0); | ||
51 | |||
52 | signals: | ||
53 | void OnModified(bool mod); | ||
54 | |||
55 | protected slots: | ||
56 | void OnTextEdited(); | ||
57 | void OnNameEdited(const QString& text); | ||
58 | |||
59 | protected: | ||
60 | SocRef m_ref; | ||
61 | QGroupBox *m_name_group; | ||
62 | QLineEdit *m_name_edit; | ||
63 | QGroupBox *m_desc_group; | ||
64 | MyTextEditor *m_desc_edit; | ||
65 | }; | ||
66 | |||
67 | class DevEditPanel : public QWidget, public AbstractRegEditPanel | ||
68 | { | ||
69 | Q_OBJECT | ||
70 | public: | ||
71 | DevEditPanel(SocDevRef ref, QWidget *parent = 0); | ||
72 | |||
73 | signals: | ||
74 | void OnModified(bool mod); | ||
75 | |||
76 | protected slots: | ||
77 | void OnInstActivated(int row, int column); | ||
78 | void OnInstChanged(int row, int column); | ||
79 | void OnNameEdited(const QString& text); | ||
80 | void OnLongNameEdited(const QString& text); | ||
81 | void OnVersionEdited(const QString& text); | ||
82 | void OnDescEdited(); | ||
83 | |||
84 | protected: | ||
85 | void FillRow(int row, const soc_dev_addr_t& addr); | ||
86 | void CreateNewRow(int row); | ||
87 | |||
88 | enum | ||
89 | { | ||
90 | DevInstDeleteType = QTableWidgetItem::UserType, | ||
91 | DevInstNewType | ||
92 | }; | ||
93 | |||
94 | enum | ||
95 | { | ||
96 | DevInstIconColumn = 0, | ||
97 | DevInstNameColumn = 1, | ||
98 | DevInstAddrColumn = 2, | ||
99 | }; | ||
100 | |||
101 | SocDevRef m_ref; | ||
102 | QGroupBox *m_name_group; | ||
103 | QLineEdit *m_name_edit; | ||
104 | QGroupBox *m_long_name_group; | ||
105 | QLineEdit *m_long_name_edit; | ||
106 | QGroupBox *m_version_group; | ||
107 | QLineEdit *m_version_edit; | ||
108 | QGroupBox *m_instances_group; | ||
109 | QTableWidget *m_instances_table; | ||
110 | QGroupBox *m_desc_group; | ||
111 | MyTextEditor *m_desc_edit; | ||
112 | }; | ||
113 | |||
114 | class RegEditPanel : public QWidget, public AbstractRegEditPanel | ||
115 | { | ||
116 | Q_OBJECT | ||
117 | public: | ||
118 | RegEditPanel(SocRegRef ref, QWidget *parent = 0); | ||
119 | |||
120 | signals: | ||
121 | void OnModified(bool mod); | ||
122 | |||
123 | protected slots: | ||
124 | void OnInstActivated(int row, int column); | ||
125 | void OnInstChanged(int row, int column); | ||
126 | void OnNameEdited(const QString& text); | ||
127 | void OnDescEdited(); | ||
128 | void OnSctEdited(int state); | ||
129 | void OnFormulaChanged(int index); | ||
130 | void OnFormulaStringChanged(const QString& text); | ||
131 | void OnFormulaGenerate(bool checked); | ||
132 | |||
133 | protected: | ||
134 | void CreateNewAddrRow(int row); | ||
135 | void FillRow(int row, const soc_reg_addr_t& addr); | ||
136 | void UpdateFormula(); | ||
137 | void UpdateWarning(int row); | ||
138 | |||
139 | enum | ||
140 | { | ||
141 | RegInstDeleteType = QTableWidgetItem::UserType, | ||
142 | RegInstNewType | ||
143 | }; | ||
144 | |||
145 | enum | ||
146 | { | ||
147 | RegInstIconColumn = 0, | ||
148 | RegInstNameColumn, | ||
149 | RegInstAddrColumn, | ||
150 | RegInstNrColumns, | ||
151 | }; | ||
152 | |||
153 | SocRegRef m_ref; | ||
154 | QGroupBox *m_name_group; | ||
155 | QLineEdit *m_name_edit; | ||
156 | QGroupBox *m_instances_group; | ||
157 | QTableWidget *m_instances_table; | ||
158 | QGroupBox *m_desc_group; | ||
159 | QGroupBox *m_flags_group; | ||
160 | QCheckBox *m_sct_check; | ||
161 | QFont m_reg_font; | ||
162 | QGroupBox *m_formula_group; | ||
163 | QButtonGroup *m_formula_radio_group; | ||
164 | QLabel *m_formula_type_label; | ||
165 | QComboBox *m_formula_combo; | ||
166 | QLineEdit *m_formula_string_edit; | ||
167 | QPushButton *m_formula_string_gen; | ||
168 | RegSexyDisplay *m_sexy_display; | ||
169 | MyTextEditor *m_desc_edit; | ||
170 | QGroupBox *m_field_group; | ||
171 | QTableWidget *m_field_table; | ||
172 | }; | ||
173 | |||
174 | class FieldEditPanel : public QWidget, public AbstractRegEditPanel | ||
175 | { | ||
176 | Q_OBJECT | ||
177 | public: | ||
178 | FieldEditPanel(SocFieldRef ref, QWidget *parent = 0); | ||
179 | |||
180 | signals: | ||
181 | void OnModified(bool mod); | ||
182 | |||
183 | protected slots: | ||
184 | void OnDescEdited(); | ||
185 | void OnNameEdited(const QString& text); | ||
186 | void OnBitRangeEdited(const QString& string); | ||
187 | void OnValueActivated(int row, int column); | ||
188 | void OnValueChanged(int row, int column); | ||
189 | |||
190 | protected: | ||
191 | void CreateNewRow(int row); | ||
192 | void FillRow(int row, const soc_reg_field_value_t& val); | ||
193 | void UpdateWarning(int row); | ||
194 | void UpdateDelegates(); | ||
195 | |||
196 | enum | ||
197 | { | ||
198 | FieldValueDeleteType = QTableWidgetItem::UserType, | ||
199 | FieldValueNewType, | ||
200 | }; | ||
201 | |||
202 | enum | ||
203 | { | ||
204 | FieldValueIconColumn = 0, | ||
205 | FieldValueNameColumn, | ||
206 | FieldValueValueColumn, | ||
207 | FieldValueDescColumn, | ||
208 | FieldValueNrColumns, | ||
209 | }; | ||
210 | |||
211 | SocFieldRef m_ref; | ||
212 | QGroupBox *m_name_group; | ||
213 | QLineEdit *m_name_edit; | ||
214 | QGroupBox *m_bitrange_group; | ||
215 | QLineEdit *m_bitrange_edit; | ||
216 | QGroupBox *m_desc_group; | ||
217 | MyTextEditor *m_desc_edit; | ||
218 | QGroupBox *m_value_group; | ||
219 | QTableWidget *m_value_table; | ||
220 | }; | ||
221 | |||
222 | class RegEdit : public QWidget, public DocumentTab | ||
223 | { | ||
224 | Q_OBJECT | ||
225 | public: | ||
226 | RegEdit(Backend *backend, QWidget *parent = 0); | ||
227 | ~RegEdit(); | ||
228 | virtual bool Quit(); | ||
229 | |||
230 | signals: | ||
231 | void OnModified(bool mod); | ||
232 | |||
233 | protected slots: | ||
234 | void OnSocItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous); | ||
235 | void OnSocItemActivated(QTreeWidgetItem *current, int column); | ||
236 | void OnOpen(); | ||
237 | void OnSave(); | ||
238 | void OnSaveAs(); | ||
239 | void OnSocModified(bool modified); | ||
240 | void OnNew(); | ||
241 | |||
242 | protected: | ||
243 | void LoadSocFile(const QString& filename); | ||
244 | void UpdateSocFile(); | ||
245 | void FillSocTree(); | ||
246 | void FillSocTreeItem(QTreeWidgetItem *_item); | ||
247 | void FillDevTreeItem(QTreeWidgetItem *_item); | ||
248 | void FillRegTreeItem(QTreeWidgetItem *_item); | ||
249 | void SetPanel(QWidget *panel); | ||
250 | void DisplaySoc(SocRef ref); | ||
251 | void DisplayDev(SocDevRef ref); | ||
252 | void DisplayReg(SocRegRef ref); | ||
253 | void DisplayField(SocFieldRef ref); | ||
254 | bool CloseSoc(); | ||
255 | bool SaveSoc(); | ||
256 | bool SaveSocAs(); | ||
257 | bool SaveSocFile(const QString& filename); | ||
258 | bool GetFilename(QString& filename, bool save); | ||
259 | void SetModified(bool add, bool mod); | ||
260 | void FixupEmptyItem(QTreeWidgetItem *item); | ||
261 | void MakeItalic(QTreeWidgetItem *item, bool it); | ||
262 | void AddDevice(QTreeWidgetItem *item); | ||
263 | void AddRegister(QTreeWidgetItem *_item); | ||
264 | void UpdateName(QTreeWidgetItem *current); | ||
265 | void AddField(QTreeWidgetItem *_item); | ||
266 | void CreateNewDeviceItem(QTreeWidgetItem *parent); | ||
267 | void CreateNewRegisterItem(QTreeWidgetItem *parent); | ||
268 | void CreateNewFieldItem(QTreeWidgetItem *parent); | ||
269 | |||
270 | QGroupBox *m_file_group; | ||
271 | QToolButton *m_file_open; | ||
272 | QToolButton *m_file_save; | ||
273 | QLineEdit *m_file_edit; | ||
274 | QSplitter *m_splitter; | ||
275 | QTreeWidget *m_soc_tree; | ||
276 | Backend *m_backend; | ||
277 | bool m_modified; | ||
278 | SocFile m_cur_socfile; | ||
279 | QWidget *m_right_panel; | ||
280 | }; | ||
281 | |||
282 | #endif /* REGEDIT_H */ | ||
diff --git a/utils/regtools/qeditor/regtab.cpp b/utils/regtools/qeditor/regtab.cpp index 4cd4e7b283..568d859c0e 100644 --- a/utils/regtools/qeditor/regtab.cpp +++ b/utils/regtools/qeditor/regtab.cpp | |||
@@ -1,406 +1,75 @@ | |||
1 | #include "regtab.h" | 1 | #include "regtab.h" |
2 | 2 | ||
3 | #include <QSplitter> | ||
4 | #include <QVBoxLayout> | ||
5 | #include <QAbstractListModel> | ||
6 | #include <QMessageBox> | ||
7 | #include <QSizePolicy> | 3 | #include <QSizePolicy> |
8 | #include <QHBoxLayout> | ||
9 | #include <QStringBuilder> | 4 | #include <QStringBuilder> |
10 | #include <QLabel> | ||
11 | #include <QGridLayout> | ||
12 | #include <QTableWidget> | ||
13 | #include <QHeaderView> | ||
14 | #include <QFileDialog> | 5 | #include <QFileDialog> |
15 | #include <QDebug> | 6 | #include <QDebug> |
16 | #include <QStyle> | 7 | #include <QStyle> |
17 | #include "backend.h" | 8 | #include "backend.h" |
18 | #include "analyser.h" | 9 | #include "analyser.h" |
10 | #include "regdisplaypanel.h" | ||
19 | 11 | ||
20 | /** | 12 | namespace |
21 | * SocFieldValidator | ||
22 | */ | ||
23 | |||
24 | SocFieldValidator::SocFieldValidator(QObject *parent) | ||
25 | :QValidator(parent) | ||
26 | { | ||
27 | m_field.first_bit = 0; | ||
28 | m_field.last_bit = 31; | ||
29 | } | ||
30 | |||
31 | SocFieldValidator::SocFieldValidator(const soc_reg_field_t& field, QObject *parent) | ||
32 | :QValidator(parent), m_field(field) | ||
33 | { | ||
34 | } | ||
35 | |||
36 | void SocFieldValidator::fixup(QString& input) const | ||
37 | { | ||
38 | input = input.trimmed(); | ||
39 | } | ||
40 | |||
41 | QValidator::State SocFieldValidator::validate(QString& input, int& pos) const | ||
42 | { | ||
43 | (void) pos; | ||
44 | soc_word_t val; | ||
45 | State state = parse(input, val); | ||
46 | return state; | ||
47 | } | ||
48 | |||
49 | QValidator::State SocFieldValidator::parse(const QString& input, soc_word_t& val) const | ||
50 | { | ||
51 | // the empty string is all alwats intermediate | ||
52 | if(input.size() == 0) | ||
53 | return Intermediate; | ||
54 | // first check named values | ||
55 | State state = Invalid; | ||
56 | foreach(const soc_reg_field_value_t& value, m_field.value) | ||
57 | { | ||
58 | QString name = QString::fromLocal8Bit(value.name.c_str()); | ||
59 | // cannot be a substring if too long or empty | ||
60 | if(input.size() > name.size()) | ||
61 | continue; | ||
62 | // check equal string | ||
63 | if(input == name) | ||
64 | { | ||
65 | state = Acceptable; | ||
66 | val = value.value; | ||
67 | break; | ||
68 | } | ||
69 | // check substring | ||
70 | if(name.startsWith(input)) | ||
71 | state = Intermediate; | ||
72 | } | ||
73 | // early return for exact match | ||
74 | if(state == Acceptable) | ||
75 | return state; | ||
76 | // do a few special cases for convenience | ||
77 | if(input.compare("0x", Qt::CaseInsensitive) == 0 || | ||
78 | input.compare("0b", Qt::CaseInsensitive) == 0) | ||
79 | return Intermediate; | ||
80 | // try by parsing | ||
81 | unsigned basis, pos; | ||
82 | if(input.size() >= 2 && input.startsWith("0x", Qt::CaseInsensitive)) | ||
83 | { | ||
84 | basis = 16; | ||
85 | pos = 2; | ||
86 | } | ||
87 | else if(input.size() >= 2 && input.startsWith("0b", Qt::CaseInsensitive)) | ||
88 | { | ||
89 | basis = 2; | ||
90 | pos = 2; | ||
91 | } | ||
92 | else if(input.size() >= 2 && input.startsWith("0")) | ||
93 | { | ||
94 | basis = 8; | ||
95 | pos = 1; | ||
96 | } | ||
97 | else | ||
98 | { | ||
99 | basis = 10; | ||
100 | pos = 0; | ||
101 | } | ||
102 | bool ok = false; | ||
103 | unsigned long v = input.mid(pos).toULong(&ok, basis); | ||
104 | // if not ok, return result of name parsing | ||
105 | if(!ok) | ||
106 | return state; | ||
107 | // if ok, check if it fits in the number of bits | ||
108 | unsigned nr_bits = m_field.last_bit - m_field.first_bit + 1; | ||
109 | unsigned long max = nr_bits == 32 ? 0xffffffff : (1 << nr_bits) - 1; | ||
110 | if(v <= max) | ||
111 | { | ||
112 | val = v; | ||
113 | return Acceptable; | ||
114 | } | ||
115 | |||
116 | return state; | ||
117 | } | ||
118 | |||
119 | /** | ||
120 | * RegLineEdit | ||
121 | */ | ||
122 | RegLineEdit::RegLineEdit(QWidget *parent) | ||
123 | :QWidget(parent) | ||
124 | { | 13 | { |
125 | m_layout = new QHBoxLayout(this); | ||
126 | m_button = new QToolButton(this); | ||
127 | m_button->setCursor(Qt::ArrowCursor); | ||
128 | m_button->setStyleSheet("QToolButton { font-weight: bold; color: white; background: black; }"); | ||
129 | m_button->setPopupMode(QToolButton::InstantPopup); | ||
130 | m_edit = new QLineEdit(this); | ||
131 | m_layout->addWidget(m_button); | ||
132 | m_layout->addWidget(m_edit); | ||
133 | m_menu = new QMenu(this); | ||
134 | connect(m_menu->addAction("Write"), SIGNAL(triggered()), this, SLOT(OnWriteAct())); | ||
135 | connect(m_menu->addAction("Set"), SIGNAL(triggered()), this, SLOT(OnSetAct())); | ||
136 | connect(m_menu->addAction("Clear"), SIGNAL(triggered()), this, SLOT(OnClearAct())); | ||
137 | connect(m_menu->addAction("Toggle"), SIGNAL(triggered()), this, SLOT(OnToggleAct())); | ||
138 | EnableSCT(false); | ||
139 | SetReadOnly(false); | ||
140 | ShowMode(true); | ||
141 | SetMode(Write); | ||
142 | } | ||
143 | 14 | ||
144 | void RegLineEdit::SetReadOnly(bool ro) | 15 | enum |
145 | { | 16 | { |
146 | m_edit->setReadOnly(ro); | 17 | RegTreeDevType = QTreeWidgetItem::UserType, |
147 | m_readonly = ro; | 18 | RegTreeRegType |
148 | ShowMode(!ro); | 19 | }; |
149 | } | ||
150 | 20 | ||
151 | void RegLineEdit::EnableSCT(bool en) | 21 | class DevTreeItem : public QTreeWidgetItem |
152 | { | 22 | { |
153 | m_has_sct = en; | 23 | public: |
154 | if(!m_has_sct) | 24 | DevTreeItem(const QString& string, const SocDevRef& ref) |
155 | { | 25 | :QTreeWidgetItem(QStringList(string), RegTreeDevType), m_ref(ref) {} |
156 | m_button->setMenu(0); | ||
157 | SetMode(Write); | ||
158 | } | ||
159 | else | ||
160 | m_button->setMenu(m_menu); | ||
161 | } | ||
162 | |||
163 | RegLineEdit::~RegLineEdit() | ||
164 | { | ||
165 | } | ||
166 | 26 | ||
167 | QLineEdit *RegLineEdit::GetLineEdit() | 27 | const SocDevRef& GetRef() { return m_ref; } |
168 | { | 28 | private: |
169 | return m_edit; | 29 | SocDevRef m_ref; |
170 | } | 30 | }; |
171 | 31 | ||
172 | void RegLineEdit::ShowMode(bool show) | 32 | class RegTreeItem : public QTreeWidgetItem |
173 | { | 33 | { |
174 | if(show) | 34 | public: |
175 | m_button->show(); | 35 | RegTreeItem(const QString& string, const SocRegRef& ref) |
176 | else | 36 | :QTreeWidgetItem(QStringList(string), RegTreeRegType), m_ref(ref) {} |
177 | m_button->hide(); | ||
178 | } | ||
179 | 37 | ||
180 | void RegLineEdit::OnWriteAct() | 38 | const SocRegRef& GetRef() { return m_ref; } |
181 | { | 39 | private: |
182 | SetMode(Write); | 40 | SocRegRef m_ref; |
183 | } | 41 | }; |
184 | |||
185 | void RegLineEdit::OnSetAct() | ||
186 | { | ||
187 | SetMode(Set); | ||
188 | } | ||
189 | |||
190 | void RegLineEdit::OnClearAct() | ||
191 | { | ||
192 | SetMode(Clear); | ||
193 | } | ||
194 | |||
195 | void RegLineEdit::OnToggleAct() | ||
196 | { | ||
197 | SetMode(Toggle); | ||
198 | } | ||
199 | |||
200 | void RegLineEdit::SetMode(EditMode mode) | ||
201 | { | ||
202 | m_mode = mode; | ||
203 | switch(m_mode) | ||
204 | { | ||
205 | case Write: m_button->setText("WR"); break; | ||
206 | case Set: m_button->setText("SET"); break; | ||
207 | case Clear: m_button->setText("CLR"); break; | ||
208 | case Toggle: m_button->setText("TOG"); break; | ||
209 | default: break; | ||
210 | } | ||
211 | } | ||
212 | 42 | ||
213 | RegLineEdit::EditMode RegLineEdit::GetMode() | ||
214 | { | ||
215 | return m_mode; | ||
216 | } | 43 | } |
217 | 44 | ||
218 | /** | 45 | /** |
219 | * RegDisplayPanel | 46 | * EmptyRegTabPanel |
220 | */ | 47 | */ |
221 | 48 | EmptyRegTabPanel::EmptyRegTabPanel(QWidget *parent) | |
222 | RegDisplayPanel::RegDisplayPanel(QWidget *parent, IoBackend *io_backend, const SocRegRef& reg_ref) | 49 | :QWidget(parent) |
223 | :QGroupBox(parent), m_io_backend(io_backend), m_reg(reg_ref) | ||
224 | { | 50 | { |
225 | bool read_only = m_io_backend->IsReadOnly(); | 51 | QVBoxLayout *l = new QVBoxLayout; |
226 | 52 | l->addStretch(); | |
227 | QVBoxLayout *right_layout = new QVBoxLayout; | 53 | setLayout(l); |
228 | |||
229 | const soc_dev_addr_t& dev_addr = m_reg.GetDevAddr(); | ||
230 | const soc_reg_t& reg = m_reg.GetReg(); | ||
231 | const soc_reg_addr_t& reg_addr = m_reg.GetRegAddr(); | ||
232 | |||
233 | QString reg_name; | ||
234 | reg_name.sprintf("HW_%s_%s", dev_addr.name.c_str(), reg_addr.name.c_str()); | ||
235 | QStringList names; | ||
236 | QVector< soc_addr_t > addresses; | ||
237 | names.append(reg_name); | ||
238 | addresses.append(reg_addr.addr); | ||
239 | if(reg.flags & REG_HAS_SCT) | ||
240 | { | ||
241 | names.append(reg_name + "_SET"); | ||
242 | names.append(reg_name + "_CLR"); | ||
243 | names.append(reg_name + "_TOG"); | ||
244 | addresses.append(reg_addr.addr + 4); | ||
245 | addresses.append(reg_addr.addr + 8); | ||
246 | addresses.append(reg_addr.addr + 12); | ||
247 | } | ||
248 | |||
249 | QString str; | ||
250 | str += "<table align=left>"; | ||
251 | for(int i = 0; i < names.size(); i++) | ||
252 | str += "<tr><td><b>" + names[i] + "</b></td></tr>"; | ||
253 | str += "</table>"; | ||
254 | QLabel *label_names = new QLabel; | ||
255 | label_names->setTextFormat(Qt::RichText); | ||
256 | label_names->setText(str); | ||
257 | |||
258 | QString str_addr; | ||
259 | str_addr += "<table align=left>"; | ||
260 | for(int i = 0; i < names.size(); i++) | ||
261 | str_addr += "<tr><td><b>" + QString().sprintf("0x%03x", addresses[i]) + "</b></td></tr>"; | ||
262 | str_addr += "</table>"; | ||
263 | QLabel *label_addr = new QLabel; | ||
264 | label_addr->setTextFormat(Qt::RichText); | ||
265 | label_addr->setText(str_addr); | ||
266 | |||
267 | QHBoxLayout *top_layout = new QHBoxLayout; | ||
268 | top_layout->addStretch(); | ||
269 | top_layout->addWidget(label_names); | ||
270 | top_layout->addWidget(label_addr); | ||
271 | top_layout->addStretch(); | ||
272 | |||
273 | soc_word_t value; | ||
274 | BackendHelper helper(m_io_backend, m_reg); | ||
275 | bool has_value = helper.ReadRegister(dev_addr.name.c_str(), reg_addr.name.c_str(), value); | ||
276 | |||
277 | QHBoxLayout *raw_val_layout = 0; | ||
278 | if(has_value) | ||
279 | { | ||
280 | QLabel *raw_val_name = new QLabel; | ||
281 | raw_val_name->setText("Raw value:"); | ||
282 | m_raw_val_edit = new RegLineEdit; | ||
283 | m_raw_val_edit->SetReadOnly(read_only); | ||
284 | m_raw_val_edit->GetLineEdit()->setText(QString().sprintf("0x%08x", value)); | ||
285 | m_raw_val_edit->GetLineEdit()->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter); | ||
286 | m_raw_val_edit->GetLineEdit()->setValidator(new SocFieldValidator(m_raw_val_edit)); | ||
287 | m_raw_val_edit->EnableSCT(!!(reg.flags & REG_HAS_SCT)); | ||
288 | connect(m_raw_val_edit->GetLineEdit(), SIGNAL(returnPressed()), this, SLOT(OnRawRegValueReturnPressed())); | ||
289 | raw_val_layout = new QHBoxLayout; | ||
290 | raw_val_layout->addStretch(); | ||
291 | raw_val_layout->addWidget(raw_val_name); | ||
292 | raw_val_layout->addWidget(m_raw_val_edit); | ||
293 | raw_val_layout->addStretch(); | ||
294 | } | ||
295 | else | ||
296 | m_raw_val_edit = 0; | ||
297 | |||
298 | QTableWidget *value_table = new QTableWidget; | ||
299 | value_table->setRowCount(reg.field.size()); | ||
300 | value_table->setColumnCount(4); | ||
301 | int row = 0; | ||
302 | foreach(const soc_reg_field_t& field, reg.field) | ||
303 | { | ||
304 | QString bits_str; | ||
305 | if(field.first_bit == field.last_bit) | ||
306 | bits_str.sprintf("%d", field.first_bit); | ||
307 | else | ||
308 | bits_str.sprintf("%d:%d", field.last_bit, field.first_bit); | ||
309 | QTableWidgetItem *item = new QTableWidgetItem(bits_str); | ||
310 | item->setTextAlignment(Qt::AlignVCenter | Qt::AlignHCenter); | ||
311 | item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); | ||
312 | value_table->setItem(row, 0, item); | ||
313 | item = new QTableWidgetItem(QString(field.name.c_str())); | ||
314 | item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); | ||
315 | value_table->setItem(row, 1, item); | ||
316 | item = new QTableWidgetItem(); | ||
317 | if(has_value) | ||
318 | { | ||
319 | soc_word_t v = (value & field.bitmask()) >> field.first_bit; | ||
320 | QString value_name; | ||
321 | foreach(const soc_reg_field_value_t& rval, field.value) | ||
322 | if(v == rval.value) | ||
323 | value_name = rval.name.c_str(); | ||
324 | const char *fmt = "%lu"; | ||
325 | // heuristic | ||
326 | if((field.last_bit - field.first_bit + 1) > 16) | ||
327 | fmt = "0x%lx"; | ||
328 | item->setText(QString().sprintf(fmt, (unsigned long)v)); | ||
329 | item->setTextAlignment(Qt::AlignVCenter | Qt::AlignHCenter); | ||
330 | |||
331 | if(value_name.size() != 0) | ||
332 | { | ||
333 | QTableWidgetItem *t = new QTableWidgetItem(value_name); | ||
334 | t->setTextAlignment(Qt::AlignVCenter | Qt::AlignHCenter); | ||
335 | t->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); | ||
336 | value_table->setItem(row, 3, t); | ||
337 | } | ||
338 | } | ||
339 | item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); | ||
340 | value_table->setItem(row, 2, item); | ||
341 | row++; | ||
342 | } | ||
343 | value_table->setHorizontalHeaderItem(0, new QTableWidgetItem("Bits")); | ||
344 | value_table->setHorizontalHeaderItem(1, new QTableWidgetItem("Name")); | ||
345 | value_table->setHorizontalHeaderItem(2, new QTableWidgetItem("Value")); | ||
346 | value_table->setHorizontalHeaderItem(3, new QTableWidgetItem("Meaning")); | ||
347 | value_table->verticalHeader()->setVisible(false); | ||
348 | value_table->resizeColumnsToContents(); | ||
349 | value_table->horizontalHeader()->setStretchLastSection(true); | ||
350 | value_table->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); | ||
351 | |||
352 | right_layout->addLayout(top_layout); | ||
353 | if(raw_val_layout) | ||
354 | right_layout->addLayout(raw_val_layout); | ||
355 | //right_layout->addWidget(bits_label); | ||
356 | right_layout->addWidget(value_table); | ||
357 | //right_layout->addStretch(); | ||
358 | |||
359 | setTitle("Register Description"); | ||
360 | setLayout(right_layout); | ||
361 | AllowWrite(false); | ||
362 | } | 54 | } |
363 | 55 | ||
364 | void RegDisplayPanel::AllowWrite(bool en) | 56 | void EmptyRegTabPanel::AllowWrite(bool en) |
365 | { | 57 | { |
366 | m_allow_write = en; | 58 | Q_UNUSED(en); |
367 | if(m_raw_val_edit) | ||
368 | m_raw_val_edit->SetReadOnly(m_io_backend->IsReadOnly() || !m_allow_write); | ||
369 | } | 59 | } |
370 | 60 | ||
371 | IoBackend::WriteMode RegDisplayPanel::EditModeToWriteMode(RegLineEdit::EditMode mode) | 61 | QWidget *EmptyRegTabPanel::GetWidget() |
372 | { | 62 | { |
373 | switch(mode) | 63 | return this; |
374 | { | ||
375 | case RegLineEdit::Write: return IoBackend::Write; | ||
376 | case RegLineEdit::Set: return IoBackend::Set; | ||
377 | case RegLineEdit::Clear: return IoBackend::Clear; | ||
378 | case RegLineEdit::Toggle: return IoBackend::Toggle; | ||
379 | default: return IoBackend::Write; | ||
380 | } | ||
381 | } | 64 | } |
382 | 65 | ||
383 | void RegDisplayPanel::OnRawRegValueReturnPressed() | ||
384 | { | ||
385 | soc_word_t val; | ||
386 | QLineEdit *edit = m_raw_val_edit->GetLineEdit(); | ||
387 | const SocFieldValidator *validator = dynamic_cast< const SocFieldValidator *>(edit->validator()); | ||
388 | QValidator::State state = validator->parse(edit->text(), val); | ||
389 | if(state != QValidator::Acceptable) | ||
390 | return; | ||
391 | IoBackend::WriteMode mode = EditModeToWriteMode(m_raw_val_edit->GetMode()); | ||
392 | BackendHelper helper(m_io_backend, m_reg); | ||
393 | helper.WriteRegister(m_reg.GetDevAddr().name.c_str(), m_reg.GetRegAddr().name.c_str(), | ||
394 | val, mode); | ||
395 | // FIXME: we should notify the UI to read value back because it has changed | ||
396 | } | ||
397 | 66 | ||
398 | /** | 67 | /** |
399 | * RegTab | 68 | * RegTab |
400 | */ | 69 | */ |
401 | 70 | ||
402 | RegTab::RegTab(Backend *backend) | 71 | RegTab::RegTab(Backend *backend, QWidget *parent) |
403 | :m_backend(backend) | 72 | :QSplitter(parent), m_backend(backend) |
404 | { | 73 | { |
405 | QWidget *left = new QWidget; | 74 | QWidget *left = new QWidget; |
406 | this->addWidget(left); | 75 | this->addWidget(left); |
@@ -432,7 +101,7 @@ RegTab::RegTab(Backend *backend) | |||
432 | QGroupBox *data_sel_group = new QGroupBox("Data selection"); | 101 | QGroupBox *data_sel_group = new QGroupBox("Data selection"); |
433 | QHBoxLayout *data_sel_layout = new QHBoxLayout; | 102 | QHBoxLayout *data_sel_layout = new QHBoxLayout; |
434 | m_data_selector = new QComboBox; | 103 | m_data_selector = new QComboBox; |
435 | m_data_selector->addItem(QIcon::fromTheme("face-sad"), "None", QVariant(DataSelNothing)); | 104 | m_data_selector->addItem(QIcon::fromTheme("text-x-generic"), "Explore", QVariant(DataSelNothing)); |
436 | m_data_selector->addItem(QIcon::fromTheme("document-open"), "File...", QVariant(DataSelFile)); | 105 | m_data_selector->addItem(QIcon::fromTheme("document-open"), "File...", QVariant(DataSelFile)); |
437 | #ifdef HAVE_HWSTUB | 106 | #ifdef HAVE_HWSTUB |
438 | m_data_selector->addItem(QIcon::fromTheme("multimedia-player"), "Device...", QVariant(DataSelDevice)); | 107 | m_data_selector->addItem(QIcon::fromTheme("multimedia-player"), "Device...", QVariant(DataSelDevice)); |
@@ -446,7 +115,8 @@ RegTab::RegTab(Backend *backend) | |||
446 | data_sel_reload->setIcon(QIcon::fromTheme("view-refresh")); | 115 | data_sel_reload->setIcon(QIcon::fromTheme("view-refresh")); |
447 | data_sel_reload->setToolTip("Reload data"); | 116 | data_sel_reload->setToolTip("Reload data"); |
448 | data_sel_layout->addWidget(m_data_selector); | 117 | data_sel_layout->addWidget(m_data_selector); |
449 | data_sel_layout->addWidget(m_data_sel_edit); | 118 | data_sel_layout->addWidget(m_data_sel_edit, 1); |
119 | data_sel_layout->addStretch(0); | ||
450 | #ifdef HAVE_HWSTUB | 120 | #ifdef HAVE_HWSTUB |
451 | m_dev_selector = new QComboBox; | 121 | m_dev_selector = new QComboBox; |
452 | data_sel_layout->addWidget(m_dev_selector, 1); | 122 | data_sel_layout->addWidget(m_dev_selector, 1); |
@@ -457,12 +127,9 @@ RegTab::RegTab(Backend *backend) | |||
457 | data_sel_group->setLayout(data_sel_layout); | 127 | data_sel_group->setLayout(data_sel_layout); |
458 | m_data_soc_label->setFrameStyle(QFrame::StyledPanel | QFrame::Raised); | 128 | m_data_soc_label->setFrameStyle(QFrame::StyledPanel | QFrame::Raised); |
459 | 129 | ||
460 | m_right_panel->addWidget(data_sel_group); | 130 | m_right_panel->addWidget(data_sel_group, 0); |
461 | m_right_content = new QWidget; | 131 | m_right_content = 0; |
462 | QVBoxLayout *l = new QVBoxLayout; | 132 | SetPanel(new EmptyRegTabPanel); |
463 | l->addStretch(); | ||
464 | m_right_content->setLayout(l); | ||
465 | m_right_panel->addWidget(m_right_content); | ||
466 | QWidget *w = new QWidget; | 133 | QWidget *w = new QWidget; |
467 | w->setLayout(m_right_panel); | 134 | w->setLayout(m_right_panel); |
468 | this->addWidget(w); | 135 | this->addWidget(w); |
@@ -470,21 +137,17 @@ RegTab::RegTab(Backend *backend) | |||
470 | 137 | ||
471 | m_io_backend = m_backend->CreateDummyIoBackend(); | 138 | m_io_backend = m_backend->CreateDummyIoBackend(); |
472 | 139 | ||
473 | connect(m_soc_selector, SIGNAL(currentIndexChanged(const QString&)), | 140 | connect(m_soc_selector, SIGNAL(currentIndexChanged(int)), |
474 | this, SLOT(OnSocChanged(const QString&))); | 141 | this, SLOT(OnSocChanged(int))); |
475 | connect(m_backend, SIGNAL(OnSocListChanged()), this, SLOT(OnSocListChanged())); | 142 | connect(m_backend, SIGNAL(OnSocListChanged()), this, SLOT(OnSocListChanged())); |
476 | connect(m_reg_tree, SIGNAL(currentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*)), | 143 | connect(m_reg_tree, SIGNAL(currentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*)), |
477 | this, SLOT(OnRegItemChanged(QTreeWidgetItem*, QTreeWidgetItem*))); | 144 | this, SLOT(OnRegItemChanged(QTreeWidgetItem*, QTreeWidgetItem*))); |
478 | connect(m_reg_tree, SIGNAL(itemClicked(QTreeWidgetItem *, int)), this, | ||
479 | SLOT(OnRegItemClicked(QTreeWidgetItem *, int))); | ||
480 | connect(m_data_selector, SIGNAL(activated(int)), | 145 | connect(m_data_selector, SIGNAL(activated(int)), |
481 | this, SLOT(OnDataSelChanged(int))); | 146 | this, SLOT(OnDataSelChanged(int))); |
482 | connect(m_data_soc_label, SIGNAL(linkActivated(const QString&)), this, | 147 | connect(m_data_soc_label, SIGNAL(linkActivated(const QString&)), this, |
483 | SLOT(OnDataSocActivated(const QString&))); | 148 | SLOT(OnDataSocActivated(const QString&))); |
484 | connect(m_analysers_list, SIGNAL(currentItemChanged(QListWidgetItem *, QListWidgetItem *)), | 149 | connect(m_analysers_list, SIGNAL(currentItemChanged(QListWidgetItem *, QListWidgetItem *)), |
485 | this, SLOT(OnAnalyserChanged(QListWidgetItem *, QListWidgetItem *))); | 150 | this, SLOT(OnAnalyserChanged(QListWidgetItem *, QListWidgetItem *))); |
486 | connect(m_analysers_list, SIGNAL(itemClicked(QListWidgetItem *)), this, | ||
487 | SLOT(OnAnalyserClicked(QListWidgetItem *))); | ||
488 | #ifdef HAVE_HWSTUB | 151 | #ifdef HAVE_HWSTUB |
489 | connect(m_dev_selector, SIGNAL(currentIndexChanged(int)), | 152 | connect(m_dev_selector, SIGNAL(currentIndexChanged(int)), |
490 | this, SLOT(OnDevChanged(int))); | 153 | this, SLOT(OnDevChanged(int))); |
@@ -492,14 +155,22 @@ RegTab::RegTab(Backend *backend) | |||
492 | connect(m_readonly_check, SIGNAL(clicked(bool)), this, SLOT(OnReadOnlyClicked(bool))); | 155 | connect(m_readonly_check, SIGNAL(clicked(bool)), this, SLOT(OnReadOnlyClicked(bool))); |
493 | 156 | ||
494 | OnSocListChanged(); | 157 | OnSocListChanged(); |
495 | OnDataSelChanged(DataSelNothing); | 158 | OnDataSelChanged(0); |
496 | } | 159 | } |
497 | 160 | ||
498 | RegTab::~RegTab() | 161 | RegTab::~RegTab() |
499 | { | 162 | { |
163 | #ifdef HAVE_HWSTUB | ||
164 | ClearDevList(); | ||
165 | #endif | ||
500 | delete m_io_backend; | 166 | delete m_io_backend; |
501 | } | 167 | } |
502 | 168 | ||
169 | bool RegTab::Quit() | ||
170 | { | ||
171 | return true; | ||
172 | } | ||
173 | |||
503 | void RegTab::SetDataSocName(const QString& socname) | 174 | void RegTab::SetDataSocName(const QString& socname) |
504 | { | 175 | { |
505 | if(socname.size() != 0) | 176 | if(socname.size() != 0) |
@@ -533,9 +204,10 @@ void RegTab::OnDataSelChanged(int index) | |||
533 | #ifdef HAVE_HWSTUB | 204 | #ifdef HAVE_HWSTUB |
534 | m_dev_selector->hide(); | 205 | m_dev_selector->hide(); |
535 | #endif | 206 | #endif |
207 | m_readonly_check->show(); | ||
536 | QFileDialog *fd = new QFileDialog(m_data_selector); | 208 | QFileDialog *fd = new QFileDialog(m_data_selector); |
537 | fd->setFilter("Textual files (*.txt);;All files (*)"); | 209 | fd->setFilter("Textual files (*.txt);;All files (*)"); |
538 | fd->setDirectory(Settings::Get()->value("regtab/loaddatadir", QDir::currentPath()).toString()); | 210 | fd->setDirectory(Settings::Get()->value("loaddatadir", QDir::currentPath()).toString()); |
539 | if(fd->exec()) | 211 | if(fd->exec()) |
540 | { | 212 | { |
541 | QStringList filenames = fd->selectedFiles(); | 213 | QStringList filenames = fd->selectedFiles(); |
@@ -545,13 +217,14 @@ void RegTab::OnDataSelChanged(int index) | |||
545 | SetDataSocName(m_io_backend->GetSocName()); | 217 | SetDataSocName(m_io_backend->GetSocName()); |
546 | OnDataSocActivated(m_io_backend->GetSocName()); | 218 | OnDataSocActivated(m_io_backend->GetSocName()); |
547 | } | 219 | } |
548 | Settings::Get()->setValue("regtab/loaddatadir", fd->directory().absolutePath()); | 220 | Settings::Get()->setValue("loaddatadir", fd->directory().absolutePath()); |
549 | SetReadOnlyIndicator(); | 221 | SetReadOnlyIndicator(); |
550 | } | 222 | } |
551 | #ifdef HAVE_HWSTUB | 223 | #ifdef HAVE_HWSTUB |
552 | else if(var == DataSelDevice) | 224 | else if(var == DataSelDevice) |
553 | { | 225 | { |
554 | m_data_sel_edit->hide(); | 226 | m_data_sel_edit->hide(); |
227 | m_readonly_check->show(); | ||
555 | m_dev_selector->show(); | 228 | m_dev_selector->show(); |
556 | OnDevListChanged(); | 229 | OnDevListChanged(); |
557 | } | 230 | } |
@@ -562,13 +235,31 @@ void RegTab::OnDataSelChanged(int index) | |||
562 | #ifdef HAVE_HWSTUB | 235 | #ifdef HAVE_HWSTUB |
563 | m_dev_selector->hide(); | 236 | m_dev_selector->hide(); |
564 | #endif | 237 | #endif |
238 | m_readonly_check->hide(); | ||
239 | |||
565 | delete m_io_backend; | 240 | delete m_io_backend; |
566 | m_io_backend = m_backend->CreateDummyIoBackend(); | 241 | m_io_backend = m_backend->CreateDummyIoBackend(); |
242 | m_readonly_check->setCheckState(Qt::Checked); | ||
567 | SetDataSocName(""); | 243 | SetDataSocName(""); |
244 | UpdateSocFilename(); | ||
568 | } | 245 | } |
569 | OnDataChanged(); | 246 | OnDataChanged(); |
570 | } | 247 | } |
571 | 248 | ||
249 | void RegTab::UpdateSocFilename() | ||
250 | { | ||
251 | int index = m_data_selector->currentIndex(); | ||
252 | if(index == -1) | ||
253 | return; | ||
254 | if(m_data_selector->itemData(index) != DataSelNothing) | ||
255 | return; | ||
256 | index = m_soc_selector->currentIndex(); | ||
257 | if(index == -1) | ||
258 | return; | ||
259 | SocRef ref = m_soc_selector->itemData(index).value< SocRef >(); | ||
260 | m_data_sel_edit->setText(ref.GetSocFile()->GetFilename()); | ||
261 | } | ||
262 | |||
572 | void RegTab::SetReadOnlyIndicator() | 263 | void RegTab::SetReadOnlyIndicator() |
573 | { | 264 | { |
574 | if(m_io_backend->IsReadOnly()) | 265 | if(m_io_backend->IsReadOnly()) |
@@ -582,23 +273,30 @@ void RegTab::OnDataChanged() | |||
582 | 273 | ||
583 | void RegTab::OnRegItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous) | 274 | void RegTab::OnRegItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous) |
584 | { | 275 | { |
585 | (void) previous; | 276 | Q_UNUSED(previous); |
586 | OnRegItemClicked(current, 0); | 277 | OnRegItemClicked(current, 0); |
587 | } | 278 | } |
588 | 279 | ||
589 | void RegTab::OnRegItemClicked(QTreeWidgetItem *current, int col) | 280 | void RegTab::OnRegItemClicked(QTreeWidgetItem *current, int col) |
590 | { | 281 | { |
591 | (void) col; | 282 | Q_UNUSED(col); |
592 | if(current == 0 || current->type() != RegTreeRegType) | 283 | if(current == 0) |
593 | return; | 284 | return; |
594 | RegTreeItem *item = dynamic_cast< RegTreeItem * >(current); | 285 | if(current->type() == RegTreeRegType) |
595 | 286 | { | |
596 | DisplayRegister(item->GetRef()); | 287 | RegTreeItem *item = dynamic_cast< RegTreeItem * >(current); |
288 | DisplayRegister(item->GetRef()); | ||
289 | } | ||
290 | else if(current->type() == RegTreeDevType) | ||
291 | { | ||
292 | DevTreeItem *item = dynamic_cast< DevTreeItem * >(current); | ||
293 | DisplayDevice(item->GetRef()); | ||
294 | } | ||
597 | } | 295 | } |
598 | 296 | ||
599 | void RegTab::OnAnalyserChanged(QListWidgetItem *current, QListWidgetItem *previous) | 297 | void RegTab::OnAnalyserChanged(QListWidgetItem *current, QListWidgetItem *previous) |
600 | { | 298 | { |
601 | (void) previous; | 299 | Q_UNUSED(previous); |
602 | OnAnalyserClicked(current); | 300 | OnAnalyserClicked(current); |
603 | } | 301 | } |
604 | 302 | ||
@@ -606,33 +304,44 @@ void RegTab::OnAnalyserClicked(QListWidgetItem *current) | |||
606 | { | 304 | { |
607 | if(current == 0) | 305 | if(current == 0) |
608 | return; | 306 | return; |
609 | delete m_right_content; | ||
610 | AnalyserFactory *ana = AnalyserFactory::GetAnalyserByName(current->text()); | 307 | AnalyserFactory *ana = AnalyserFactory::GetAnalyserByName(current->text()); |
611 | m_right_content = ana->Create(m_cur_soc, m_io_backend)->GetWidget(); | 308 | SetPanel(ana->Create(m_cur_soc, m_io_backend)); |
612 | m_right_panel->addWidget(m_right_content, 1); | ||
613 | } | 309 | } |
614 | 310 | ||
615 | void RegTab::DisplayRegister(const SocRegRef& ref) | 311 | void RegTab::DisplayRegister(const SocRegRef& ref) |
616 | { | 312 | { |
313 | SetPanel(new RegDisplayPanel(this, m_io_backend, ref)); | ||
314 | } | ||
315 | |||
316 | void RegTab::DisplayDevice(const SocDevRef& ref) | ||
317 | { | ||
318 | SetPanel(new DevDisplayPanel(this, ref)); | ||
319 | } | ||
320 | |||
321 | void RegTab::SetPanel(RegTabPanel *panel) | ||
322 | { | ||
617 | delete m_right_content; | 323 | delete m_right_content; |
618 | RegDisplayPanel *panel = new RegDisplayPanel(this, m_io_backend, ref); | ||
619 | panel->AllowWrite(m_readonly_check->checkState() == Qt::Unchecked); | ||
620 | m_right_content = panel; | 324 | m_right_content = panel; |
621 | m_right_panel->addWidget(m_right_content); | 325 | m_right_content->AllowWrite(m_readonly_check->checkState() == Qt::Unchecked); |
326 | m_right_panel->addWidget(m_right_content->GetWidget(), 1); | ||
622 | } | 327 | } |
623 | 328 | ||
624 | void RegTab::OnSocListChanged() | 329 | void RegTab::OnSocListChanged() |
625 | { | 330 | { |
626 | m_soc_selector->clear(); | 331 | m_soc_selector->clear(); |
627 | QStringList socs = m_backend->GetSocNameList(); | 332 | QList< SocRef > socs = m_backend->GetSocList(); |
628 | for(int i = 0; i < socs.size(); i++) | 333 | for(int i = 0; i < socs.size(); i++) |
629 | m_soc_selector->addItem(socs[i]); | 334 | { |
335 | QVariant v; | ||
336 | v.setValue(socs[i]); | ||
337 | m_soc_selector->addItem(QString::fromStdString(socs[i].GetSoc().name), v); | ||
338 | } | ||
630 | } | 339 | } |
631 | 340 | ||
632 | #ifdef HAVE_HWSTUB | 341 | #ifdef HAVE_HWSTUB |
633 | void RegTab::OnDevListChanged() | 342 | void RegTab::OnDevListChanged() |
634 | { | 343 | { |
635 | m_dev_selector->clear(); | 344 | ClearDevList(); |
636 | QList< HWStubDevice* > list = m_hwstub_helper.GetDevList(); | 345 | QList< HWStubDevice* > list = m_hwstub_helper.GetDevList(); |
637 | foreach(HWStubDevice *dev, list) | 346 | foreach(HWStubDevice *dev, list) |
638 | { | 347 | { |
@@ -659,10 +368,21 @@ void RegTab::OnDevChanged(int index) | |||
659 | OnDataSocActivated(m_io_backend->GetSocName()); | 368 | OnDataSocActivated(m_io_backend->GetSocName()); |
660 | OnDataChanged(); | 369 | OnDataChanged(); |
661 | } | 370 | } |
371 | |||
372 | void RegTab::ClearDevList() | ||
373 | { | ||
374 | while(m_dev_selector->count() > 0) | ||
375 | { | ||
376 | HWStubDevice *dev = reinterpret_cast< HWStubDevice* >(m_dev_selector->itemData(0).value< void* >()); | ||
377 | delete dev; | ||
378 | m_dev_selector->removeItem(0); | ||
379 | } | ||
380 | } | ||
662 | #endif | 381 | #endif |
663 | 382 | ||
664 | void RegTab::FillDevSubTree(DevTreeItem *item) | 383 | void RegTab::FillDevSubTree(QTreeWidgetItem *_item) |
665 | { | 384 | { |
385 | DevTreeItem *item = dynamic_cast< DevTreeItem* >(_item); | ||
666 | const soc_dev_t& dev = item->GetRef().GetDev(); | 386 | const soc_dev_t& dev = item->GetRef().GetDev(); |
667 | for(size_t i = 0; i < dev.reg.size(); i++) | 387 | for(size_t i = 0; i < dev.reg.size(); i++) |
668 | { | 388 | { |
@@ -697,23 +417,21 @@ void RegTab::FillAnalyserList() | |||
697 | m_analysers_list->addItems(AnalyserFactory::GetAnalysersForSoc(m_cur_soc.GetSoc().name.c_str())); | 417 | m_analysers_list->addItems(AnalyserFactory::GetAnalysersForSoc(m_cur_soc.GetSoc().name.c_str())); |
698 | } | 418 | } |
699 | 419 | ||
700 | void RegTab::OnSocChanged(const QString& soc) | 420 | void RegTab::OnSocChanged(int index) |
701 | { | 421 | { |
702 | m_reg_tree->clear(); | 422 | if(index == -1) |
703 | if(!m_backend->GetSocByName(soc, m_cur_soc)) | ||
704 | return; | 423 | return; |
424 | m_reg_tree->clear(); | ||
425 | m_cur_soc = m_soc_selector->itemData(index).value< SocRef >(); | ||
705 | FillRegTree(); | 426 | FillRegTree(); |
706 | FillAnalyserList(); | 427 | FillAnalyserList(); |
428 | UpdateSocFilename(); | ||
707 | } | 429 | } |
708 | 430 | ||
709 | void RegTab::OnReadOnlyClicked(bool checked) | 431 | void RegTab::OnReadOnlyClicked(bool checked) |
710 | { | 432 | { |
711 | if(m_io_backend->IsReadOnly()) | 433 | if(m_io_backend->IsReadOnly()) |
712 | return SetReadOnlyIndicator(); | 434 | return SetReadOnlyIndicator(); |
713 | if(m_right_content == 0) | 435 | m_right_content->AllowWrite(!checked); |
714 | return; | 436 | UpdateSocFilename(); |
715 | RegDisplayPanel *panel = dynamic_cast< RegDisplayPanel* >(m_right_content); | ||
716 | if(panel == 0) | ||
717 | return; | ||
718 | panel->AllowWrite(!checked); | ||
719 | } | 437 | } |
diff --git a/utils/regtools/qeditor/regtab.h b/utils/regtools/qeditor/regtab.h index 9fa1437119..78a10ba379 100644 --- a/utils/regtools/qeditor/regtab.h +++ b/utils/regtools/qeditor/regtab.h | |||
@@ -2,7 +2,6 @@ | |||
2 | #define REGTAB_H | 2 | #define REGTAB_H |
3 | 3 | ||
4 | #include <QComboBox> | 4 | #include <QComboBox> |
5 | #include <QEvent> | ||
6 | #include <QTreeWidget> | 5 | #include <QTreeWidget> |
7 | #include <QVBoxLayout> | 6 | #include <QVBoxLayout> |
8 | #include <QTabWidget> | 7 | #include <QTabWidget> |
@@ -11,118 +10,41 @@ | |||
11 | #include <QPushButton> | 10 | #include <QPushButton> |
12 | #include <QLabel> | 11 | #include <QLabel> |
13 | #include <QListWidget> | 12 | #include <QListWidget> |
14 | #include <QValidator> | ||
15 | #include <QGroupBox> | 13 | #include <QGroupBox> |
16 | #include <QToolButton> | 14 | #include <QToolButton> |
17 | #include <QMenu> | 15 | #include <QMenu> |
18 | #include <QCheckBox> | 16 | #include <QCheckBox> |
19 | #include <soc_desc.hpp> | ||
20 | #include "backend.h" | 17 | #include "backend.h" |
21 | #include "settings.h" | 18 | #include "settings.h" |
19 | #include "mainwindow.h" | ||
22 | 20 | ||
23 | enum | 21 | class RegTabPanel |
24 | { | ||
25 | RegTreeDevType = QTreeWidgetItem::UserType, | ||
26 | RegTreeRegType | ||
27 | }; | ||
28 | |||
29 | class DevTreeItem : public QTreeWidgetItem | ||
30 | { | ||
31 | public: | ||
32 | DevTreeItem(const QString& string, const SocDevRef& ref) | ||
33 | :QTreeWidgetItem(QStringList(string), RegTreeDevType), m_ref(ref) {} | ||
34 | |||
35 | const SocDevRef& GetRef() { return m_ref; } | ||
36 | private: | ||
37 | SocDevRef m_ref; | ||
38 | }; | ||
39 | |||
40 | class RegTreeItem : public QTreeWidgetItem | ||
41 | { | 22 | { |
42 | public: | 23 | public: |
43 | RegTreeItem(const QString& string, const SocRegRef& ref) | 24 | RegTabPanel() {} |
44 | :QTreeWidgetItem(QStringList(string), RegTreeRegType), m_ref(ref) {} | 25 | virtual ~RegTabPanel() {} |
45 | 26 | virtual void AllowWrite(bool en) = 0; | |
46 | const SocRegRef& GetRef() { return m_ref; } | 27 | virtual QWidget *GetWidget() = 0; |
47 | private: | ||
48 | SocRegRef m_ref; | ||
49 | }; | 28 | }; |
50 | 29 | ||
51 | class SocFieldValidator : public QValidator | 30 | class EmptyRegTabPanel : public QWidget, public RegTabPanel |
52 | { | 31 | { |
53 | Q_OBJECT | ||
54 | public: | 32 | public: |
55 | SocFieldValidator(QObject *parent = 0); | 33 | EmptyRegTabPanel(QWidget *parent = 0); |
56 | SocFieldValidator(const soc_reg_field_t& field, QObject *parent = 0); | ||
57 | |||
58 | virtual void fixup(QString& input) const; | ||
59 | virtual State validate(QString& input, int& pos) const; | ||
60 | /* validate and return the interpreted value */ | ||
61 | State parse(const QString& input, soc_word_t& val) const; | ||
62 | |||
63 | protected: | ||
64 | soc_reg_field_t m_field; | ||
65 | }; | ||
66 | |||
67 | class RegLineEdit : public QWidget | ||
68 | { | ||
69 | Q_OBJECT | ||
70 | public: | ||
71 | enum EditMode | ||
72 | { | ||
73 | Write, Set, Clear, Toggle | ||
74 | }; | ||
75 | |||
76 | RegLineEdit(QWidget *parent = 0); | ||
77 | ~RegLineEdit(); | ||
78 | void SetReadOnly(bool ro); | ||
79 | void EnableSCT(bool en); | ||
80 | void SetMode(EditMode mode); | ||
81 | EditMode GetMode(); | ||
82 | QLineEdit *GetLineEdit(); | ||
83 | |||
84 | protected slots: | ||
85 | void OnWriteAct(); | ||
86 | void OnSetAct(); | ||
87 | void OnClearAct(); | ||
88 | void OnToggleAct(); | ||
89 | protected: | ||
90 | void ShowMode(bool show); | ||
91 | |||
92 | QHBoxLayout *m_layout; | ||
93 | QToolButton *m_button; | ||
94 | QLineEdit *m_edit; | ||
95 | EditMode m_mode; | ||
96 | bool m_has_sct; | ||
97 | bool m_readonly; | ||
98 | QMenu *m_menu; | ||
99 | }; | ||
100 | |||
101 | class RegDisplayPanel : public QGroupBox | ||
102 | { | ||
103 | Q_OBJECT | ||
104 | public: | ||
105 | RegDisplayPanel(QWidget *parent, IoBackend *io_backend, const SocRegRef& reg); | ||
106 | void AllowWrite(bool en); | 34 | void AllowWrite(bool en); |
107 | 35 | QWidget *GetWidget(); | |
108 | protected: | ||
109 | IoBackend::WriteMode EditModeToWriteMode(RegLineEdit::EditMode mode); | ||
110 | |||
111 | IoBackend *m_io_backend; | ||
112 | const SocRegRef& m_reg; | ||
113 | bool m_allow_write; | ||
114 | RegLineEdit *m_raw_val_edit; | ||
115 | |||
116 | private slots: | ||
117 | void OnRawRegValueReturnPressed(); | ||
118 | }; | 36 | }; |
119 | 37 | ||
120 | class RegTab : public QSplitter | 38 | class RegTab : public QSplitter, public DocumentTab |
121 | { | 39 | { |
122 | Q_OBJECT | 40 | Q_OBJECT |
123 | public: | 41 | public: |
124 | RegTab(Backend *backend); | 42 | RegTab(Backend *backend, QWidget *parent = 0); |
125 | ~RegTab(); | 43 | ~RegTab(); |
44 | virtual bool Quit(); | ||
45 | |||
46 | signals: | ||
47 | void OnModified(bool modified); | ||
126 | 48 | ||
127 | protected: | 49 | protected: |
128 | enum | 50 | enum |
@@ -134,12 +56,16 @@ protected: | |||
134 | #endif | 56 | #endif |
135 | }; | 57 | }; |
136 | 58 | ||
137 | void FillDevSubTree(DevTreeItem *item); | 59 | void FillDevSubTree(QTreeWidgetItem *item); |
138 | void FillRegTree(); | 60 | void FillRegTree(); |
139 | void FillAnalyserList(); | 61 | void FillAnalyserList(); |
140 | void UpdateSocList(); | 62 | void UpdateSocList(); |
141 | void DisplayRegister(const SocRegRef& ref); | 63 | void DisplayRegister(const SocRegRef& ref); |
64 | void DisplayDevice(const SocDevRef& ref); | ||
142 | void SetDataSocName(const QString& socname); | 65 | void SetDataSocName(const QString& socname); |
66 | void SetPanel(RegTabPanel *panel); | ||
67 | void UpdateSocFilename(); | ||
68 | |||
143 | QComboBox *m_soc_selector; | 69 | QComboBox *m_soc_selector; |
144 | #ifdef HAVE_HWSTUB | 70 | #ifdef HAVE_HWSTUB |
145 | QComboBox *m_dev_selector; | 71 | QComboBox *m_dev_selector; |
@@ -149,7 +75,7 @@ protected: | |||
149 | QTreeWidget *m_reg_tree; | 75 | QTreeWidget *m_reg_tree; |
150 | SocRef m_cur_soc; | 76 | SocRef m_cur_soc; |
151 | QVBoxLayout *m_right_panel; | 77 | QVBoxLayout *m_right_panel; |
152 | QWidget *m_right_content; | 78 | RegTabPanel *m_right_content; |
153 | QLineEdit *m_data_sel_edit; | 79 | QLineEdit *m_data_sel_edit; |
154 | QCheckBox *m_readonly_check; | 80 | QCheckBox *m_readonly_check; |
155 | QLabel *m_data_soc_label; | 81 | QLabel *m_data_soc_label; |
@@ -163,9 +89,10 @@ private slots: | |||
163 | #ifdef HAVE_HWSTUB | 89 | #ifdef HAVE_HWSTUB |
164 | void OnDevListChanged(); | 90 | void OnDevListChanged(); |
165 | void OnDevChanged(int index); | 91 | void OnDevChanged(int index); |
92 | void ClearDevList(); | ||
166 | #endif | 93 | #endif |
167 | void SetReadOnlyIndicator(); | 94 | void SetReadOnlyIndicator(); |
168 | void OnSocChanged(const QString& text); | 95 | void OnSocChanged(int index); |
169 | void OnSocListChanged(); | 96 | void OnSocListChanged(); |
170 | void OnRegItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous); | 97 | void OnRegItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous); |
171 | void OnRegItemClicked(QTreeWidgetItem *clicked, int col); | 98 | void OnRegItemClicked(QTreeWidgetItem *clicked, int col); |
diff --git a/utils/regtools/qeditor/std_analysers.cpp b/utils/regtools/qeditor/std_analysers.cpp index 2cc84cb488..5847e39f7d 100644 --- a/utils/regtools/qeditor/std_analysers.cpp +++ b/utils/regtools/qeditor/std_analysers.cpp | |||
@@ -23,6 +23,7 @@ ClockAnalyser::ClockAnalyser(const SocRef& soc, IoBackend *backend) | |||
23 | 23 | ||
24 | ClockAnalyser::~ClockAnalyser() | 24 | ClockAnalyser::~ClockAnalyser() |
25 | { | 25 | { |
26 | delete m_group; | ||
26 | } | 27 | } |
27 | 28 | ||
28 | QWidget *ClockAnalyser::GetWidget() | 29 | QWidget *ClockAnalyser::GetWidget() |
@@ -287,9 +288,9 @@ void ClockAnalyser::FillTree() | |||
287 | else | 288 | else |
288 | AddClock(ref_xtal, "clk_rtc32k", INVALID); | 289 | AddClock(ref_xtal, "clk_rtc32k", INVALID); |
289 | 290 | ||
290 | (void) clk_x; | 291 | Q_UNUSED(clk_x); |
291 | (void) clk_gpmi; | 292 | Q_UNUSED(clk_gpmi); |
292 | (void) clk_h; | 293 | Q_UNUSED(clk_h); |
293 | 294 | ||
294 | m_tree_widget->expandAll(); | 295 | m_tree_widget->expandAll(); |
295 | m_tree_widget->resizeColumnToContents(0); | 296 | m_tree_widget->resizeColumnToContents(0); |
@@ -334,6 +335,7 @@ EmiAnalyser::EmiAnalyser(const SocRef& soc, IoBackend *backend) | |||
334 | 335 | ||
335 | EmiAnalyser::~EmiAnalyser() | 336 | EmiAnalyser::~EmiAnalyser() |
336 | { | 337 | { |
338 | delete m_group; | ||
337 | } | 339 | } |
338 | 340 | ||
339 | QWidget *EmiAnalyser::GetWidget() | 341 | QWidget *EmiAnalyser::GetWidget() |
@@ -671,6 +673,7 @@ PinAnalyser::PinAnalyser(const SocRef& soc, IoBackend *backend) | |||
671 | 673 | ||
672 | PinAnalyser::~PinAnalyser() | 674 | PinAnalyser::~PinAnalyser() |
673 | { | 675 | { |
676 | delete m_group; | ||
674 | } | 677 | } |
675 | 678 | ||
676 | QWidget *PinAnalyser::GetWidget() | 679 | QWidget *PinAnalyser::GetWidget() |
diff --git a/utils/regtools/qeditor/std_analysers.h b/utils/regtools/qeditor/std_analysers.h index aae8e40207..cca8b12b99 100644 --- a/utils/regtools/qeditor/std_analysers.h +++ b/utils/regtools/qeditor/std_analysers.h | |||
@@ -21,7 +21,6 @@ | |||
21 | 21 | ||
22 | class ClockAnalyser : public Analyser | 22 | class ClockAnalyser : public Analyser |
23 | { | 23 | { |
24 | Q_OBJECT | ||
25 | public: | 24 | public: |
26 | ClockAnalyser(const SocRef& soc, IoBackend *backend); | 25 | ClockAnalyser(const SocRef& soc, IoBackend *backend); |
27 | virtual ~ClockAnalyser(); | 26 | virtual ~ClockAnalyser(); |
@@ -50,7 +49,7 @@ private: | |||
50 | /** | 49 | /** |
51 | * EMI analyser | 50 | * EMI analyser |
52 | */ | 51 | */ |
53 | class EmiAnalyser : public Analyser | 52 | class EmiAnalyser : public QObject, public Analyser |
54 | { | 53 | { |
55 | Q_OBJECT | 54 | Q_OBJECT |
56 | public: | 55 | public: |
@@ -96,7 +95,6 @@ private: | |||
96 | */ | 95 | */ |
97 | class PinAnalyser : public Analyser | 96 | class PinAnalyser : public Analyser |
98 | { | 97 | { |
99 | Q_OBJECT | ||
100 | public: | 98 | public: |
101 | PinAnalyser(const SocRef& soc, IoBackend *backend); | 99 | PinAnalyser(const SocRef& soc, IoBackend *backend); |
102 | virtual ~PinAnalyser(); | 100 | virtual ~PinAnalyser(); |