Amaury Pouly | fe1fed8 | 2014-09-26 10:46:48 +0200 | [diff] [blame] | 1 | /*************************************************************************** |
| 2 | * __________ __ ___. |
| 3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ |
| 4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / |
| 5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < |
| 6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ |
| 7 | * \/ \/ \/ \/ \/ |
| 8 | * $Id$ |
| 9 | * |
| 10 | * Copyright (C) 2014 by Amaury Pouly |
| 11 | * |
| 12 | * This program is free software; you can redistribute it and/or |
| 13 | * modify it under the terms of the GNU General Public License |
| 14 | * as published by the Free Software Foundation; either version 2 |
| 15 | * of the License, or (at your option) any later version. |
| 16 | * |
| 17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY |
| 18 | * KIND, either express or implied. |
| 19 | * |
| 20 | ****************************************************************************/ |
Amaury Pouly | 4356666 | 2014-04-07 11:28:04 +0200 | [diff] [blame] | 21 | #include "regdisplaypanel.h" |
| 22 | #include <QHeaderView> |
| 23 | #include <QDebug> |
| 24 | |
| 25 | /** |
| 26 | * RegItemEditorCreator |
| 27 | */ |
| 28 | |
| 29 | QWidget *RegItemEditorCreator::createWidget(QWidget * parent) const |
| 30 | { |
| 31 | return new RegLineEdit(parent); |
| 32 | } |
| 33 | |
| 34 | QByteArray RegItemEditorCreator::valuePropertyName () const |
| 35 | { |
| 36 | return QByteArray("text"); |
| 37 | } |
| 38 | |
| 39 | /** |
Amaury Pouly | ef0299c | 2014-08-09 18:39:45 +0200 | [diff] [blame] | 40 | * SocDisplayPanel |
| 41 | */ |
| 42 | SocDisplayPanel::SocDisplayPanel(QWidget *parent, const SocRef& dev_ref) |
| 43 | :QGroupBox(parent), m_soc(dev_ref) |
| 44 | { |
| 45 | QVBoxLayout *right_layout = new QVBoxLayout; |
| 46 | |
| 47 | m_name = new QLabel(this); |
| 48 | m_name->setTextFormat(Qt::RichText); |
| 49 | m_name->setText("<h1>" + QString::fromStdString(m_soc.GetSoc().name) + "</h1>"); |
| 50 | |
| 51 | m_desc = new QLabel(this); |
| 52 | m_name->setTextFormat(Qt::RichText); |
| 53 | m_desc->setText(QString::fromStdString(m_soc.GetSoc().desc)); |
| 54 | |
| 55 | right_layout->addWidget(m_name, 0); |
| 56 | right_layout->addWidget(m_desc, 0); |
| 57 | right_layout->addStretch(1); |
| 58 | |
| 59 | setTitle("System-on-Chip Description"); |
| 60 | setLayout(right_layout); |
| 61 | } |
| 62 | |
| 63 | void SocDisplayPanel::AllowWrite(bool en) |
| 64 | { |
| 65 | Q_UNUSED(en); |
| 66 | } |
| 67 | |
| 68 | QWidget *SocDisplayPanel::GetWidget() |
| 69 | { |
| 70 | return this; |
| 71 | } |
| 72 | |
| 73 | /** |
Amaury Pouly | 4356666 | 2014-04-07 11:28:04 +0200 | [diff] [blame] | 74 | * DevDisplayPanel |
| 75 | */ |
| 76 | DevDisplayPanel::DevDisplayPanel(QWidget *parent, const SocDevRef& dev_ref) |
| 77 | :QGroupBox(parent), m_dev(dev_ref), m_reg_font(font()) |
| 78 | { |
| 79 | QVBoxLayout *right_layout = new QVBoxLayout; |
| 80 | const soc_dev_addr_t& dev_addr = m_dev.GetDevAddr(); |
| 81 | |
| 82 | m_reg_font.setWeight(100); |
| 83 | m_reg_font.setKerning(false); |
| 84 | |
| 85 | QString dev_name; |
| 86 | dev_name.sprintf("HW_%s_BASE", dev_addr.name.c_str()); |
| 87 | |
| 88 | QLabel *label_names = new QLabel("<b>" + dev_name + "</b>"); |
| 89 | label_names->setTextFormat(Qt::RichText); |
| 90 | |
| 91 | QLabel *label_addr = new QLabel("<b>" + QString().sprintf("0x%03x", dev_addr.addr) + "</b>"); |
| 92 | label_addr->setTextFormat(Qt::RichText); |
| 93 | |
| 94 | QHBoxLayout *top_layout = new QHBoxLayout; |
| 95 | top_layout->addStretch(); |
| 96 | top_layout->addWidget(label_names); |
| 97 | top_layout->addWidget(label_addr); |
| 98 | top_layout->addStretch(); |
| 99 | |
| 100 | m_name = new QLabel(this); |
| 101 | m_name->setTextFormat(Qt::RichText); |
| 102 | m_name->setText("<h1>" + QString::fromStdString(m_dev.GetDev().long_name) + "</h1>"); |
| 103 | |
| 104 | m_desc = new QLabel(this); |
| 105 | m_name->setTextFormat(Qt::RichText); |
| 106 | m_desc->setText(QString::fromStdString(m_dev.GetDev().desc)); |
| 107 | |
Amaury Pouly | 4356666 | 2014-04-07 11:28:04 +0200 | [diff] [blame] | 108 | right_layout->addWidget(m_name, 0); |
Amaury Pouly | ef0299c | 2014-08-09 18:39:45 +0200 | [diff] [blame] | 109 | right_layout->addLayout(top_layout, 0); |
Amaury Pouly | 4356666 | 2014-04-07 11:28:04 +0200 | [diff] [blame] | 110 | right_layout->addWidget(m_desc, 0); |
| 111 | right_layout->addStretch(1); |
| 112 | |
| 113 | setTitle("Device Description"); |
| 114 | setLayout(right_layout); |
| 115 | } |
| 116 | |
| 117 | void DevDisplayPanel::AllowWrite(bool en) |
| 118 | { |
| 119 | Q_UNUSED(en); |
| 120 | } |
| 121 | |
| 122 | QWidget *DevDisplayPanel::GetWidget() |
| 123 | { |
| 124 | return this; |
| 125 | } |
| 126 | |
| 127 | /** |
| 128 | * RegDisplayPanel |
| 129 | */ |
| 130 | |
| 131 | RegDisplayPanel::RegDisplayPanel(QWidget *parent, IoBackend *io_backend, const SocRegRef& reg_ref) |
| 132 | :QGroupBox(parent), m_io_backend(io_backend), m_reg(reg_ref), m_reg_font(font()) |
| 133 | { |
| 134 | bool read_only = m_io_backend->IsReadOnly(); |
| 135 | |
| 136 | QVBoxLayout *right_layout = new QVBoxLayout; |
| 137 | |
| 138 | const soc_dev_addr_t& dev_addr = m_reg.GetDevAddr(); |
| 139 | const soc_reg_t& reg = m_reg.GetReg(); |
| 140 | const soc_reg_addr_t& reg_addr = m_reg.GetRegAddr(); |
| 141 | |
| 142 | m_reg_font.setWeight(100); |
| 143 | m_reg_font.setKerning(false); |
| 144 | |
| 145 | QString reg_name; |
| 146 | reg_name.sprintf("HW_%s_%s", dev_addr.name.c_str(), reg_addr.name.c_str()); |
| 147 | QStringList names; |
| 148 | QVector< soc_addr_t > addresses; |
| 149 | names.append(reg_name); |
| 150 | addresses.append(reg_addr.addr); |
| 151 | if(reg.flags & REG_HAS_SCT) |
| 152 | { |
| 153 | names.append(reg_name + "_SET"); |
| 154 | names.append(reg_name + "_CLR"); |
| 155 | names.append(reg_name + "_TOG"); |
| 156 | addresses.append(reg_addr.addr + 4); |
| 157 | addresses.append(reg_addr.addr + 8); |
| 158 | addresses.append(reg_addr.addr + 12); |
| 159 | } |
| 160 | |
| 161 | QString str; |
| 162 | str += "<table align=left>"; |
| 163 | for(int i = 0; i < names.size(); i++) |
| 164 | str += "<tr><td><b>" + names[i] + "</b></td></tr>"; |
| 165 | str += "</table>"; |
| 166 | QLabel *label_names = new QLabel; |
| 167 | label_names->setTextFormat(Qt::RichText); |
| 168 | label_names->setText(str); |
| 169 | |
| 170 | QString str_addr; |
| 171 | str_addr += "<table align=left>"; |
| 172 | for(int i = 0; i < names.size(); i++) |
| 173 | str_addr += "<tr><td><b>" + QString().sprintf("0x%03x", addresses[i]) + "</b></td></tr>"; |
| 174 | str_addr += "</table>"; |
| 175 | QLabel *label_addr = new QLabel; |
| 176 | label_addr->setTextFormat(Qt::RichText); |
| 177 | label_addr->setText(str_addr); |
| 178 | |
| 179 | QHBoxLayout *top_layout = new QHBoxLayout; |
| 180 | top_layout->addStretch(); |
| 181 | top_layout->addWidget(label_names); |
| 182 | top_layout->addWidget(label_addr); |
| 183 | top_layout->addStretch(); |
| 184 | |
| 185 | m_raw_val_name = new QLabel; |
| 186 | m_raw_val_name->setText("Raw value:"); |
| 187 | m_raw_val_edit = new RegLineEdit; |
| 188 | m_raw_val_edit->SetReadOnly(read_only); |
| 189 | m_raw_val_edit->GetLineEdit()->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter); |
| 190 | m_raw_val_edit->GetLineEdit()->setValidator(new SocFieldValidator(m_raw_val_edit)); |
| 191 | m_raw_val_edit->EnableSCT(!!(reg.flags & REG_HAS_SCT)); |
| 192 | m_raw_val_edit->GetLineEdit()->setFont(m_reg_font); |
Amaury Pouly | 4356666 | 2014-04-07 11:28:04 +0200 | [diff] [blame] | 193 | QHBoxLayout *raw_val_layout = new QHBoxLayout; |
| 194 | raw_val_layout->addStretch(); |
| 195 | raw_val_layout->addWidget(m_raw_val_name); |
| 196 | raw_val_layout->addWidget(m_raw_val_edit); |
| 197 | raw_val_layout->addStretch(); |
| 198 | |
Amaury Pouly | 5dab768 | 2014-10-22 18:00:59 +0200 | [diff] [blame] | 199 | m_value_table = new GrowingTableView; |
| 200 | m_value_model = new RegFieldTableModel(m_value_table); // view takes ownership |
| 201 | m_value_model->SetRegister(m_reg.GetReg()); |
| 202 | m_value_model->SetReadOnly(read_only); |
| 203 | m_value_table->setModel(m_value_model); |
Amaury Pouly | 4356666 | 2014-04-07 11:28:04 +0200 | [diff] [blame] | 204 | m_value_table->verticalHeader()->setVisible(false); |
| 205 | m_value_table->resizeColumnsToContents(); |
| 206 | m_value_table->horizontalHeader()->setStretchLastSection(true); |
| 207 | m_value_table->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); |
Amaury Pouly | 5dab768 | 2014-10-22 18:00:59 +0200 | [diff] [blame] | 208 | // FIXME we cannot use setAlternatingRowColors() because we override the |
| 209 | // background color, should it be part of the model ? |
Amaury Pouly | 4356666 | 2014-04-07 11:28:04 +0200 | [diff] [blame] | 210 | |
Amaury Pouly | 7b590a9 | 2014-05-11 19:51:55 +0200 | [diff] [blame] | 211 | SocFieldCachedItemDelegate *m_table_delegate = new SocFieldCachedItemDelegate(this); |
Amaury Pouly | 4356666 | 2014-04-07 11:28:04 +0200 | [diff] [blame] | 212 | m_table_edit_factory = new QItemEditorFactory(); |
Amaury Pouly | 7b590a9 | 2014-05-11 19:51:55 +0200 | [diff] [blame] | 213 | SocFieldCachedEditorCreator *m_table_edit_creator = new SocFieldCachedEditorCreator(); |
| 214 | // FIXME see QTBUG-30392 |
| 215 | m_table_edit_factory->registerEditor((QVariant::Type)qMetaTypeId< SocFieldCachedValue >(), |
| 216 | m_table_edit_creator); |
Amaury Pouly | 4356666 | 2014-04-07 11:28:04 +0200 | [diff] [blame] | 217 | m_table_delegate->setItemEditorFactory(m_table_edit_factory); |
| 218 | m_value_table->setItemDelegate(m_table_delegate); |
| 219 | |
| 220 | m_sexy_display = new RegSexyDisplay(reg_ref, this); |
| 221 | m_sexy_display->setFont(m_reg_font); |
| 222 | |
| 223 | m_desc = new QLabel(this); |
| 224 | m_desc->setTextFormat(Qt::RichText); |
| 225 | m_desc->setText(QString::fromStdString(m_reg.GetReg().desc)); |
| 226 | |
| 227 | right_layout->addWidget(m_desc); |
| 228 | right_layout->addLayout(top_layout); |
| 229 | if(raw_val_layout) |
| 230 | right_layout->addLayout(raw_val_layout); |
| 231 | right_layout->addWidget(m_sexy_display); |
| 232 | right_layout->addWidget(m_value_table); |
| 233 | |
| 234 | setTitle("Register Description"); |
| 235 | m_viewport = new QWidget; |
| 236 | m_viewport->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); |
| 237 | m_viewport->setLayout(right_layout); |
| 238 | m_scroll = new QScrollArea; |
| 239 | m_scroll->setWidget(m_viewport); |
| 240 | m_scroll->setWidgetResizable(true); |
| 241 | m_scroll->setFrameShape(QFrame::NoFrame); |
| 242 | QHBoxLayout *layout = new QHBoxLayout; |
| 243 | layout->addWidget(m_scroll, 1); |
| 244 | setLayout(layout); |
| 245 | AllowWrite(false); |
| 246 | |
| 247 | // load data |
| 248 | Reload(); |
Amaury Pouly | 7b590a9 | 2014-05-11 19:51:55 +0200 | [diff] [blame] | 249 | |
Amaury Pouly | 5dab768 | 2014-10-22 18:00:59 +0200 | [diff] [blame] | 250 | connect(m_raw_val_edit->GetLineEdit(), SIGNAL(returnPressed()), this, |
| 251 | SLOT(OnRawRegValueReturnPressed())); |
| 252 | connect(m_value_table->model(), SIGNAL(OnValueModified(int)), this, |
| 253 | SLOT(OnRegValueChanged(int))); |
Amaury Pouly | 4356666 | 2014-04-07 11:28:04 +0200 | [diff] [blame] | 254 | } |
| 255 | |
| 256 | RegDisplayPanel::~RegDisplayPanel() |
| 257 | { |
| 258 | delete m_table_edit_factory; |
| 259 | } |
| 260 | |
| 261 | void RegDisplayPanel::Reload() |
| 262 | { |
| 263 | const soc_dev_addr_t& dev_addr = m_reg.GetDevAddr(); |
| 264 | const soc_reg_t& reg = m_reg.GetReg(); |
| 265 | const soc_reg_addr_t& reg_addr = m_reg.GetRegAddr(); |
| 266 | soc_word_t value; |
| 267 | BackendHelper helper(m_io_backend, m_reg); |
| 268 | bool has_value = helper.ReadRegister(dev_addr.name.c_str(), reg_addr.name.c_str(), value); |
| 269 | |
| 270 | if(has_value) |
| 271 | { |
| 272 | m_raw_val_name->show(); |
| 273 | m_raw_val_edit->show(); |
| 274 | m_raw_val_edit->GetLineEdit()->setText(QString().sprintf("0x%08x", value)); |
Amaury Pouly | 5dab768 | 2014-10-22 18:00:59 +0200 | [diff] [blame] | 275 | m_value_model->SetValues(QVector< QVariant >(1, QVariant(value))); |
Amaury Pouly | 4356666 | 2014-04-07 11:28:04 +0200 | [diff] [blame] | 276 | } |
| 277 | else |
| 278 | { |
| 279 | m_raw_val_name->hide(); |
| 280 | m_raw_val_edit->hide(); |
Amaury Pouly | 5dab768 | 2014-10-22 18:00:59 +0200 | [diff] [blame] | 281 | m_value_model->SetValues(QVector< QVariant >()); |
Amaury Pouly | 4356666 | 2014-04-07 11:28:04 +0200 | [diff] [blame] | 282 | } |
| 283 | |
Amaury Pouly | 7b590a9 | 2014-05-11 19:51:55 +0200 | [diff] [blame] | 284 | m_value_table->resizeColumnsToContents(); |
| 285 | m_value_table->horizontalHeader()->setStretchLastSection(true); |
Amaury Pouly | 4356666 | 2014-04-07 11:28:04 +0200 | [diff] [blame] | 286 | } |
| 287 | |
| 288 | void RegDisplayPanel::AllowWrite(bool en) |
| 289 | { |
| 290 | m_allow_write = en; |
| 291 | if(m_raw_val_edit) |
Amaury Pouly | 5dab768 | 2014-10-22 18:00:59 +0200 | [diff] [blame] | 292 | { |
Amaury Pouly | 4356666 | 2014-04-07 11:28:04 +0200 | [diff] [blame] | 293 | m_raw_val_edit->SetReadOnly(m_io_backend->IsReadOnly() || !m_allow_write); |
Amaury Pouly | 5dab768 | 2014-10-22 18:00:59 +0200 | [diff] [blame] | 294 | m_value_model->SetReadOnly(m_io_backend->IsReadOnly() || !m_allow_write); |
| 295 | } |
Amaury Pouly | 7b590a9 | 2014-05-11 19:51:55 +0200 | [diff] [blame] | 296 | Reload(); |
Amaury Pouly | 4356666 | 2014-04-07 11:28:04 +0200 | [diff] [blame] | 297 | } |
| 298 | |
| 299 | IoBackend::WriteMode RegDisplayPanel::EditModeToWriteMode(RegLineEdit::EditMode mode) |
| 300 | { |
| 301 | switch(mode) |
| 302 | { |
| 303 | case RegLineEdit::Write: return IoBackend::Write; |
| 304 | case RegLineEdit::Set: return IoBackend::Set; |
| 305 | case RegLineEdit::Clear: return IoBackend::Clear; |
| 306 | case RegLineEdit::Toggle: return IoBackend::Toggle; |
| 307 | default: return IoBackend::Write; |
| 308 | } |
| 309 | } |
| 310 | |
| 311 | void RegDisplayPanel::OnRawRegValueReturnPressed() |
| 312 | { |
| 313 | soc_word_t val; |
| 314 | QLineEdit *edit = m_raw_val_edit->GetLineEdit(); |
| 315 | const SocFieldValidator *validator = dynamic_cast< const SocFieldValidator *>(edit->validator()); |
| 316 | QValidator::State state = validator->parse(edit->text(), val); |
| 317 | if(state != QValidator::Acceptable) |
| 318 | return; |
| 319 | IoBackend::WriteMode mode = EditModeToWriteMode(m_raw_val_edit->GetMode()); |
| 320 | BackendHelper helper(m_io_backend, m_reg); |
| 321 | helper.WriteRegister(m_reg.GetDevAddr().name.c_str(), m_reg.GetRegAddr().name.c_str(), |
| 322 | val, mode); |
Amaury Pouly | 5dab768 | 2014-10-22 18:00:59 +0200 | [diff] [blame] | 323 | // register write can change all fields |
Amaury Pouly | 7b590a9 | 2014-05-11 19:51:55 +0200 | [diff] [blame] | 324 | Reload(); |
| 325 | } |
| 326 | |
Amaury Pouly | 5dab768 | 2014-10-22 18:00:59 +0200 | [diff] [blame] | 327 | void RegDisplayPanel::OnRegValueChanged(int index) |
Amaury Pouly | 7b590a9 | 2014-05-11 19:51:55 +0200 | [diff] [blame] | 328 | { |
Amaury Pouly | 5dab768 | 2014-10-22 18:00:59 +0200 | [diff] [blame] | 329 | QVariant var = m_value_model->GetValue(index); |
| 330 | if(!var.isValid()) |
Amaury Pouly | 7b590a9 | 2014-05-11 19:51:55 +0200 | [diff] [blame] | 331 | return; |
Amaury Pouly | 7b590a9 | 2014-05-11 19:51:55 +0200 | [diff] [blame] | 332 | BackendHelper helper(m_io_backend, m_reg); |
Amaury Pouly | 7b590a9 | 2014-05-11 19:51:55 +0200 | [diff] [blame] | 333 | helper.WriteRegister(m_reg.GetDevAddr().name.c_str(), m_reg.GetRegAddr().name.c_str(), |
Amaury Pouly | 5dab768 | 2014-10-22 18:00:59 +0200 | [diff] [blame] | 334 | var.value< soc_word_t >(), IoBackend::Write); |
| 335 | // register write can change all fields |
Amaury Pouly | 4356666 | 2014-04-07 11:28:04 +0200 | [diff] [blame] | 336 | Reload(); |
| 337 | } |
| 338 | |
| 339 | QWidget *RegDisplayPanel::GetWidget() |
| 340 | { |
| 341 | return this; |
| 342 | } |
| 343 | |