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/regedit.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/regedit.cpp')
-rw-r--r-- | utils/regtools/qeditor/regedit.cpp | 1324 |
1 files changed, 1324 insertions, 0 deletions
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 | ||