diff options
Diffstat (limited to 'utils/regtools/qeditor')
-rw-r--r-- | utils/regtools/qeditor/analyser.h | 5 | ||||
-rw-r--r-- | utils/regtools/qeditor/aux.cpp | 746 | ||||
-rw-r--r-- | utils/regtools/qeditor/aux.h | 227 | ||||
-rw-r--r-- | utils/regtools/qeditor/backend.cpp | 67 | ||||
-rw-r--r-- | utils/regtools/qeditor/backend.h | 79 | ||||
-rw-r--r-- | utils/regtools/qeditor/mainwindow.cpp | 63 | ||||
-rw-r--r-- | utils/regtools/qeditor/mainwindow.h | 16 | ||||
-rw-r--r-- | utils/regtools/qeditor/qeditor.pro | 6 | ||||
-rw-r--r-- | utils/regtools/qeditor/regdisplaypanel.cpp | 314 | ||||
-rw-r--r-- | utils/regtools/qeditor/regdisplaypanel.h | 77 | ||||
-rw-r--r-- | utils/regtools/qeditor/regedit.cpp | 1324 | ||||
-rw-r--r-- | utils/regtools/qeditor/regedit.h | 282 | ||||
-rw-r--r-- | utils/regtools/qeditor/regtab.cpp | 534 | ||||
-rw-r--r-- | utils/regtools/qeditor/regtab.h | 119 | ||||
-rw-r--r-- | utils/regtools/qeditor/std_analysers.cpp | 9 | ||||
-rw-r--r-- | utils/regtools/qeditor/std_analysers.h | 4 |
16 files changed, 3308 insertions, 564 deletions
diff --git a/utils/regtools/qeditor/analyser.h b/utils/regtools/qeditor/analyser.h index a06652bfb0..4f9830ac4c 100644 --- a/utils/regtools/qeditor/analyser.h +++ b/utils/regtools/qeditor/analyser.h @@ -5,13 +5,14 @@ #include <QVector> #include <QString> #include "backend.h" +#include "regtab.h" -class Analyser : public QObject +class Analyser : public RegTabPanel { - Q_OBJECT public: Analyser(const SocRef& soc, IoBackend *backend); virtual ~Analyser(); + virtual void AllowWrite(bool en) { Q_UNUSED(en); } virtual QWidget *GetWidget() = 0; protected: diff --git a/utils/regtools/qeditor/aux.cpp b/utils/regtools/qeditor/aux.cpp new file mode 100644 index 0000000000..0614bb57f6 --- /dev/null +++ b/utils/regtools/qeditor/aux.cpp @@ -0,0 +1,746 @@ +#include "aux.h" +#include <QFontMetrics> +#include <QPainter> +#include <QTextDocument> +#include <QAbstractTextDocumentLayout> +#include <QHeaderView> +#include <QDebug> +#include <QElapsedTimer> +#include <QXmlStreamReader> +#include <QXmlStreamWriter> +#include <QTextBlock> + +/** + * SocBitRangeValidator + */ +SocBitRangeValidator::SocBitRangeValidator(QObject *parent) + :QValidator(parent) +{ +} + +void SocBitRangeValidator::fixup(QString& input) const +{ + input = input.trimmed(); +} + +QValidator::State SocBitRangeValidator::validate(QString& input, int& pos) const +{ + Q_UNUSED(pos); + int first, last; + State state = parse(input, last, first); + return state; +} + +QValidator::State SocBitRangeValidator::parse(const QString& input, int& last, int& first) const +{ + // the empty string is always intermediate + if(input.size() == 0) + return Intermediate; + // check if there is ':' + int pos = input.indexOf(':'); + if(pos == -1) + pos = input.size(); + // if field start with ':', the last bit is implicit and is 31 + if(pos > 0) + { + // parse last bit and check it's between 0 and 31 + bool ok = false; + last = input.left(pos).toInt(&ok); + if(!ok || last < 0 || last >= 32) + return Invalid; + } + else + last = 31; + // parse first bit + if(pos < input.size() - 1) + { + bool ok = false; + first = input.mid(pos + 1).toInt(&ok); + if(!ok || first < 0 || first > last) + return Invalid; + } + // if input ends with ':', first bit is implicit and is 0 + else if(pos == input.size() - 1) + first = 0; + // if there no ':', first=last + else + first = last; + return Acceptable; +} + +/** + * SocFieldValidator + */ + +SocFieldValidator::SocFieldValidator(QObject *parent) + :QValidator(parent) +{ + m_field.first_bit = 0; + m_field.last_bit = 31; +} + +SocFieldValidator::SocFieldValidator(const soc_reg_field_t& field, QObject *parent) + :QValidator(parent), m_field(field) +{ +} + +void SocFieldValidator::fixup(QString& input) const +{ + input = input.trimmed(); +} + +QValidator::State SocFieldValidator::validate(QString& input, int& pos) const +{ + Q_UNUSED(pos); + soc_word_t val; + State state = parse(input, val); + return state; +} + +QValidator::State SocFieldValidator::parse(const QString& input, soc_word_t& val) const +{ + // the empty string is always intermediate + if(input.size() == 0) + return Intermediate; + // first check named values + State state = Invalid; + foreach(const soc_reg_field_value_t& value, m_field.value) + { + QString name = QString::fromLocal8Bit(value.name.c_str()); + // cannot be a substring if too long or empty + if(input.size() > name.size()) + continue; + // check equal string + if(input == name) + { + state = Acceptable; + val = value.value; + break; + } + // check substring + if(name.startsWith(input)) + state = Intermediate; + } + // early return for exact match + if(state == Acceptable) + return state; + // do a few special cases for convenience + if(input.compare("0x", Qt::CaseInsensitive) == 0 || + input.compare("0b", Qt::CaseInsensitive) == 0) + return Intermediate; + // try by parsing + unsigned basis, pos; + if(input.size() >= 2 && input.startsWith("0x", Qt::CaseInsensitive)) + { + basis = 16; + pos = 2; + } + else if(input.size() >= 2 && input.startsWith("0b", Qt::CaseInsensitive)) + { + basis = 2; + pos = 2; + } + else if(input.size() >= 2 && input.startsWith("0")) + { + basis = 8; + pos = 1; + } + else + { + basis = 10; + pos = 0; + } + bool ok = false; + unsigned long v = input.mid(pos).toULong(&ok, basis); + // if not ok, return result of name parsing + if(!ok) + return state; + // if ok, check if it fits in the number of bits + unsigned nr_bits = m_field.last_bit - m_field.first_bit + 1; + unsigned long max = nr_bits == 32 ? 0xffffffff : (1 << nr_bits) - 1; + if(v <= max) + { + val = v; + return Acceptable; + } + + return state; +} + +/** + * RegLineEdit + */ +RegLineEdit::RegLineEdit(QWidget *parent) + :QWidget(parent) +{ + m_layout = new QHBoxLayout(this); + m_button = new QToolButton(this); + m_button->setCursor(Qt::ArrowCursor); + m_button->setStyleSheet("QToolButton { font-weight: bold; color: white; background: black; }"); + m_button->setPopupMode(QToolButton::InstantPopup); + m_edit = new QLineEdit(this); + m_layout->addWidget(m_button); + m_layout->addWidget(m_edit); + m_menu = new QMenu(this); + connect(m_menu->addAction("Write"), SIGNAL(triggered()), this, SLOT(OnWriteAct())); + connect(m_menu->addAction("Set"), SIGNAL(triggered()), this, SLOT(OnSetAct())); + connect(m_menu->addAction("Clear"), SIGNAL(triggered()), this, SLOT(OnClearAct())); + connect(m_menu->addAction("Toggle"), SIGNAL(triggered()), this, SLOT(OnToggleAct())); + EnableSCT(false); + SetReadOnly(false); + ShowMode(true); + SetMode(Write); +} + +void RegLineEdit::SetReadOnly(bool ro) +{ + m_edit->setReadOnly(ro); + m_readonly = ro; + ShowMode(!ro); +} + +void RegLineEdit::EnableSCT(bool en) +{ + m_has_sct = en; + if(!m_has_sct) + { + m_button->setMenu(0); + SetMode(Write); + } + else + m_button->setMenu(m_menu); +} + +RegLineEdit::~RegLineEdit() +{ +} + +QLineEdit *RegLineEdit::GetLineEdit() +{ + return m_edit; +} + +void RegLineEdit::ShowMode(bool show) +{ + if(show) + m_button->show(); + else + m_button->hide(); +} + +void RegLineEdit::OnWriteAct() +{ + SetMode(Write); +} + +void RegLineEdit::OnSetAct() +{ + SetMode(Set); +} + +void RegLineEdit::OnClearAct() +{ + SetMode(Clear); +} + +void RegLineEdit::OnToggleAct() +{ + SetMode(Toggle); +} + +void RegLineEdit::SetMode(EditMode mode) +{ + m_mode = mode; + switch(m_mode) + { + case Write: m_button->setText("WR"); break; + case Set: m_button->setText("SET"); break; + case Clear: m_button->setText("CLR"); break; + case Toggle: m_button->setText("TOG"); break; + default: break; + } +} + +RegLineEdit::EditMode RegLineEdit::GetMode() +{ + return m_mode; +} + +void RegLineEdit::setText(const QString& text) +{ + m_edit->setText(text); +} + +QString RegLineEdit::text() const +{ + return m_edit->text(); +} + +/** + * SocFieldItemDelegate + */ + +QString SocFieldItemDelegate::displayText(const QVariant& value, const QLocale& locale) const +{ + if(value.type() == QVariant::UInt) + return QString("0x%1").arg(value.toUInt(), (m_bitcount + 3) / 4, 16, QChar('0')); + else + return QStyledItemDelegate::displayText(value, locale); +} + +/** + * SocFieldEditor + */ +SocFieldEditor::SocFieldEditor(const soc_reg_field_t& field, QWidget *parent) + :QLineEdit(parent), m_reg_field(field) +{ + m_validator = new SocFieldValidator(field); + setValidator(m_validator); +} + +SocFieldEditor::~SocFieldEditor() +{ + delete m_validator; +} + +uint SocFieldEditor::field() const +{ + soc_word_t v; + /* in case validator fails to parse, return old value */ + if(m_validator->parse(text(), v) == QValidator::Acceptable) + return v; + else + return m_field; +} + +void SocFieldEditor::setField(uint field) +{ + m_field = field; + int digits = (m_reg_field.last_bit - m_reg_field.first_bit + 4) / 4; + setText(QString("0x%1").arg(field, digits, 16, QChar('0'))); +} + +/** + * SocFieldEditorCreator + */ +QWidget *SocFieldEditorCreator::createWidget(QWidget *parent) const +{ + return new SocFieldEditor(m_field, parent); +} + +QByteArray SocFieldEditorCreator::valuePropertyName() const +{ + return QByteArray("field"); +} + +/** + * RegSexyDisplay + */ +RegSexyDisplay::RegSexyDisplay(const SocRegRef& reg, QWidget *parent) + :QWidget(parent), m_reg(reg) +{ + m_size = QSize(); +} + +int RegSexyDisplay::separatorSize() const +{ + return 1; +} + +int RegSexyDisplay::marginSize() const +{ + return fontMetrics().height() / 3; +} + +int RegSexyDisplay::textSep() const +{ + return marginSize() / 2; +} + +int RegSexyDisplay::headerHeight() const +{ + return 2 * marginSize() + textSep() + 2 * fontMetrics().height(); +} + +int RegSexyDisplay::columnWidth() const +{ + return 2 * marginSize() + fontMetrics().height(); +} + +int RegSexyDisplay::maxContentHeight() const +{ + int max = 0; + QFontMetrics metrics = fontMetrics(); + for(size_t i = 0; i < m_reg.GetReg().field.size(); i++) + { + QString s = QString::fromStdString(m_reg.GetReg().field[i].name); + // add extra spaces arounds + s = " " + s + " "; + max = qMax(max, metrics.boundingRect(s).width()); + } + return 2 * marginSize() + max; +} + +int RegSexyDisplay::gapHeight() const +{ + return marginSize() / 2; +} + +QSize RegSexyDisplay::minimumSizeHint() const +{ + /* cache computation because it's expensive */ + if(m_size.isValid()) + return m_size; + /* width: display 32 columns + 33 vertical separators */ + m_size.setWidth(32 * columnWidth() + 33 * separatorSize()); + /* height: one separator + two digits + one separator + margin + separator + * + names + separator */ + m_size.setHeight(4 * separatorSize() + headerHeight() + gapHeight() + maxContentHeight()); + return m_size; +} + +QSize RegSexyDisplay::sizeHint() const +{ + return minimumSizeHint(); +} + +void RegSexyDisplay::paintEvent(QPaintEvent *event) +{ + // FIXME could be optimised with QStaticText + Q_UNUSED(event); + int txt_h = fontMetrics().height(); + int sep_sz = separatorSize(); + int w = width(); + int h = height() - 1; + int col_w = (w - 33 * sep_sz) / 32; + int hdr_h = headerHeight(); + int gap_h = gapHeight(); + int tot_w = 33 * sep_sz + 32 * col_w; + int margin = marginSize(); + int txt_sep = textSep(); + int tot_hdr_sz = 2 * sep_sz + hdr_h; + // computer xshift + int x_shift = (w - tot_w) / 2; +#define ith_col_x(i) (x_shift + (i) * (sep_sz + col_w)) + + QPainter painter(this); + QBrush back_brush = palette().base(); + QBrush line_brush = palette().dark(); + + // fill interesting zone with base + painter.fillRect(x_shift, 0, tot_w, h, back_brush); + + // draw top and bottom lines + painter.setPen(QPen(palette().dark(), sep_sz)); + painter.fillRect(x_shift, 0, tot_w, sep_sz, line_brush); + painter.fillRect(x_shift, h - sep_sz, tot_w, sep_sz, line_brush); + // draw intemediate lines + for(int i = 0; i <= 32; i++) + painter.fillRect(ith_col_x(i), 0, sep_sz, 2 * sep_sz + hdr_h, line_brush); + // draw bottom header lines + painter.fillRect(ith_col_x(0), sep_sz + hdr_h, tot_w, sep_sz, line_brush); + painter.fillRect(ith_col_x(0), tot_hdr_sz + gap_h, tot_w, sep_sz, line_brush); + // redraw some lines but wider + for(int i = 4; i < 32; i += 4) + painter.fillRect(ith_col_x(i) - sep_sz, 0, 3 * sep_sz, tot_hdr_sz, line_brush); + // draw numbers in the header + painter.setPen(palette().brush(QPalette::ButtonText).color()); + for(int i = 0; i < 32; i++) + { + QRect r(ith_col_x(i), sep_sz + margin, col_w, txt_h); + painter.drawText(r, Qt::AlignCenter, QString("%1").arg((31 - i) / 10)); + r.translate(0, txt_h + txt_sep); + painter.drawText(r, Qt::AlignCenter, QString("%1").arg((31 - i) % 10)); + } + // display content + for(size_t i = 0; i < m_reg.GetReg().field.size(); i++) + { + const soc_reg_field_t& field = m_reg.GetReg().field[i]; + QRect r(QPoint(ith_col_x(31 - field.last_bit) + sep_sz, tot_hdr_sz), + QPoint(ith_col_x(32 - field.first_bit), h - sep_sz)); + painter.fillRect(r.x() - sep_sz, r.y(), sep_sz, r.height(), line_brush); + painter.fillRect(r.right(), r.y(), sep_sz, r.height(), line_brush); + r.setY(r.y() + gap_h + sep_sz); + // draw rotated text + painter.save(); + painter.translate(r.bottomLeft()); + painter.rotate(-90); + //painter.fillRect(QRect(0, 0, r.height(), r.width()), QBrush(Qt::red)); + QRect r2(0, 0, r.height(), r.width()); + painter.drawText(r2, Qt::AlignCenter, QString::fromStdString(field.name)); + painter.restore(); + } +#undef ith_col_x +} + +/** + * GrowingTextEdit + */ +GrowingTextEdit::GrowingTextEdit(QWidget *parent) + :QTextEdit(parent) +{ + connect(this, SIGNAL(textChanged()), this, SLOT(TextChanged())); + setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); + setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); +} + +void GrowingTextEdit::TextChanged() +{ + int content_size = document()->documentLayout()->documentSize().height(); + content_size = qMax(content_size, fontMetrics().height()); + setFixedHeight(content_size + contentsMargins().top() + contentsMargins().bottom()); +} + +/** + * GrowingTableWidget + */ +GrowingTableWidget::GrowingTableWidget(QWidget *parent) + :QTableWidget(parent) +{ + connect(model(), SIGNAL(dataChanged(const QModelIndex&, const QModelIndex&)), + this, SLOT(DataChanged(const QModelIndex&, const QModelIndex&))); +} + +void GrowingTableWidget::DataChanged(const QModelIndex& tl, const QModelIndex& br) +{ + Q_UNUSED(tl); + Q_UNUSED(br); + resizeRowsToContents(); + resizeColumnsToContents(); + int h = contentsMargins().top() + contentsMargins().bottom(); + h += horizontalHeader()->height(); + for(int i = 0; i < rowCount(); i++) + h += rowHeight(i); + setMinimumHeight(h); +} + +/** + * MyTextEditor + */ +MyTextEditor::MyTextEditor(QWidget *parent) + :QWidget(parent) +{ + QVBoxLayout *layout = new QVBoxLayout; + m_toolbar = new QToolBar(this); + m_edit = new QTextEdit(this); + layout->addWidget(m_toolbar, 0); + layout->addWidget(m_edit, 1); + setLayout(layout); + setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + + m_edit->setAcceptRichText(false); + m_edit->setAutoFormatting(QTextEdit::AutoAll); + + m_bold_button = new QToolButton(this); + m_bold_button->setIcon(QIcon::fromTheme("format-text-bold")); + m_bold_button->setText("bold"); + m_bold_button->setCheckable(true); + + m_italic_button = new QToolButton(this); + m_italic_button->setIcon(QIcon::fromTheme("format-text-italic")); + m_italic_button->setText("italic"); + m_italic_button->setCheckable(true); + + m_underline_button = new QToolButton(this); + m_underline_button->setIcon(QIcon::fromTheme("format-text-underline")); + m_underline_button->setText("underline"); + m_underline_button->setCheckable(true); + + m_toolbar->addWidget(m_bold_button); + m_toolbar->addWidget(m_italic_button); + m_toolbar->addWidget(m_underline_button); + + connect(m_bold_button, SIGNAL(toggled(bool)), this, SLOT(OnTextBold(bool))); + connect(m_italic_button, SIGNAL(toggled(bool)), this, SLOT(OnTextItalic(bool))); + connect(m_underline_button, SIGNAL(toggled(bool)), this, SLOT(OnTextUnderline(bool))); + connect(m_edit, SIGNAL(textChanged()), this, SLOT(OnInternalTextChanged())); + connect(m_edit, SIGNAL(currentCharFormatChanged(const QTextCharFormat&)), + this, SLOT(OnCharFormatChanged(const QTextCharFormat&))); + + SetGrowingMode(false); + SetReadOnly(false); +} + +void MyTextEditor::SetReadOnly(bool en) +{ + m_read_only = en; + if(en) + m_toolbar->hide(); + else + m_toolbar->hide(); + m_edit->setReadOnly(en); +} + +void MyTextEditor::SetGrowingMode(bool en) +{ + m_growing_mode = en; + if(en) + { + m_edit->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum); + m_edit->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + OnTextChanged(); + } + else + { + m_edit->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + m_edit->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); + } +} + +void MyTextEditor::OnInternalTextChanged() +{ + if(m_growing_mode) + { + int content_size = m_edit->document()->documentLayout()->documentSize().height(); + content_size = qMax(content_size, m_edit->fontMetrics().height()); + m_edit->setMinimumHeight(content_size + m_edit->contentsMargins().top() + + m_edit->contentsMargins().bottom()); + } + emit OnTextChanged(); +} + +void MyTextEditor::OnTextBold(bool checked) +{ + QTextCursor cursor = m_edit->textCursor(); + QTextCharFormat fmt = cursor.charFormat(); + fmt.setFontWeight(checked ? QFont::Bold : QFont::Normal); + cursor.setCharFormat(fmt); + m_edit->setTextCursor(cursor); +} + +void MyTextEditor::OnTextItalic(bool checked) +{ + QTextCursor cursor = m_edit->textCursor(); + QTextCharFormat fmt = cursor.charFormat(); + fmt.setFontItalic(checked); + cursor.setCharFormat(fmt); + m_edit->setTextCursor(cursor); +} + +void MyTextEditor::OnTextUnderline(bool checked) +{ + QTextCursor cursor = m_edit->textCursor(); + QTextCharFormat fmt = cursor.charFormat(); + fmt.setFontUnderline(checked); + cursor.setCharFormat(fmt); + m_edit->setTextCursor(cursor); +} + +void MyTextEditor::OnCharFormatChanged(const QTextCharFormat& fmt) +{ + /* NOTE: changing the button states programmaticaly doesn't trigger + * the toggled() signals, otherwise it would result in a loop + * between this function and OnText{Bold,Italic,Underline,...} */ + m_bold_button->setChecked(fmt.fontWeight() > QFont::Normal); + m_italic_button->setChecked(fmt.fontItalic()); + m_underline_button->setChecked(fmt.fontUnderline()); +} + +void MyTextEditor::SetTextHtml(const QString& text) +{ + m_edit->setHtml(text); +} + +QString MyTextEditor::GetTextHtml() +{ + return m_edit->toPlainText(); +} + +bool MyTextEditor::IsModified() +{ + return m_edit->document()->isModified(); +} + +/** + * MySwitchableTextEditor + */ +MySwitchableTextEditor::MySwitchableTextEditor(QWidget *parent) + :QWidget(parent) +{ + QVBoxLayout *layout = new QVBoxLayout(this); + m_edit = new MyTextEditor(this); + m_label = new QLabel(this); + m_label->setTextFormat(Qt::RichText); + m_label->setAlignment(Qt::AlignTop); + m_line = new QLineEdit(this); + + layout->addWidget(m_label); + layout->addWidget(m_edit); + layout->addWidget(m_line); + + setLayout(layout); + + m_editor_mode = false; + m_line_mode = false; + UpdateVisibility(); +} + +void MySwitchableTextEditor::SetEditorMode(bool edit) +{ + if(edit == m_editor_mode) + return; + QString text = GetTextHtml(); + m_editor_mode = edit; + UpdateVisibility(); + SetTextHtml(text); +} + +QString MySwitchableTextEditor::GetTextHtml() +{ + if(m_editor_mode) + return m_line_mode ? m_line->text() : m_edit->GetTextHtml(); + else + return m_label->text(); +} + +void MySwitchableTextEditor::SetTextHtml(const QString& text) +{ + if(m_editor_mode) + { + if(m_line_mode) + m_line->setText(text); + else + m_edit->SetTextHtml(text); + } + else + m_label->setText(text); +} + +MyTextEditor *MySwitchableTextEditor::GetEditor() +{ + return m_edit; +} + +void MySwitchableTextEditor::SetLineMode(bool en) +{ + if(m_line_mode == en) + return; + QString text = GetTextHtml(); + m_line_mode = en; + SetTextHtml(text); + UpdateVisibility(); +} + +QLineEdit *MySwitchableTextEditor::GetLineEdit() +{ + return m_line; +} + +void MySwitchableTextEditor::UpdateVisibility() +{ + m_label->setVisible(!m_editor_mode); + m_edit->setVisible(m_editor_mode && !m_line_mode); + m_line->setVisible(m_editor_mode && m_line_mode); +} + +QLabel *MySwitchableTextEditor::GetLabel() +{ + return m_label; +} + +bool MySwitchableTextEditor::IsModified() +{ + if(!m_editor_mode) + return false; + return m_line_mode ? m_line->isModified() : m_edit->IsModified(); +} diff --git a/utils/regtools/qeditor/aux.h b/utils/regtools/qeditor/aux.h new file mode 100644 index 0000000000..d6a572826c --- /dev/null +++ b/utils/regtools/qeditor/aux.h @@ -0,0 +1,227 @@ +#ifndef AUX_H +#define AUX_H + +#include <QEvent> +#include <QPaintEvent> +#include <QLineEdit> +#include <QValidator> +#include <QToolButton> +#include <QMenu> +#include <QHBoxLayout> +#include <QTextEdit> +#include <QTableWidget> +#include <QToolBar> +#include <QLabel> +#include <QHBoxLayout> +#include <QItemEditorCreatorBase> +#include <QStyledItemDelegate> +#include "backend.h" + +class SocBitRangeValidator : public QValidator +{ + Q_OBJECT +public: + SocBitRangeValidator(QObject *parent = 0); + + virtual void fixup(QString& input) const; + virtual State validate(QString& input, int& pos) const; + /* validate and return the interpreted value */ + State parse(const QString& input, int& last_bit, int& first_bit) const; +}; + +class SocFieldValidator : public QValidator +{ + Q_OBJECT +public: + SocFieldValidator(QObject *parent = 0); + SocFieldValidator(const soc_reg_field_t& field, QObject *parent = 0); + + virtual void fixup(QString& input) const; + virtual State validate(QString& input, int& pos) const; + /* validate and return the interpreted value */ + State parse(const QString& input, soc_word_t& val) const; + +protected: + soc_reg_field_t m_field; +}; + +class RegLineEdit : public QWidget +{ + Q_OBJECT +public: + enum EditMode + { + Write, Set, Clear, Toggle + }; + + RegLineEdit(QWidget *parent = 0); + ~RegLineEdit(); + void SetReadOnly(bool ro); + void EnableSCT(bool en); + void SetMode(EditMode mode); + EditMode GetMode(); + QLineEdit *GetLineEdit(); + void setText(const QString& text); + QString text() const; + + Q_PROPERTY(QString text READ text WRITE setText USER true) + +protected slots: + void OnWriteAct(); + void OnSetAct(); + void OnClearAct(); + void OnToggleAct(); +protected: + void ShowMode(bool show); + void DoAutoHide(); + + QHBoxLayout *m_layout; + QToolButton *m_button; + QLineEdit *m_edit; + EditMode m_mode; + bool m_has_sct; + bool m_readonly; + QMenu *m_menu; +}; + +class SocFieldItemDelegate : public QStyledItemDelegate +{ +public: + SocFieldItemDelegate(QObject *parent = 0):QStyledItemDelegate(parent), m_bitcount(32) {} + SocFieldItemDelegate(const soc_reg_field_t& field, QObject *parent = 0) + :QStyledItemDelegate(parent), m_bitcount(field.last_bit - field.first_bit + 1) {} + + virtual QString displayText(const QVariant& value, const QLocale& locale) const; +protected: + int m_bitcount; +}; + +class SocFieldEditor : public QLineEdit +{ + Q_OBJECT + Q_PROPERTY(uint field READ field WRITE setField USER true) +public: + SocFieldEditor(const soc_reg_field_t& field, QWidget *parent = 0); + virtual ~SocFieldEditor(); + + uint field() const; + void setField(uint field); + +protected: + SocFieldValidator *m_validator; + uint m_field; + soc_reg_field_t m_reg_field; +}; + +class SocFieldEditorCreator : public QItemEditorCreatorBase +{ +public: + SocFieldEditorCreator() { m_field.first_bit = 0; m_field.last_bit = 31; } + SocFieldEditorCreator(const soc_reg_field_t& field):m_field(field) {} + + virtual QWidget *createWidget(QWidget *parent) const; + virtual QByteArray valuePropertyName() const; + +protected: + soc_reg_field_t m_field; +}; + +class RegSexyDisplay : public QWidget +{ + Q_OBJECT +public: + RegSexyDisplay(const SocRegRef& reg, QWidget *parent = 0); + + QSize minimumSizeHint() const; + QSize sizeHint() const; + +protected: + int marginSize() const; + int separatorSize() const; + int columnWidth() const; + int headerHeight() const; + int gapHeight() const; + int maxContentHeight() const; + int textSep() const; + void paintEvent(QPaintEvent *event); + +private: + SocRegRef m_reg; + mutable QSize m_size; +}; + +class GrowingTextEdit : public QTextEdit +{ + Q_OBJECT +public: + GrowingTextEdit(QWidget *parent = 0); + +protected slots: + void TextChanged(); +}; + +class GrowingTableWidget : public QTableWidget +{ + Q_OBJECT +public: + GrowingTableWidget(QWidget *parent = 0); + +protected slots: + void DataChanged(const QModelIndex& tl, const QModelIndex& br); +}; + +class MyTextEditor : public QWidget +{ + Q_OBJECT +public: + MyTextEditor(QWidget *parent = 0); + void SetGrowingMode(bool en); + void SetReadOnly(bool ro); + void SetTextHtml(const QString& text); + QString GetTextHtml(); + bool IsModified(); +signals: + void OnTextChanged(); + +protected slots: + void OnInternalTextChanged(); + void OnTextBold(bool checked); + void OnTextItalic(bool checked); + void OnTextUnderline(bool checked); + void OnCharFormatChanged(const QTextCharFormat& fmt); + +protected: + bool m_growing_mode; + bool m_read_only; + QToolBar *m_toolbar; + QTextEdit *m_edit; + QToolButton *m_bold_button; + QToolButton *m_italic_button; + QToolButton *m_underline_button; +}; + +class MySwitchableTextEditor : public QWidget +{ + Q_OBJECT +public: + MySwitchableTextEditor(QWidget *parent = 0); + QString GetTextHtml(); + void SetTextHtml(const QString& text); + void SetEditorMode(bool en); + MyTextEditor *GetEditor(); + QLineEdit *GetLineEdit(); + QLabel *GetLabel(); + void SetLineMode(bool en); + bool IsModified(); + +protected: + void UpdateVisibility(); + + bool m_editor_mode; + bool m_line_mode; + QLabel *m_label; + MyTextEditor *m_edit; + QLineEdit *m_line; +}; + +#endif /* AUX_H */ diff --git a/utils/regtools/qeditor/backend.cpp b/utils/regtools/qeditor/backend.cpp index eebda31989..204c160054 100644 --- a/utils/regtools/qeditor/backend.cpp +++ b/utils/regtools/qeditor/backend.cpp @@ -5,6 +5,36 @@ #include "backend.h" /** + * SocFile + */ +SocFile::SocFile() + :m_valid(false) +{ +} + +SocFile::SocFile(const QString& filename) + :m_filename(filename) +{ + m_valid = soc_desc_parse_xml(filename.toStdString(), m_soc); + soc_desc_normalize(m_soc); +} + +bool SocFile::IsValid() +{ + return m_valid; +} + +SocRef SocFile::GetSocRef() +{ + return SocRef(this); +} + +QString SocFile::GetFilename() +{ + return m_filename; +} + +/** * Backend */ @@ -12,33 +42,31 @@ Backend::Backend() { } -QStringList Backend::GetSocNameList() + +QList< SocFileRef > Backend::GetSocFileList() { - QStringList sl; - foreach(const soc_t& soc, m_socs) - sl.append(QString(soc.name.c_str())); - return sl; + QList< SocFileRef > list; + for(std::list< SocFile >::iterator it = m_socs.begin(); it != m_socs.end(); ++it) + list.append(SocFileRef(&(*it))); + return list; } -bool Backend::GetSocByName(const QString& name, SocRef& s) +QList< SocRef > Backend::GetSocList() { - for(std::list< soc_t >::iterator it = m_socs.begin(); it != m_socs.end(); ++it) - if(it->name == name.toStdString()) - { - s = SocRef(&(*it)); - return true; - } - return false; + QList< SocRef > list; + for(std::list< SocFile >::iterator it = m_socs.begin(); it != m_socs.end(); ++it) + list.append(it->GetSocRef()); + return list; } bool Backend::LoadSocDesc(const QString& filename) { - std::vector< soc_t > new_socs; - bool ret = soc_desc_parse_xml(filename.toStdString(), new_socs); - for(size_t i = 0; i < new_socs.size(); i++) - m_socs.push_back(new_socs[i]); + SocFile f(filename); + if(!f.IsValid()) + return false; + m_socs.push_back(f); emit OnSocListChanged(); - return ret; + return true; } IoBackend *Backend::CreateFileIoBackend(const QString& filename) @@ -321,7 +349,7 @@ HWStubBackendHelper::HWStubBackendHelper() if(m_hotplug) { m_hotplug = LIBUSB_SUCCESS == libusb_hotplug_register_callback( - NULL, LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED | LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT, + NULL, (libusb_hotplug_event)(LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED | LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT), LIBUSB_HOTPLUG_ENUMERATE, HWSTUB_USB_VID, HWSTUB_USB_PID, HWSTUB_CLASS, &HWStubBackendHelper::HotPlugCallback, reinterpret_cast< void* >(this), &m_hotplug_handle); } @@ -364,6 +392,7 @@ void HWStubBackendHelper::OnHotPlug(bool arrived, struct libusb_device *dev) int HWStubBackendHelper::HotPlugCallback(struct libusb_context *ctx, struct libusb_device *dev, libusb_hotplug_event event, void *user_data) { + Q_UNUSED(ctx); HWStubBackendHelper *helper = reinterpret_cast< HWStubBackendHelper* >(user_data); switch(event) { diff --git a/utils/regtools/qeditor/backend.h b/utils/regtools/qeditor/backend.h index 939ed9529f..a813f5929f 100644 --- a/utils/regtools/qeditor/backend.h +++ b/utils/regtools/qeditor/backend.h @@ -5,10 +5,11 @@ #include <QStringList> #include <QMap> #include <QVector> -#include "soc_desc.hpp" +#include <QMetaType> #ifdef HAVE_HWSTUB #include "hwstub.h" #endif +#include "soc.h" class IoBackend : public QObject { @@ -62,18 +63,18 @@ class DummyIoBackend : public IoBackend public: DummyIoBackend() {} - virtual bool SupportAccess(AccessType type) { (void) type; return false; } + virtual bool SupportAccess(AccessType type) { Q_UNUSED(type); return false; } virtual QString GetSocName() { return ""; } virtual bool ReadRegister(const QString& name, soc_word_t& value) - { (void) name; (void) value; return false; } + { Q_UNUSED(name); Q_UNUSED(value); return false; } virtual bool ReadRegister(soc_addr_t addr, soc_word_t& value) - { (void) addr; (void) value; return false; } + { Q_UNUSED(addr); Q_UNUSED(value); return false; } virtual bool Reload() { return false; } virtual bool IsReadOnly() { return true; } virtual bool WriteRegister(const QString& name, soc_word_t value, WriteMode mode) - { (void) name; (void) value; (void) mode; return false; } + { Q_UNUSED(name); Q_UNUSED(value); Q_UNUSED(mode); return false; } virtual bool WriteRegister(soc_addr_t addr, soc_word_t value, WriteMode mode) - { (void) addr; (void) value; (void) mode; return false; } + { Q_UNUSED(addr); Q_UNUSED(value); Q_UNUSED(mode); return false; } virtual bool IsDirty() { return false; } virtual bool Commit() { return false; } }; @@ -90,12 +91,12 @@ public: virtual QString GetSocName(); virtual bool ReadRegister(const QString& name, soc_word_t& value); virtual bool ReadRegister(soc_addr_t addr, soc_word_t& value) - { (void) addr; (void) value; return false; } + { Q_UNUSED(addr); Q_UNUSED(value); return false; } virtual bool Reload(); virtual bool IsReadOnly() { return m_readonly; } virtual bool WriteRegister(const QString& name, soc_word_t value, WriteMode mode); virtual bool WriteRegister(soc_addr_t addr, soc_word_t value, WriteMode mode) - { (void) addr; (void) value; (void) mode; return false; } + { Q_UNUSED(addr); Q_UNUSED(value); Q_UNUSED(mode); return false; } virtual bool IsDirty() { return m_dirty; } virtual bool Commit(); @@ -149,12 +150,12 @@ public: virtual bool SupportAccess(AccessType type) { return type == ByAddress; } virtual QString GetSocName(); virtual bool ReadRegister(const QString& name, soc_word_t& value) - { (void) name; (void) value; return false; } + { Q_UNUSED(name); Q_UNUSED(value); return false; } virtual bool ReadRegister(soc_addr_t addr, soc_word_t& value); virtual bool Reload(); virtual bool IsReadOnly() { return false; } virtual bool WriteRegister(const QString& name, soc_word_t value, WriteMode mode) - { (void) name; (void) value; (void) mode; return false; } + { Q_UNUSED(name); Q_UNUSED(value); Q_UNUSED(mode); return false; } virtual bool WriteRegister(soc_addr_t addr, soc_word_t value, WriteMode mode); virtual bool IsDirty() { return false; } virtual bool Commit() { return true; } @@ -191,16 +192,48 @@ protected: }; #endif -class SocRef +class SocRef; + +class SocFile +{ +public: + SocFile(); + SocFile(const QString& filename); + bool IsValid(); + + SocRef GetSocRef(); + QString GetFilename(); + soc_t& GetSoc() { return m_soc; } + +protected: + bool m_valid; + QString m_filename; + soc_t m_soc; +}; + +class SocFileRef { public: - SocRef():m_soc(0) {} - SocRef(const soc_t *soc):m_soc(soc) {} - const soc_t& GetSoc() const { return *m_soc; } + SocFileRef():m_socfile(0) {} + SocFileRef(SocFile *file):m_socfile(file) {} + SocFile *GetSocFile() const { return m_socfile; } + protected: - const soc_t *m_soc; + SocFile *m_socfile; }; +Q_DECLARE_METATYPE(SocFileRef) + +class SocRef : public SocFileRef +{ +public: + SocRef() {} + SocRef(SocFile *file):SocFileRef(file) {} + soc_t& GetSoc() const { return GetSocFile()->GetSoc(); } +}; + +Q_DECLARE_METATYPE(SocRef) + class SocDevRef : public SocRef { public: @@ -208,9 +241,9 @@ public: SocDevRef(const SocRef& soc, int dev_idx, int dev_addr_idx) :SocRef(soc), m_dev_idx(dev_idx), m_dev_addr_idx(dev_addr_idx) {} int GetDevIndex() const { return m_dev_idx; } - const soc_dev_t& GetDev() const { return GetSoc().dev[GetDevIndex()]; } + soc_dev_t& GetDev() const { return GetSoc().dev[GetDevIndex()]; } int GetDevAddrIndex() const { return m_dev_addr_idx; } - const soc_dev_addr_t& GetDevAddr() const { return GetDev().addr[GetDevAddrIndex()]; } + soc_dev_addr_t& GetDevAddr() const { return GetDev().addr[GetDevAddrIndex()]; } protected: int m_dev_idx, m_dev_addr_idx; }; @@ -222,9 +255,9 @@ public: SocRegRef(const SocDevRef& dev, int reg_idx, int reg_addr_idx) :SocDevRef(dev), m_reg_idx(reg_idx), m_reg_addr_idx(reg_addr_idx) {} int GetRegIndex() const { return m_reg_idx; } - const soc_reg_t& GetReg() const { return GetDev().reg[GetRegIndex()]; } + soc_reg_t& GetReg() const { return GetDev().reg[GetRegIndex()]; } int GetRegAddrIndex() const { return m_reg_addr_idx; } - const soc_reg_addr_t& GetRegAddr() const { return GetReg().addr[GetRegAddrIndex()]; } + soc_reg_addr_t& GetRegAddr() const { return GetReg().addr[GetRegAddrIndex()]; } protected: int m_reg_idx, m_reg_addr_idx; }; @@ -236,7 +269,7 @@ public: SocFieldRef(const SocRegRef& reg, int field_idx) :SocRegRef(reg), m_field_idx(field_idx) {} int GetFieldIndex() const { return m_field_idx; } - const soc_reg_field_t& GetField() const { return GetReg().field[GetFieldIndex()]; } + soc_reg_field_t& GetField() const { return GetReg().field[GetFieldIndex()]; } protected: int m_field_idx; }; @@ -247,9 +280,9 @@ class Backend : public QObject public: Backend(); - QStringList GetSocNameList(); + QList< SocFileRef > GetSocFileList(); + QList< SocRef > GetSocList(); bool LoadSocDesc(const QString& filename); - bool GetSocByName(const QString& name, SocRef& s); IoBackend *CreateDummyIoBackend(); IoBackend *CreateFileIoBackend(const QString& filename); #ifdef HAVE_HWSTUB @@ -259,7 +292,7 @@ public: signals: void OnSocListChanged(); private: - std::list< soc_t > m_socs; + std::list< SocFile > m_socs; }; class BackendHelper diff --git a/utils/regtools/qeditor/mainwindow.cpp b/utils/regtools/qeditor/mainwindow.cpp index 2ba781b042..cd0926851c 100644 --- a/utils/regtools/qeditor/mainwindow.cpp +++ b/utils/regtools/qeditor/mainwindow.cpp @@ -12,6 +12,7 @@ #include "mainwindow.h" #include "regtab.h" +#include "regedit.h" MyTabWidget::MyTabWidget() { @@ -20,23 +21,37 @@ MyTabWidget::MyTabWidget() connect(this, SIGNAL(tabCloseRequested(int)), this, SLOT(OnCloseTab(int))); } -void MyTabWidget::OnCloseTab(int index) +bool MyTabWidget::CloseTab(int index) { QWidget *w = this->widget(index); - removeTab(index); - delete w; + DocumentTab *doc = dynamic_cast< DocumentTab* >(w); + if(doc->Quit()) + { + removeTab(index); + delete w; + return true; + } + else + return false; +} + +void MyTabWidget::OnCloseTab(int index) +{ + CloseTab(index); } MainWindow::MainWindow(Backend *backend) :m_backend(backend) { - QAction *new_regtab_act = new QAction(QIcon::fromTheme("document-new"), tr("&Register Tab"), this); + QAction *new_regtab_act = new QAction(QIcon::fromTheme("document-new"), tr("Register &Tab"), this); + QAction *new_regedit_act = new QAction(QIcon::fromTheme("document-edit"), tr("Register &Editor"), this); QAction *load_desc_act = new QAction(QIcon::fromTheme("document-open"), tr("&Soc Description"), this); QAction *quit_act = new QAction(QIcon::fromTheme("application-exit"), tr("&Quit"), this); QAction *about_act = new QAction(QIcon::fromTheme("help-about"), tr("&About"), this); QAction *about_qt_act = new QAction(QIcon::fromTheme("help-about"), tr("About &Qt"), this); connect(new_regtab_act, SIGNAL(triggered()), this, SLOT(OnNewRegTab())); + connect(new_regedit_act, SIGNAL(triggered()), this, SLOT(OnNewRegEdit())); connect(load_desc_act, SIGNAL(triggered()), this, SLOT(OnLoadDesc())); connect(quit_act, SIGNAL(triggered()), this, SLOT(OnQuit())); connect(about_act, SIGNAL(triggered()), this, SLOT(OnAbout())); @@ -48,6 +63,7 @@ MainWindow::MainWindow(Backend *backend) file_menu->addAction(quit_act); new_submenu->addAction(new_regtab_act); + new_submenu->addAction(new_regedit_act); load_submenu->addAction(load_desc_act); @@ -91,6 +107,8 @@ void MainWindow::OnAboutQt() void MainWindow::closeEvent(QCloseEvent *event) { + if(!Quit()) + return event->ignore(); WriteSettings(); event->accept(); } @@ -100,7 +118,7 @@ void MainWindow::OnLoadDesc() QFileDialog *fd = new QFileDialog(this); fd->setFilter("XML files (*.xml);;All files (*)"); fd->setFileMode(QFileDialog::ExistingFiles); - fd->setDirectory(Settings::Get()->value("mainwindow/loaddescdir", QDir::currentPath()).toString()); + fd->setDirectory(Settings::Get()->value("loaddescdir", QDir::currentPath()).toString()); if(fd->exec()) { QStringList filenames = fd->selectedFiles(); @@ -111,11 +129,42 @@ void MainWindow::OnLoadDesc() msg.setText(QString("Cannot load ") + filenames[i]); msg.exec(); } - Settings::Get()->setValue("mainwindow/loaddescdir", fd->directory().absolutePath()); + Settings::Get()->setValue("loaddescdir", fd->directory().absolutePath()); } } +void MainWindow::OnTabModified(bool modified) +{ + QWidget *sender = qobject_cast< QWidget* >(QObject::sender()); + int index = m_tab->indexOf(sender); + if(modified) + m_tab->setTabIcon(index, QIcon::fromTheme("document-save")); + else + m_tab->setTabIcon(index, QIcon()); +} + +void MainWindow::AddTab(QWidget *tab, const QString& title) +{ + connect(tab, SIGNAL(OnModified(bool)), this, SLOT(OnTabModified(bool))); + m_tab->setCurrentIndex(m_tab->addTab(tab, title)); +} + void MainWindow::OnNewRegTab() { - m_tab->addTab(new RegTab(m_backend), "Register Tab"); + AddTab(new RegTab(m_backend, this), "Register Tab"); +} + +void MainWindow::OnNewRegEdit() +{ + AddTab(new RegEdit(m_backend, this), "Register Editor"); +} + +bool MainWindow::Quit() +{ + while(m_tab->count() > 0) + { + if(!m_tab->CloseTab(0)) + return false; + } + return true; } diff --git a/utils/regtools/qeditor/mainwindow.h b/utils/regtools/qeditor/mainwindow.h index d7dab3717f..b32b0647f5 100644 --- a/utils/regtools/qeditor/mainwindow.h +++ b/utils/regtools/qeditor/mainwindow.h @@ -7,11 +7,19 @@ #include "backend.h" #include "settings.h" +class DocumentTab +{ +public: + virtual bool Quit() = 0; + virtual void OnModified(bool modified) = 0; +}; + class MyTabWidget : public QTabWidget { Q_OBJECT public: MyTabWidget(); + bool CloseTab(int index); private slots: void OnCloseTab(int index); @@ -30,15 +38,21 @@ public: private: void closeEvent(QCloseEvent *event); +protected: + void AddTab(QWidget *tab, const QString& title); + bool Quit(); + private slots: void OnQuit(); void OnAbout(); void OnAboutQt(); void OnLoadDesc(); void OnNewRegTab(); + void OnNewRegEdit(); + void OnTabModified(bool modified); private: - QTabWidget *m_tab; + MyTabWidget *m_tab; Backend *m_backend; }; diff --git a/utils/regtools/qeditor/qeditor.pro b/utils/regtools/qeditor/qeditor.pro index 5604fe9d41..38d7c987bf 100644 --- a/utils/regtools/qeditor/qeditor.pro +++ b/utils/regtools/qeditor/qeditor.pro @@ -1,7 +1,9 @@ QT += widgets -HEADERS += mainwindow.h backend.h regtab.h analyser.h settings.h std_analysers.h -SOURCES += main.cpp mainwindow.cpp regtab.cpp backend.cpp analyser.cpp std_analysers.cpp settings.cpp +HEADERS += mainwindow.h backend.h regtab.h analyser.h settings.h \ + std_analysers.h aux.h regdisplaypanel.h regedit.h +SOURCES += main.cpp mainwindow.cpp regtab.cpp backend.cpp analyser.cpp \ + std_analysers.cpp settings.cpp aux.cpp regdisplaypanel.cpp regedit.cpp LIBS += -L../lib/ -lsocdesc -lxml2 INCLUDEPATH += ../lib/ ../../hwstub/lib diff --git a/utils/regtools/qeditor/regdisplaypanel.cpp b/utils/regtools/qeditor/regdisplaypanel.cpp new file mode 100644 index 0000000000..cef5f9807b --- /dev/null +++ b/utils/regtools/qeditor/regdisplaypanel.cpp @@ -0,0 +1,314 @@ +#include "regdisplaypanel.h" +#include <QHeaderView> +#include <QDebug> + +/** + * RegItemEditorCreator + */ + +QWidget *RegItemEditorCreator::createWidget(QWidget * parent) const +{ + return new RegLineEdit(parent); +} + +QByteArray RegItemEditorCreator::valuePropertyName () const +{ + return QByteArray("text"); +} + +/** + * DevDisplayPanel + */ +DevDisplayPanel::DevDisplayPanel(QWidget *parent, const SocDevRef& dev_ref) + :QGroupBox(parent), m_dev(dev_ref), m_reg_font(font()) +{ + QVBoxLayout *right_layout = new QVBoxLayout; + const soc_dev_addr_t& dev_addr = m_dev.GetDevAddr(); + + m_reg_font.setWeight(100); + m_reg_font.setKerning(false); + + QString dev_name; + dev_name.sprintf("HW_%s_BASE", dev_addr.name.c_str()); + + QLabel *label_names = new QLabel("<b>" + dev_name + "</b>"); + label_names->setTextFormat(Qt::RichText); + + QLabel *label_addr = new QLabel("<b>" + QString().sprintf("0x%03x", dev_addr.addr) + "</b>"); + label_addr->setTextFormat(Qt::RichText); + + QHBoxLayout *top_layout = new QHBoxLayout; + top_layout->addStretch(); + top_layout->addWidget(label_names); + top_layout->addWidget(label_addr); + top_layout->addStretch(); + + m_name = new QLabel(this); + m_name->setTextFormat(Qt::RichText); + m_name->setText("<h1>" + QString::fromStdString(m_dev.GetDev().long_name) + "</h1>"); + + m_desc = new QLabel(this); + m_name->setTextFormat(Qt::RichText); + m_desc->setText(QString::fromStdString(m_dev.GetDev().desc)); + + right_layout->addLayout(top_layout, 0); + right_layout->addWidget(m_name, 0); + right_layout->addWidget(m_desc, 0); + right_layout->addStretch(1); + + setTitle("Device Description"); + setLayout(right_layout); +} + +void DevDisplayPanel::AllowWrite(bool en) +{ + Q_UNUSED(en); +} + +QWidget *DevDisplayPanel::GetWidget() +{ + return this; +} + +/** + * RegDisplayPanel + */ + +RegDisplayPanel::RegDisplayPanel(QWidget *parent, IoBackend *io_backend, const SocRegRef& reg_ref) + :QGroupBox(parent), m_io_backend(io_backend), m_reg(reg_ref), m_reg_font(font()) +{ + bool read_only = m_io_backend->IsReadOnly(); + + QVBoxLayout *right_layout = new QVBoxLayout; + + const soc_dev_addr_t& dev_addr = m_reg.GetDevAddr(); + const soc_reg_t& reg = m_reg.GetReg(); + const soc_reg_addr_t& reg_addr = m_reg.GetRegAddr(); + + m_reg_font.setWeight(100); + m_reg_font.setKerning(false); + + QString reg_name; + reg_name.sprintf("HW_%s_%s", dev_addr.name.c_str(), reg_addr.name.c_str()); + QStringList names; + QVector< soc_addr_t > addresses; + names.append(reg_name); + addresses.append(reg_addr.addr); + if(reg.flags & REG_HAS_SCT) + { + names.append(reg_name + "_SET"); + names.append(reg_name + "_CLR"); + names.append(reg_name + "_TOG"); + addresses.append(reg_addr.addr + 4); + addresses.append(reg_addr.addr + 8); + addresses.append(reg_addr.addr + 12); + } + + QString str; + str += "<table align=left>"; + for(int i = 0; i < names.size(); i++) + str += "<tr><td><b>" + names[i] + "</b></td></tr>"; + str += "</table>"; + QLabel *label_names = new QLabel; + label_names->setTextFormat(Qt::RichText); + label_names->setText(str); + + QString str_addr; + str_addr += "<table align=left>"; + for(int i = 0; i < names.size(); i++) + str_addr += "<tr><td><b>" + QString().sprintf("0x%03x", addresses[i]) + "</b></td></tr>"; + str_addr += "</table>"; + QLabel *label_addr = new QLabel; + label_addr->setTextFormat(Qt::RichText); + label_addr->setText(str_addr); + + QHBoxLayout *top_layout = new QHBoxLayout; + top_layout->addStretch(); + top_layout->addWidget(label_names); + top_layout->addWidget(label_addr); + top_layout->addStretch(); + + m_raw_val_name = new QLabel; + m_raw_val_name->setText("Raw value:"); + m_raw_val_edit = new RegLineEdit; + m_raw_val_edit->SetReadOnly(read_only); + m_raw_val_edit->GetLineEdit()->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter); + m_raw_val_edit->GetLineEdit()->setValidator(new SocFieldValidator(m_raw_val_edit)); + m_raw_val_edit->EnableSCT(!!(reg.flags & REG_HAS_SCT)); + m_raw_val_edit->GetLineEdit()->setFont(m_reg_font); + connect(m_raw_val_edit->GetLineEdit(), SIGNAL(returnPressed()), this, SLOT(OnRawRegValueReturnPressed())); + QHBoxLayout *raw_val_layout = new QHBoxLayout; + raw_val_layout->addStretch(); + raw_val_layout->addWidget(m_raw_val_name); + raw_val_layout->addWidget(m_raw_val_edit); + raw_val_layout->addStretch(); + + m_value_table = new GrowingTableWidget; + m_value_table->setRowCount(reg.field.size()); + m_value_table->setColumnCount(5); + for(size_t row = 0; row < reg.field.size(); row++) + { + const soc_reg_field_t& field = reg.field[row]; + QString bits_str; + if(field.first_bit == field.last_bit) + bits_str.sprintf("%d", field.first_bit); + else + bits_str.sprintf("%d:%d", field.last_bit, field.first_bit); + QTableWidgetItem *item = new QTableWidgetItem(bits_str); + item->setTextAlignment(Qt::AlignVCenter | Qt::AlignHCenter); + item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); + m_value_table->setItem(row, 0, item); + item = new QTableWidgetItem(QString(field.name.c_str())); + item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); + m_value_table->setItem(row, 1, item); + item = new QTableWidgetItem(QString(field.desc.c_str())); + item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); + m_value_table->setItem(row, 4, item); + } + m_value_table->setHorizontalHeaderItem(0, new QTableWidgetItem("Bits")); + m_value_table->setHorizontalHeaderItem(1, new QTableWidgetItem("Name")); + m_value_table->setHorizontalHeaderItem(2, new QTableWidgetItem("Value")); + m_value_table->setHorizontalHeaderItem(3, new QTableWidgetItem("Meaning")); + m_value_table->setHorizontalHeaderItem(4, new QTableWidgetItem("Description")); + m_value_table->verticalHeader()->setVisible(false); + m_value_table->resizeColumnsToContents(); + m_value_table->horizontalHeader()->setStretchLastSection(true); + m_value_table->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + + m_table_delegate = new QStyledItemDelegate(this); + m_table_edit_factory = new QItemEditorFactory(); + m_regedit_creator = new RegItemEditorCreator(); + m_table_edit_factory->registerEditor(QVariant::String, m_regedit_creator); + m_table_delegate->setItemEditorFactory(m_table_edit_factory); + m_value_table->setItemDelegate(m_table_delegate); + + m_sexy_display = new RegSexyDisplay(reg_ref, this); + m_sexy_display->setFont(m_reg_font); + + m_desc = new QLabel(this); + m_desc->setTextFormat(Qt::RichText); + m_desc->setText(QString::fromStdString(m_reg.GetReg().desc)); + + right_layout->addWidget(m_desc); + right_layout->addLayout(top_layout); + if(raw_val_layout) + right_layout->addLayout(raw_val_layout); + right_layout->addWidget(m_sexy_display); + right_layout->addWidget(m_value_table); + + setTitle("Register Description"); + m_viewport = new QWidget; + m_viewport->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + m_viewport->setLayout(right_layout); + m_scroll = new QScrollArea; + m_scroll->setWidget(m_viewport); + m_scroll->setWidgetResizable(true); + m_scroll->setFrameShape(QFrame::NoFrame); + QHBoxLayout *layout = new QHBoxLayout; + layout->addWidget(m_scroll, 1); + setLayout(layout); + AllowWrite(false); + + // load data + Reload(); +} + +RegDisplayPanel::~RegDisplayPanel() +{ + delete m_table_edit_factory; +} + +void RegDisplayPanel::Reload() +{ + const soc_dev_addr_t& dev_addr = m_reg.GetDevAddr(); + const soc_reg_t& reg = m_reg.GetReg(); + const soc_reg_addr_t& reg_addr = m_reg.GetRegAddr(); + soc_word_t value; + BackendHelper helper(m_io_backend, m_reg); + bool has_value = helper.ReadRegister(dev_addr.name.c_str(), reg_addr.name.c_str(), value); + + if(has_value) + { + m_raw_val_name->show(); + m_raw_val_edit->show(); + m_raw_val_edit->GetLineEdit()->setText(QString().sprintf("0x%08x", value)); + } + else + { + m_raw_val_name->hide(); + m_raw_val_edit->hide(); + } + + int row = 0; + foreach(const soc_reg_field_t& field, reg.field) + { + QTableWidgetItem *item = new QTableWidgetItem(); + QTableWidgetItem *desc_item = new QTableWidgetItem(); + if(has_value) + { + soc_word_t v = (value & field.bitmask()) >> field.first_bit; + QString value_name; + foreach(const soc_reg_field_value_t& rval, field.value) + if(v == rval.value) + value_name = rval.name.c_str(); + const char *fmt = "%lu"; + // heuristic + if((field.last_bit - field.first_bit + 1) > 16) + fmt = "0x%lx"; + item->setText(QString().sprintf(fmt, (unsigned long)v)); + item->setTextAlignment(Qt::AlignVCenter | Qt::AlignHCenter); + + if(value_name.size() != 0) + { + desc_item->setText(value_name); + desc_item->setTextAlignment(Qt::AlignVCenter | Qt::AlignHCenter); + } + } + item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); + desc_item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); + m_value_table->setItem(row, 2, item); + m_value_table->setItem(row, 3, desc_item); + row++; + } +} + +void RegDisplayPanel::AllowWrite(bool en) +{ + m_allow_write = en; + if(m_raw_val_edit) + m_raw_val_edit->SetReadOnly(m_io_backend->IsReadOnly() || !m_allow_write); +} + +IoBackend::WriteMode RegDisplayPanel::EditModeToWriteMode(RegLineEdit::EditMode mode) +{ + switch(mode) + { + case RegLineEdit::Write: return IoBackend::Write; + case RegLineEdit::Set: return IoBackend::Set; + case RegLineEdit::Clear: return IoBackend::Clear; + case RegLineEdit::Toggle: return IoBackend::Toggle; + default: return IoBackend::Write; + } +} + +void RegDisplayPanel::OnRawRegValueReturnPressed() +{ + soc_word_t val; + QLineEdit *edit = m_raw_val_edit->GetLineEdit(); + const SocFieldValidator *validator = dynamic_cast< const SocFieldValidator *>(edit->validator()); + QValidator::State state = validator->parse(edit->text(), val); + if(state != QValidator::Acceptable) + return; + IoBackend::WriteMode mode = EditModeToWriteMode(m_raw_val_edit->GetMode()); + BackendHelper helper(m_io_backend, m_reg); + helper.WriteRegister(m_reg.GetDevAddr().name.c_str(), m_reg.GetRegAddr().name.c_str(), + val, mode); + // FIXME: we should notify the UI to read value back because it has changed + Reload(); +} + +QWidget *RegDisplayPanel::GetWidget() +{ + return this; +} + diff --git a/utils/regtools/qeditor/regdisplaypanel.h b/utils/regtools/qeditor/regdisplaypanel.h new file mode 100644 index 0000000000..444f3615f2 --- /dev/null +++ b/utils/regtools/qeditor/regdisplaypanel.h @@ -0,0 +1,77 @@ +#ifndef REGDISPLAYPANEL_H +#define REGDISPLAYPANEL_H + +#include <QVBoxLayout> +#include <QLabel> +#include <QGroupBox> +#include <QTableWidget> +#include <QStyledItemDelegate> +#include <QItemEditorCreatorBase> +#include <QTextEdit> +#include <QScrollArea> +#include <soc_desc.hpp> +#include "backend.h" +#include "settings.h" +#include "aux.h" +#include "regtab.h" + +class RegItemEditorCreator : public QItemEditorCreatorBase +{ +public: + RegItemEditorCreator() {} + virtual QWidget *createWidget(QWidget * parent) const; + virtual QByteArray valuePropertyName () const; +}; + +class DevDisplayPanel : public QGroupBox, public RegTabPanel +{ + Q_OBJECT +public: + DevDisplayPanel(QWidget *parent, const SocDevRef& reg); + void Reload(); + void AllowWrite(bool en); + QWidget *GetWidget(); + bool Quit(); + +protected: + + const SocDevRef& m_dev; + QFont m_reg_font; + QLabel *m_name; + QLabel *m_desc; +}; + +class RegDisplayPanel : public QGroupBox, public RegTabPanel +{ + Q_OBJECT +public: + RegDisplayPanel(QWidget *parent, IoBackend *io_backend, const SocRegRef& reg); + ~RegDisplayPanel(); + void AllowWrite(bool en); + void Reload(); + QWidget *GetWidget(); + bool Quit(); + +protected: + IoBackend::WriteMode EditModeToWriteMode(RegLineEdit::EditMode mode); + + IoBackend *m_io_backend; + const SocRegRef& m_reg; + bool m_allow_write; + RegLineEdit *m_raw_val_edit; + RegSexyDisplay *m_sexy_display; + GrowingTableWidget *m_value_table; + QStyledItemDelegate *m_table_delegate; + QItemEditorFactory *m_table_edit_factory; + RegItemEditorCreator *m_regedit_creator; + QLabel *m_raw_val_name; + QFont m_reg_font; + QLabel *m_desc; + QWidget *m_viewport; + QScrollArea *m_scroll; + +private slots: + void OnRawRegValueReturnPressed(); +}; + +#endif /* REGDISPLAYPANEL_H */ diff --git a/utils/regtools/qeditor/regedit.cpp b/utils/regtools/qeditor/regedit.cpp new file mode 100644 index 0000000000..5e498ce496 --- /dev/null +++ b/utils/regtools/qeditor/regedit.cpp @@ -0,0 +1,1324 @@ +#include "regedit.h" +#include <QFileDialog> +#include <QDebug> +#include <QHeaderView> +#include <QMessageBox> +#include <QInputDialog> + +/** + * EmptyEditPanel + */ +EmptyEditPanel::EmptyEditPanel(QWidget *parent) + :QWidget(parent) +{ +} + +/** + * SocEditPanel + */ +SocEditPanel::SocEditPanel(SocRef ref, QWidget *parent) + :QWidget(parent), m_ref(ref) +{ + m_name_group = new QGroupBox("Name", this); + m_name_edit = new QLineEdit(this); + m_name_edit->setText(QString::fromStdString(ref.GetSoc().name)); + QVBoxLayout *name_group_layout = new QVBoxLayout; + name_group_layout->addWidget(m_name_edit); + m_name_group->setLayout(name_group_layout); + + m_desc_group = new QGroupBox("Description", this); + QHBoxLayout *group_layout = new QHBoxLayout; + m_desc_edit = new MyTextEditor(this); + m_desc_edit->SetTextHtml(QString::fromStdString(ref.GetSoc().desc)); + group_layout->addWidget(m_desc_edit); + m_desc_group->setLayout(group_layout); + + QVBoxLayout *layout = new QVBoxLayout; + layout->addWidget(m_name_group); + layout->addWidget(m_desc_group); + layout->addStretch(1); + + connect(m_name_edit, SIGNAL(textChanged(const QString&)), this, SLOT(OnNameEdited(const QString&))); + connect(m_desc_edit, SIGNAL(OnTextChanged()), this, SLOT(OnTextEdited())); + + setLayout(layout); +} + +void SocEditPanel::OnNameEdited(const QString& text) +{ + m_ref.GetSoc().name = text.toStdString(); + emit OnModified(m_name_edit->isModified()); +} + +void SocEditPanel::OnTextEdited() +{ + m_ref.GetSoc().desc = m_desc_edit->GetTextHtml().toStdString(); + emit OnModified(m_desc_edit->IsModified()); +} + +/** + * DevEditPanel + */ +DevEditPanel::DevEditPanel(SocDevRef ref, QWidget *parent) + :QWidget(parent), m_ref(ref) +{ + m_name_group = new QGroupBox("Name", this); + m_name_edit = new QLineEdit(this); + m_name_edit->setText(QString::fromStdString(ref.GetDev().name)); + QVBoxLayout *name_group_layout = new QVBoxLayout; + name_group_layout->addWidget(m_name_edit); + m_name_group->setLayout(name_group_layout); + + m_long_name_group = new QGroupBox("Long Name", this); + m_long_name_edit = new QLineEdit(this); + m_long_name_edit->setText(QString::fromStdString(ref.GetDev().long_name)); + QVBoxLayout *long_name_group_layout = new QVBoxLayout; + long_name_group_layout->addWidget(m_long_name_edit); + m_long_name_group->setLayout(long_name_group_layout); + + m_version_group = new QGroupBox("Version", this); + m_version_edit = new QLineEdit(this); + m_version_edit->setText(QString::fromStdString(ref.GetDev().version)); + QVBoxLayout *version_group_layout = new QVBoxLayout; + version_group_layout->addWidget(m_version_edit); + m_version_group->setLayout(version_group_layout); + + QVBoxLayout *name_ver_layout = new QVBoxLayout; + name_ver_layout->addWidget(m_name_group); + name_ver_layout->addWidget(m_long_name_group); + name_ver_layout->addWidget(m_version_group); + name_ver_layout->addStretch(); + + m_instances_table = new QTableWidget(this); + m_instances_table->setRowCount(ref.GetDev().addr.size() + 1); + m_instances_table->setColumnCount(3); + for(size_t row = 0; row < ref.GetDev().addr.size(); row++) + FillRow(row, ref.GetDev().addr[row]); + CreateNewRow(ref.GetDev().addr.size()); + m_instances_table->setHorizontalHeaderItem(0, new QTableWidgetItem("")); + m_instances_table->setHorizontalHeaderItem(1, new QTableWidgetItem("Name")); + m_instances_table->setHorizontalHeaderItem(2, new QTableWidgetItem("Address")); + m_instances_table->verticalHeader()->setVisible(false); + m_instances_table->resizeColumnsToContents(); + m_instances_table->horizontalHeader()->setStretchLastSection(true); + m_instances_table->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); + m_instances_group = new QGroupBox("Instances", this); + QHBoxLayout *instances_group_layout = new QHBoxLayout; + instances_group_layout->addWidget(m_instances_table); + m_instances_group->setLayout(instances_group_layout); + + QHBoxLayout *top_layout = new QHBoxLayout; + top_layout->addWidget(m_instances_group); + top_layout->addLayout(name_ver_layout); + top_layout->addStretch(); + + m_desc_group = new QGroupBox("Description", this); + QHBoxLayout *group_layout = new QHBoxLayout; + m_desc_edit = new MyTextEditor(this); + m_desc_edit->SetTextHtml(QString::fromStdString(ref.GetDev().desc)); + group_layout->addWidget(m_desc_edit); + m_desc_group->setLayout(group_layout); + + QVBoxLayout *layout = new QVBoxLayout; + layout->addLayout(top_layout, 0); + layout->addWidget(m_desc_group, 1); + + setLayout(layout); + + SocFieldItemDelegate *m_table_delegate = new SocFieldItemDelegate(this); + QItemEditorFactory *m_table_edit_factory = new QItemEditorFactory(); + SocFieldEditorCreator *m_table_edit_creator = new SocFieldEditorCreator(); + m_table_edit_factory->registerEditor(QVariant::UInt, m_table_edit_creator); + m_table_delegate->setItemEditorFactory(m_table_edit_factory); + m_instances_table->setItemDelegate(m_table_delegate); + + connect(m_instances_table, SIGNAL(cellActivated(int,int)), this, SLOT(OnInstActivated(int,int))); + connect(m_instances_table, SIGNAL(cellChanged(int,int)), this, SLOT(OnInstChanged(int,int))); + connect(m_name_edit, SIGNAL(textChanged(const QString&)), this, SLOT(OnNameEdited(const QString&))); + connect(m_long_name_edit, SIGNAL(textChanged(const QString&)), this, SLOT(OnLongNameEdited(const QString&))); + connect(m_version_edit, SIGNAL(textChanged(const QString&)), this, SLOT(OnVersionEdited(const QString&))); + connect(m_desc_edit, SIGNAL(OnTextChanged()), this, SLOT(OnDescEdited())); +} + +void DevEditPanel::OnNameEdited(const QString& text) +{ + m_ref.GetDev().name = text.toStdString(); + emit OnModified(m_name_edit->isModified()); +} + +void DevEditPanel::OnLongNameEdited(const QString& text) +{ + m_ref.GetDev().long_name = text.toStdString(); + emit OnModified(m_long_name_edit->isModified()); +} + +void DevEditPanel::OnVersionEdited(const QString& text) +{ + m_ref.GetDev().version = text.toStdString(); + emit OnModified(m_version_edit->isModified()); +} + +void DevEditPanel::OnDescEdited() +{ + m_ref.GetDev().desc = m_desc_edit->GetTextHtml().toStdString(); + emit OnModified(m_desc_edit->IsModified()); +} + +void DevEditPanel::CreateNewRow(int row) +{ + QTableWidgetItem *item = new QTableWidgetItem(QIcon::fromTheme("list-add"), "", DevInstNewType); + item->setToolTip("New?"); + item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); + m_instances_table->setItem(row, DevInstIconColumn, item); + item = new QTableWidgetItem("New instance..."); + QFont font = item->font(); + font.setItalic(true); + item->setFont(font); + item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); + m_instances_table->setItem(row, DevInstNameColumn, item); + item = new QTableWidgetItem(""); + item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); + m_instances_table->setItem(row, DevInstAddrColumn, item); +} + +void DevEditPanel::FillRow(int row, const soc_dev_addr_t& addr) +{ + QTableWidgetItem *item = new QTableWidgetItem(QString::fromStdString(addr.name)); + item->setTextAlignment(Qt::AlignVCenter | Qt::AlignHCenter); + item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsEditable); + m_instances_table->setItem(row, DevInstNameColumn, item); + item = new QTableWidgetItem(); + item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsEditable); + item->setData(Qt::DisplayRole, QVariant(addr.addr)); + m_instances_table->setItem(row, DevInstAddrColumn, item); + item = new QTableWidgetItem(QIcon::fromTheme("list-remove"), "", DevInstDeleteType); + item->setToolTip("Remove?"); + item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); + m_instances_table->setItem(row, DevInstIconColumn, item); +} + +void DevEditPanel::OnInstActivated(int row, int column) +{ + if(column != 0) + return; + int type = m_instances_table->item(row, column)->type(); + if(type == DevInstDeleteType) + { + m_ref.GetDev().addr.erase(m_ref.GetDev().addr.begin() + row); + m_instances_table->removeRow(row); + } + else if(type == DevInstNewType) + { + m_instances_table->insertRow(row); + soc_dev_addr_t addr; + addr.name = QString("UNNAMED_%1").arg(row).toStdString(); + addr.addr = 0; + m_ref.GetDev().addr.push_back(addr); + FillRow(row, addr); + } +} + +void DevEditPanel::OnInstChanged(int row, int column) +{ + /* ignore extra row for addition */ + if(row >= (int)m_ref.GetDev().addr.size()) + return; + QTableWidgetItem *item = m_instances_table->item(row, column); + if(column == DevInstNameColumn) + { + m_ref.GetDev().addr[row].name = item->text().toStdString(); + emit OnModified(true); + } + else if(column == DevInstAddrColumn) + { + m_ref.GetDev().addr[row].addr = item->data(Qt::DisplayRole).toUInt(); + emit OnModified(true); + } +} + +/** + * RegEditPanel + */ + +RegEditPanel::RegEditPanel(SocRegRef ref, QWidget *parent) + :QWidget(parent), m_ref(ref), m_reg_font(font()) +{ + m_reg_font.setWeight(100); + m_reg_font.setKerning(false); + + m_name_group = new QGroupBox("Name", this); + m_name_edit = new QLineEdit(this); + m_name_edit->setText(QString::fromStdString(ref.GetReg().name)); + QVBoxLayout *name_group_layout = new QVBoxLayout; + name_group_layout->addWidget(m_name_edit); + m_name_group->setLayout(name_group_layout); + + m_instances_table = new QTableWidget(this); + m_instances_table->setRowCount(ref.GetReg().addr.size() + 1); + m_instances_table->setColumnCount(RegInstNrColumns); + for(size_t row = 0; row < ref.GetReg().addr.size(); row++) + FillRow(row, ref.GetReg().addr[row]); + CreateNewAddrRow(ref.GetReg().addr.size()); + m_instances_table->setHorizontalHeaderItem(RegInstIconColumn, new QTableWidgetItem("")); + m_instances_table->setHorizontalHeaderItem(RegInstNameColumn, new QTableWidgetItem("Name")); + m_instances_table->setHorizontalHeaderItem(RegInstAddrColumn, new QTableWidgetItem("Address")); + m_instances_table->verticalHeader()->setVisible(false); + m_instances_table->resizeColumnsToContents(); + m_instances_table->horizontalHeader()->setStretchLastSection(true); + m_instances_table->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); + m_instances_group = new QGroupBox("Instances", this); + QHBoxLayout *instances_group_layout = new QHBoxLayout; + instances_group_layout->addWidget(m_instances_table); + m_instances_group->setLayout(instances_group_layout); + + m_desc_group = new QGroupBox("Description", this); + QHBoxLayout *group_layout = new QHBoxLayout; + m_desc_edit = new MyTextEditor(this); + m_desc_edit->SetTextHtml(QString::fromStdString(ref.GetReg().desc)); + group_layout->addWidget(m_desc_edit); + m_desc_group->setLayout(group_layout); + + bool has_sct = m_ref.GetReg().flags & REG_HAS_SCT; + m_sct_check = new QCheckBox("Set/Clear/Toggle", this); + m_sct_check->setCheckState(has_sct ? Qt::Checked : Qt::Unchecked); + QHBoxLayout *flags_layout = new QHBoxLayout; + flags_layout->addWidget(m_sct_check); + flags_layout->addStretch(); + m_flags_group = new QGroupBox("Flags", this); + m_flags_group->setLayout(flags_layout); + + m_formula_combo = new QComboBox(this); + m_formula_combo->addItem("None", QVariant(REG_FORMULA_NONE)); + m_formula_combo->addItem("String", QVariant(REG_FORMULA_STRING)); + m_formula_combo->setCurrentIndex(m_formula_combo->findData(QVariant(m_ref.GetReg().formula.type))); + m_formula_type_label = new QLabel("Type:", this); + QHBoxLayout *formula_top_layout = new QHBoxLayout; + formula_top_layout->addWidget(m_formula_type_label); + formula_top_layout->addWidget(m_formula_combo); + m_formula_string_edit = new QLineEdit(QString::fromStdString(ref.GetReg().formula.string), this); + QVBoxLayout *formula_layout = new QVBoxLayout; + formula_layout->addLayout(formula_top_layout); + formula_layout->addWidget(m_formula_string_edit); + m_formula_string_gen = new QPushButton("Generate", this); + formula_layout->addWidget(m_formula_string_gen); + m_formula_group = new QGroupBox("Formula", this); + m_formula_group->setLayout(formula_layout); + + QVBoxLayout *name_layout = new QVBoxLayout; + name_layout->addWidget(m_name_group); + name_layout->addWidget(m_flags_group); + name_layout->addWidget(m_formula_group); + name_layout->addStretch(); + + QHBoxLayout *top_layout = new QHBoxLayout; + top_layout->addWidget(m_instances_group); + top_layout->addLayout(name_layout); + top_layout->addWidget(m_desc_group, 1); + + m_sexy_display = new RegSexyDisplay(m_ref, this); + m_sexy_display->setFont(m_reg_font); + + m_field_table = new QTableWidget; + m_field_table->setRowCount(m_ref.GetReg().field.size()); + m_field_table->setColumnCount(4); + for(size_t row = 0; row < m_ref.GetReg().field.size(); row++) + { + const soc_reg_field_t& field = m_ref.GetReg().field[row]; + QString bits_str; + if(field.first_bit == field.last_bit) + bits_str.sprintf("%d", field.first_bit); + else + bits_str.sprintf("%d:%d", field.last_bit, field.first_bit); + QTableWidgetItem *item = new QTableWidgetItem(bits_str); + item->setTextAlignment(Qt::AlignVCenter | Qt::AlignHCenter); + item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); + m_field_table->setItem(row, 1, item); + item = new QTableWidgetItem(QString(field.name.c_str())); + item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); + m_field_table->setItem(row, 2, item); + item = new QTableWidgetItem(QString(field.desc.c_str())); + item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); + m_field_table->setItem(row, 3, item); + UpdateWarning(row); + } + m_field_table->setHorizontalHeaderItem(0, new QTableWidgetItem("")); + m_field_table->setHorizontalHeaderItem(1, new QTableWidgetItem("Bits")); + m_field_table->setHorizontalHeaderItem(2, new QTableWidgetItem("Name")); + m_field_table->setHorizontalHeaderItem(3, new QTableWidgetItem("Description")); + m_field_table->verticalHeader()->setVisible(false); + m_field_table->resizeColumnsToContents(); + m_field_table->horizontalHeader()->setStretchLastSection(true); + QHBoxLayout *field_layout = new QHBoxLayout; + field_layout->addWidget(m_field_table); + m_field_group = new QGroupBox("Flags", this); + m_field_group->setLayout(field_layout); + + QVBoxLayout *layout = new QVBoxLayout; + layout->addLayout(top_layout, 0); + layout->addWidget(m_sexy_display, 0); + layout->addWidget(m_field_group); + + UpdateFormula(); + + setLayout(layout); + + SocFieldItemDelegate *m_table_delegate = new SocFieldItemDelegate(this); + QItemEditorFactory *m_table_edit_factory = new QItemEditorFactory(); + SocFieldEditorCreator *m_table_edit_creator = new SocFieldEditorCreator(); + m_table_edit_factory->registerEditor(QVariant::UInt, m_table_edit_creator); + m_table_delegate->setItemEditorFactory(m_table_edit_factory); + m_instances_table->setItemDelegate(m_table_delegate); + + connect(m_instances_table, SIGNAL(cellActivated(int,int)), this, SLOT(OnInstActivated(int,int))); + connect(m_instances_table, SIGNAL(cellChanged(int,int)), this, SLOT(OnInstChanged(int,int))); + connect(m_name_edit, SIGNAL(textChanged(const QString&)), this, SLOT(OnNameEdited(const QString&))); + connect(m_desc_edit, SIGNAL(OnTextChanged()), this, SLOT(OnDescEdited())); + connect(m_sct_check, SIGNAL(stateChanged(int)), this, SLOT(OnSctEdited(int))); + connect(m_formula_combo, SIGNAL(currentIndexChanged(int)), this, SLOT(OnFormulaChanged(int))); + connect(m_formula_string_edit, SIGNAL(textChanged(const QString&)), this, + SLOT(OnFormulaStringChanged(const QString&))); + connect(m_formula_string_gen, SIGNAL(clicked(bool)), this, SLOT(OnFormulaGenerate(bool))); +} + +void RegEditPanel::UpdateWarning(int row) +{ + Q_UNUSED(row); +} + +void RegEditPanel::OnFormulaStringChanged(const QString& text) +{ + m_ref.GetReg().formula.string = text.toStdString(); + emit OnModified(true); +} + +void RegEditPanel::OnFormulaGenerate(bool checked) +{ + Q_UNUSED(checked); + bool ok; + int count = QInputDialog::getInt(this, "Instance generator", "Number of instances", + 0, 0, 100, 1, &ok); + if(!ok) + return; + std::string name(m_ref.GetReg().name); + size_t pos = name.find('n'); + if(pos == std::string::npos) + { + name.push_back('n'); + pos = name.size() - 1; + } + std::map< std::string, soc_word_t > map; + std::vector< std::pair< std::string, soc_word_t > > list; + std::string formula = m_ref.GetReg().formula.string; + for(int n = 0; n < count; n++) + { + map["n"] = n; + std::string err; + soc_word_t res; + if(!soc_desc_evaluate_formula(formula, map, res, err)) + { + qDebug() << "Cannot evaluator " << QString::fromStdString(formula) + << "for n=" << n << ": " << QString::fromStdString(err); + return; + } + std::string regname = name; + std::string strn = QString("%1").arg(n).toStdString(); + regname.replace(pos, 1, strn); + list.push_back(std::make_pair(regname, res)); + } + // everything went good, commit result + while(m_instances_table->rowCount() > 1) + m_instances_table->removeRow(0); + m_ref.GetReg().addr.resize(list.size()); + for(size_t i = 0; i < list.size(); i++) + { + m_instances_table->insertRow(i); + m_ref.GetReg().addr[i].name = list[i].first; + m_ref.GetReg().addr[i].addr = list[i].second; + FillRow(i, m_ref.GetReg().addr[i]); + } +} + +void RegEditPanel::OnFormulaChanged(int index) +{ + if(index == -1) + return; + m_ref.GetReg().formula.type = static_cast< soc_reg_formula_type_t >(m_formula_combo->itemData(index).toInt()); + UpdateFormula(); + emit OnModified(true); +} + +void RegEditPanel::UpdateFormula() +{ + m_formula_string_edit->hide(); + m_formula_string_gen->hide(); + switch(m_ref.GetReg().formula.type) + { + case REG_FORMULA_STRING: + m_formula_string_edit->show(); + m_formula_string_gen->show(); + break; + case REG_FORMULA_NONE: + default: + break; + } +} + +void RegEditPanel::OnSctEdited(int state) +{ + if(state == Qt::Checked) + m_ref.GetReg().flags |= REG_HAS_SCT; + else + m_ref.GetReg().flags &= ~REG_HAS_SCT; + emit OnModified(true); +} + +void RegEditPanel::FillRow(int row, const soc_reg_addr_t& addr) +{ + QTableWidgetItem *item = new QTableWidgetItem(QString::fromStdString(addr.name)); + item->setTextAlignment(Qt::AlignVCenter | Qt::AlignHCenter); + item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsEditable); + m_instances_table->setItem(row, RegInstNameColumn, item); + item = new QTableWidgetItem(); + item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsEditable); + item->setData(Qt::DisplayRole, QVariant(addr.addr)); + m_instances_table->setItem(row, RegInstAddrColumn, item); + item = new QTableWidgetItem(QIcon::fromTheme("list-remove"), "", RegInstDeleteType); + item->setToolTip("Remove?"); + item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); + m_instances_table->setItem(row, RegInstIconColumn, item); +} + +void RegEditPanel::CreateNewAddrRow(int row) +{ + QTableWidgetItem *item = new QTableWidgetItem(QIcon::fromTheme("list-add"), "", RegInstNewType); + item->setToolTip("New?"); + item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); + m_instances_table->setItem(row, RegInstIconColumn, item); + item = new QTableWidgetItem("New instance..."); + QFont font = item->font(); + font.setItalic(true); + item->setFont(font); + item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); + m_instances_table->setItem(row, RegInstNameColumn, item); + item = new QTableWidgetItem(""); + item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); + m_instances_table->setItem(row, RegInstAddrColumn, item); +} + +void RegEditPanel::OnNameEdited(const QString& text) +{ + m_ref.GetReg().name = text.toStdString(); + emit OnModified(m_name_edit->isModified()); +} + +void RegEditPanel::OnDescEdited() +{ + m_ref.GetReg().desc = m_desc_edit->GetTextHtml().toStdString(); + emit OnModified(m_desc_edit->IsModified()); +} + +void RegEditPanel::OnInstActivated(int row, int column) +{ + if(column != 0) + return; + int type = m_instances_table->item(row, column)->type(); + if(type == RegInstDeleteType) + { + m_ref.GetReg().addr.erase(m_ref.GetReg().addr.begin() + row); + m_instances_table->removeRow(row); + } + else if(type == RegInstNewType) + { + m_instances_table->insertRow(row); + soc_reg_addr_t addr; + addr.name = QString("UNNAMED_%1").arg(row).toStdString(); + addr.addr = 0; + m_ref.GetReg().addr.push_back(addr); + FillRow(row, addr); + } +} + +void RegEditPanel::OnInstChanged(int row, int column) +{ + /* ignore extra row for addition */ + if(row >= (int)m_ref.GetReg().addr.size()) + return; + QTableWidgetItem *item = m_instances_table->item(row, column); + if(column == RegInstNameColumn) + { + m_ref.GetReg().addr[row].name = item->text().toStdString(); + emit OnModified(true); + } + else if(column == RegInstAddrColumn) + { + m_ref.GetReg().addr[row].addr = item->data(Qt::DisplayRole).toUInt(); + emit OnModified(true); + } +} + +/** + * FieldEditPanel + */ +FieldEditPanel::FieldEditPanel(SocFieldRef ref, QWidget *parent) + :QWidget(parent), m_ref(ref) +{ + m_name_group = new QGroupBox("Name", this); + m_name_edit = new QLineEdit(this); + m_name_edit->setText(QString::fromStdString(ref.GetField().name)); + QVBoxLayout *name_group_layout = new QVBoxLayout; + name_group_layout->addWidget(m_name_edit); + m_name_group->setLayout(name_group_layout); + + m_bitrange_group = new QGroupBox("Bit Range", this); + m_bitrange_edit = new QLineEdit(this); + const soc_reg_field_t& field = ref.GetField(); + QString bits_str; + if(field.first_bit == field.last_bit) + bits_str.sprintf("%d", field.first_bit); + else + bits_str.sprintf("%d:%d", field.last_bit, field.first_bit); + m_bitrange_edit->setText(bits_str); + m_bitrange_edit->setValidator(new SocBitRangeValidator(m_bitrange_edit)); + QVBoxLayout *bitrange_group_layout = new QVBoxLayout; + bitrange_group_layout->addWidget(m_bitrange_edit); + m_bitrange_group->setLayout(bitrange_group_layout); + + m_desc_group = new QGroupBox("Description", this); + QHBoxLayout *group_layout = new QHBoxLayout; + m_desc_edit = new MyTextEditor(this); + m_desc_edit->SetTextHtml(QString::fromStdString(ref.GetField().desc)); + group_layout->addWidget(m_desc_edit); + m_desc_group->setLayout(group_layout); + + m_value_group = new QGroupBox("Values", this); + QHBoxLayout *value_layout = new QHBoxLayout; + m_value_table = new QTableWidget(this); + m_value_table->setRowCount(ref.GetField().value.size() + 1); + m_value_table->setColumnCount(FieldValueNrColumns); + for(size_t row = 0; row < ref.GetField().value.size(); row++) + FillRow(row, ref.GetField().value[row]); + CreateNewRow(ref.GetField().value.size()); + m_value_table->setHorizontalHeaderItem(FieldValueIconColumn, new QTableWidgetItem("")); + m_value_table->setHorizontalHeaderItem(FieldValueNameColumn, new QTableWidgetItem("Name")); + m_value_table->setHorizontalHeaderItem(FieldValueValueColumn, new QTableWidgetItem("Value")); + m_value_table->setHorizontalHeaderItem(FieldValueDescColumn, new QTableWidgetItem("Description")); + m_value_table->verticalHeader()->setVisible(false); + m_value_table->horizontalHeader()->setStretchLastSection(true); + value_layout->addWidget(m_value_table); + m_value_group->setLayout(value_layout); + + QHBoxLayout *line_layout = new QHBoxLayout; + line_layout->addWidget(m_name_group); + line_layout->addWidget(m_bitrange_group); + line_layout->addStretch(); + + QVBoxLayout *left_layout = new QVBoxLayout; + left_layout->addLayout(line_layout); + left_layout->addWidget(m_desc_group); + left_layout->addWidget(m_value_group, 1); + + UpdateDelegates(); + + connect(m_name_edit, SIGNAL(textChanged(const QString&)), this, SLOT(OnNameEdited(const QString&))); + connect(m_desc_edit, SIGNAL(OnTextChanged()), this, SLOT(OnDescEdited())); + connect(m_value_table, SIGNAL(cellActivated(int,int)), this, SLOT(OnValueActivated(int,int))); + connect(m_value_table, SIGNAL(cellChanged(int,int)), this, SLOT(OnValueChanged(int,int))); + connect(m_bitrange_edit, SIGNAL(textChanged(const QString&)), this, SLOT(OnBitRangeEdited(const QString&))); + + setLayout(left_layout); +} + +void FieldEditPanel::UpdateDelegates() +{ + SocFieldItemDelegate *m_table_delegate = new SocFieldItemDelegate(m_ref.GetField(), this); + QItemEditorFactory *m_table_edit_factory = new QItemEditorFactory(); + SocFieldEditorCreator *m_table_edit_creator = new SocFieldEditorCreator(m_ref.GetField()); + m_table_edit_factory->registerEditor(QVariant::UInt, m_table_edit_creator); + m_table_delegate->setItemEditorFactory(m_table_edit_factory); + m_value_table->setItemDelegate(m_table_delegate); + m_value_table->resizeColumnsToContents(); +} + +void FieldEditPanel::UpdateWarning(int row) +{ + soc_word_t val = m_ref.GetField().value[row].value; + soc_word_t max = m_ref.GetField().bitmask() >> m_ref.GetField().first_bit; + QTableWidgetItem *item = m_value_table->item(row, FieldValueValueColumn); + if(val > max) + { + item->setIcon(QIcon::fromTheme("dialog-warning")); + item->setToolTip("Value is too big for the field"); + } + else + { + item->setIcon(QIcon()); + item->setToolTip(""); + } +} + +void FieldEditPanel::FillRow(int row, const soc_reg_field_value_t& val) +{ + QTableWidgetItem *item = new QTableWidgetItem(QString::fromStdString(val.name)); + item->setTextAlignment(Qt::AlignVCenter | Qt::AlignHCenter); + item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsEditable); + m_value_table->setItem(row, FieldValueNameColumn, item); + item = new QTableWidgetItem(); + item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsEditable); + item->setData(Qt::DisplayRole, QVariant(val.value)); + m_value_table->setItem(row, FieldValueValueColumn, item); + item = new QTableWidgetItem(QString::fromStdString(val.desc)); + item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsEditable); + m_value_table->setItem(row, FieldValueDescColumn, item); + item = new QTableWidgetItem(QIcon::fromTheme("list-remove"), "", FieldValueDeleteType); + item->setToolTip("Remove?"); + item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); + m_value_table->setItem(row, FieldValueIconColumn, item); + UpdateWarning(row); +} + +void FieldEditPanel::CreateNewRow(int row) +{ + QTableWidgetItem *item = new QTableWidgetItem(QIcon::fromTheme("list-add"), "", FieldValueNewType); + item->setToolTip("New?"); + item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); + m_value_table->setItem(row, FieldValueIconColumn, item); + item = new QTableWidgetItem("New value..."); + QFont font = item->font(); + font.setItalic(true); + item->setFont(font); + item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); + m_value_table->setItem(row, FieldValueNameColumn, item); +} + +void FieldEditPanel::OnBitRangeEdited(const QString& input) +{ + const SocBitRangeValidator *validator = + dynamic_cast< const SocBitRangeValidator *>(m_bitrange_edit->validator()); + int first, last; + QValidator::State state = validator->parse(input, last, first); + if(state != QValidator::Acceptable) + return; + m_ref.GetField().first_bit = first; + m_ref.GetField().last_bit = last; + // update all warning signs + for(size_t row = 0; row < m_ref.GetField().value.size(); row++) + UpdateWarning(row); + // also updates delegates because they now have the wrong view of the field + UpdateDelegates(); + emit OnModified(true); +} + +void FieldEditPanel::OnNameEdited(const QString& text) +{ + m_ref.GetField().name = text.toStdString(); + emit OnModified(m_name_edit->isModified()); +} + +void FieldEditPanel::OnDescEdited() +{ + m_ref.GetField().desc = m_desc_edit->GetTextHtml().toStdString(); + emit OnModified(m_desc_edit->IsModified()); +} + +void FieldEditPanel::OnValueActivated(int row, int column) +{ + if(column != 0) + return; + int type = m_value_table->item(row, column)->type(); + if(type == FieldValueDeleteType) + { + m_ref.GetField().value.erase(m_ref.GetField().value.begin() + row); + m_value_table->removeRow(row); + } + else if(type == FieldValueNewType) + { + m_value_table->insertRow(row); + soc_reg_field_value_t val; + val.name = QString("UNNAMED_%1").arg(row).toStdString(); + val.value = 0; + m_ref.GetField().value.push_back(val); + FillRow(row, val); + } +} + +void FieldEditPanel::OnValueChanged(int row, int column) +{ + /* ignore extra row for addition */ + if(row >= (int)m_ref.GetField().value.size()) + return; + QTableWidgetItem *item = m_value_table->item(row, column); + if(column == FieldValueNameColumn) + m_ref.GetField().value[row].name = item->text().toStdString(); + else if(column == FieldValueValueColumn) + { + soc_word_t& fval = m_ref.GetField().value[row].value; + soc_word_t new_val = item->data(Qt::DisplayRole).toUInt(); + /* avoid infinite recursion by calling UpdateWarning() when + * only the icon changes which would trigger this callback again */ + if(fval != new_val) + { + fval = new_val; + UpdateWarning(row); + } + } + else if(column == FieldValueDescColumn) + m_ref.GetField().value[row].desc = item->text().toStdString(); + emit OnModified(true); +} + +namespace +{ + +enum +{ + SocTreeSocType = QTreeWidgetItem::UserType, + SocTreeDevType, + SocTreeRegType, + SocTreeFieldType, + SocTreeNewDevType, + SocTreeNewRegType, + SocTreeNewFieldType, +}; + +/** + * SocTreeItem + */ + +class SocTreeItem : public QTreeWidgetItem +{ +public: + SocTreeItem(const QString& string, const SocRef& ref) + :QTreeWidgetItem(QStringList(string), SocTreeSocType), m_ref(ref) {} + + const SocRef& GetRef() { return m_ref; } +private: + SocRef m_ref; +}; + +/** + * NewDevTreeItem + */ + +class NewDevTreeItem : public QTreeWidgetItem +{ +public: + NewDevTreeItem(const QString& string, const SocRef& ref) + :QTreeWidgetItem(QStringList(string), SocTreeNewDevType), m_ref(ref) {} + + const SocRef& GetRef() { return m_ref; } +private: + SocRef m_ref; +}; + +/** + * DevTreeItem + */ + +class DevTreeItem : public QTreeWidgetItem +{ +public: + DevTreeItem(const QString& string, const SocDevRef& ref) + :QTreeWidgetItem(QStringList(string), SocTreeDevType), m_ref(ref) {} + + const SocDevRef& GetRef() { return m_ref; } +private: + SocDevRef m_ref; +}; + +/** + * NewRegTreeItem + */ + +class NewRegTreeItem : public QTreeWidgetItem +{ +public: + NewRegTreeItem(const QString& string, const SocDevRef& ref) + :QTreeWidgetItem(QStringList(string), SocTreeNewRegType), m_ref(ref) {} + + const SocDevRef& GetRef() { return m_ref; } +private: + SocDevRef m_ref; +}; + +/** + * RegTreeItem + */ + +class RegTreeItem : public QTreeWidgetItem +{ +public: + RegTreeItem(const QString& string, const SocRegRef& ref) + :QTreeWidgetItem(QStringList(string), SocTreeRegType), m_ref(ref) {} + + const SocRegRef& GetRef() { return m_ref; } +private: + SocRegRef m_ref; +}; + +/** + * NewFieldTreeItem + */ + +class NewFieldTreeItem : public QTreeWidgetItem +{ +public: + NewFieldTreeItem(const QString& string, const SocRegRef& ref) + :QTreeWidgetItem(QStringList(string), SocTreeNewFieldType), m_ref(ref) {} + + const SocRegRef& GetRef() { return m_ref; } +private: + SocRegRef m_ref; +}; + +/** + * FieldTreeItem + */ + +class FieldTreeItem : public QTreeWidgetItem +{ +public: + FieldTreeItem(const QString& string, const SocFieldRef& ref) + :QTreeWidgetItem(QStringList(string), SocTreeFieldType), m_ref(ref) {} + + const SocFieldRef& GetRef() { return m_ref; } +private: + SocFieldRef m_ref; +}; + +} + +/** + * RegEdit + */ +RegEdit::RegEdit(Backend *backend, QWidget *parent) + :QWidget(parent), m_backend(backend) +{ + QVBoxLayout *m_vert_layout = new QVBoxLayout(); + m_file_group = new QGroupBox("File selection", this); + QHBoxLayout *m_file_group_layout = new QHBoxLayout(); + m_file_edit = new QLineEdit(this); + m_file_edit->setReadOnly(true); + m_file_open = new QToolButton(this); + m_file_open->setText("Open"); + m_file_open->setIcon(QIcon::fromTheme("document-open")); + m_file_open->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); + QMenu *file_open_menu = new QMenu(this); + QAction *new_act = file_open_menu->addAction(QIcon::fromTheme("document-new"), "New..."); + m_file_open->setMenu(file_open_menu); + + m_file_save = new QToolButton(this); + m_file_save->setText("Save"); + m_file_save->setIcon(QIcon::fromTheme("document-save")); + m_file_save->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); + QMenu *file_save_menu = new QMenu(this); + QAction *saveas_act = file_save_menu->addAction(QIcon::fromTheme("document-save-as"), "Save as..."); + m_file_save->setMenu(file_save_menu); + m_file_group_layout->addWidget(m_file_open); + m_file_group_layout->addWidget(m_file_save); + m_file_group_layout->addWidget(m_file_edit); + + m_splitter = new QSplitter(this); + m_soc_tree = new QTreeWidget(this); + m_soc_tree->setColumnCount(1); + m_soc_tree->setHeaderLabel(QString("Name")); + m_splitter->addWidget(m_soc_tree); + m_splitter->setStretchFactor(0, 0); + + m_file_group->setLayout(m_file_group_layout); + m_vert_layout->addWidget(m_file_group); + m_vert_layout->addWidget(m_splitter, 1); + + setLayout(m_vert_layout); + + SetModified(false, false); + m_right_panel = 0; + SetPanel(new EmptyEditPanel(this)); + + connect(m_file_open, SIGNAL(clicked()), this, SLOT(OnOpen())); + connect(m_file_save, SIGNAL(clicked()), this, SLOT(OnSave())); + connect(new_act, SIGNAL(triggered()), this, SLOT(OnNew())); + connect(saveas_act, SIGNAL(triggered()), this, SLOT(OnSaveAs())); + connect(m_soc_tree, SIGNAL(currentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*)), + this, SLOT(OnSocItemChanged(QTreeWidgetItem*, QTreeWidgetItem*))); + connect(m_soc_tree, SIGNAL(itemActivated(QTreeWidgetItem*, int)), + this, SLOT(OnSocItemActivated(QTreeWidgetItem*, int))); +} + +RegEdit::~RegEdit() +{ +} + +void RegEdit::OnSave() +{ + SaveSoc(); +} + +void RegEdit::OnSaveAs() +{ + SaveSocAs(); +} + +bool RegEdit::CloseSoc() +{ + if(!m_modified) + return true; + QMessageBox msgBox; + msgBox.setText("The description has been modified."); + msgBox.setInformativeText("Do you want to save your changes?"); + msgBox.setStandardButtons(QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel); + msgBox.setDefaultButton(QMessageBox::Save); + int ret = msgBox.exec(); + if(ret == QMessageBox::Discard) + return true; + if(ret == QMessageBox::Cancel) + return false; + return SaveSoc(); +} + +bool RegEdit::SaveSoc() +{ + if(m_file_edit->text().size() == 0) + return SaveSocAs(); + else + return SaveSocFile(m_file_edit->text()); +} + +bool RegEdit::GetFilename(QString& filename, bool save) +{ + QFileDialog *fd = new QFileDialog(this); + if(save) + fd->setAcceptMode(QFileDialog::AcceptSave); + fd->setFilter("Description files (*.xml);;All files (*)"); + fd->setDirectory(Settings::Get()->value("loaddescdir", QDir::currentPath()).toString()); + if(fd->exec()) + { + QStringList filenames = fd->selectedFiles(); + filename = filenames[0]; + Settings::Get()->setValue("loaddescdir", fd->directory().absolutePath()); + return true; + } + else + return false; +} + +bool RegEdit::SaveSocAs() +{ + QString filename; + if(!GetFilename(filename, true)) + return false; + m_file_edit->setText(filename); + return SaveSocFile(filename); +} + +void RegEdit::OnOpen() +{ + if(!CloseSoc()) + return; + QString filename; + if(!GetFilename(filename, false)) + return; + LoadSocFile(filename); +} + +void RegEdit::OnNew() +{ + if(!CloseSoc()) + return; + m_cur_socfile = SocFile(); + m_file_edit->setText(""); + SetModified(false, false); + UpdateSocFile(); +} + +bool RegEdit::SaveSocFile(const QString& filename) +{ + soc_desc_normalize(m_cur_socfile.GetSoc()); + if(!soc_desc_produce_xml(filename.toStdString(), m_cur_socfile.GetSoc())) + { + QMessageBox::warning(this, "The description was not saved", + "There was an error when saving the file"); + return false; + } + m_soc_tree->clear(); + FillSocTree(); + SetModified(false, false); + return true; +} + +void RegEdit::LoadSocFile(const QString& filename) +{ + m_cur_socfile = SocFile(filename); + if(!m_cur_socfile.IsValid()) + { + QMessageBox::warning(this, "The description was not loaded", + "There was an error when loading the file"); + return; + } + m_file_edit->setText(filename); + SetModified(false, false); + UpdateSocFile(); +} + +void RegEdit::CreateNewFieldItem(QTreeWidgetItem *_parent) +{ + RegTreeItem *parent = dynamic_cast< RegTreeItem* >(_parent); + NewFieldTreeItem *newdev_item = new NewFieldTreeItem("New field...", parent->GetRef()); + MakeItalic(newdev_item, true); + newdev_item->setIcon(0, QIcon::fromTheme("list-add")); + parent->addChild(newdev_item); +} + +void RegEdit::FillRegTreeItem(QTreeWidgetItem *_item) +{ + RegTreeItem *item = dynamic_cast< RegTreeItem* >(_item); + const soc_reg_t& reg = item->GetRef().GetReg(); + for(size_t i = 0; i < reg.field.size(); i++) + { + const soc_reg_field_t& field = reg.field[i]; + FieldTreeItem *field_item = new FieldTreeItem(QString::fromStdString(field.name), + SocFieldRef(item->GetRef(), i)); + FixupEmptyItem(field_item); + item->addChild(field_item); + } + CreateNewFieldItem(item); +} + +void RegEdit::CreateNewRegisterItem(QTreeWidgetItem *_parent) +{ + DevTreeItem *parent = dynamic_cast< DevTreeItem* >(_parent); + NewRegTreeItem *newdev_item = new NewRegTreeItem("New register...", parent->GetRef()); + MakeItalic(newdev_item, true); + newdev_item->setIcon(0, QIcon::fromTheme("list-add")); + parent->addChild(newdev_item); +} + +void RegEdit::FillDevTreeItem(QTreeWidgetItem *_item) +{ + DevTreeItem *item = dynamic_cast< DevTreeItem* >(_item); + const soc_dev_t& dev = item->GetRef().GetDev(); + for(size_t i = 0; i < dev.reg.size(); i++) + { + const soc_reg_t& reg = dev.reg[i]; + RegTreeItem *reg_item = new RegTreeItem(QString::fromStdString(reg.name), + SocRegRef(item->GetRef(), i, -1)); + FixupEmptyItem(reg_item); + FillRegTreeItem(reg_item); + item->addChild(reg_item); + } + CreateNewRegisterItem(item); +} + +void RegEdit::CreateNewDeviceItem(QTreeWidgetItem *_parent) +{ + SocTreeItem *parent = dynamic_cast< SocTreeItem* >(_parent); + NewDevTreeItem *newdev_item = new NewDevTreeItem("New device...", parent->GetRef()); + MakeItalic(newdev_item, true); + newdev_item->setIcon(0, QIcon::fromTheme("list-add")); + parent->addChild(newdev_item); +} + +void RegEdit::FillSocTreeItem(QTreeWidgetItem *_item) +{ + SocTreeItem *item = dynamic_cast< SocTreeItem* >(_item); + const soc_t& soc = item->GetRef().GetSoc(); + for(size_t i = 0; i < soc.dev.size(); i++) + { + const soc_dev_t& reg = soc.dev[i]; + DevTreeItem *dev_item = new DevTreeItem(QString::fromStdString(reg.name), + SocDevRef(item->GetRef(), i, -1)); + FixupEmptyItem(dev_item); + FillDevTreeItem(dev_item); + item->addChild(dev_item); + } + CreateNewDeviceItem(item); +} + +void RegEdit::FillSocTree() +{ + SocRef ref = m_cur_socfile.GetSocRef(); + SocTreeItem *soc_item = new SocTreeItem( + QString::fromStdString(ref.GetSoc().name), ref); + FixupEmptyItem(soc_item); + FillSocTreeItem(soc_item); + m_soc_tree->addTopLevelItem(soc_item); + soc_item->setExpanded(true); +} + +void RegEdit::MakeItalic(QTreeWidgetItem *item, bool it) +{ + QFont font = item->font(0); + font.setItalic(it); + item->setFont(0, font); +} + +void RegEdit::FixupEmptyItem(QTreeWidgetItem *item) +{ + if(item->text(0).size() == 0) + { + item->setIcon(0, QIcon::fromTheme("dialog-error")); + MakeItalic(item, true); + item->setText(0, "Unnamed"); + } + else + { + item->setIcon(0, QIcon::fromTheme("cpu")); + MakeItalic(item, false); + } +} + +void RegEdit::UpdateSocFile() +{ + m_soc_tree->clear(); + FillSocTree(); + SetPanel(new EmptyEditPanel(this)); +} + +void RegEdit::SetPanel(QWidget *panel) +{ + delete m_right_panel; + m_right_panel = panel; + connect(m_right_panel, SIGNAL(OnModified(bool)), this, SLOT(OnSocModified(bool))); + m_splitter->addWidget(m_right_panel); + m_splitter->setStretchFactor(1, 2); +} + +void RegEdit::SetModified(bool add, bool mod) +{ + m_modified = add ? (m_modified || mod) : mod; + emit OnModified(mod); +} + +void RegEdit::OnSocModified(bool modified) +{ + // we might need to update the name in the tree + UpdateName(m_soc_tree->currentItem()); + if(modified) + SetModified(true, true); +} + +void RegEdit::DisplaySoc(SocRef ref) +{ + SetPanel(new SocEditPanel(ref, this)); +} + +void RegEdit::DisplayDev(SocDevRef ref) +{ + SetPanel(new DevEditPanel(ref, this)); +} + +void RegEdit::DisplayReg(SocRegRef ref) +{ + SetPanel(new RegEditPanel(ref, this)); +} + +void RegEdit::DisplayField(SocFieldRef ref) +{ + SetPanel(new FieldEditPanel(ref, this)); +} + +void RegEdit::UpdateName(QTreeWidgetItem *current) +{ + if(current == 0) + return; + if(current->type() == SocTreeSocType) + { + SocTreeItem *item = dynamic_cast< SocTreeItem * >(current); + item->setText(0, QString::fromStdString(item->GetRef().GetSoc().name)); + } + else if(current->type() == SocTreeDevType) + { + DevTreeItem *item = dynamic_cast< DevTreeItem * >(current); + item->setText(0, QString::fromStdString(item->GetRef().GetDev().name)); + } + else if(current->type() == SocTreeRegType) + { + RegTreeItem *item = dynamic_cast< RegTreeItem * >(current); + item->setText(0, QString::fromStdString(item->GetRef().GetReg().name)); + } + else if(current->type() == SocTreeFieldType) + { + FieldTreeItem *item = dynamic_cast< FieldTreeItem * >(current); + item->setText(0, QString::fromStdString(item->GetRef().GetField().name)); + } + FixupEmptyItem(current); +} + +void RegEdit::OnSocItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous) +{ + Q_UNUSED(previous); + if(current == 0) + return; + if(current->type() == SocTreeSocType) + { + SocTreeItem *item = dynamic_cast< SocTreeItem * >(current); + DisplaySoc(item->GetRef()); + } + else if(current->type() == SocTreeDevType) + { + DevTreeItem *item = dynamic_cast< DevTreeItem * >(current); + DisplayDev(item->GetRef()); + } + else if(current->type() == SocTreeRegType) + { + RegTreeItem *item = dynamic_cast< RegTreeItem * >(current); + DisplayReg(item->GetRef()); + } + else if(current->type() == SocTreeFieldType) + { + FieldTreeItem *item = dynamic_cast< FieldTreeItem * >(current); + DisplayField(item->GetRef()); + } +} + +void RegEdit::OnSocItemActivated(QTreeWidgetItem *current, int column) +{ + Q_UNUSED(column); + if(current == 0) + return; + if(current->type() == SocTreeNewDevType) + AddDevice(current); + else if(current->type() == SocTreeNewRegType) + AddRegister(current); + else if(current->type() == SocTreeNewFieldType) + AddField(current); +} + +void RegEdit::AddDevice(QTreeWidgetItem *_item) +{ + NewDevTreeItem *item = dynamic_cast< NewDevTreeItem * >(_item); + item->GetRef().GetSoc().dev.push_back(soc_dev_t()); + DevTreeItem *dev_item = new DevTreeItem("", + SocDevRef(item->GetRef(), item->GetRef().GetSoc().dev.size() - 1, -1)); + FixupEmptyItem(dev_item); + item->parent()->insertChild(item->parent()->indexOfChild(item), dev_item); + CreateNewRegisterItem(dev_item); + m_soc_tree->setCurrentItem(dev_item); +} + +void RegEdit::AddRegister(QTreeWidgetItem *_item) +{ + NewRegTreeItem *item = dynamic_cast< NewRegTreeItem * >(_item); + item->GetRef().GetDev().reg.push_back(soc_reg_t()); + RegTreeItem *reg_item = new RegTreeItem("", + SocRegRef(item->GetRef(), item->GetRef().GetDev().reg.size() - 1, -1)); + FixupEmptyItem(reg_item); + item->parent()->insertChild(item->parent()->indexOfChild(item), reg_item); + CreateNewFieldItem(reg_item); + m_soc_tree->setCurrentItem(reg_item); +} + +void RegEdit::AddField(QTreeWidgetItem *_item) +{ + NewFieldTreeItem *item = dynamic_cast< NewFieldTreeItem * >(_item); + item->GetRef().GetReg().field.push_back(soc_reg_field_t()); + FieldTreeItem *field_item = new FieldTreeItem("", + SocFieldRef(item->GetRef(), item->GetRef().GetReg().field.size() - 1)); + FixupEmptyItem(field_item); + item->parent()->insertChild(item->parent()->indexOfChild(item), field_item); + m_soc_tree->setCurrentItem(field_item); +} + +bool RegEdit::Quit() +{ + return CloseSoc(); +}
\ No newline at end of file diff --git a/utils/regtools/qeditor/regedit.h b/utils/regtools/qeditor/regedit.h new file mode 100644 index 0000000000..8615816783 --- /dev/null +++ b/utils/regtools/qeditor/regedit.h @@ -0,0 +1,282 @@ +#ifndef REGEDIT_H +#define REGEDIT_H + +#include <QComboBox> +#include <QTreeWidget> +#include <QVBoxLayout> +#include <QTabWidget> +#include <QSplitter> +#include <QLineEdit> +#include <QPushButton> +#include <QLabel> +#include <QListWidget> +#include <QGroupBox> +#include <QToolButton> +#include <QMenu> +#include <QCheckBox> +#include <QRadioButton> +#include <QButtonGroup> +#include <QDebug> +#include <QScrollArea> +#include "backend.h" +#include "settings.h" +#include "mainwindow.h" +#include "aux.h" + +class AbstractRegEditPanel +{ +public: + AbstractRegEditPanel() {} + virtual ~AbstractRegEditPanel() {} + virtual void OnModified(bool mod) = 0; +}; + +class EmptyEditPanel : public QWidget, public AbstractRegEditPanel +{ + Q_OBJECT +public: + EmptyEditPanel(QWidget *parent); + +signals: + void OnModified(bool mod); + +protected: +}; + +class SocEditPanel : public QWidget, public AbstractRegEditPanel +{ + Q_OBJECT +public: + SocEditPanel(SocRef ref, QWidget *parent = 0); + +signals: + void OnModified(bool mod); + +protected slots: + void OnTextEdited(); + void OnNameEdited(const QString& text); + +protected: + SocRef m_ref; + QGroupBox *m_name_group; + QLineEdit *m_name_edit; + QGroupBox *m_desc_group; + MyTextEditor *m_desc_edit; +}; + +class DevEditPanel : public QWidget, public AbstractRegEditPanel +{ + Q_OBJECT +public: + DevEditPanel(SocDevRef ref, QWidget *parent = 0); + +signals: + void OnModified(bool mod); + +protected slots: + void OnInstActivated(int row, int column); + void OnInstChanged(int row, int column); + void OnNameEdited(const QString& text); + void OnLongNameEdited(const QString& text); + void OnVersionEdited(const QString& text); + void OnDescEdited(); + +protected: + void FillRow(int row, const soc_dev_addr_t& addr); + void CreateNewRow(int row); + + enum + { + DevInstDeleteType = QTableWidgetItem::UserType, + DevInstNewType + }; + + enum + { + DevInstIconColumn = 0, + DevInstNameColumn = 1, + DevInstAddrColumn = 2, + }; + + SocDevRef m_ref; + QGroupBox *m_name_group; + QLineEdit *m_name_edit; + QGroupBox *m_long_name_group; + QLineEdit *m_long_name_edit; + QGroupBox *m_version_group; + QLineEdit *m_version_edit; + QGroupBox *m_instances_group; + QTableWidget *m_instances_table; + QGroupBox *m_desc_group; + MyTextEditor *m_desc_edit; +}; + +class RegEditPanel : public QWidget, public AbstractRegEditPanel +{ + Q_OBJECT +public: + RegEditPanel(SocRegRef ref, QWidget *parent = 0); + +signals: + void OnModified(bool mod); + +protected slots: + void OnInstActivated(int row, int column); + void OnInstChanged(int row, int column); + void OnNameEdited(const QString& text); + void OnDescEdited(); + void OnSctEdited(int state); + void OnFormulaChanged(int index); + void OnFormulaStringChanged(const QString& text); + void OnFormulaGenerate(bool checked); + +protected: + void CreateNewAddrRow(int row); + void FillRow(int row, const soc_reg_addr_t& addr); + void UpdateFormula(); + void UpdateWarning(int row); + + enum + { + RegInstDeleteType = QTableWidgetItem::UserType, + RegInstNewType + }; + + enum + { + RegInstIconColumn = 0, + RegInstNameColumn, + RegInstAddrColumn, + RegInstNrColumns, + }; + + SocRegRef m_ref; + QGroupBox *m_name_group; + QLineEdit *m_name_edit; + QGroupBox *m_instances_group; + QTableWidget *m_instances_table; + QGroupBox *m_desc_group; + QGroupBox *m_flags_group; + QCheckBox *m_sct_check; + QFont m_reg_font; + QGroupBox *m_formula_group; + QButtonGroup *m_formula_radio_group; + QLabel *m_formula_type_label; + QComboBox *m_formula_combo; + QLineEdit *m_formula_string_edit; + QPushButton *m_formula_string_gen; + RegSexyDisplay *m_sexy_display; + MyTextEditor *m_desc_edit; + QGroupBox *m_field_group; + QTableWidget *m_field_table; +}; + +class FieldEditPanel : public QWidget, public AbstractRegEditPanel +{ + Q_OBJECT +public: + FieldEditPanel(SocFieldRef ref, QWidget *parent = 0); + +signals: + void OnModified(bool mod); + +protected slots: + void OnDescEdited(); + void OnNameEdited(const QString& text); + void OnBitRangeEdited(const QString& string); + void OnValueActivated(int row, int column); + void OnValueChanged(int row, int column); + +protected: + void CreateNewRow(int row); + void FillRow(int row, const soc_reg_field_value_t& val); + void UpdateWarning(int row); + void UpdateDelegates(); + + enum + { + FieldValueDeleteType = QTableWidgetItem::UserType, + FieldValueNewType, + }; + + enum + { + FieldValueIconColumn = 0, + FieldValueNameColumn, + FieldValueValueColumn, + FieldValueDescColumn, + FieldValueNrColumns, + }; + + SocFieldRef m_ref; + QGroupBox *m_name_group; + QLineEdit *m_name_edit; + QGroupBox *m_bitrange_group; + QLineEdit *m_bitrange_edit; + QGroupBox *m_desc_group; + MyTextEditor *m_desc_edit; + QGroupBox *m_value_group; + QTableWidget *m_value_table; +}; + +class RegEdit : public QWidget, public DocumentTab +{ + Q_OBJECT +public: + RegEdit(Backend *backend, QWidget *parent = 0); + ~RegEdit(); + virtual bool Quit(); + +signals: + void OnModified(bool mod); + +protected slots: + void OnSocItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous); + void OnSocItemActivated(QTreeWidgetItem *current, int column); + void OnOpen(); + void OnSave(); + void OnSaveAs(); + void OnSocModified(bool modified); + void OnNew(); + +protected: + void LoadSocFile(const QString& filename); + void UpdateSocFile(); + void FillSocTree(); + void FillSocTreeItem(QTreeWidgetItem *_item); + void FillDevTreeItem(QTreeWidgetItem *_item); + void FillRegTreeItem(QTreeWidgetItem *_item); + void SetPanel(QWidget *panel); + void DisplaySoc(SocRef ref); + void DisplayDev(SocDevRef ref); + void DisplayReg(SocRegRef ref); + void DisplayField(SocFieldRef ref); + bool CloseSoc(); + bool SaveSoc(); + bool SaveSocAs(); + bool SaveSocFile(const QString& filename); + bool GetFilename(QString& filename, bool save); + void SetModified(bool add, bool mod); + void FixupEmptyItem(QTreeWidgetItem *item); + void MakeItalic(QTreeWidgetItem *item, bool it); + void AddDevice(QTreeWidgetItem *item); + void AddRegister(QTreeWidgetItem *_item); + void UpdateName(QTreeWidgetItem *current); + void AddField(QTreeWidgetItem *_item); + void CreateNewDeviceItem(QTreeWidgetItem *parent); + void CreateNewRegisterItem(QTreeWidgetItem *parent); + void CreateNewFieldItem(QTreeWidgetItem *parent); + + QGroupBox *m_file_group; + QToolButton *m_file_open; + QToolButton *m_file_save; + QLineEdit *m_file_edit; + QSplitter *m_splitter; + QTreeWidget *m_soc_tree; + Backend *m_backend; + bool m_modified; + SocFile m_cur_socfile; + QWidget *m_right_panel; +}; + +#endif /* REGEDIT_H */ diff --git a/utils/regtools/qeditor/regtab.cpp b/utils/regtools/qeditor/regtab.cpp index 4cd4e7b283..568d859c0e 100644 --- a/utils/regtools/qeditor/regtab.cpp +++ b/utils/regtools/qeditor/regtab.cpp @@ -1,406 +1,75 @@ #include "regtab.h" -#include <QSplitter> -#include <QVBoxLayout> -#include <QAbstractListModel> -#include <QMessageBox> #include <QSizePolicy> -#include <QHBoxLayout> #include <QStringBuilder> -#include <QLabel> -#include <QGridLayout> -#include <QTableWidget> -#include <QHeaderView> #include <QFileDialog> #include <QDebug> #include <QStyle> #include "backend.h" #include "analyser.h" +#include "regdisplaypanel.h" -/** - * SocFieldValidator - */ - -SocFieldValidator::SocFieldValidator(QObject *parent) - :QValidator(parent) -{ - m_field.first_bit = 0; - m_field.last_bit = 31; -} - -SocFieldValidator::SocFieldValidator(const soc_reg_field_t& field, QObject *parent) - :QValidator(parent), m_field(field) -{ -} - -void SocFieldValidator::fixup(QString& input) const -{ - input = input.trimmed(); -} - -QValidator::State SocFieldValidator::validate(QString& input, int& pos) const -{ - (void) pos; - soc_word_t val; - State state = parse(input, val); - return state; -} - -QValidator::State SocFieldValidator::parse(const QString& input, soc_word_t& val) const -{ - // the empty string is all alwats intermediate - if(input.size() == 0) - return Intermediate; - // first check named values - State state = Invalid; - foreach(const soc_reg_field_value_t& value, m_field.value) - { - QString name = QString::fromLocal8Bit(value.name.c_str()); - // cannot be a substring if too long or empty - if(input.size() > name.size()) - continue; - // check equal string - if(input == name) - { - state = Acceptable; - val = value.value; - break; - } - // check substring - if(name.startsWith(input)) - state = Intermediate; - } - // early return for exact match - if(state == Acceptable) - return state; - // do a few special cases for convenience - if(input.compare("0x", Qt::CaseInsensitive) == 0 || - input.compare("0b", Qt::CaseInsensitive) == 0) - return Intermediate; - // try by parsing - unsigned basis, pos; - if(input.size() >= 2 && input.startsWith("0x", Qt::CaseInsensitive)) - { - basis = 16; - pos = 2; - } - else if(input.size() >= 2 && input.startsWith("0b", Qt::CaseInsensitive)) - { - basis = 2; - pos = 2; - } - else if(input.size() >= 2 && input.startsWith("0")) - { - basis = 8; - pos = 1; - } - else - { - basis = 10; - pos = 0; - } - bool ok = false; - unsigned long v = input.mid(pos).toULong(&ok, basis); - // if not ok, return result of name parsing - if(!ok) - return state; - // if ok, check if it fits in the number of bits - unsigned nr_bits = m_field.last_bit - m_field.first_bit + 1; - unsigned long max = nr_bits == 32 ? 0xffffffff : (1 << nr_bits) - 1; - if(v <= max) - { - val = v; - return Acceptable; - } - - return state; -} - -/** - * RegLineEdit - */ -RegLineEdit::RegLineEdit(QWidget *parent) - :QWidget(parent) +namespace { - m_layout = new QHBoxLayout(this); - m_button = new QToolButton(this); - m_button->setCursor(Qt::ArrowCursor); - m_button->setStyleSheet("QToolButton { font-weight: bold; color: white; background: black; }"); - m_button->setPopupMode(QToolButton::InstantPopup); - m_edit = new QLineEdit(this); - m_layout->addWidget(m_button); - m_layout->addWidget(m_edit); - m_menu = new QMenu(this); - connect(m_menu->addAction("Write"), SIGNAL(triggered()), this, SLOT(OnWriteAct())); - connect(m_menu->addAction("Set"), SIGNAL(triggered()), this, SLOT(OnSetAct())); - connect(m_menu->addAction("Clear"), SIGNAL(triggered()), this, SLOT(OnClearAct())); - connect(m_menu->addAction("Toggle"), SIGNAL(triggered()), this, SLOT(OnToggleAct())); - EnableSCT(false); - SetReadOnly(false); - ShowMode(true); - SetMode(Write); -} -void RegLineEdit::SetReadOnly(bool ro) +enum { - m_edit->setReadOnly(ro); - m_readonly = ro; - ShowMode(!ro); -} + RegTreeDevType = QTreeWidgetItem::UserType, + RegTreeRegType +}; -void RegLineEdit::EnableSCT(bool en) +class DevTreeItem : public QTreeWidgetItem { - m_has_sct = en; - if(!m_has_sct) - { - m_button->setMenu(0); - SetMode(Write); - } - else - m_button->setMenu(m_menu); -} - -RegLineEdit::~RegLineEdit() -{ -} +public: + DevTreeItem(const QString& string, const SocDevRef& ref) + :QTreeWidgetItem(QStringList(string), RegTreeDevType), m_ref(ref) {} -QLineEdit *RegLineEdit::GetLineEdit() -{ - return m_edit; -} + const SocDevRef& GetRef() { return m_ref; } +private: + SocDevRef m_ref; +}; -void RegLineEdit::ShowMode(bool show) +class RegTreeItem : public QTreeWidgetItem { - if(show) - m_button->show(); - else - m_button->hide(); -} +public: + RegTreeItem(const QString& string, const SocRegRef& ref) + :QTreeWidgetItem(QStringList(string), RegTreeRegType), m_ref(ref) {} -void RegLineEdit::OnWriteAct() -{ - SetMode(Write); -} - -void RegLineEdit::OnSetAct() -{ - SetMode(Set); -} - -void RegLineEdit::OnClearAct() -{ - SetMode(Clear); -} - -void RegLineEdit::OnToggleAct() -{ - SetMode(Toggle); -} - -void RegLineEdit::SetMode(EditMode mode) -{ - m_mode = mode; - switch(m_mode) - { - case Write: m_button->setText("WR"); break; - case Set: m_button->setText("SET"); break; - case Clear: m_button->setText("CLR"); break; - case Toggle: m_button->setText("TOG"); break; - default: break; - } -} + const SocRegRef& GetRef() { return m_ref; } +private: + SocRegRef m_ref; +}; -RegLineEdit::EditMode RegLineEdit::GetMode() -{ - return m_mode; } /** - * RegDisplayPanel + * EmptyRegTabPanel */ - -RegDisplayPanel::RegDisplayPanel(QWidget *parent, IoBackend *io_backend, const SocRegRef& reg_ref) - :QGroupBox(parent), m_io_backend(io_backend), m_reg(reg_ref) +EmptyRegTabPanel::EmptyRegTabPanel(QWidget *parent) + :QWidget(parent) { - bool read_only = m_io_backend->IsReadOnly(); - - QVBoxLayout *right_layout = new QVBoxLayout; - - const soc_dev_addr_t& dev_addr = m_reg.GetDevAddr(); - const soc_reg_t& reg = m_reg.GetReg(); - const soc_reg_addr_t& reg_addr = m_reg.GetRegAddr(); - - QString reg_name; - reg_name.sprintf("HW_%s_%s", dev_addr.name.c_str(), reg_addr.name.c_str()); - QStringList names; - QVector< soc_addr_t > addresses; - names.append(reg_name); - addresses.append(reg_addr.addr); - if(reg.flags & REG_HAS_SCT) - { - names.append(reg_name + "_SET"); - names.append(reg_name + "_CLR"); - names.append(reg_name + "_TOG"); - addresses.append(reg_addr.addr + 4); - addresses.append(reg_addr.addr + 8); - addresses.append(reg_addr.addr + 12); - } - - QString str; - str += "<table align=left>"; - for(int i = 0; i < names.size(); i++) - str += "<tr><td><b>" + names[i] + "</b></td></tr>"; - str += "</table>"; - QLabel *label_names = new QLabel; - label_names->setTextFormat(Qt::RichText); - label_names->setText(str); - - QString str_addr; - str_addr += "<table align=left>"; - for(int i = 0; i < names.size(); i++) - str_addr += "<tr><td><b>" + QString().sprintf("0x%03x", addresses[i]) + "</b></td></tr>"; - str_addr += "</table>"; - QLabel *label_addr = new QLabel; - label_addr->setTextFormat(Qt::RichText); - label_addr->setText(str_addr); - - QHBoxLayout *top_layout = new QHBoxLayout; - top_layout->addStretch(); - top_layout->addWidget(label_names); - top_layout->addWidget(label_addr); - top_layout->addStretch(); - - soc_word_t value; - BackendHelper helper(m_io_backend, m_reg); - bool has_value = helper.ReadRegister(dev_addr.name.c_str(), reg_addr.name.c_str(), value); - - QHBoxLayout *raw_val_layout = 0; - if(has_value) - { - QLabel *raw_val_name = new QLabel; - raw_val_name->setText("Raw value:"); - m_raw_val_edit = new RegLineEdit; - m_raw_val_edit->SetReadOnly(read_only); - m_raw_val_edit->GetLineEdit()->setText(QString().sprintf("0x%08x", value)); - m_raw_val_edit->GetLineEdit()->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter); - m_raw_val_edit->GetLineEdit()->setValidator(new SocFieldValidator(m_raw_val_edit)); - m_raw_val_edit->EnableSCT(!!(reg.flags & REG_HAS_SCT)); - connect(m_raw_val_edit->GetLineEdit(), SIGNAL(returnPressed()), this, SLOT(OnRawRegValueReturnPressed())); - raw_val_layout = new QHBoxLayout; - raw_val_layout->addStretch(); - raw_val_layout->addWidget(raw_val_name); - raw_val_layout->addWidget(m_raw_val_edit); - raw_val_layout->addStretch(); - } - else - m_raw_val_edit = 0; - - QTableWidget *value_table = new QTableWidget; - value_table->setRowCount(reg.field.size()); - value_table->setColumnCount(4); - int row = 0; - foreach(const soc_reg_field_t& field, reg.field) - { - QString bits_str; - if(field.first_bit == field.last_bit) - bits_str.sprintf("%d", field.first_bit); - else - bits_str.sprintf("%d:%d", field.last_bit, field.first_bit); - QTableWidgetItem *item = new QTableWidgetItem(bits_str); - item->setTextAlignment(Qt::AlignVCenter | Qt::AlignHCenter); - item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); - value_table->setItem(row, 0, item); - item = new QTableWidgetItem(QString(field.name.c_str())); - item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); - value_table->setItem(row, 1, item); - item = new QTableWidgetItem(); - if(has_value) - { - soc_word_t v = (value & field.bitmask()) >> field.first_bit; - QString value_name; - foreach(const soc_reg_field_value_t& rval, field.value) - if(v == rval.value) - value_name = rval.name.c_str(); - const char *fmt = "%lu"; - // heuristic - if((field.last_bit - field.first_bit + 1) > 16) - fmt = "0x%lx"; - item->setText(QString().sprintf(fmt, (unsigned long)v)); - item->setTextAlignment(Qt::AlignVCenter | Qt::AlignHCenter); - - if(value_name.size() != 0) - { - QTableWidgetItem *t = new QTableWidgetItem(value_name); - t->setTextAlignment(Qt::AlignVCenter | Qt::AlignHCenter); - t->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); - value_table->setItem(row, 3, t); - } - } - item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); - value_table->setItem(row, 2, item); - row++; - } - value_table->setHorizontalHeaderItem(0, new QTableWidgetItem("Bits")); - value_table->setHorizontalHeaderItem(1, new QTableWidgetItem("Name")); - value_table->setHorizontalHeaderItem(2, new QTableWidgetItem("Value")); - value_table->setHorizontalHeaderItem(3, new QTableWidgetItem("Meaning")); - value_table->verticalHeader()->setVisible(false); - value_table->resizeColumnsToContents(); - value_table->horizontalHeader()->setStretchLastSection(true); - value_table->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); - - right_layout->addLayout(top_layout); - if(raw_val_layout) - right_layout->addLayout(raw_val_layout); - //right_layout->addWidget(bits_label); - right_layout->addWidget(value_table); - //right_layout->addStretch(); - - setTitle("Register Description"); - setLayout(right_layout); - AllowWrite(false); + QVBoxLayout *l = new QVBoxLayout; + l->addStretch(); + setLayout(l); } -void RegDisplayPanel::AllowWrite(bool en) +void EmptyRegTabPanel::AllowWrite(bool en) { - m_allow_write = en; - if(m_raw_val_edit) - m_raw_val_edit->SetReadOnly(m_io_backend->IsReadOnly() || !m_allow_write); + Q_UNUSED(en); } -IoBackend::WriteMode RegDisplayPanel::EditModeToWriteMode(RegLineEdit::EditMode mode) +QWidget *EmptyRegTabPanel::GetWidget() { - switch(mode) - { - case RegLineEdit::Write: return IoBackend::Write; - case RegLineEdit::Set: return IoBackend::Set; - case RegLineEdit::Clear: return IoBackend::Clear; - case RegLineEdit::Toggle: return IoBackend::Toggle; - default: return IoBackend::Write; - } + return this; } -void RegDisplayPanel::OnRawRegValueReturnPressed() -{ - soc_word_t val; - QLineEdit *edit = m_raw_val_edit->GetLineEdit(); - const SocFieldValidator *validator = dynamic_cast< const SocFieldValidator *>(edit->validator()); - QValidator::State state = validator->parse(edit->text(), val); - if(state != QValidator::Acceptable) - return; - IoBackend::WriteMode mode = EditModeToWriteMode(m_raw_val_edit->GetMode()); - BackendHelper helper(m_io_backend, m_reg); - helper.WriteRegister(m_reg.GetDevAddr().name.c_str(), m_reg.GetRegAddr().name.c_str(), - val, mode); - // FIXME: we should notify the UI to read value back because it has changed -} /** * RegTab */ -RegTab::RegTab(Backend *backend) - :m_backend(backend) +RegTab::RegTab(Backend *backend, QWidget *parent) + :QSplitter(parent), m_backend(backend) { QWidget *left = new QWidget; this->addWidget(left); @@ -432,7 +101,7 @@ RegTab::RegTab(Backend *backend) QGroupBox *data_sel_group = new QGroupBox("Data selection"); QHBoxLayout *data_sel_layout = new QHBoxLayout; m_data_selector = new QComboBox; - m_data_selector->addItem(QIcon::fromTheme("face-sad"), "None", QVariant(DataSelNothing)); + m_data_selector->addItem(QIcon::fromTheme("text-x-generic"), "Explore", QVariant(DataSelNothing)); m_data_selector->addItem(QIcon::fromTheme("document-open"), "File...", QVariant(DataSelFile)); #ifdef HAVE_HWSTUB m_data_selector->addItem(QIcon::fromTheme("multimedia-player"), "Device...", QVariant(DataSelDevice)); @@ -446,7 +115,8 @@ RegTab::RegTab(Backend *backend) data_sel_reload->setIcon(QIcon::fromTheme("view-refresh")); data_sel_reload->setToolTip("Reload data"); data_sel_layout->addWidget(m_data_selector); - data_sel_layout->addWidget(m_data_sel_edit); + data_sel_layout->addWidget(m_data_sel_edit, 1); + data_sel_layout->addStretch(0); #ifdef HAVE_HWSTUB m_dev_selector = new QComboBox; data_sel_layout->addWidget(m_dev_selector, 1); @@ -457,12 +127,9 @@ RegTab::RegTab(Backend *backend) data_sel_group->setLayout(data_sel_layout); m_data_soc_label->setFrameStyle(QFrame::StyledPanel | QFrame::Raised); - m_right_panel->addWidget(data_sel_group); - m_right_content = new QWidget; - QVBoxLayout *l = new QVBoxLayout; - l->addStretch(); - m_right_content->setLayout(l); - m_right_panel->addWidget(m_right_content); + m_right_panel->addWidget(data_sel_group, 0); + m_right_content = 0; + SetPanel(new EmptyRegTabPanel); QWidget *w = new QWidget; w->setLayout(m_right_panel); this->addWidget(w); @@ -470,21 +137,17 @@ RegTab::RegTab(Backend *backend) m_io_backend = m_backend->CreateDummyIoBackend(); - connect(m_soc_selector, SIGNAL(currentIndexChanged(const QString&)), - this, SLOT(OnSocChanged(const QString&))); + connect(m_soc_selector, SIGNAL(currentIndexChanged(int)), + this, SLOT(OnSocChanged(int))); connect(m_backend, SIGNAL(OnSocListChanged()), this, SLOT(OnSocListChanged())); connect(m_reg_tree, SIGNAL(currentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*)), this, SLOT(OnRegItemChanged(QTreeWidgetItem*, QTreeWidgetItem*))); - connect(m_reg_tree, SIGNAL(itemClicked(QTreeWidgetItem *, int)), this, - SLOT(OnRegItemClicked(QTreeWidgetItem *, int))); connect(m_data_selector, SIGNAL(activated(int)), this, SLOT(OnDataSelChanged(int))); connect(m_data_soc_label, SIGNAL(linkActivated(const QString&)), this, SLOT(OnDataSocActivated(const QString&))); connect(m_analysers_list, SIGNAL(currentItemChanged(QListWidgetItem *, QListWidgetItem *)), this, SLOT(OnAnalyserChanged(QListWidgetItem *, QListWidgetItem *))); - connect(m_analysers_list, SIGNAL(itemClicked(QListWidgetItem *)), this, - SLOT(OnAnalyserClicked(QListWidgetItem *))); #ifdef HAVE_HWSTUB connect(m_dev_selector, SIGNAL(currentIndexChanged(int)), this, SLOT(OnDevChanged(int))); @@ -492,14 +155,22 @@ RegTab::RegTab(Backend *backend) connect(m_readonly_check, SIGNAL(clicked(bool)), this, SLOT(OnReadOnlyClicked(bool))); OnSocListChanged(); - OnDataSelChanged(DataSelNothing); + OnDataSelChanged(0); } RegTab::~RegTab() { +#ifdef HAVE_HWSTUB + ClearDevList(); +#endif delete m_io_backend; } +bool RegTab::Quit() +{ + return true; +} + void RegTab::SetDataSocName(const QString& socname) { if(socname.size() != 0) @@ -533,9 +204,10 @@ void RegTab::OnDataSelChanged(int index) #ifdef HAVE_HWSTUB m_dev_selector->hide(); #endif + m_readonly_check->show(); QFileDialog *fd = new QFileDialog(m_data_selector); fd->setFilter("Textual files (*.txt);;All files (*)"); - fd->setDirectory(Settings::Get()->value("regtab/loaddatadir", QDir::currentPath()).toString()); + fd->setDirectory(Settings::Get()->value("loaddatadir", QDir::currentPath()).toString()); if(fd->exec()) { QStringList filenames = fd->selectedFiles(); @@ -545,13 +217,14 @@ void RegTab::OnDataSelChanged(int index) SetDataSocName(m_io_backend->GetSocName()); OnDataSocActivated(m_io_backend->GetSocName()); } - Settings::Get()->setValue("regtab/loaddatadir", fd->directory().absolutePath()); + Settings::Get()->setValue("loaddatadir", fd->directory().absolutePath()); SetReadOnlyIndicator(); } #ifdef HAVE_HWSTUB else if(var == DataSelDevice) { m_data_sel_edit->hide(); + m_readonly_check->show(); m_dev_selector->show(); OnDevListChanged(); } @@ -562,13 +235,31 @@ void RegTab::OnDataSelChanged(int index) #ifdef HAVE_HWSTUB m_dev_selector->hide(); #endif + m_readonly_check->hide(); + delete m_io_backend; m_io_backend = m_backend->CreateDummyIoBackend(); + m_readonly_check->setCheckState(Qt::Checked); SetDataSocName(""); + UpdateSocFilename(); } OnDataChanged(); } +void RegTab::UpdateSocFilename() +{ + int index = m_data_selector->currentIndex(); + if(index == -1) + return; + if(m_data_selector->itemData(index) != DataSelNothing) + return; + index = m_soc_selector->currentIndex(); + if(index == -1) + return; + SocRef ref = m_soc_selector->itemData(index).value< SocRef >(); + m_data_sel_edit->setText(ref.GetSocFile()->GetFilename()); +} + void RegTab::SetReadOnlyIndicator() { if(m_io_backend->IsReadOnly()) @@ -582,23 +273,30 @@ void RegTab::OnDataChanged() void RegTab::OnRegItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous) { - (void) previous; + Q_UNUSED(previous); OnRegItemClicked(current, 0); } void RegTab::OnRegItemClicked(QTreeWidgetItem *current, int col) { - (void) col; - if(current == 0 || current->type() != RegTreeRegType) + Q_UNUSED(col); + if(current == 0) return; - RegTreeItem *item = dynamic_cast< RegTreeItem * >(current); - - DisplayRegister(item->GetRef()); + if(current->type() == RegTreeRegType) + { + RegTreeItem *item = dynamic_cast< RegTreeItem * >(current); + DisplayRegister(item->GetRef()); + } + else if(current->type() == RegTreeDevType) + { + DevTreeItem *item = dynamic_cast< DevTreeItem * >(current); + DisplayDevice(item->GetRef()); + } } void RegTab::OnAnalyserChanged(QListWidgetItem *current, QListWidgetItem *previous) { - (void) previous; + Q_UNUSED(previous); OnAnalyserClicked(current); } @@ -606,33 +304,44 @@ void RegTab::OnAnalyserClicked(QListWidgetItem *current) { if(current == 0) return; - delete m_right_content; AnalyserFactory *ana = AnalyserFactory::GetAnalyserByName(current->text()); - m_right_content = ana->Create(m_cur_soc, m_io_backend)->GetWidget(); - m_right_panel->addWidget(m_right_content, 1); + SetPanel(ana->Create(m_cur_soc, m_io_backend)); } void RegTab::DisplayRegister(const SocRegRef& ref) { + SetPanel(new RegDisplayPanel(this, m_io_backend, ref)); +} + +void RegTab::DisplayDevice(const SocDevRef& ref) +{ + SetPanel(new DevDisplayPanel(this, ref)); +} + +void RegTab::SetPanel(RegTabPanel *panel) +{ delete m_right_content; - RegDisplayPanel *panel = new RegDisplayPanel(this, m_io_backend, ref); - panel->AllowWrite(m_readonly_check->checkState() == Qt::Unchecked); m_right_content = panel; - m_right_panel->addWidget(m_right_content); + m_right_content->AllowWrite(m_readonly_check->checkState() == Qt::Unchecked); + m_right_panel->addWidget(m_right_content->GetWidget(), 1); } void RegTab::OnSocListChanged() { m_soc_selector->clear(); - QStringList socs = m_backend->GetSocNameList(); + QList< SocRef > socs = m_backend->GetSocList(); for(int i = 0; i < socs.size(); i++) - m_soc_selector->addItem(socs[i]); + { + QVariant v; + v.setValue(socs[i]); + m_soc_selector->addItem(QString::fromStdString(socs[i].GetSoc().name), v); + } } #ifdef HAVE_HWSTUB void RegTab::OnDevListChanged() { - m_dev_selector->clear(); + ClearDevList(); QList< HWStubDevice* > list = m_hwstub_helper.GetDevList(); foreach(HWStubDevice *dev, list) { @@ -659,10 +368,21 @@ void RegTab::OnDevChanged(int index) OnDataSocActivated(m_io_backend->GetSocName()); OnDataChanged(); } + +void RegTab::ClearDevList() +{ + while(m_dev_selector->count() > 0) + { + HWStubDevice *dev = reinterpret_cast< HWStubDevice* >(m_dev_selector->itemData(0).value< void* >()); + delete dev; + m_dev_selector->removeItem(0); + } +} #endif -void RegTab::FillDevSubTree(DevTreeItem *item) +void RegTab::FillDevSubTree(QTreeWidgetItem *_item) { + DevTreeItem *item = dynamic_cast< DevTreeItem* >(_item); const soc_dev_t& dev = item->GetRef().GetDev(); for(size_t i = 0; i < dev.reg.size(); i++) { @@ -697,23 +417,21 @@ void RegTab::FillAnalyserList() m_analysers_list->addItems(AnalyserFactory::GetAnalysersForSoc(m_cur_soc.GetSoc().name.c_str())); } -void RegTab::OnSocChanged(const QString& soc) +void RegTab::OnSocChanged(int index) { - m_reg_tree->clear(); - if(!m_backend->GetSocByName(soc, m_cur_soc)) + if(index == -1) return; + m_reg_tree->clear(); + m_cur_soc = m_soc_selector->itemData(index).value< SocRef >(); FillRegTree(); FillAnalyserList(); + UpdateSocFilename(); } void RegTab::OnReadOnlyClicked(bool checked) { if(m_io_backend->IsReadOnly()) return SetReadOnlyIndicator(); - if(m_right_content == 0) - return; - RegDisplayPanel *panel = dynamic_cast< RegDisplayPanel* >(m_right_content); - if(panel == 0) - return; - panel->AllowWrite(!checked); + m_right_content->AllowWrite(!checked); + UpdateSocFilename(); } diff --git a/utils/regtools/qeditor/regtab.h b/utils/regtools/qeditor/regtab.h index 9fa1437119..78a10ba379 100644 --- a/utils/regtools/qeditor/regtab.h +++ b/utils/regtools/qeditor/regtab.h @@ -2,7 +2,6 @@ #define REGTAB_H #include <QComboBox> -#include <QEvent> #include <QTreeWidget> #include <QVBoxLayout> #include <QTabWidget> @@ -11,118 +10,41 @@ #include <QPushButton> #include <QLabel> #include <QListWidget> -#include <QValidator> #include <QGroupBox> #include <QToolButton> #include <QMenu> #include <QCheckBox> -#include <soc_desc.hpp> #include "backend.h" #include "settings.h" +#include "mainwindow.h" -enum -{ - RegTreeDevType = QTreeWidgetItem::UserType, - RegTreeRegType -}; - -class DevTreeItem : public QTreeWidgetItem -{ -public: - DevTreeItem(const QString& string, const SocDevRef& ref) - :QTreeWidgetItem(QStringList(string), RegTreeDevType), m_ref(ref) {} - - const SocDevRef& GetRef() { return m_ref; } -private: - SocDevRef m_ref; -}; - -class RegTreeItem : public QTreeWidgetItem +class RegTabPanel { public: - RegTreeItem(const QString& string, const SocRegRef& ref) - :QTreeWidgetItem(QStringList(string), RegTreeRegType), m_ref(ref) {} - - const SocRegRef& GetRef() { return m_ref; } -private: - SocRegRef m_ref; + RegTabPanel() {} + virtual ~RegTabPanel() {} + virtual void AllowWrite(bool en) = 0; + virtual QWidget *GetWidget() = 0; }; -class SocFieldValidator : public QValidator +class EmptyRegTabPanel : public QWidget, public RegTabPanel { - Q_OBJECT public: - SocFieldValidator(QObject *parent = 0); - SocFieldValidator(const soc_reg_field_t& field, QObject *parent = 0); - - virtual void fixup(QString& input) const; - virtual State validate(QString& input, int& pos) const; - /* validate and return the interpreted value */ - State parse(const QString& input, soc_word_t& val) const; - -protected: - soc_reg_field_t m_field; -}; - -class RegLineEdit : public QWidget -{ - Q_OBJECT -public: - enum EditMode - { - Write, Set, Clear, Toggle - }; - - RegLineEdit(QWidget *parent = 0); - ~RegLineEdit(); - void SetReadOnly(bool ro); - void EnableSCT(bool en); - void SetMode(EditMode mode); - EditMode GetMode(); - QLineEdit *GetLineEdit(); - -protected slots: - void OnWriteAct(); - void OnSetAct(); - void OnClearAct(); - void OnToggleAct(); -protected: - void ShowMode(bool show); - - QHBoxLayout *m_layout; - QToolButton *m_button; - QLineEdit *m_edit; - EditMode m_mode; - bool m_has_sct; - bool m_readonly; - QMenu *m_menu; -}; - -class RegDisplayPanel : public QGroupBox -{ - Q_OBJECT -public: - RegDisplayPanel(QWidget *parent, IoBackend *io_backend, const SocRegRef& reg); + EmptyRegTabPanel(QWidget *parent = 0); void AllowWrite(bool en); - -protected: - IoBackend::WriteMode EditModeToWriteMode(RegLineEdit::EditMode mode); - - IoBackend *m_io_backend; - const SocRegRef& m_reg; - bool m_allow_write; - RegLineEdit *m_raw_val_edit; - -private slots: - void OnRawRegValueReturnPressed(); + QWidget *GetWidget(); }; -class RegTab : public QSplitter +class RegTab : public QSplitter, public DocumentTab { Q_OBJECT public: - RegTab(Backend *backend); + RegTab(Backend *backend, QWidget *parent = 0); ~RegTab(); + virtual bool Quit(); + +signals: + void OnModified(bool modified); protected: enum @@ -134,12 +56,16 @@ protected: #endif }; - void FillDevSubTree(DevTreeItem *item); + void FillDevSubTree(QTreeWidgetItem *item); void FillRegTree(); void FillAnalyserList(); void UpdateSocList(); void DisplayRegister(const SocRegRef& ref); + void DisplayDevice(const SocDevRef& ref); void SetDataSocName(const QString& socname); + void SetPanel(RegTabPanel *panel); + void UpdateSocFilename(); + QComboBox *m_soc_selector; #ifdef HAVE_HWSTUB QComboBox *m_dev_selector; @@ -149,7 +75,7 @@ protected: QTreeWidget *m_reg_tree; SocRef m_cur_soc; QVBoxLayout *m_right_panel; - QWidget *m_right_content; + RegTabPanel *m_right_content; QLineEdit *m_data_sel_edit; QCheckBox *m_readonly_check; QLabel *m_data_soc_label; @@ -163,9 +89,10 @@ private slots: #ifdef HAVE_HWSTUB void OnDevListChanged(); void OnDevChanged(int index); + void ClearDevList(); #endif void SetReadOnlyIndicator(); - void OnSocChanged(const QString& text); + void OnSocChanged(int index); void OnSocListChanged(); void OnRegItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous); void OnRegItemClicked(QTreeWidgetItem *clicked, int col); diff --git a/utils/regtools/qeditor/std_analysers.cpp b/utils/regtools/qeditor/std_analysers.cpp index 2cc84cb488..5847e39f7d 100644 --- a/utils/regtools/qeditor/std_analysers.cpp +++ b/utils/regtools/qeditor/std_analysers.cpp @@ -23,6 +23,7 @@ ClockAnalyser::ClockAnalyser(const SocRef& soc, IoBackend *backend) ClockAnalyser::~ClockAnalyser() { + delete m_group; } QWidget *ClockAnalyser::GetWidget() @@ -287,9 +288,9 @@ void ClockAnalyser::FillTree() else AddClock(ref_xtal, "clk_rtc32k", INVALID); - (void) clk_x; - (void) clk_gpmi; - (void) clk_h; + Q_UNUSED(clk_x); + Q_UNUSED(clk_gpmi); + Q_UNUSED(clk_h); m_tree_widget->expandAll(); m_tree_widget->resizeColumnToContents(0); @@ -334,6 +335,7 @@ EmiAnalyser::EmiAnalyser(const SocRef& soc, IoBackend *backend) EmiAnalyser::~EmiAnalyser() { + delete m_group; } QWidget *EmiAnalyser::GetWidget() @@ -671,6 +673,7 @@ PinAnalyser::PinAnalyser(const SocRef& soc, IoBackend *backend) PinAnalyser::~PinAnalyser() { + delete m_group; } QWidget *PinAnalyser::GetWidget() diff --git a/utils/regtools/qeditor/std_analysers.h b/utils/regtools/qeditor/std_analysers.h index aae8e40207..cca8b12b99 100644 --- a/utils/regtools/qeditor/std_analysers.h +++ b/utils/regtools/qeditor/std_analysers.h @@ -21,7 +21,6 @@ class ClockAnalyser : public Analyser { - Q_OBJECT public: ClockAnalyser(const SocRef& soc, IoBackend *backend); virtual ~ClockAnalyser(); @@ -50,7 +49,7 @@ private: /** * EMI analyser */ -class EmiAnalyser : public Analyser +class EmiAnalyser : public QObject, public Analyser { Q_OBJECT public: @@ -96,7 +95,6 @@ private: */ class PinAnalyser : public Analyser { - Q_OBJECT public: PinAnalyser(const SocRef& soc, IoBackend *backend); virtual ~PinAnalyser(); |