summaryrefslogtreecommitdiffstats
path: root/utils/regtools/qeditor
diff options
context:
space:
mode:
Diffstat (limited to 'utils/regtools/qeditor')
-rw-r--r--utils/regtools/qeditor/analyser.h5
-rw-r--r--utils/regtools/qeditor/aux.cpp746
-rw-r--r--utils/regtools/qeditor/aux.h227
-rw-r--r--utils/regtools/qeditor/backend.cpp67
-rw-r--r--utils/regtools/qeditor/backend.h79
-rw-r--r--utils/regtools/qeditor/mainwindow.cpp63
-rw-r--r--utils/regtools/qeditor/mainwindow.h16
-rw-r--r--utils/regtools/qeditor/qeditor.pro6
-rw-r--r--utils/regtools/qeditor/regdisplaypanel.cpp314
-rw-r--r--utils/regtools/qeditor/regdisplaypanel.h77
-rw-r--r--utils/regtools/qeditor/regedit.cpp1324
-rw-r--r--utils/regtools/qeditor/regedit.h282
-rw-r--r--utils/regtools/qeditor/regtab.cpp534
-rw-r--r--utils/regtools/qeditor/regtab.h119
-rw-r--r--utils/regtools/qeditor/std_analysers.cpp9
-rw-r--r--utils/regtools/qeditor/std_analysers.h4
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();