diff options
author | Amaury Pouly <amaury.pouly@gmail.com> | 2014-04-07 11:28:04 +0200 |
---|---|---|
committer | Amaury Pouly <amaury.pouly@gmail.com> | 2014-05-01 19:34:18 +0200 |
commit | 4356666101e0e7985e65a19f86bc4a74519e93f9 (patch) | |
tree | bf8de8057d93d0fab0a30cae92a90f5a4edc79dc /utils/regtools/qeditor/regtab.cpp | |
parent | 3754624edc48539c5cc5acbf426ce909477e87d8 (diff) | |
download | rockbox-4356666101e0e7985e65a19f86bc4a74519e93f9.tar.gz rockbox-4356666101e0e7985e65a19f86bc4a74519e93f9.zip |
regtools: completely rework qeditor, improve soc desc library and tools
The graphical editor can now display and editor description files.
The library has been improved to provide more useful function.
The XML format has been slightly changed: only one soc is allowed per file
(this is was already de facto the case since <soc> was the root tag).
Also introduce a DTD to validate the files.
Change-Id: If70ba35b6dc0242bdb87411cf4baee9597798aac
Diffstat (limited to 'utils/regtools/qeditor/regtab.cpp')
-rw-r--r-- | utils/regtools/qeditor/regtab.cpp | 534 |
1 files changed, 126 insertions, 408 deletions
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 | } |