A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
at master 390 lines 14 kB view raw
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 ****************************************************************************/ 21#include "regdisplaypanel.h" 22#include <QHeaderView> 23#include <QDebug> 24#include <QStandardItemModel> 25 26/** 27 * SocDisplayPanel 28 */ 29SocDisplayPanel::SocDisplayPanel(QWidget *parent, IoBackend *io_backend, 30 const soc_desc::soc_ref_t& ref) 31 :QGroupBox(parent), m_soc(ref) 32{ 33 Q_UNUSED(io_backend) 34 QVBoxLayout *right_layout = new QVBoxLayout; 35 36 m_name = new QLabel(this); 37 m_name->setTextFormat(Qt::RichText); 38 m_name->setText("<h1>" + QString::fromStdString(m_soc.get()->name) + "</h1>"); 39 40 m_desc = new QLabel(this); 41 m_name->setTextFormat(Qt::RichText); 42 m_desc->setText(QString::fromStdString(m_soc.get()->desc)); 43 m_desc->setVisible(m_desc->text().size() != 0); 44 45 right_layout->addWidget(m_name, 0); 46 right_layout->addWidget(m_desc, 0); 47 right_layout->addStretch(1); 48 49 setTitle(""); 50 setLayout(right_layout); 51} 52 53void SocDisplayPanel::AllowWrite(bool en) 54{ 55 Q_UNUSED(en); 56} 57 58QWidget *SocDisplayPanel::GetWidget() 59{ 60 return this; 61} 62 63/** 64 * NodeDisplayPanel 65 */ 66NodeDisplayPanel::NodeDisplayPanel(QWidget *parent, IoBackend *io_backend, 67 const soc_desc::node_inst_t& ref) 68 :QGroupBox(parent), m_node(ref) 69{ 70 BackendHelper helper(io_backend, ref.soc()); 71 QVBoxLayout *right_layout = new QVBoxLayout; 72 73 QString dev_name = helper.GetPath(ref); 74 75 QLabel *label_names = new QLabel("<b>" + dev_name + "</b>"); 76 label_names->setTextFormat(Qt::RichText); 77 78 QLabel *label_addr = new QLabel("<b>" + QString().sprintf("0x%03x", ref.addr()) + "</b>"); 79 label_addr->setTextFormat(Qt::RichText); 80 81 QHBoxLayout *top_layout = new QHBoxLayout; 82 top_layout->addStretch(); 83 top_layout->addWidget(label_names); 84 top_layout->addWidget(label_addr); 85 top_layout->addStretch(); 86 87 m_name = new QLabel(this); 88 m_name->setTextFormat(Qt::RichText); 89 /* if instance has a title, it overrides node title.*/ 90 std::string title = ref.get()->title; 91 if(title.empty()) 92 title = ref.node().get()->title; 93 m_name->setText("<h1>" + QString::fromStdString(title) + "</h1>"); 94 95 /* put description from the node and from the instance */ 96 m_node_desc = new QLabel(this); 97 m_node_desc->setTextFormat(Qt::RichText); 98 m_node_desc->setText(QString::fromStdString(ref.node().get()->desc)); 99 m_node_desc->setVisible(m_node_desc->text().size() != 0); 100 m_inst_desc = new QLabel(this); 101 m_inst_desc->setTextFormat(Qt::RichText); 102 m_inst_desc->setText(QString::fromStdString(ref.get()->desc)); 103 m_inst_desc->setVisible(m_inst_desc->text().size() != 0); 104 105 right_layout->addWidget(m_name, 0); 106 right_layout->addLayout(top_layout, 0); 107 right_layout->addWidget(m_node_desc, 0); 108 right_layout->addWidget(m_inst_desc, 0); 109 right_layout->addStretch(1); 110 111 setTitle(""); 112 setLayout(right_layout); 113} 114 115void NodeDisplayPanel::AllowWrite(bool en) 116{ 117 Q_UNUSED(en); 118} 119 120QWidget *NodeDisplayPanel::GetWidget() 121{ 122 return this; 123} 124 125/** 126 * RegDisplayPanel 127 */ 128 129namespace 130{ 131 QString access_string(soc_desc::access_t acc, QString dflt = "") 132 { 133 switch(acc) 134 { 135 case soc_desc::UNSPECIFIED: return dflt; 136 case soc_desc::READ_ONLY: return "Read only"; 137 case soc_desc::READ_WRITE: return "Read-write"; 138 case soc_desc::WRITE_ONLY: return "Write-only"; 139 default: return ""; 140 } 141 } 142} 143 144RegDisplayPanel::RegDisplayPanel(QWidget *parent, IoBackend *io_backend, 145 const soc_desc::node_inst_t& ref) 146 :QGroupBox(parent), m_io_backend(io_backend), m_node(ref), m_reg_font(font()) 147{ 148 bool read_only = m_io_backend->IsReadOnly(); 149 BackendHelper helper(m_io_backend, ref.soc()); 150 151 QVBoxLayout *right_layout = new QVBoxLayout; 152 153 m_reg_font.setWeight(100); 154 m_reg_font.setKerning(false); 155 156 QString reg_name = helper.GetPath(ref); 157 QStringList names, access; 158 QVector< soc_addr_t > addresses; 159 names.append(reg_name); 160 addresses.append(ref.addr()); 161 access.append(access_string(ref.node().reg().get()->access)); 162 163 std::vector< soc_desc::variant_ref_t > variants = ref.node().reg().variants(); 164 for(size_t i = 0; i < variants.size(); i++) 165 { 166 names.append(reg_name + "/" + QString::fromStdString(variants[i].get()->type)); 167 addresses.append(ref.addr() + variants[i].get()->offset); 168 access.append(access_string(ref.node().reg().get()->access, access[0])); 169 } 170 171 QString str; 172 str += "<table align=left>"; 173 for(int i = 0; i < names.size(); i++) 174 str += "<tr><td><b>" + names[i] + "</b></td></tr>"; 175 str += "</table>"; 176 QLabel *label_names = new QLabel; 177 label_names->setTextFormat(Qt::RichText); 178 label_names->setText(str); 179 180 QString str_addr; 181 str_addr += "<table align=left>"; 182 for(int i = 0; i < names.size(); i++) 183 str_addr += "<tr><td><b>" + QString().sprintf("0x%03x", addresses[i]) + "</b></td></tr>"; 184 str_addr += "</table>"; 185 QLabel *label_addr = new QLabel; 186 label_addr->setTextFormat(Qt::RichText); 187 label_addr->setText(str_addr); 188 189 QString str_acc; 190 str_acc += "<table align=left>"; 191 for(int i = 0; i < names.size(); i++) 192 str_acc += "<tr><td><b>" + access[i] + "</b></td></tr>"; 193 str_acc += "</table>"; 194 QLabel *label_access = new QLabel; 195 label_access->setTextFormat(Qt::RichText); 196 label_access->setText(str_acc); 197 198 QHBoxLayout *top_layout = new QHBoxLayout; 199 top_layout->addStretch(); 200 top_layout->addWidget(label_names); 201 top_layout->addWidget(label_addr); 202 top_layout->addWidget(label_access); 203 top_layout->addStretch(); 204 205 m_raw_val_name = new QLabel; 206 m_raw_val_name->setText("Raw value:"); 207 m_raw_val_edit = new RegLineEdit; 208 m_raw_val_edit->SetReadOnly(read_only); 209 m_raw_val_edit->GetLineEdit()->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter); 210 m_raw_val_edit->GetLineEdit()->setValidator(new SocFieldValidator(m_raw_val_edit)); 211 //m_raw_val_edit->EnableSCT(!!(reg.flags & REG_HAS_SCT)); 212 m_raw_val_edit->GetLineEdit()->setFont(m_reg_font); 213 QHBoxLayout *raw_val_layout = new QHBoxLayout; 214 raw_val_layout->addStretch(); 215 raw_val_layout->addWidget(m_raw_val_name); 216 raw_val_layout->addWidget(m_raw_val_edit); 217 raw_val_layout->addStretch(); 218 219 m_value_table = new GrowingTableView(); 220 m_value_model = new RegFieldTableModel(m_value_table); // view takes ownership 221 m_value_model->SetRegister(*m_node.node().reg().get()); 222 m_value_model->SetReadOnly(read_only); 223 RegFieldProxyModel *proxy_model = new RegFieldProxyModel(this); 224 proxy_model->setSourceModel(m_value_model); 225 m_value_table->setModel(proxy_model); 226 m_value_table->setSortingEnabled(true); 227 m_value_table->sortByColumn(0, Qt::DescendingOrder); 228 m_value_table->verticalHeader()->setVisible(false); 229 m_value_table->resizeColumnsToContents(); 230 m_value_table->horizontalHeader()->setStretchLastSection(true); 231 m_value_table->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); 232 // FIXME we cannot use setAlternatingRowColors() because we override the 233 // background color, should it be part of the model ? 234 235 m_table_delegate = new SocFieldCachedItemDelegate(this); 236 m_table_edit_factory = new QItemEditorFactory(); 237 SocFieldCachedEditorCreator *m_table_edit_creator = new SocFieldCachedEditorCreator(); 238 // FIXME see QTBUG-30392 239 m_table_edit_factory->registerEditor((QVariant::Type)qMetaTypeId< SocFieldCachedValue >(), 240 m_table_edit_creator); 241 m_table_delegate->setItemEditorFactory(m_table_edit_factory); 242 m_value_table->setItemDelegate(m_table_delegate); 243 244 m_sexy_display2 = new Unscroll<YRegDisplay>(this); 245 m_sexy_display2->setFont(m_reg_font); 246 m_sexy_display2->setModel(m_value_model); 247 m_sexy_display2->setWidth(m_node.node().reg().get()->width); 248 m_sexy_display2->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); 249 250 m_name = new QLabel(this); 251 m_name->setTextFormat(Qt::RichText); 252 m_name->setText("<h1>" + QString::fromStdString(ref.node().get()->title) + "</h1>"); 253 254 /* put description from the node, from the instance and register */ 255 m_node_desc = new QLabel(this); 256 m_node_desc->setTextFormat(Qt::RichText); 257 m_node_desc->setText(QString::fromStdString(ref.node().get()->desc)); 258 m_node_desc->setVisible(m_node_desc->text().size() != 0); 259 m_inst_desc = new QLabel(this); 260 m_inst_desc->setTextFormat(Qt::RichText); 261 m_inst_desc->setText(QString::fromStdString(ref.get()->desc)); 262 m_inst_desc->setVisible(m_inst_desc->text().size() != 0); 263 m_desc = new QLabel(this); 264 m_desc->setTextFormat(Qt::RichText); 265 m_desc->setText(QString::fromStdString(m_node.node().reg().get()->desc)); 266 m_desc->setVisible(m_desc->text().size() != 0); 267 268 right_layout->addWidget(m_name); 269 right_layout->addWidget(m_desc); 270 right_layout->addLayout(top_layout); 271 right_layout->addWidget(m_node_desc); 272 right_layout->addWidget(m_inst_desc); 273 right_layout->addWidget(m_desc); 274 if(raw_val_layout) 275 right_layout->addLayout(raw_val_layout); 276 right_layout->addWidget(m_sexy_display2); 277 right_layout->addWidget(m_value_table); 278 right_layout->addStretch(); 279 280 setTitle(""); 281 m_viewport = new QWidget; 282 m_viewport->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); 283 m_viewport->setLayout(right_layout); 284 m_scroll = new QScrollArea; 285 m_scroll->setWidget(m_viewport); 286 m_scroll->setWidgetResizable(true); 287 m_scroll->setFrameShape(QFrame::NoFrame); 288 QHBoxLayout *layout = new QHBoxLayout; 289 layout->addWidget(m_scroll, 1); 290 setLayout(layout); 291 AllowWrite(false); 292 293 // load data 294 Reload(); 295 296 connect(m_raw_val_edit->GetLineEdit(), SIGNAL(returnPressed()), this, 297 SLOT(OnRawRegValueReturnPressed())); 298 connect(m_value_model, SIGNAL(OnValueModified(int)), this, 299 SLOT(OnRegValueChanged(int))); 300 connect(m_sexy_display2, SIGNAL(clicked(const QModelIndex&)), this, 301 SLOT(OnRegFieldActivated(const QModelIndex&))); 302} 303 304RegDisplayPanel::~RegDisplayPanel() 305{ 306 delete m_table_edit_factory; 307} 308 309void RegDisplayPanel::Reload() 310{ 311 soc_word_t value; 312 BackendHelper helper(m_io_backend, m_node.soc()); 313 bool has_value = helper.ReadRegister(m_node, value); 314 315 if(has_value) 316 { 317 m_raw_val_name->show(); 318 m_raw_val_edit->show(); 319 m_raw_val_edit->GetLineEdit()->setText(QString().sprintf("0x%08x", value)); 320 m_value_model->SetValues(QVector< QVariant >(1, QVariant(value))); 321 } 322 else 323 { 324 m_raw_val_name->hide(); 325 m_raw_val_edit->hide(); 326 m_value_model->SetValues(QVector< QVariant >()); 327 } 328 329 m_value_table->resizeColumnsToContents(); 330 m_value_table->horizontalHeader()->setStretchLastSection(true); 331} 332 333void RegDisplayPanel::AllowWrite(bool en) 334{ 335 m_allow_write = en; 336 if(m_raw_val_edit) 337 { 338 m_raw_val_edit->SetReadOnly(m_io_backend->IsReadOnly() || !m_allow_write); 339 m_value_model->SetReadOnly(m_io_backend->IsReadOnly() || !m_allow_write); 340 } 341} 342 343IoBackend::WriteMode RegDisplayPanel::EditModeToWriteMode(RegLineEdit::EditMode mode) 344{ 345 switch(mode) 346 { 347 case RegLineEdit::Write: return IoBackend::Write; 348 case RegLineEdit::Set: return IoBackend::Set; 349 case RegLineEdit::Clear: return IoBackend::Clear; 350 case RegLineEdit::Toggle: return IoBackend::Toggle; 351 default: return IoBackend::Write; 352 } 353} 354 355void RegDisplayPanel::OnRawRegValueReturnPressed() 356{ 357 soc_word_t val; 358 QLineEdit *edit = m_raw_val_edit->GetLineEdit(); 359 const SocFieldValidator *validator = dynamic_cast< const SocFieldValidator *>(edit->validator()); 360 QValidator::State state = validator->parse(edit->text(), val); 361 if(state != QValidator::Acceptable) 362 return; 363 IoBackend::WriteMode mode = EditModeToWriteMode(m_raw_val_edit->GetMode()); 364 BackendHelper helper(m_io_backend, m_node.soc()); 365 helper.WriteRegister(m_node, val, mode); 366 // register write can change all fields 367 Reload(); 368} 369 370void RegDisplayPanel::OnRegValueChanged(int index) 371{ 372 QVariant var = m_value_model->GetValue(index); 373 if(!var.isValid()) 374 return; 375 BackendHelper helper(m_io_backend, m_node.soc()); 376 helper.WriteRegister(m_node, var.value< soc_word_t >(), IoBackend::Write); 377 // register write can change all fields 378 Reload(); 379} 380 381void RegDisplayPanel::OnRegFieldActivated(const QModelIndex& index) 382{ 383 Q_UNUSED(index); 384} 385 386QWidget *RegDisplayPanel::GetWidget() 387{ 388 return this; 389} 390