diff --git a/utils/regtools/qeditor/analyser.cpp b/utils/regtools/qeditor/analyser.cpp index 7b60dcffcd..aa422cbc6f 100644 --- a/utils/regtools/qeditor/analyser.cpp +++ b/utils/regtools/qeditor/analyser.cpp @@ -20,7 +20,7 @@ ****************************************************************************/ #include "analyser.h" -Analyser::Analyser(const SocRef& soc, IoBackend *backend) +Analyser::Analyser(const soc_desc::soc_ref_t& soc, IoBackend *backend) :m_soc(soc), m_io_backend(backend) { } diff --git a/utils/regtools/qeditor/analyser.h b/utils/regtools/qeditor/analyser.h index 83b0a9c469..a099399a3b 100644 --- a/utils/regtools/qeditor/analyser.h +++ b/utils/regtools/qeditor/analyser.h @@ -30,13 +30,13 @@ class Analyser : public RegTabPanel { public: - Analyser(const SocRef& soc, IoBackend *backend); + Analyser(const soc_desc::soc_ref_t& soc, IoBackend *backend); virtual ~Analyser(); virtual void AllowWrite(bool en) { Q_UNUSED(en); } virtual QWidget *GetWidget() = 0; protected: - const SocRef& m_soc; + soc_desc::soc_ref_t m_soc; IoBackend *m_io_backend; }; @@ -49,7 +49,7 @@ public: virtual QString GetName() = 0; virtual bool SupportSoc(const QString& soc_name) = 0; // return NULL of soc is not handled by the analyser - virtual Analyser *Create(const SocRef& soc, IoBackend *backend) = 0; + virtual Analyser *Create(const soc_desc::soc_ref_t& soc, IoBackend *backend) = 0; private: QString m_name; @@ -72,9 +72,9 @@ public: virtual QString GetName() { return m_name; } virtual bool SupportSoc(const QString& soc_name) { return T::SupportSoc(soc_name); } // return NULL of soc is not handled by the analyser - virtual T *Create(const SocRef& soc, IoBackend *backend) + virtual T *Create(const soc_desc::soc_ref_t& soc, IoBackend *backend) { - if(!T::SupportSoc(soc.GetSoc().name.c_str())) + if(!T::SupportSoc(QString::fromStdString(soc.get()->name))) return 0; return new T(soc, backend); } diff --git a/utils/regtools/qeditor/backend.cpp b/utils/regtools/qeditor/backend.cpp index cbaff7370d..5f006b0aa7 100644 --- a/utils/regtools/qeditor/backend.cpp +++ b/utils/regtools/qeditor/backend.cpp @@ -28,15 +28,15 @@ * SocFile */ SocFile::SocFile() - :m_valid(false) + :m_valid(true) { } SocFile::SocFile(const QString& filename) :m_filename(filename) { - m_valid = parse_xml(filename.toStdString(), m_soc); - normalize(m_soc); + soc_desc::error_context_t ctx; + m_valid = soc_desc::parse_xml(filename.toStdString(), m_soc, ctx); } bool SocFile::IsValid() @@ -44,9 +44,12 @@ bool SocFile::IsValid() return m_valid; } -SocRef SocFile::GetSocRef() +soc_desc::soc_ref_t SocFile::GetSocRef() { - return SocRef(this); + if(m_valid) + return soc_desc::soc_ref_t(&m_soc); + else + return soc_desc::soc_ref_t(); } QString SocFile::GetFilename() @@ -67,15 +70,22 @@ QList< SocFileRef > Backend::GetSocFileList() { QList< SocFileRef > list; for(std::list< SocFile >::iterator it = m_socs.begin(); it != m_socs.end(); ++it) - list.append(SocFileRef(&(*it))); + { + if(it->IsValid()) + list.append(SocFileRef(&(*it))); + } return list; } -QList< SocRef > Backend::GetSocList() +QList< soc_desc::soc_ref_t > Backend::GetSocList() { - QList< SocRef > list; + QList< soc_desc::soc_ref_t > list; for(std::list< SocFile >::iterator it = m_socs.begin(); it != m_socs.end(); ++it) - list.append(it->GetSocRef()); + { + soc_desc::soc_ref_t r = it->GetSocRef(); + if(r.valid()) + list.append(r); + } return list; } @@ -85,7 +95,7 @@ bool Backend::LoadSocDesc(const QString& filename) if(!f.IsValid()) return false; m_socs.push_back(f); - emit OnSocListChanged(); + emit OnSocAdded(SocFileRef(&m_socs.back())); return true; } @@ -106,6 +116,63 @@ IoBackend *Backend::CreateHWStubIoBackend(HWStubDevice *dev) } #endif +/** + * DummyIoBackend + */ + +DummyIoBackend::DummyIoBackend() +{ +} + +bool DummyIoBackend::IsValid() +{ + return false; +} + +QString DummyIoBackend::GetSocName() +{ + return ""; +} + +bool DummyIoBackend::ReadRegister(soc_addr_t addr, soc_word_t& value, + unsigned width) +{ + Q_UNUSED(addr); + Q_UNUSED(value); + Q_UNUSED(width); + return false; +} + +bool DummyIoBackend::Reload() +{ + return false; +} + +bool DummyIoBackend::IsReadOnly() +{ + return true; +} + +bool DummyIoBackend::WriteRegister(soc_addr_t addr, soc_word_t value, + unsigned width, WriteMode mode) +{ + Q_UNUSED(addr); + Q_UNUSED(value); + Q_UNUSED(mode); + Q_UNUSED(width); + return false; +} + +bool DummyIoBackend::IsDirty() +{ + return false; +} + +bool DummyIoBackend::Commit() +{ + return false; +} + /** * RamIoBackend */ @@ -114,9 +181,36 @@ RamIoBackend::RamIoBackend(const QString& soc_name) m_soc = soc_name; } -bool RamIoBackend::ReadRegister(const QString& name, soc_word_t& value) +bool RamIoBackend::IsValid() { - QMap::const_iterator it = m_map.find(name); + return m_soc != ""; +} + +QString RamIoBackend::GetSocName() +{ + return m_soc; +} + +void RamIoBackend::SetSocName(const QString& soc_name) +{ + m_soc = soc_name; +} + +bool RamIoBackend::RamIoBackend::Reload() +{ + return false; +} + +bool RamIoBackend::IsReadOnly() +{ + return false; +} + +bool RamIoBackend::ReadRegister(soc_addr_t addr, soc_word_t& value, + unsigned width) +{ + Q_UNUSED(width); + QMap::const_iterator it = m_map.find(addr); if(it == m_map.end()) return false; value = it.value(); @@ -128,19 +222,29 @@ void RamIoBackend::DeleteAll() m_map.clear(); } -bool RamIoBackend::WriteRegister(const QString& name, soc_word_t value, WriteMode mode) +bool RamIoBackend::WriteRegister(soc_addr_t addr, soc_word_t value, + unsigned width, WriteMode mode) { + Q_UNUSED(width); switch(mode) { - case Write: m_map[name] = value; return true; - case Set: m_map[name] |= value; return true; - case Clear: m_map[name] &= ~value; return true; - case Toggle: m_map[name] ^= value; return true; + case Write: m_map[addr] = value; return true; + case Set: m_map[addr] |= value; return true; + case Clear: m_map[addr] &= ~value; return true; + case Toggle: m_map[addr] ^= value; return true; default: return false; } } +bool RamIoBackend::IsDirty() +{ + return false; +} +bool RamIoBackend::Commit() +{ + return false; +} /** * FileIoBackend @@ -154,6 +258,10 @@ FileIoBackend::FileIoBackend(const QString& filename, const QString& soc_name) Reload(); } +bool FileIoBackend::IsValid() +{ + return m_valid; +} bool FileIoBackend::Reload() { @@ -170,25 +278,27 @@ bool FileIoBackend::Reload() int idx = line.indexOf('='); if(idx == -1) continue; - QString key = line.left(idx).trimmed(); - bool ok; - soc_word_t val = line.mid(idx + 1).trimmed().toULong(&ok, 0); - if(key == "HW") - m_soc = line.mid(idx + 1).trimmed(); - else if(ok) - RamIoBackend::WriteRegister(key, val, Write); + QString key_str = line.left(idx).trimmed(); + QString val_str = line.mid(idx + 1).trimmed(); + bool key_ok,val_ok; + soc_word_t val = val_str.toULong(&val_ok, 0); + soc_word_t key = key_str.toULong(&key_ok, 0); + if(key_str == "soc") + m_soc = val_str; + else if(key_ok && val_ok) + RamIoBackend::WriteRegister(key, val, 32, Write); } - m_readonly = !QFileInfo(file).isWritable(); m_dirty = false; m_valid = true; return true; } -bool FileIoBackend::WriteRegister(const QString& name, soc_word_t value, WriteMode mode) +bool FileIoBackend::WriteRegister(soc_addr_t addr, soc_word_t value, + unsigned width, WriteMode mode) { m_dirty = true; - return RamIoBackend::WriteRegister(name, value, mode); + return RamIoBackend::WriteRegister(addr, value, width, mode); } bool FileIoBackend::Commit() @@ -199,17 +309,32 @@ bool FileIoBackend::Commit() if(!file.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text)) return false; QTextStream out(&file); - out << "HW = " << m_soc << "\n"; - QMapIterator< QString, soc_word_t > it(m_map); + out << "soc = " << m_soc << "\n"; + QMapIterator< soc_addr_t, soc_word_t > it(m_map); while(it.hasNext()) { it.next(); - out << it.key() << " = " << hex << showbase << it.value() << "\n"; + out << hex << showbase << it.key() << " = " << hex << showbase << it.value() << "\n"; } out.flush(); return file.flush(); } +bool FileIoBackend::IsReadOnly() +{ + return m_readonly; +} + +bool FileIoBackend::IsDirty() +{ + return m_dirty; +} + +QString FileIoBackend::GetFileName() +{ + return m_filename; +} + #ifdef HAVE_HWSTUB /** * HWStubDevice @@ -355,6 +480,8 @@ HWStubIoBackend::HWStubIoBackend(HWStubDevice *dev) else m_soc = QString("pp%1").arg(pp.wChipID, 4, 16, QChar('0')); } + else if(target.dID == HWSTUB_TARGET_ATJ) + m_soc = "atj213x"; else m_soc = target.bName; } @@ -369,13 +496,44 @@ HWStubIoBackend::~HWStubIoBackend() delete m_dev; } -bool HWStubIoBackend::ReadRegister(soc_addr_t addr, soc_word_t& value) +bool HWStubIoBackend::IsValid() { - return m_dev->ReadMem(addr, sizeof(value), &value); + return m_dev->IsValid(); } -bool HWStubIoBackend::WriteRegister(soc_addr_t addr, soc_word_t value, WriteMode mode) +bool HWStubIoBackend::IsReadOnly() { + return false; +} + +bool HWStubIoBackend::IsDirty() +{ + return false; +} + +bool HWStubIoBackend::Commit() +{ + return true; +} + +HWStubDevice *HWStubIoBackend::GetDevice() +{ + return m_dev; +} + +bool HWStubIoBackend::ReadRegister(soc_addr_t addr, soc_word_t& value, + unsigned width) +{ + if(width != 8 && width != 16 && width != 32) + return false; + return m_dev->ReadMem(addr, width / 8, &value); +} + +bool HWStubIoBackend::WriteRegister(soc_addr_t addr, soc_word_t value, + unsigned width, WriteMode mode) +{ + if(width != 8 && width != 16 && width != 32) + return false; switch(mode) { case Set: addr += 4; break; @@ -383,7 +541,7 @@ bool HWStubIoBackend::WriteRegister(soc_addr_t addr, soc_word_t value, WriteMode case Toggle: addr += 12; break; default: break; } - return m_dev->WriteMem(addr, sizeof(value), &value); + return m_dev->WriteMem(addr, width / 8, &value); } bool HWStubIoBackend::Reload() @@ -486,146 +644,146 @@ lib_usb_init __lib_usb_init; * BackendHelper */ -BackendHelper::BackendHelper(IoBackend *io_backend, const SocRef& soc) +BackendHelper::BackendHelper(IoBackend *io_backend, const soc_desc::soc_ref_t& soc) :m_io_backend(io_backend), m_soc(soc) { } -bool BackendHelper::ReadRegister(const QString& dev, const QString& reg, soc_word_t& v) +QString BackendHelper::GetPath(const soc_desc::node_inst_t& inst) { - if(m_io_backend->SupportAccess(IoBackend::ByName)) - return m_io_backend->ReadRegister("HW." + dev + "." + reg, v); - if(m_io_backend->SupportAccess(IoBackend::ByAddress)) - { - soc_addr_t addr; - if(GetRegisterAddress(dev, reg, addr)) - return m_io_backend->ReadRegister(addr, v); - } - return false; + if(!inst.valid() || inst.is_root()) + return QString(); + QString s = GetPath(inst.parent()); + if(!s.isEmpty()) + s += "."; + s += inst.name().c_str(); + if(inst.is_indexed()) + s = QString("%1[%2]").arg(s).arg(inst.index()); + return s; } -bool BackendHelper::WriteRegister(const QString& dev, const QString& reg, +soc_desc::node_inst_t BackendHelper::ParsePath(const QString& path) +{ + soc_desc::node_inst_t inst = m_soc.root_inst(); + /* empty path is root */ + if(path.isEmpty()) + return inst; + int pos = 0; + while(pos < path.size()) + { + /* try to find the next separator */ + int next = path.indexOf('.', pos); + if(next == -1) + next = path.size(); + /* try to find the index, if any */ + int lidx = path.indexOf('[', pos); + if(lidx == -1 || lidx > next) + lidx = next; + /* extract name */ + std::string name = path.mid(pos, lidx - pos).toStdString(); + /* and index */ + if(lidx < next) + { + int ridx = path.indexOf(']', lidx + 1); + /* syntax error ? */ + if(ridx == -1 || ridx > next) + return soc_desc::node_inst_t(); + /* invalid number ? */ + bool ok = false; + size_t idx = path.mid(lidx + 1, ridx - lidx - 1).toUInt(&ok); + if(ok) + inst = inst.child(name, idx); + else + inst = soc_desc::node_inst_t(); + } + else + inst = inst.child(name); + /* advance right after the separator */ + pos = next + 1; + } + return inst; +} + +bool BackendHelper::ReadRegister(const soc_desc::node_inst_t& inst, + soc_word_t& v) +{ + soc_addr_t addr; + if(!GetRegisterAddress(inst, addr)) + return false; + return m_io_backend->ReadRegister(addr, v, inst.node().reg().get()->width); +} + +bool BackendHelper::WriteRegister(const soc_desc::node_inst_t& inst, soc_word_t v, IoBackend::WriteMode mode) { - if(m_io_backend->SupportAccess(IoBackend::ByName)) - return m_io_backend->WriteRegister("HW." + dev + "." + reg, v, mode); - if(m_io_backend->SupportAccess(IoBackend::ByAddress)) - { - soc_addr_t addr; - if(GetRegisterAddress(dev, reg, addr)) - return m_io_backend->WriteRegister(addr, v, mode); - } - return false; + soc_addr_t addr; + if(!GetRegisterAddress(inst, addr)) + return false; + return m_io_backend->WriteRegister(addr, v, inst.node().reg().get()->width, mode); } -bool BackendHelper::GetDevRef(const QString& sdev, SocDevRef& ref) -{ - for(size_t i = 0; i < m_soc.GetSoc().dev.size(); i++) - { - const soc_dev_t& dev = m_soc.GetSoc().dev[i]; - for(size_t j = 0; j < dev.addr.size(); j++) - if(dev.addr[j].name.c_str() == sdev) - { - ref = SocDevRef(m_soc, i, j); - return true; - } - } - return false; -} - -bool BackendHelper::GetRegRef(const SocDevRef& dev, const QString& sreg, SocRegRef& ref) -{ - const soc_dev_t& sdev = dev.GetDev(); - for(size_t i = 0; i < sdev.reg.size(); i++) - { - const soc_reg_t& reg = sdev.reg[i]; - for(size_t j = 0; j < reg.addr.size(); j++) - { - if(reg.addr[j].name.c_str() == sreg) - { - ref = SocRegRef(dev, i, j); - return true; - } - } - } - return false; -} - -bool BackendHelper::GetFieldRef(const SocRegRef& reg, const QString& sfield, SocFieldRef& ref) -{ - for(size_t i = 0; i < reg.GetReg().field.size(); i++) - if(reg.GetReg().field[i].name.c_str() == sfield) - { - ref = SocFieldRef(reg, i); - return true; - } - return false; -} - -bool BackendHelper::GetRegisterAddress(const QString& dev, const QString& reg, +bool BackendHelper::GetRegisterAddress(const soc_desc::node_inst_t& inst, soc_addr_t& addr) { - SocDevRef dev_ref; - SocRegRef reg_ref; - if(!GetDevRef(dev, dev_ref) || !GetRegRef(dev_ref, reg, reg_ref)) + if(!inst.valid()) return false; - addr = dev_ref.GetDevAddr().addr + reg_ref.GetRegAddr().addr; + addr = inst.addr(); return true; } -bool BackendHelper::ReadRegisterField(const QString& dev, const QString& reg, +bool BackendHelper::ReadRegisterField(const soc_desc::node_inst_t& inst, const QString& field, soc_word_t& v) { - SocDevRef dev_ref; - SocRegRef reg_ref; - SocFieldRef field_ref; - if(!GetDevRef(dev, dev_ref) || !GetRegRef(dev_ref, reg, reg_ref) || - !GetFieldRef(reg_ref, field, field_ref)) + soc_desc::field_ref_t ref = inst.node().reg().field(field.toStdString()); + if(!ref.valid()) return false; - if(!ReadRegister(dev, reg, v)) + if(!ReadRegister(inst, v)) return false; - v = (v & field_ref.GetField().bitmask()) >> field_ref.GetField().first_bit; + v = (v & ref.get()->bitmask()) >> ref.get()->pos; return true; } bool BackendHelper::DumpAllRegisters(const QString& filename, bool ignore_errors) { - FileIoBackend b(filename, QString::fromStdString(m_soc.GetSoc().name)); + FileIoBackend b(filename, QString::fromStdString(m_soc.get()->name)); bool ret = DumpAllRegisters(&b, ignore_errors); return ret && b.Commit(); } bool BackendHelper::DumpAllRegisters(IoBackend *backend, bool ignore_errors) { - BackendHelper bh(backend, m_soc); + BackendHelper helper(backend, m_soc); + return DumpAllRegisters(&helper, m_soc.root_inst(), ignore_errors); +} + +bool BackendHelper::DumpAllRegisters(BackendHelper *bh, + const soc_desc::node_inst_t& inst, bool ignore_errors) +{ bool ret = true; - for(size_t i = 0; i < m_soc.GetSoc().dev.size(); i++) + if(inst.node().reg().valid()) { - const soc_dev_t& dev = m_soc.GetSoc().dev[i]; - for(size_t j = 0; j < dev.addr.size(); j++) + soc_word_t val; + if(!ReadRegister(inst, val)) { - QString devname = QString::fromStdString(dev.addr[j].name); - for(size_t k = 0; k < dev.reg.size(); k++) - { - const soc_reg_t& reg = dev.reg[k]; - for(size_t l = 0; l < reg.addr.size(); l++) - { - QString regname = QString::fromStdString(reg.addr[l].name); - soc_word_t val; - if(!ReadRegister(devname, regname, val)) - { - ret = false; - if(!ignore_errors) - return false; - } - else if(!bh.WriteRegister(devname, regname, val)) - { - ret = false; - if(!ignore_errors) - return false; - } - } - } + ret = false; + if(!ignore_errors) + return false; + } + else if(!bh->WriteRegister(inst, val)) + { + ret = false; + if(!ignore_errors) + return false; + } + } + std::vector< soc_desc::node_inst_t > list = inst.children(); + for(size_t i = 0; i < list.size(); i++) + { + if(!DumpAllRegisters(bh, list[i], ignore_errors)) + { + ret = false; + if(!ignore_errors) + return false; } } return ret; diff --git a/utils/regtools/qeditor/backend.h b/utils/regtools/qeditor/backend.h index 934c1c359b..17eeb44533 100644 --- a/utils/regtools/qeditor/backend.h +++ b/utils/regtools/qeditor/backend.h @@ -26,14 +26,17 @@ #include #include #include +#include #ifdef HAVE_HWSTUB #include "hwstub.h" #endif -#include "soc_desc_v1.hpp" +#include "soc_desc.hpp" /* we don't want to import the entire soc_desc except for a few selected * pieces */ -using namespace soc_desc_v1; +using soc_desc::soc_word_t; +using soc_desc::soc_addr_t; +using soc_desc::soc_id_t; class IoBackend : public QObject { @@ -47,35 +50,20 @@ public: Write, Set, Clear, Toggle }; - enum AccessType - { - ByName, - ByAddress, - }; - - /** Register naming convention: name based access are of the form: - * HW.dev.reg - * where is the device name (including index like APPUART1) - * and is the register name (including index like PRIORITY29) */ /* report whether backend is valid */ virtual bool IsValid() = 0; - /* report whether backend supports register access type */ - virtual bool SupportAccess(AccessType type) = 0; /* get SoC name */ virtual QString GetSocName() = 0; - /* read a register by name or address */ - virtual bool ReadRegister(const QString& name, soc_word_t& value) = 0; - virtual bool ReadRegister(soc_addr_t addr, soc_word_t& value) = 0; + /* read a register */ + virtual bool ReadRegister(soc_addr_t addr, soc_word_t& value, unsigned width) = 0; /* reload content (if it makes sense) */ virtual bool Reload() = 0; /* check whether backend supports writing */ virtual bool IsReadOnly() = 0; /* write a register by name or address - * NOTE: even on a read-only backend, a write is allowed be successful as long + * NOTE: even on a read-only backend, a write is allowed to be successful as long * as commit fails */ - virtual bool WriteRegister(const QString& name, soc_word_t value, - WriteMode mode = Write) = 0; - virtual bool WriteRegister(soc_addr_t addr, soc_word_t value, + virtual bool WriteRegister(soc_addr_t addr, soc_word_t value, unsigned width, WriteMode mode = Write) = 0; /* check whether backend contains uncommitted (ie cached) writes */ virtual bool IsDirty() = 0; @@ -87,23 +75,17 @@ class DummyIoBackend : public IoBackend { Q_OBJECT public: - DummyIoBackend() {} + DummyIoBackend(); - virtual bool IsValid() { 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) - { Q_UNUSED(name); Q_UNUSED(value); return false; } - virtual bool ReadRegister(soc_addr_t addr, soc_word_t& value) - { 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) - { Q_UNUSED(name); Q_UNUSED(value); Q_UNUSED(mode); return false; } - virtual bool WriteRegister(soc_addr_t addr, soc_word_t value, WriteMode mode) - { Q_UNUSED(addr); Q_UNUSED(value); Q_UNUSED(mode); return false; } - virtual bool IsDirty() { return false; } - virtual bool Commit() { return false; } + virtual bool IsValid(); + virtual QString GetSocName(); + virtual bool ReadRegister(soc_addr_t addr, soc_word_t& value, unsigned width); + virtual bool Reload(); + virtual bool IsReadOnly(); + virtual bool WriteRegister(soc_addr_t addr, soc_word_t value, unsigned width, + WriteMode mode); + virtual bool IsDirty(); + virtual bool Commit(); }; /** The RAM backend doesn't have any backend storage and stores all values in @@ -114,26 +96,22 @@ class RamIoBackend : public IoBackend public: RamIoBackend(const QString& soc_name = ""); - virtual bool IsValid() { return m_soc != ""; } - virtual bool SupportAccess(AccessType type) { return type == ByName; } - virtual QString GetSocName() { return m_soc; } - virtual void SetSocName(const QString& soc_name) { m_soc = soc_name; } - virtual bool ReadRegister(const QString& name, soc_word_t& value); - virtual bool ReadRegister(soc_addr_t addr, soc_word_t& value) - { Q_UNUSED(addr); Q_UNUSED(value); return false; } - virtual bool Reload() { return false; } - virtual bool IsReadOnly() { return false; } - 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) - { Q_UNUSED(addr); Q_UNUSED(value); Q_UNUSED(mode); return false; } - virtual bool IsDirty() { return false; } - virtual bool Commit() { return false; } + virtual bool IsValid(); + virtual QString GetSocName(); + virtual void SetSocName(const QString& soc_name); + virtual bool ReadRegister(soc_addr_t addr, soc_word_t& value, unsigned width); + virtual bool Reload(); + virtual bool IsReadOnly(); + virtual bool WriteRegister(soc_addr_t addr, soc_word_t value, unsigned width, + WriteMode mode); + virtual bool IsDirty(); + virtual bool Commit(); /* clear all entries of the backend */ virtual void DeleteAll(); protected: QString m_soc; - QMap< QString, soc_word_t > m_map; + QMap< soc_addr_t, soc_word_t > m_map; }; /** NOTE the File backend makes a difference between writes and commits: @@ -144,14 +122,14 @@ class FileIoBackend : public RamIoBackend public: FileIoBackend(const QString& filename, const QString& soc_name = ""); - virtual bool IsValid() { return m_valid; } - virtual bool SupportAccess(AccessType type) { return type == ByName; } + virtual bool IsValid(); virtual bool Reload(); - virtual bool IsReadOnly() { return m_readonly; } - virtual bool WriteRegister(const QString& name, soc_word_t value, WriteMode mode); - virtual bool IsDirty() { return m_dirty; } + virtual bool IsReadOnly(); + virtual bool WriteRegister(soc_addr_t addr, soc_word_t value, unsigned width, + WriteMode mode); + virtual bool IsDirty(); virtual bool Commit(); - QString GetFileName() { return m_filename; } + QString GetFileName(); protected: QString m_filename; @@ -204,20 +182,16 @@ public: HWStubIoBackend(HWStubDevice *dev); virtual ~HWStubIoBackend(); - virtual bool IsValid() { return m_dev->IsValid(); } - virtual bool SupportAccess(AccessType type) { return type == ByAddress; } + virtual bool IsValid(); virtual QString GetSocName(); - virtual bool ReadRegister(const QString& name, soc_word_t& value) - { Q_UNUSED(name); Q_UNUSED(value); return false; } - virtual bool ReadRegister(soc_addr_t addr, soc_word_t& value); + virtual bool ReadRegister(soc_addr_t addr, soc_word_t& value, unsigned width); virtual bool Reload(); - virtual bool IsReadOnly() { return false; } - virtual bool WriteRegister(const QString& name, soc_word_t value, WriteMode mode) - { 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; } - HWStubDevice *GetDevice() { return m_dev; } + virtual bool IsReadOnly(); + virtual bool WriteRegister(soc_addr_t addr, soc_word_t value, unsigned width, + WriteMode mode); + virtual bool IsDirty(); + virtual bool Commit(); + HWStubDevice *GetDevice(); protected: QString m_soc; @@ -251,8 +225,6 @@ protected: }; #endif -class SocRef; - class SocFile { public: @@ -260,14 +232,14 @@ public: SocFile(const QString& filename); bool IsValid(); - SocRef GetSocRef(); + soc_desc::soc_ref_t GetSocRef(); QString GetFilename(); - soc_t& GetSoc() { return m_soc; } + soc_desc::soc_t& GetSoc() { return m_soc; } protected: bool m_valid; QString m_filename; - soc_t m_soc; + soc_desc::soc_t m_soc; }; class SocFileRef @@ -283,56 +255,17 @@ protected: 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(soc_desc::instance_t::type_t) +Q_DECLARE_METATYPE(soc_desc::range_t::type_t) -Q_DECLARE_METATYPE(SocRef) - -class SocDevRef : public SocRef -{ -public: - SocDevRef() {} - 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; } - soc_dev_t& GetDev() const { return GetSoc().dev[GetDevIndex()]; } - int GetDevAddrIndex() const { return m_dev_addr_idx; } - soc_dev_addr_t& GetDevAddr() const { return GetDev().addr[GetDevAddrIndex()]; } -protected: - int m_dev_idx, m_dev_addr_idx; -}; - -class SocRegRef : public SocDevRef -{ -public: - SocRegRef() {} - 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; } - soc_reg_t& GetReg() const { return GetDev().reg[GetRegIndex()]; } - int GetRegAddrIndex() const { return m_reg_addr_idx; } - soc_reg_addr_t& GetRegAddr() const { return GetReg().addr[GetRegAddrIndex()]; } -protected: - int m_reg_idx, m_reg_addr_idx; -}; - -class SocFieldRef : public SocRegRef -{ -public: - SocFieldRef(){} - SocFieldRef(const SocRegRef& reg, int field_idx) - :SocRegRef(reg), m_field_idx(field_idx) {} - int GetFieldIndex() const { return m_field_idx; } - soc_reg_field_t& GetField() const { return GetReg().field[GetFieldIndex()]; } -protected: - int m_field_idx; -}; +Q_DECLARE_METATYPE(soc_desc::soc_ref_t) +Q_DECLARE_METATYPE(soc_desc::node_ref_t) +Q_DECLARE_METATYPE(soc_desc::register_ref_t) +Q_DECLARE_METATYPE(soc_desc::field_ref_t) +Q_DECLARE_METATYPE(soc_desc::node_inst_t) +/** NOTE the Backend stores soc descriptions in a way that pointers are never + * invalidated */ class Backend : public QObject { Q_OBJECT @@ -340,7 +273,7 @@ public: Backend(); QList< SocFileRef > GetSocFileList(); - QList< SocRef > GetSocList(); + QList< soc_desc::soc_ref_t > GetSocList(); bool LoadSocDesc(const QString& filename); IoBackend *CreateDummyIoBackend(); IoBackend *CreateFileIoBackend(const QString& filename); @@ -349,33 +282,38 @@ public: #endif signals: - void OnSocListChanged(); + void OnSocAdded(const SocFileRef& ref); + private: + /* store them as a list so that pointers are never invalidated */ std::list< SocFile > m_socs; }; class BackendHelper { public: - BackendHelper(IoBackend *io_backend, const SocRef& soc); - bool ReadRegister(const QString& dev, const QString& reg, soc_word_t& v); - bool ReadRegisterField(const QString& dev, const QString& reg, + BackendHelper(IoBackend *io_backend, const soc_desc::soc_ref_t& soc); + QString GetPath(const soc_desc::node_inst_t& inst); + soc_desc::node_inst_t ParsePath(const QString& path); + bool ReadRegister(const soc_desc::node_inst_t& inst, soc_word_t& v); + bool ReadRegisterField(const soc_desc::node_inst_t& inst, const QString& field, soc_word_t& v); - bool WriteRegister(const QString& dev, const QString& reg, soc_word_t v, + bool WriteRegister(const soc_desc::node_inst_t& inst, soc_word_t v, IoBackend::WriteMode mode = IoBackend::Write); - bool GetDevRef(const QString& dev, SocDevRef& ref); - bool GetRegRef(const SocDevRef& dev, const QString& reg, SocRegRef& ref); - bool GetFieldRef(const SocRegRef& reg, const QString& field, SocFieldRef& ref); - bool GetRegisterAddress(const QString& dev, const QString& reg, soc_addr_t& addr); + bool GetRegisterAddress(const soc_desc::node_inst_t& inst, soc_addr_t& addr); /* NOTE: does not commit writes to the backend * if ignore_errors is true, the dump will continue even on errors, and the * function will return false if one or more errors occured */ bool DumpAllRegisters(IoBackend *backend, bool ignore_errors = true); bool DumpAllRegisters(const QString& filename, bool ignore_errors = true); +protected: + bool DumpAllRegisters(BackendHelper *bh, const soc_desc::node_inst_t& inst, + bool ignore_errors); + private: IoBackend *m_io_backend; - const SocRef& m_soc; + const soc_desc::soc_ref_t& m_soc; }; #endif /* __BACKEND_H__ */ diff --git a/utils/regtools/qeditor/main.cpp b/utils/regtools/qeditor/main.cpp index d62047e2bb..86a8b96763 100644 --- a/utils/regtools/qeditor/main.cpp +++ b/utils/regtools/qeditor/main.cpp @@ -20,12 +20,22 @@ ****************************************************************************/ #include #include +#include #include "mainwindow.h" int main(int argc, char *argv[]) { QApplication app(argc, argv); app.setApplicationVersion(APP_VERSION); +#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) + /** NOTE: Qt4 only + * use the locale codec as the C-string codec, otherwise QString::toStdString() + * performs as toLatin1() which breaks conversion on virtually all systems. + * FIXME The documentation mentions that the C-string codec should produce ASCII + * compatible (ie 7-bit) encodings but nowadays most system are using UTF-8 + * so I don't see why this is a problem */ + QTextCodec::setCodecForCStrings(QTextCodec::codecForLocale()); +#endif Backend backend;; QDir dir(QCoreApplication::applicationDirPath()); @@ -47,4 +57,4 @@ int main(int argc, char *argv[]) MainWindow win(&backend); win.show(); return app.exec(); -} +} diff --git a/utils/regtools/qeditor/mainwindow.cpp b/utils/regtools/qeditor/mainwindow.cpp index b44306d701..8b83be6bae 100644 --- a/utils/regtools/qeditor/mainwindow.cpp +++ b/utils/regtools/qeditor/mainwindow.cpp @@ -43,7 +43,7 @@ void DocumentTab::OnModified(bool modified) m_tab->SetTabModified(this, modified); } -void DocumentTab::SetTabWidget(MyTabWidget *tab) +void DocumentTab::SetTabWidget(DocumentTabWidget *tab) { m_tab = tab; SetTabName(m_tabname); @@ -57,17 +57,17 @@ void DocumentTab::SetTabName(const QString& name) } /** - * MyTabWidget + * DocumentTabWidget */ -MyTabWidget::MyTabWidget() +DocumentTabWidget::DocumentTabWidget() { setMovable(true); setTabsClosable(true); connect(this, SIGNAL(tabCloseRequested(int)), this, SLOT(OnCloseTab(int))); } -void MyTabWidget::SetTabModified(DocumentTab *doc, bool modified) +void DocumentTabWidget::SetTabModified(DocumentTab *doc, bool modified) { int index = indexOf(doc->GetWidget()); if(modified) @@ -76,12 +76,12 @@ void MyTabWidget::SetTabModified(DocumentTab *doc, bool modified) setTabIcon(index, QIcon()); } -void MyTabWidget::SetTabName(DocumentTab *doc, const QString& name) +void DocumentTabWidget::SetTabName(DocumentTab *doc, const QString& name) { setTabText(indexOf(doc->GetWidget()), name); } -bool MyTabWidget::CloseTab(int index) +bool DocumentTabWidget::CloseTab(int index) { QWidget *w = this->widget(index); DocumentTab *doc = dynamic_cast< DocumentTab* >(w); @@ -95,7 +95,7 @@ bool MyTabWidget::CloseTab(int index) return false; } -void MyTabWidget::OnCloseTab(int index) +void DocumentTabWidget::OnCloseTab(int index) { CloseTab(index); } @@ -135,7 +135,9 @@ MainWindow::MainWindow(Backend *backend) about_menu->addAction(about_act); about_menu->addAction(about_qt_act); - m_tab = new MyTabWidget(); + m_tab = new DocumentTabWidget(); + m_tab->setTabOpenable(true); + m_tab->setTabOpenMenu(new_submenu); setCentralWidget(m_tab); @@ -161,8 +163,8 @@ void MainWindow::OnQuit() void MainWindow::OnAbout() { - QString soc_desc_ver = QString("%1.%2.%3").arg(MAJOR_VERSION) - .arg(MINOR_VERSION).arg(REVISION_VERSION); + QString soc_desc_ver = QString("%1.%2.%3").arg(soc_desc::MAJOR_VERSION) + .arg(soc_desc::MINOR_VERSION).arg(soc_desc::REVISION_VERSION); QMessageBox::about(this, "About", "

QEditor

" "

Version "APP_VERSION"

" @@ -193,7 +195,10 @@ void MainWindow::closeEvent(QCloseEvent *event) void MainWindow::OnLoadDesc() { QFileDialog *fd = new QFileDialog(this); - fd->setFilter("XML files (*.xml);;All files (*)"); + QStringList filters; + filters << "XML files (*.xml)"; + filters << "All files (*)"; + fd->setNameFilters(filters); fd->setFileMode(QFileDialog::ExistingFiles); fd->setDirectory(Settings::Get()->value("loaddescdir", QDir::currentPath()).toString()); if(fd->exec()) diff --git a/utils/regtools/qeditor/mainwindow.h b/utils/regtools/qeditor/mainwindow.h index c5da66758e..5d0bf4ed06 100644 --- a/utils/regtools/qeditor/mainwindow.h +++ b/utils/regtools/qeditor/mainwindow.h @@ -26,8 +26,9 @@ #include #include "backend.h" #include "settings.h" +#include "utils.h" -class MyTabWidget; +class DocumentTabWidget; class DocumentTab { @@ -35,20 +36,20 @@ public: DocumentTab() { m_tab = 0; } virtual bool Quit() = 0; virtual QWidget *GetWidget() = 0; - void SetTabWidget(MyTabWidget *tab); + void SetTabWidget(DocumentTabWidget *tab); protected: void OnModified(bool modified); void SetTabName(const QString& name); - MyTabWidget *m_tab; + DocumentTabWidget *m_tab; QString m_tabname; }; -class MyTabWidget : public QTabWidget +class DocumentTabWidget : public YTabWidget { Q_OBJECT public: - MyTabWidget(); + DocumentTabWidget(); bool CloseTab(int index); void SetTabModified(DocumentTab *tab, bool mod); void SetTabName(DocumentTab *tab, const QString& name); @@ -83,7 +84,7 @@ private slots: void OnNewRegEdit(); private: - MyTabWidget *m_tab; + DocumentTabWidget *m_tab; Backend *m_backend; }; diff --git a/utils/regtools/qeditor/qeditor.pro b/utils/regtools/qeditor/qeditor.pro index 265cc93171..0ec7c3dde1 100644 --- a/utils/regtools/qeditor/qeditor.pro +++ b/utils/regtools/qeditor/qeditor.pro @@ -12,7 +12,7 @@ libsocdesc.commands = cd ../lib && make QMAKE_EXTRA_TARGETS += libsocdesc PRE_TARGETDEPS += libsocdesc -VERSION = 2.1.0 +VERSION = 3.0.0 DEFINES += APP_VERSION=\\\"$$VERSION\\\" diff --git a/utils/regtools/qeditor/regdisplaypanel.cpp b/utils/regtools/qeditor/regdisplaypanel.cpp index 167c776cce..a72d280d6c 100644 --- a/utils/regtools/qeditor/regdisplaypanel.cpp +++ b/utils/regtools/qeditor/regdisplaypanel.cpp @@ -21,36 +21,26 @@ #include "regdisplaypanel.h" #include #include - -/** - * RegItemEditorCreator - */ - -QWidget *RegItemEditorCreator::createWidget(QWidget * parent) const -{ - return new RegLineEdit(parent); -} - -QByteArray RegItemEditorCreator::valuePropertyName () const -{ - return QByteArray("text"); -} +#include /** * SocDisplayPanel */ -SocDisplayPanel::SocDisplayPanel(QWidget *parent, const SocRef& dev_ref) - :QGroupBox(parent), m_soc(dev_ref) +SocDisplayPanel::SocDisplayPanel(QWidget *parent, IoBackend *io_backend, + const soc_desc::soc_ref_t& ref) + :QGroupBox(parent), m_soc(ref) { + Q_UNUSED(io_backend) QVBoxLayout *right_layout = new QVBoxLayout; m_name = new QLabel(this); m_name->setTextFormat(Qt::RichText); - m_name->setText("

" + QString::fromStdString(m_soc.GetSoc().name) + "

"); + m_name->setText("

" + QString::fromStdString(m_soc.get()->name) + "

"); m_desc = new QLabel(this); m_name->setTextFormat(Qt::RichText); - m_desc->setText(QString::fromStdString(m_soc.GetSoc().desc)); + m_desc->setText(QString::fromStdString(m_soc.get()->desc)); + m_desc->setVisible(m_desc->text().size() != 0); right_layout->addWidget(m_name, 0); right_layout->addWidget(m_desc, 0); @@ -71,24 +61,21 @@ QWidget *SocDisplayPanel::GetWidget() } /** - * DevDisplayPanel + * NodeDisplayPanel */ -DevDisplayPanel::DevDisplayPanel(QWidget *parent, const SocDevRef& dev_ref) - :QGroupBox(parent), m_dev(dev_ref), m_reg_font(font()) +NodeDisplayPanel::NodeDisplayPanel(QWidget *parent, IoBackend *io_backend, + const soc_desc::node_inst_t& ref) + :QGroupBox(parent), m_node(ref) { + BackendHelper helper(io_backend, ref.soc()); 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()); + QString dev_name = helper.GetPath(ref); QLabel *label_names = new QLabel("" + dev_name + ""); label_names->setTextFormat(Qt::RichText); - QLabel *label_addr = new QLabel("" + QString().sprintf("0x%03x", dev_addr.addr) + ""); + QLabel *label_addr = new QLabel("" + QString().sprintf("0x%03x", ref.addr()) + ""); label_addr->setTextFormat(Qt::RichText); QHBoxLayout *top_layout = new QHBoxLayout; @@ -99,27 +86,38 @@ DevDisplayPanel::DevDisplayPanel(QWidget *parent, const SocDevRef& dev_ref) m_name = new QLabel(this); m_name->setTextFormat(Qt::RichText); - m_name->setText("

" + QString::fromStdString(m_dev.GetDev().long_name) + "

"); + /* if instance has a title, it overrides node title.*/ + std::string title = ref.get()->title; + if(title.empty()) + title = ref.node().get()->title; + m_name->setText("

" + QString::fromStdString(title) + "

"); - m_desc = new QLabel(this); - m_name->setTextFormat(Qt::RichText); - m_desc->setText(QString::fromStdString(m_dev.GetDev().desc)); + /* put description from the node and from the instance */ + m_node_desc = new QLabel(this); + m_node_desc->setTextFormat(Qt::RichText); + m_node_desc->setText(QString::fromStdString(ref.node().get()->desc)); + m_node_desc->setVisible(m_node_desc->text().size() != 0); + m_inst_desc = new QLabel(this); + m_inst_desc->setTextFormat(Qt::RichText); + m_inst_desc->setText(QString::fromStdString(ref.get()->desc)); + m_inst_desc->setVisible(m_inst_desc->text().size() != 0); right_layout->addWidget(m_name, 0); right_layout->addLayout(top_layout, 0); - right_layout->addWidget(m_desc, 0); + right_layout->addWidget(m_node_desc, 0); + right_layout->addWidget(m_inst_desc, 0); right_layout->addStretch(1); setTitle("Device Description"); setLayout(right_layout); } -void DevDisplayPanel::AllowWrite(bool en) +void NodeDisplayPanel::AllowWrite(bool en) { Q_UNUSED(en); } -QWidget *DevDisplayPanel::GetWidget() +QWidget *NodeDisplayPanel::GetWidget() { return this; } @@ -128,34 +126,29 @@ QWidget *DevDisplayPanel::GetWidget() * 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()) +RegDisplayPanel::RegDisplayPanel(QWidget *parent, IoBackend *io_backend, + const soc_desc::node_inst_t& ref) + :QGroupBox(parent), m_io_backend(io_backend), m_node(ref), m_reg_font(font()) { bool read_only = m_io_backend->IsReadOnly(); + BackendHelper helper(m_io_backend, ref.soc()); 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()); + QString reg_name = helper.GetPath(ref); QStringList names; QVector< soc_addr_t > addresses; names.append(reg_name); - addresses.append(reg_addr.addr); - if(reg.flags & REG_HAS_SCT) + addresses.append(ref.addr()); + + std::vector< soc_desc::variant_ref_t > variants = ref.node().reg().variants(); + for(size_t i = 0; i < variants.size(); i++) { - 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); + names.append(reg_name + "/" + QString::fromStdString(variants[i].get()->type)); + addresses.append(ref.addr() + variants[i].get()->offset); } QString str; @@ -188,7 +181,7 @@ RegDisplayPanel::RegDisplayPanel(QWidget *parent, IoBackend *io_backend, const S 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->EnableSCT(!!(reg.flags & REG_HAS_SCT)); m_raw_val_edit->GetLineEdit()->setFont(m_reg_font); QHBoxLayout *raw_val_layout = new QHBoxLayout; raw_val_layout->addStretch(); @@ -198,9 +191,13 @@ RegDisplayPanel::RegDisplayPanel(QWidget *parent, IoBackend *io_backend, const S m_value_table = new GrowingTableView(); m_value_model = new RegFieldTableModel(m_value_table); // view takes ownership - m_value_model->SetRegister(m_reg.GetReg()); + m_value_model->SetRegister(*m_node.node().reg().get()); m_value_model->SetReadOnly(read_only); - m_value_table->setModel(m_value_model); + RegFieldProxyModel *proxy_model = new RegFieldProxyModel(this); + proxy_model->setSourceModel(m_value_model); + m_value_table->setModel(proxy_model); + m_value_table->setSortingEnabled(true); + m_value_table->sortByColumn(0, Qt::DescendingOrder); m_value_table->verticalHeader()->setVisible(false); m_value_table->resizeColumnsToContents(); m_value_table->horizontalHeader()->setStretchLastSection(true); @@ -217,17 +214,36 @@ RegDisplayPanel::RegDisplayPanel(QWidget *parent, IoBackend *io_backend, const S m_table_delegate->setItemEditorFactory(m_table_edit_factory); m_value_table->setItemDelegate(m_table_delegate); - m_sexy_display2 = new Unscroll(this); + m_sexy_display2 = new Unscroll(this); m_sexy_display2->setFont(m_reg_font); m_sexy_display2->setModel(m_value_model); + m_sexy_display2->setWidth(m_node.node().reg().get()->width); m_sexy_display2->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + m_name = new QLabel(this); + m_name->setTextFormat(Qt::RichText); + m_name->setText("

" + QString::fromStdString(ref.node().get()->title) + "

"); + + /* put description from the node, from the instance and register */ + m_node_desc = new QLabel(this); + m_node_desc->setTextFormat(Qt::RichText); + m_node_desc->setText(QString::fromStdString(ref.node().get()->desc)); + m_node_desc->setVisible(m_node_desc->text().size() != 0); + m_inst_desc = new QLabel(this); + m_inst_desc->setTextFormat(Qt::RichText); + m_inst_desc->setText(QString::fromStdString(ref.get()->desc)); + m_inst_desc->setVisible(m_inst_desc->text().size() != 0); m_desc = new QLabel(this); m_desc->setTextFormat(Qt::RichText); - m_desc->setText(QString::fromStdString(m_reg.GetReg().desc)); + m_desc->setText(QString::fromStdString(m_node.node().reg().get()->desc)); + m_desc->setVisible(m_desc->text().size() != 0); + right_layout->addWidget(m_name); right_layout->addWidget(m_desc); right_layout->addLayout(top_layout); + right_layout->addWidget(m_node_desc); + right_layout->addWidget(m_inst_desc); + right_layout->addWidget(m_desc); if(raw_val_layout) right_layout->addLayout(raw_val_layout); right_layout->addWidget(m_sexy_display2); @@ -252,8 +268,10 @@ RegDisplayPanel::RegDisplayPanel(QWidget *parent, IoBackend *io_backend, const S connect(m_raw_val_edit->GetLineEdit(), SIGNAL(returnPressed()), this, SLOT(OnRawRegValueReturnPressed())); - connect(m_value_table->model(), SIGNAL(OnValueModified(int)), this, + connect(m_value_model, SIGNAL(OnValueModified(int)), this, SLOT(OnRegValueChanged(int))); + connect(m_sexy_display2, SIGNAL(clicked(const QModelIndex&)), this, + SLOT(OnRegFieldActivated(const QModelIndex&))); } RegDisplayPanel::~RegDisplayPanel() @@ -263,12 +281,9 @@ RegDisplayPanel::~RegDisplayPanel() 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); + BackendHelper helper(m_io_backend, m_node.soc()); + bool has_value = helper.ReadRegister(m_node, value); if(has_value) { @@ -296,7 +311,6 @@ void RegDisplayPanel::AllowWrite(bool en) m_raw_val_edit->SetReadOnly(m_io_backend->IsReadOnly() || !m_allow_write); m_value_model->SetReadOnly(m_io_backend->IsReadOnly() || !m_allow_write); } - Reload(); } IoBackend::WriteMode RegDisplayPanel::EditModeToWriteMode(RegLineEdit::EditMode mode) @@ -320,9 +334,8 @@ void RegDisplayPanel::OnRawRegValueReturnPressed() 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); + BackendHelper helper(m_io_backend, m_node.soc()); + helper.WriteRegister(m_node, val, mode); // register write can change all fields Reload(); } @@ -332,13 +345,17 @@ void RegDisplayPanel::OnRegValueChanged(int index) QVariant var = m_value_model->GetValue(index); if(!var.isValid()) return; - BackendHelper helper(m_io_backend, m_reg); - helper.WriteRegister(m_reg.GetDevAddr().name.c_str(), m_reg.GetRegAddr().name.c_str(), - var.value< soc_word_t >(), IoBackend::Write); + BackendHelper helper(m_io_backend, m_node.soc()); + helper.WriteRegister(m_node, var.value< soc_word_t >(), IoBackend::Write); // register write can change all fields Reload(); } +void RegDisplayPanel::OnRegFieldActivated(const QModelIndex& index) +{ + Q_UNUSED(index); +} + QWidget *RegDisplayPanel::GetWidget() { return this; diff --git a/utils/regtools/qeditor/regdisplaypanel.h b/utils/regtools/qeditor/regdisplaypanel.h index 9a692778fe..a34b9319d5 100644 --- a/utils/regtools/qeditor/regdisplaypanel.h +++ b/utils/regtools/qeditor/regdisplaypanel.h @@ -35,19 +35,12 @@ #include "utils.h" #include "regtab.h" -class RegItemEditorCreator : public QItemEditorCreatorBase -{ -public: - RegItemEditorCreator() {} - virtual QWidget *createWidget(QWidget * parent) const; - virtual QByteArray valuePropertyName () const; -}; - class SocDisplayPanel : public QGroupBox, public RegTabPanel { Q_OBJECT public: - SocDisplayPanel(QWidget *parent, const SocRef& reg); + SocDisplayPanel(QWidget *parent, IoBackend *io_backend, + const soc_desc::soc_ref_t& reg); void Reload(); void AllowWrite(bool en); QWidget *GetWidget(); @@ -55,16 +48,17 @@ public: protected: - const SocRef& m_soc; + soc_desc::soc_ref_t m_soc; QLabel *m_name; QLabel *m_desc; }; -class DevDisplayPanel : public QGroupBox, public RegTabPanel +class NodeDisplayPanel : public QGroupBox, public RegTabPanel { Q_OBJECT public: - DevDisplayPanel(QWidget *parent, const SocDevRef& reg); + NodeDisplayPanel(QWidget *parent, IoBackend *io_backend, + const soc_desc::node_inst_t& reg); void Reload(); void AllowWrite(bool en); QWidget *GetWidget(); @@ -72,17 +66,18 @@ public: protected: - const SocDevRef& m_dev; - QFont m_reg_font; + soc_desc::node_inst_t m_node; QLabel *m_name; - QLabel *m_desc; + QLabel *m_node_desc; + QLabel *m_inst_desc; }; class RegDisplayPanel : public QGroupBox, public RegTabPanel { Q_OBJECT public: - RegDisplayPanel(QWidget *parent, IoBackend *io_backend, const SocRegRef& reg); + RegDisplayPanel(QWidget *parent, IoBackend *io_backend, + const soc_desc::node_inst_t& reg); ~RegDisplayPanel(); void AllowWrite(bool en); void Reload(); @@ -102,17 +97,19 @@ protected: }; IoBackend *m_io_backend; - const SocRegRef& m_reg; + soc_desc::node_inst_t m_node; bool m_allow_write; RegLineEdit *m_raw_val_edit; - Unscroll< RegSexyDisplay2 > *m_sexy_display2; + Unscroll< YRegDisplay > *m_sexy_display2; GrowingTableView *m_value_table; RegFieldTableModel *m_value_model; QStyledItemDelegate *m_table_delegate; QItemEditorFactory *m_table_edit_factory; - RegItemEditorCreator *m_regedit_creator; QLabel *m_raw_val_name; QFont m_reg_font; + QLabel *m_name; + QLabel *m_node_desc; + QLabel *m_inst_desc; QLabel *m_desc; QWidget *m_viewport; QScrollArea *m_scroll; @@ -120,6 +117,7 @@ protected: private slots: void OnRawRegValueReturnPressed(); void OnRegValueChanged(int index); + void OnRegFieldActivated(const QModelIndex& index); }; #endif /* REGDISPLAYPANEL_H */ diff --git a/utils/regtools/qeditor/regedit.cpp b/utils/regtools/qeditor/regedit.cpp index 8b4bfb7c49..826452fdbd 100644 --- a/utils/regtools/qeditor/regedit.cpp +++ b/utils/regtools/qeditor/regedit.cpp @@ -24,6 +24,7 @@ #include #include #include +#include /** * EmptyEditPanel @@ -36,743 +37,1270 @@ EmptyEditPanel::EmptyEditPanel(QWidget *parent) /** * SocEditPanel */ -SocEditPanel::SocEditPanel(SocRef ref, QWidget *parent) + +namespace +{ + +template< typename T > +void my_remove_at(std::vector< T >& v, size_t at) +{ + v.erase(v.begin() + at); +} + +enum +{ + SocEditPanelDelType = QTableWidgetItem::UserType, + SocEditPanelAddType, +}; + +} + +SocEditPanel::SocEditPanel(const soc_desc::soc_ref_t& 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); + QLineEdit *name_edit = new QLineEdit(this); + QLineEdit *title_edit = new QLineEdit(this); + QLineEdit *isa_edit = new QLineEdit(this); + QLineEdit *version_edit = new QLineEdit(this); + + m_authors_list = new QTableWidget(this); + QGroupBox *authors_group = Misc::EncloseInBox("Authors", m_authors_list); - 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); + + QGroupBox *desc_group = Misc::EncloseInBox("Description", m_desc_edit); + + QFormLayout *banner_left_layout = new QFormLayout; + banner_left_layout->addRow("Name:", name_edit); + banner_left_layout->addRow("Title:", title_edit); + banner_left_layout->addRow("Instruction Set:", isa_edit); + banner_left_layout->addRow("Version:", version_edit); + + QGroupBox *banner_left_group = new QGroupBox("Information"); + banner_left_group->setLayout(banner_left_layout); + + QHBoxLayout *banner_layout = new QHBoxLayout; + banner_layout->addWidget(banner_left_group); + banner_layout->addWidget(authors_group); + banner_layout->addStretch(0); QVBoxLayout *layout = new QVBoxLayout; - layout->addWidget(m_name_group); - layout->addWidget(m_desc_group); + layout->addLayout(banner_layout); + layout->addWidget(desc_group); layout->addStretch(1); - connect(m_name_edit, SIGNAL(textChanged(const QString&)), this, SLOT(OnNameEdited(const QString&))); + /* fill data */ + name_edit->setText(QString::fromStdString(ref.get()->name)); + title_edit->setText(QString::fromStdString(ref.get()->title)); + isa_edit->setText(QString::fromStdString(ref.get()->isa)); + version_edit->setText(QString::fromStdString(ref.get()->version)); + m_desc_edit->SetTextHtml(QString::fromStdString(ref.get()->desc)); + + m_authors_list->setColumnCount(2); + m_authors_list->setHorizontalHeaderItem(0, new QTableWidgetItem("")); + m_authors_list->setHorizontalHeaderItem(1, new QTableWidgetItem("Name")); + m_authors_list->horizontalHeader()->setVisible(false); + m_authors_list->verticalHeader()->setVisible(false); + m_authors_list->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + std::vector< std::string >& authors = ref.get()->author; + m_authors_list->setRowCount(authors.size() + 1); + for(size_t i = 0; i < authors.size(); i++) + { + QTableWidgetItem *item = new QTableWidgetItem( + QIcon::fromTheme("list-remove"), "", SocEditPanelDelType); + item->setFlags(Qt::ItemIsEnabled); + m_authors_list->setItem(i, 0, item); + item = new QTableWidgetItem(QString::fromStdString(authors[i])); + m_authors_list->setItem(i, 1, item); + } + QTableWidgetItem *new_item = new QTableWidgetItem( + QIcon::fromTheme("list-add"), "", SocEditPanelAddType); + new_item->setFlags(Qt::ItemIsEnabled); + m_authors_list->setItem(authors.size(), 0, new_item); + new_item = new QTableWidgetItem("New author...", QTableWidgetItem::UserType); + new_item->setFlags(Qt::ItemIsEnabled); + QFont font = new_item->font(); + font.setItalic(true); + new_item->setFont(font); + m_authors_list->setItem(authors.size(), 1, new_item); + m_authors_list->resizeColumnsToContents(); + m_authors_list->horizontalHeader()->setStretchLastSection(true); + + connect(name_edit, SIGNAL(textChanged(const QString&)), this, + SLOT(OnNameEdited(const QString&))); connect(m_desc_edit, SIGNAL(OnTextChanged()), this, SLOT(OnTextEdited())); + connect(title_edit, SIGNAL(textChanged(const QString&)), this, + SLOT(OnTitleEdited(const QString&))); + connect(version_edit, SIGNAL(textChanged(const QString&)), this, + SLOT(OnVersionEdited(const QString&))); + connect(isa_edit, SIGNAL(textChanged(const QString&)), this, + SLOT(OnIsaEdited(const QString&))); + connect(m_authors_list, SIGNAL(itemActivated(QTableWidgetItem *)), this, + SLOT(OnAuthorActivated(QTableWidgetItem *))); + connect(m_authors_list, SIGNAL(itemChanged(QTableWidgetItem *)), this, + SLOT(OnAuthorChanged(QTableWidgetItem *))); setLayout(layout); } void SocEditPanel::OnNameEdited(const QString& text) { - m_ref.GetSoc().name = text.toStdString(); - OnModified(m_name_edit->isModified()); + m_ref.get()->name = text.toStdString(); + OnModified(); +} + +void SocEditPanel::OnTitleEdited(const QString& text) +{ + m_ref.get()->title = text.toStdString(); + OnModified(); +} + +void SocEditPanel::OnVersionEdited(const QString& text) +{ + m_ref.get()->version = text.toStdString(); + OnModified(); +} + +void SocEditPanel::OnIsaEdited(const QString& text) +{ + m_ref.get()->isa = text.toStdString(); + OnModified(); } void SocEditPanel::OnTextEdited() { - m_ref.GetSoc().desc = m_desc_edit->GetTextHtml().toStdString(); - OnModified(m_desc_edit->IsModified()); + m_ref.get()->desc = m_desc_edit->GetTextHtml().toStdString(); + OnModified(); +} + +void SocEditPanel::OnAuthorActivated(QTableWidgetItem *item) +{ + if(item->type() == SocEditPanelDelType) + { + int row = item->row(); + my_remove_at(m_ref.get()->author, row); + m_authors_list->removeRow(row); + OnModified(); + } + else if(item->type() == SocEditPanelAddType) + { + int row = m_ref.get()->author.size(); + m_ref.get()->author.push_back("Anonymous"); + m_authors_list->insertRow(row); + QTableWidgetItem *item = new QTableWidgetItem( + QIcon::fromTheme("list-remove"), "", SocEditPanelDelType); + item->setFlags(Qt::ItemIsEnabled); + m_authors_list->setItem(row, 0, item); + item = new QTableWidgetItem(QString::fromStdString(m_ref.get()->author.back())); + m_authors_list->setItem(row, 1, item); + OnModified(); + } +} + +void SocEditPanel::OnAuthorChanged(QTableWidgetItem *item) +{ + if((size_t)item->row() >= m_ref.get()->author.size()) + return; + if(item->column() == 1) + m_ref.get()->author[item->row()] = item->text().toStdString(); + OnModified(); } /** - * DevEditPanel + * NodeInstanceEditPanel */ -DevEditPanel::DevEditPanel(SocDevRef ref, QWidget *parent) + +namespace +{ + +template< typename T > +soc_id_t GetFreshId(const std::vector< T >& list) +{ + soc_id_t id = 0; + for(size_t i = 0; i < list.size(); i++) + id = std::max(id, list[i].id); + return id + 1; +} + +template< typename T > +int GetIndexById(const std::vector< T >& list, soc_id_t id) +{ + for(size_t i = 0; i < list.size(); i++) + if(list[i].id == id) + return i; + return -1; +} + +soc_desc::instance_t *GetInstanceById(const soc_desc::node_ref_t& node, soc_id_t id) +{ + std::vector< soc_desc::instance_t >& inst_list = node.get()->instance; + for(size_t i = 0; i < inst_list.size(); i++) + if(inst_list[i].id == id) + return &inst_list[i]; + return 0; +} + +bool RemoveInstanceById(const soc_desc::node_ref_t& node, soc_id_t id) +{ + std::vector< soc_desc::instance_t >& inst_list = node.get()->instance; + for(size_t i = 0; i < inst_list.size(); i++) + if(inst_list[i].id == id) + { + my_remove_at(inst_list, i); + return true; + } + return false; +} + +enum +{ + InstTypeSingle, + InstTypeRangeStride, + InstTypeRangeFormula, + InstTypeRangeList +}; + +enum +{ + NodeInstEditPanelDelType = QTableWidgetItem::UserType, + NodeInstEditPanelAddType +}; + +} + +NodeInstanceEditPanel::NodeInstanceEditPanel(const soc_desc::node_ref_t& ref, + soc_id_t inst_id, QWidget *parent) + :QWidget(parent), m_ref(ref), m_id(inst_id) +{ + QLineEdit *name_edit = new QLineEdit(this); + QLineEdit *title_edit = new QLineEdit(this); + m_type_combo = new QComboBox(this); + QLabel *type_label = new QLabel("Type:", this); + QFont f = type_label->font(); + f.setBold(true); + type_label->setFont(f); + + QHBoxLayout *type_layout = new QHBoxLayout; + type_layout->addWidget(type_label); + type_layout->addWidget(m_type_combo); + type_layout->addStretch(0); + + soc_desc::field_t fake_field; + fake_field.pos = 0; + fake_field.width = 32; + + m_single_group = new QWidget(this); + QHBoxLayout *sg_layout = new QHBoxLayout; + sg_layout->addWidget(new QLabel("Address:", m_single_group)); + SocFieldEditor *addr_edit = new SocFieldEditor(fake_field, m_single_group); + sg_layout->addWidget(addr_edit); + m_single_group->setLayout(sg_layout); + + m_range_group = new QWidget(this); + QGridLayout *rg_layout = new QGridLayout; + rg_layout->addWidget(new QLabel("First:", m_range_group), 0, 0); + QSpinBox *first_spin = new QSpinBox(m_range_group); + rg_layout->addWidget(first_spin, 0, 1); + rg_layout->addWidget(new QLabel("Count:", m_range_group), 1, 0); + QSpinBox *count_spin = new QSpinBox(m_range_group); + rg_layout->addWidget(count_spin, 1, 1); + m_range_group->setLayout(rg_layout); + + m_stride_group = new QWidget(m_range_group); + QGridLayout *rsg_layout = new QGridLayout; + rsg_layout->addWidget(new QLabel("Base:", m_stride_group), 0, 0); + SocFieldEditor *base_edit = new SocFieldEditor(fake_field, m_stride_group); + rsg_layout->addWidget(base_edit, 0, 1); + rsg_layout->addWidget(new QLabel("Stride:", m_stride_group), 1, 0); + SocFieldEditor *stride_edit = new SocFieldEditor(fake_field, m_stride_group); + rsg_layout->addWidget(stride_edit, 1, 1); + m_stride_group->setLayout(rsg_layout); + + m_formula_group = new QWidget(m_range_group); + QGridLayout *fsg_layout = new QGridLayout; + fsg_layout->addWidget(new QLabel("Variable:", m_formula_group), 0, 0); + QLineEdit *variable_edit = new QLineEdit(m_formula_group); + fsg_layout->addWidget(variable_edit, 0, 1); + fsg_layout->addWidget(new QLabel("Formula:", m_formula_group), 1, 0); + QLineEdit *formula_edit = new QLineEdit(m_formula_group); + fsg_layout->addWidget(formula_edit, 1, 1); + m_formula_group->setLayout(fsg_layout); + + QTableWidget *addr_list = new QTableWidget(m_range_group); + m_list_group = addr_list; + + QHBoxLayout *inst_layout = new QHBoxLayout; + inst_layout->addWidget(m_single_group); + inst_layout->addWidget(m_range_group); + inst_layout->addWidget(m_stride_group); + inst_layout->addWidget(m_formula_group); + inst_layout->addWidget(m_list_group); + inst_layout->addStretch(0); + + QGroupBox *inst_groupbox = new QGroupBox(this); + inst_groupbox->setLayout(inst_layout); + + MyTextEditor *desc_edit = new MyTextEditor(this); + QVBoxLayout *ii_layout = new QVBoxLayout; + + QFormLayout *info_layout = new QFormLayout(); + info_layout->addRow("Name", name_edit); + info_layout->addRow("Title", title_edit); + + QGroupBox *info_group = Misc::EncloseInBox("Information", info_layout); + QGroupBox *desc_group = Misc::EncloseInBox("Description", desc_edit); + QHBoxLayout *name_title_desc_layout = new QHBoxLayout; + name_title_desc_layout->addWidget(info_group, 1); + name_title_desc_layout->addWidget(desc_group, 2); + + ii_layout->addLayout(name_title_desc_layout); + ii_layout->addLayout(type_layout); + ii_layout->addWidget(inst_groupbox); + ii_layout->addStretch(1); + + m_type_combo->addItem("Single", QVariant(InstTypeSingle)); + m_type_combo->addItem("Range > Stride", QVariant(InstTypeRangeStride)); + m_type_combo->addItem("Range > Formula", QVariant(InstTypeRangeFormula)); + m_type_combo->addItem("Range > List", QVariant(InstTypeRangeList)); + + /* fill info */ + soc_desc::instance_t& inst = GetInstance(); + name_edit->setText(QString::fromStdString(inst.name)); + title_edit->setText(QString::fromStdString(inst.title)); + desc_edit->SetTextHtml(QString::fromStdString(inst.desc)); + addr_edit->setField(inst.addr); + base_edit->setField(inst.range.base); + stride_edit->setField(inst.range.stride); + first_spin->setValue(inst.range.first); + count_spin->setValue(inst.range.count); + formula_edit->setText(QString::fromStdString(inst.range.formula)); + variable_edit->setText(QString::fromStdString(inst.range.variable)); + addr_list->setColumnCount(2); + addr_list->setHorizontalHeaderItem(0, new QTableWidgetItem("")); + addr_list->setHorizontalHeaderItem(1, new QTableWidgetItem("Address")); + addr_list->horizontalHeader()->setVisible(false); + addr_list->verticalHeader()->setVisible(false); + addr_list->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + std::vector< soc_word_t >& addrs = inst.range.list; + addr_list->setRowCount(addrs.size() + 1); + for(size_t i = 0; i < addrs.size(); i++) + { + QTableWidgetItem *item = new QTableWidgetItem( + QIcon::fromTheme("list-remove"), "", NodeInstEditPanelDelType); + item->setFlags(Qt::ItemIsEnabled); + addr_list->setItem(i, 0, item); + item = new QTableWidgetItem(); + item->setData(Qt::EditRole, QVariant::fromValue(addrs[i])); + addr_list->setItem(i, 1, item); + } + QTableWidgetItem *new_item = new QTableWidgetItem( + QIcon::fromTheme("list-add"), "", NodeInstEditPanelAddType); + new_item->setFlags(Qt::ItemIsEnabled); + addr_list->setItem(addrs.size(), 0, new_item); + new_item = new QTableWidgetItem("New address...", QTableWidgetItem::UserType); + new_item->setFlags(Qt::ItemIsEnabled); + QFont font = new_item->font(); + font.setItalic(true); + new_item->setFont(font); + addr_list->setItem(addrs.size(), 1, new_item); + addr_list->resizeColumnsToContents(); + addr_list->horizontalHeader()->setStretchLastSection(true); + m_table_delegate = new SocFieldItemDelegate(this); + m_table_delegate->setItemEditorFactory(new QItemEditorFactory); + m_table_edit_factory = new SocFieldEditorCreator; + m_table_delegate->itemEditorFactory()->registerEditor(QVariant::UInt, m_table_edit_factory); + addr_list->setItemDelegate(m_table_delegate); + + setLayout(ii_layout); + + connect(name_edit, SIGNAL(textChanged(const QString&)), this, + SLOT(OnNameEdited(const QString&))); + connect(desc_edit, SIGNAL(OnTextChanged(const QString&)), this, + SLOT(OnDescEdited(const QString&))); + connect(title_edit, SIGNAL(textChanged(const QString&)), this, + SLOT(OnTitleEdited(const QString&))); + connect(addr_edit, SIGNAL(editingFinished(uint)), this, SLOT(OnAddrChanged(uint))); + connect(base_edit, SIGNAL(editingFinished(uint)), this, SLOT(OnBaseChanged(uint))); + connect(stride_edit, SIGNAL(editingFinished(uint)), this, SLOT(OnStrideChanged(uint))); + connect(first_spin, SIGNAL(valueChanged(int)), this, SLOT(OnFirstChanged(int))); + connect(count_spin, SIGNAL(valueChanged(int)), this, SLOT(OnCountChanged(int))); + connect(formula_edit, SIGNAL(textChanged(const QString&)), this, + SLOT(OnFormulaChanged(const QString&))); + connect(variable_edit, SIGNAL(textChanged(const QString&)), this, + SLOT(OnVariableChanged(const QString&))); + connect(m_type_combo, SIGNAL(currentIndexChanged(int)), + this, SLOT(OnTypeChanged(int))); + connect(addr_list, SIGNAL(itemActivated(QTableWidgetItem *)), this, + SLOT(OnAddressActivated(QTableWidgetItem *))); + connect(addr_list, SIGNAL(itemChanged(QTableWidgetItem *)), this, + SLOT(OnAddressChanged(QTableWidgetItem *))); + + /* fill info */ + int combo_type; + if(inst.type == soc_desc::instance_t::RANGE) + { + if(inst.range.type == soc_desc::range_t::STRIDE) + combo_type = InstTypeRangeStride; + else if(inst.range.type == soc_desc::range_t::FORMULA) + combo_type = InstTypeRangeFormula; + else /* LIST */ + combo_type = InstTypeRangeList; + } + else + combo_type = InstTypeSingle; + m_type_combo->setCurrentIndex(m_type_combo->findData(QVariant(combo_type))); + UpdateType(combo_type); +} + +soc_desc::instance_t& NodeInstanceEditPanel::GetInstance() +{ + return *GetInstanceById(m_ref, m_id); +} + +void NodeInstanceEditPanel::OnNameEdited(const QString& text) +{ + GetInstance().name = text.toStdString(); + OnModified(); +} + +void NodeInstanceEditPanel::OnTitleEdited(const QString& text) +{ + GetInstance().title = text.toStdString(); + OnModified(); +} + +void NodeInstanceEditPanel::OnDescEdited(const QString& text) +{ + GetInstance().desc = text.toStdString(); + OnModified(); +} + +void NodeInstanceEditPanel::OnAddrChanged(uint addr) +{ + GetInstance().addr = addr; + OnModified(); +} + +void NodeInstanceEditPanel::OnBaseChanged(uint base) +{ + GetInstance().range.base = base; + OnModified(); +} + +void NodeInstanceEditPanel::OnStrideChanged(uint stride) +{ + GetInstance().range.stride = stride; + OnModified(); +} + +void NodeInstanceEditPanel::OnFirstChanged(int first) +{ + GetInstance().range.first = first; + OnModified(); +} + +void NodeInstanceEditPanel::OnCountChanged(int count) +{ + GetInstance().range.count = count; + OnModified(); +} + +void NodeInstanceEditPanel::OnFormulaChanged(const QString& formula) +{ + GetInstance().range.formula = formula.toStdString(); + OnModified(); +} + +void NodeInstanceEditPanel::OnVariableChanged(const QString& variable) +{ + GetInstance().range.variable = variable.toStdString(); + OnModified(); +} + +void NodeInstanceEditPanel::OnAddressActivated(QTableWidgetItem *item) +{ + QTableWidget *table = item->tableWidget(); + soc_desc::instance_t& inst = GetInstance(); + if(item->type() == NodeInstEditPanelDelType) + { + int row = item->row(); + my_remove_at(inst.range.list, row); + table->removeRow(row); + OnModified(); + } + else if(item->type() == NodeInstEditPanelAddType) + { + int row = inst.range.list.size(); + soc_word_t new_addr = 0; + GetInstance().range.list.push_back(new_addr); + table->insertRow(row); + QTableWidgetItem *item = new QTableWidgetItem( + QIcon::fromTheme("list-remove"), "", NodeInstEditPanelDelType); + item->setFlags(Qt::ItemIsEnabled); + table->setItem(row, 0, item); + item = new QTableWidgetItem(); + item->setData(Qt::EditRole, QVariant(new_addr)); + table->setItem(row, 1, item); + OnModified(); + } +} + +void NodeInstanceEditPanel::OnAddressChanged(QTableWidgetItem *item) +{ + soc_desc::instance_t& inst = GetInstance(); + if((size_t)item->row() >= inst.range.list.size()) + return; + soc_word_t& addr = inst.range.list[item->row()]; + if(item->column() == 1) + addr = item->data(Qt::EditRole).value< soc_word_t >(); + OnModified(); +} + +void NodeInstanceEditPanel::UpdateType(int type) +{ + m_single_group->hide(); + m_range_group->hide(); + m_stride_group->hide(); + m_formula_group->hide(); + m_list_group->hide(); + + switch(type) + { + case InstTypeSingle: + m_single_group->show(); + GetInstance().type = soc_desc::instance_t::SINGLE; + break; + case InstTypeRangeStride: + m_range_group->show(); + m_stride_group->show(); + GetInstance().type = soc_desc::instance_t::RANGE; + GetInstance().range.type = soc_desc::range_t::STRIDE; + break; + case InstTypeRangeFormula: + m_range_group->show(); + m_formula_group->show(); + GetInstance().type = soc_desc::instance_t::RANGE; + GetInstance().range.type = soc_desc::range_t::FORMULA; + break; + case InstTypeRangeList: + m_range_group->show(); + m_formula_group->hide(); + m_list_group->show(); + GetInstance().type = soc_desc::instance_t::RANGE; + GetInstance().range.type = soc_desc::range_t::LIST; + break; + default: + break; + } +} + +void NodeInstanceEditPanel::OnTypeChanged(int index) +{ + if(index == -1) + return; + UpdateType(m_type_combo->itemData(index).toInt()); + OnModified(); +} + +soc_id_t NodeInstanceEditPanel::GetId() +{ + return m_id; +} + +/** + * NodeEditPanel + */ + +NodeEditPanel::NodeEditPanel(const soc_desc::node_ref_t& 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); + /* top layout: name, title then desc */ + QLineEdit *name_edit = new QLineEdit(this); + name_edit->setText(QString::fromStdString(ref.get()->name)); - 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); + QLineEdit *title_edit = new QLineEdit(this); + title_edit->setText(QString::fromStdString(ref.get()->title)); - 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); + QFormLayout *info_layout = new QFormLayout(); + info_layout->addRow("Name", name_edit); + info_layout->addRow("Title", title_edit); - 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(); + QGroupBox *info_group = Misc::EncloseInBox("Information", info_layout); - 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); + m_desc_edit->SetTextHtml(QString::fromStdString(ref.get()->desc)); + QGroupBox *desc_group = Misc::EncloseInBox("Description", m_desc_edit); + QHBoxLayout *name_title_desc_layout = new QHBoxLayout; + name_title_desc_layout->addWidget(info_group, 1); + name_title_desc_layout->addWidget(desc_group, 2); + + /* instance tab */ + m_instances_tab = new YTabWidget(0, this); + m_instances_tab->setTabOpenable(true); + std::vector< soc_desc::instance_t >& inst_list = m_ref.get()->instance; + m_instances_tab->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Expanding); + m_instances_tab->setTabsClosable(true); + QGroupBox *instance_tab_group = Misc::EncloseInBox("Instances", m_instances_tab); + for(size_t i = 0; i < inst_list.size(); i++) + { + NodeInstanceEditPanel *p = new NodeInstanceEditPanel(m_ref, inst_list[i].id, this); + connect(p, SIGNAL(OnModified()), this, SLOT(OnInstModified())); + m_instances_tab->addTab(p, QString::fromStdString(inst_list[i].name)); + } + + /* boring */ QVBoxLayout *layout = new QVBoxLayout; - layout->addLayout(top_layout, 0); - layout->addWidget(m_desc_group, 1); + layout->addLayout(name_title_desc_layout); + layout->addWidget(instance_tab_group); + layout->addStretch(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(name_edit, SIGNAL(textChanged(const QString&)), this, + SLOT(OnNameEdited(const QString&))); connect(m_desc_edit, SIGNAL(OnTextChanged()), this, SLOT(OnDescEdited())); + connect(title_edit, SIGNAL(textChanged(const QString&)), this, + SLOT(OnTitleEdited(const QString&))); + connect(m_instances_tab, SIGNAL(tabCloseRequested(int)), this, + SLOT(OnInstRemove(int))); + connect(m_instances_tab, SIGNAL(tabOpenRequested()), this, SLOT(OnInstCreate())); } -void DevEditPanel::OnNameEdited(const QString& text) +void NodeEditPanel::OnNameEdited(const QString& text) { - m_ref.GetDev().name = text.toStdString(); - OnModified(m_name_edit->isModified()); + m_ref.get()->name = text.toStdString(); + OnModified(); } -void DevEditPanel::OnLongNameEdited(const QString& text) +void NodeEditPanel::OnTitleEdited(const QString& text) { - m_ref.GetDev().long_name = text.toStdString(); - OnModified(m_long_name_edit->isModified()); + m_ref.get()->title = text.toStdString(); + OnModified(); } -void DevEditPanel::OnVersionEdited(const QString& text) +void NodeEditPanel::OnDescEdited() { - m_ref.GetDev().version = text.toStdString(); - OnModified(m_version_edit->isModified()); + m_ref.get()->desc = m_desc_edit->GetTextHtml().toStdString(); + OnModified(); } -void DevEditPanel::OnDescEdited() +void NodeEditPanel::OnInstRemove(int index) { - m_ref.GetDev().desc = m_desc_edit->GetTextHtml().toStdString(); - OnModified(m_desc_edit->IsModified()); + NodeInstanceEditPanel *panel = + dynamic_cast< NodeInstanceEditPanel * >(m_instances_tab->widget(index)); + RemoveInstanceById(m_ref, panel->GetId()); + m_instances_tab->removeTab(index); + delete panel; + OnModified(); } -void DevEditPanel::CreateNewRow(int row) +void NodeEditPanel::OnInstModified() { - 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(); + int index = m_instances_tab->currentIndex(); + NodeInstanceEditPanel *panel = + dynamic_cast< NodeInstanceEditPanel * >(m_instances_tab->widget(index)); + m_instances_tab->setTabText(index, QString::fromStdString(panel->GetInstance().name)); + OnModified(); +} + +QString NodeEditPanel::GuessName() +{ + /* try to find instances named Xddd where X is the node name (case insensitive) + * and d are digits. */ + int max_nr_digits = -1; + int max_value = -1; + QString node_name = QString::fromStdString(m_ref.get()->name); + std::vector< soc_desc::instance_t >& inst_list = m_ref.get()->instance; + for(size_t i = 0; i < inst_list.size(); i++) + { + QString inst_name = QString::fromStdString(inst_list[i].name); + /* ignore name if it doesn't start like the node name */ + if(!inst_name.startsWith(node_name, Qt::CaseInsensitive)) + continue; + /* check if the suffix is a digit */ + QString suffix = inst_name.mid(node_name.size()); + if(suffix.size() == 0) + { + max_nr_digits = qMax(max_nr_digits, 0); + continue; + } + bool ok; + int value = suffix.toUInt(&ok); + if(!ok) + continue; + max_value = qMax(max_value, value); + max_nr_digits = qMax(max_nr_digits, suffix.size()); + } + /* if no match, use node name */ + if(max_nr_digits == -1) + return node_name; + /* match of size 0, add "1" at the end */ + if(max_nr_digits == 0) + return node_name + "1"; + /* otherwise, pick next value */ + return QString("%1%2").arg(node_name) + .arg(max_value + 1, max_nr_digits, 10, QChar('0')); +} + +void NodeEditPanel::OnInstCreate() +{ + std::vector< soc_desc::instance_t >& inst_list = m_ref.get()->instance; + soc_desc::instance_t inst; + inst.id = GetFreshId(inst_list); + inst.name = GuessName().toStdString(); + inst.type = soc_desc::instance_t::SINGLE; + inst.addr = 0; + inst.range.type = soc_desc::range_t::STRIDE; + inst.range.first = 0; + inst.range.count = 0; + inst.range.stride = 0; + inst_list.push_back(inst); + NodeInstanceEditPanel *p = new NodeInstanceEditPanel(m_ref, inst.id, this); + connect(p, SIGNAL(OnModified()), this, SLOT(OnInstModified())); + int idx = m_instances_tab->addTab(p, QString::fromStdString(inst.name)); + m_instances_tab->setCurrentIndex(idx); + OnModified(); +} + +/** + * RegFieldEditPanel + */ + +namespace +{ + +enum +{ + RegFieldEditPanelDelType = QTableWidgetItem::UserType, + RegFieldEditPanelAddType, +}; + +} + +RegFieldEditPanel::RegFieldEditPanel(const soc_desc::field_ref_t& ref, QWidget *parent) + :QWidget(parent), m_ref(ref) +{ + m_name_edit = new QLineEdit(this); + m_range_edit = new QLineEdit(this); + m_range_validator = new SocBitRangeValidator(this); + m_range_validator->setWidth(m_ref.reg().get()->width); + m_range_edit->setValidator(m_range_validator); + m_desc_edit = new MyTextEditor(this); + QHBoxLayout *namepos_layout = new QHBoxLayout; + namepos_layout->addWidget(new QLabel("Name:")); + namepos_layout->addWidget(m_name_edit); + namepos_layout->addWidget(new QLabel("Range:")); + namepos_layout->addWidget(m_range_edit); + QVBoxLayout *nameposdesc_layout = new QVBoxLayout; + nameposdesc_layout->addWidget(Misc::EncloseInBox("Information", namepos_layout)); + nameposdesc_layout->addWidget(Misc::EncloseInBox("Description", m_desc_edit)); + nameposdesc_layout->addStretch(0); + + m_enum_table = new QTableWidget(this); + m_enum_table->setColumnCount(4); + m_enum_table->setHorizontalHeaderItem(0, new QTableWidgetItem("")); + m_enum_table->setHorizontalHeaderItem(1, new QTableWidgetItem("Name")); + m_enum_table->setHorizontalHeaderItem(2, new QTableWidgetItem("Value")); + m_enum_table->setHorizontalHeaderItem(3, new QTableWidgetItem("Description")); + m_enum_table->verticalHeader()->setVisible(false); + m_enum_table->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + m_enum_delegate = new SocFieldItemDelegate(this); + m_enum_delegate->setItemEditorFactory(new QItemEditorFactory); + m_enum_editor = new SocFieldEditorCreator; + m_enum_delegate->itemEditorFactory()->registerEditor(QVariant::UInt, m_enum_editor); + m_enum_table->setItemDelegate(m_enum_delegate); + + QHBoxLayout *field_layout = new QHBoxLayout; + field_layout->addLayout(nameposdesc_layout); + field_layout->addWidget(Misc::EncloseInBox("Special Values", m_enum_table), 1); + + setLayout(field_layout); + + const soc_desc::field_t& field = *m_ref.get(); + m_name_edit->setText(QString::fromStdString(field.name)); + m_range_edit->setText(m_range_validator->generate( + field.pos + field.width - 1, field.pos)); + m_desc_edit->SetTextHtml(QString::fromStdString(field.desc)); + m_enum_delegate->setWidth(field.width); + m_enum_editor->setWidth(field.width); + m_enum_table->setRowCount(field.enum_.size() + 1); + for(size_t i = 0; i < field.enum_.size(); i++) + { + QTableWidgetItem *item = new QTableWidgetItem( + QIcon::fromTheme("list-remove"), "", RegFieldEditPanelDelType); + item->setFlags(Qt::ItemIsEnabled); + m_enum_table->setItem(i, 0, item); + item = new QTableWidgetItem(QString::fromStdString(field.enum_[i].name)); + m_enum_table->setItem(i, 1, item); + item = new QTableWidgetItem(); + item->setData(Qt::EditRole, QVariant(field.enum_[i].value)); + m_enum_table->setItem(i, 2, item); + item = new QTableWidgetItem(QString::fromStdString(field.enum_[i].desc)); + m_enum_table->setItem(i, 3, item); + } + QTableWidgetItem *new_item = new QTableWidgetItem( + QIcon::fromTheme("list-add"), "", RegFieldEditPanelAddType); + new_item->setFlags(Qt::ItemIsEnabled); + m_enum_table->setItem(field.enum_.size(), 0, new_item); + new_item = new QTableWidgetItem("New field..."); + new_item->setFlags(Qt::ItemIsEnabled); + QFont font = new_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); + new_item->setFont(font); + m_enum_table->setItem(field.enum_.size(), 1, new_item); + new_item = new QTableWidgetItem(); + new_item->setFlags(Qt::ItemIsEnabled); + m_enum_table->setItem(field.enum_.size(), 2, new_item); + new_item = new QTableWidgetItem(); + new_item->setFlags(Qt::ItemIsEnabled); + m_enum_table->setItem(field.enum_.size(), 3, new_item); + m_enum_table->resizeColumnsToContents(); + m_enum_table->horizontalHeader()->setStretchLastSection(true); + + connect(m_name_edit, SIGNAL(textChanged(const QString&)), this, + SLOT(OnFieldNameChanged(const QString&))); + connect(m_range_edit, SIGNAL(textChanged(const QString&)), this, + SLOT(OnFieldRangeChanged(const QString&))); + connect(m_desc_edit, SIGNAL(OnTextChanged(const QString&)), this, + SLOT(OnFieldDescChanged(const QString&))); + connect(m_enum_table, SIGNAL(itemActivated(QTableWidgetItem *)), this, + SLOT(OnFieldValueActivated(QTableWidgetItem *))); + connect(m_enum_table, SIGNAL(itemChanged(QTableWidgetItem *)), this, + SLOT(OnFieldValueChanged(QTableWidgetItem *))); } -void DevEditPanel::FillRow(int row, const soc_dev_addr_t& addr) +void RegFieldEditPanel::UpdateWidth() { - 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); + m_range_validator->setWidth(m_ref.reg().get()->width); } -void DevEditPanel::OnInstActivated(int row, int column) +void RegFieldEditPanel::OnFieldValueActivated(QTableWidgetItem *item) { - if(column != 0) + if(item->type() == RegFieldEditPanelDelType) + { + int row = item->row(); + my_remove_at(m_ref.get()->enum_, row); + m_enum_table->removeRow(row); + OnModified(); + } + else if(item->type() == RegFieldEditPanelAddType) + { + soc_desc::field_t& field = *m_ref.get(); + int row = field.enum_.size(); + soc_desc::enum_t new_enum; + new_enum.id = GetFreshId(field.enum_); + new_enum.name = "UNNAMED"; + new_enum.value = 0; + field.enum_.push_back(new_enum); + m_enum_table->insertRow(row); + QTableWidgetItem *item = new QTableWidgetItem( + QIcon::fromTheme("list-remove"), "", RegFieldEditPanelDelType); + item->setFlags(Qt::ItemIsEnabled); + m_enum_table->setItem(row, 0, item); + item = new QTableWidgetItem(QString::fromStdString(new_enum.name)); + m_enum_table->setItem(row, 1, item); + item = new QTableWidgetItem(); + item->setData(Qt::EditRole, QVariant(new_enum.value)); + m_enum_table->setItem(row, 2, item); + item = new QTableWidgetItem(QString::fromStdString(new_enum.desc)); + m_enum_table->setItem(row, 3, item); + OnModified(); + } +} + +void RegFieldEditPanel::OnFieldValueChanged(QTableWidgetItem *item) +{ + soc_desc::field_t& field = *m_ref.get(); + if((size_t)item->row() >= field.enum_.size()) 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); - OnModified(true); - } - 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); - } + soc_desc::enum_t& enum_ = field.enum_[item->row()]; + if(item->column() == 1) + enum_.name = item->text().toStdString(); + else if(item->column() == 2) + enum_.value = item->data(Qt::EditRole).value< soc_word_t >(); + else if(item->column() == 3) + enum_.desc = item->text().toStdString(); + OnModified(); } -void DevEditPanel::OnInstChanged(int row, int column) +void RegFieldEditPanel::OnFieldNameChanged(const QString& name) { - /* ignore extra row for addition */ - if(row >= (int)m_ref.GetDev().addr.size()) + m_ref.get()->name = name.toStdString(); + OnModified(); +} + +void RegFieldEditPanel::OnFieldRangeChanged(const QString& range) +{ + soc_desc::field_t *field = m_ref.get(); + int last, first; + if(m_range_validator->parse(range, last, first) != QValidator::Acceptable) return; - QTableWidgetItem *item = m_instances_table->item(row, column); - if(column == DevInstNameColumn) - { - m_ref.GetDev().addr[row].name = item->text().toStdString(); - OnModified(true); - } - else if(column == DevInstAddrColumn) - { - m_ref.GetDev().addr[row].addr = item->data(Qt::DisplayRole).toUInt(); - OnModified(true); - } + field->pos = first; + field->width = last - first + 1; + m_enum_delegate->setWidth(field->width); + m_enum_editor->setWidth(field->width); + OnModified(); +} + +void RegFieldEditPanel::OnFieldDescChanged(const QString& desc) +{ + m_ref.get()->desc = desc.toStdString(); + OnModified(); +} + +soc_desc::field_ref_t RegFieldEditPanel::GetField() +{ + return m_ref; } /** * RegEditPanel */ -RegEditPanel::RegEditPanel(SocRegRef ref, QWidget *parent) +namespace +{ + +enum +{ + RegVariantEditPanelDelType = QTableWidgetItem::UserType, + RegVariantEditPanelAddType, +}; + +} + +RegEditPanel::RegEditPanel(const soc_desc::register_ref_t& 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_value_table = new QTableView(this); - m_value_model = new RegFieldTableModel(m_value_table); // view takes ownership - m_value_model->SetRegister(m_ref.GetReg()); + m_value_model = new RegFieldTableModel(this); // view takes ownership + m_value_model->SetRegister(*ref.get()); m_value_model->SetReadOnly(true); - m_value_table->setModel(m_value_model); - m_value_table->verticalHeader()->setVisible(false); - m_value_table->horizontalHeader()->setStretchLastSection(true); - m_value_table->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); - // FIXME we cannot use setAlternatingRowColors() because we override the - // background color, should it be part of the model ? - m_table_delegate = new SocFieldCachedItemDelegate(this); - m_value_table->setItemDelegate(m_table_delegate); - m_value_table->resizeColumnsToContents(); - m_sexy_display2 = new Unscroll(this); + m_sexy_display2 = new Unscroll(this); m_sexy_display2->setFont(m_reg_font); m_sexy_display2->setModel(m_value_model); m_sexy_display2->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + m_sexy_display2->setContextMenuPolicy(Qt::CustomContextMenu); + m_sexy_display2->setWidth(m_ref.get()->width); - QHBoxLayout *field_layout = new QHBoxLayout; - field_layout->addWidget(m_value_table); - m_field_group = new QGroupBox("Flags", this); - m_field_group->setLayout(field_layout); + m_view_tab = new QTabWidget(this); + m_view_tab->setTabPosition(QTabWidget::West); - QVBoxLayout *layout = new QVBoxLayout; - layout->addLayout(top_layout, 0); - layout->addWidget(m_sexy_display2, 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(); - 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) + /* field tab */ + m_fields_tab = new YTabWidget(0, this); + m_fields_tab->setTabOpenable(true); + std::vector< soc_desc::field_ref_t > field_list = m_ref.fields(); + m_fields_tab->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Expanding); + m_fields_tab->setTabsClosable(true); + m_fields_tab->setElideMode(Qt::ElideRight); + for(size_t i = 0; i < field_list.size(); i++) { - name.push_back('n'); - pos = name.size() - 1; + RegFieldEditPanel *p = new RegFieldEditPanel(field_list[i], this); + connect(p, SIGNAL(OnModified()), this, SLOT(OnFieldModified())); + m_fields_tab->addTab(p, QString::fromStdString(field_list[i].get()->name)); } - 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++) + + m_reg_size_group = new QButtonGroup(this); + QRadioButton *reg_size_32 = new QRadioButton("32-bit"); + QRadioButton *reg_size_16 = new QRadioButton("16-bit"); + QRadioButton *reg_size_8 = new QRadioButton("8-bit"); + m_reg_size_group->addButton(reg_size_32, 32); + m_reg_size_group->addButton(reg_size_16, 16); + m_reg_size_group->addButton(reg_size_8, 8); + if(m_reg_size_group->button(m_ref.get()->width)) + m_reg_size_group->button(m_ref.get()->width)->click(); + QVBoxLayout *width_group_layout = new QVBoxLayout; + width_group_layout->addWidget(reg_size_32); + width_group_layout->addWidget(reg_size_16); + width_group_layout->addWidget(reg_size_8); + width_group_layout->addStretch(0); + QGroupBox *width_group = new QGroupBox("Width"); + width_group->setLayout(width_group_layout); + + m_variant_table = new QTableWidget; + m_variant_table->setColumnCount(3); + m_variant_table->setHorizontalHeaderItem(0, new QTableWidgetItem("")); + m_variant_table->setHorizontalHeaderItem(1, new QTableWidgetItem("Type")); + m_variant_table->setHorizontalHeaderItem(2, new QTableWidgetItem("Offset")); + m_variant_table->verticalHeader()->setVisible(false); + m_variant_table->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + m_variant_delegate = new SocFieldItemDelegate(this); + m_variant_delegate->setItemEditorFactory(new QItemEditorFactory); + m_variant_editor = new SocFieldEditorCreator; + m_variant_delegate->itemEditorFactory()->registerEditor(QVariant::UInt, m_variant_editor); + m_variant_table->setItemDelegate(m_variant_delegate); + + std::vector< soc_desc::variant_ref_t > variants = m_ref.variants(); + m_variant_table->setRowCount(variants.size() + 1); + for(size_t i = 0; i < variants.size(); i++) { - map["n"] = n; - std::string err; - soc_word_t res; - if(!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)); + QTableWidgetItem *item = new QTableWidgetItem( + QIcon::fromTheme("list-remove"), "", RegVariantEditPanelDelType); + item->setFlags(Qt::ItemIsEnabled); + m_variant_table->setItem(i, 0, item); + item = new QTableWidgetItem(QString::fromStdString(variants[i].get()->type)); + m_variant_table->setItem(i, 1, item); + item = new QTableWidgetItem(); + item->setData(Qt::EditRole, QVariant(variants[i].get()->offset)); + m_variant_table->setItem(i, 2, item); } - // 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(); - 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; - 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(); + QTableWidgetItem *new_item = new QTableWidgetItem( + QIcon::fromTheme("list-add"), "", RegVariantEditPanelAddType); + new_item->setFlags(Qt::ItemIsEnabled); + m_variant_table->setItem(variants.size(), 0, new_item); + new_item = new QTableWidgetItem("New variant..."); + new_item->setFlags(Qt::ItemIsEnabled); + QFont font = new_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); + new_item->setFont(font); + m_variant_table->setItem(variants.size(), 1, new_item); + new_item = new QTableWidgetItem(); + new_item->setFlags(Qt::ItemIsEnabled); + m_variant_table->setItem(variants.size(), 2, new_item); + new_item = new QTableWidgetItem(); + new_item->setFlags(Qt::ItemIsEnabled); + m_variant_table->resizeColumnsToContents(); + m_variant_table->horizontalHeader()->setStretchLastSection(true); + + m_desc_edit = new MyTextEditor(this); + m_desc_edit->SetTextHtml(QString::fromStdString(ref.get()->desc)); + + QHBoxLayout *top_info_layout = new QHBoxLayout; + top_info_layout->addWidget(width_group); + top_info_layout->addWidget(Misc::EncloseInBox("Variants", m_variant_table)); + top_info_layout->addWidget(Misc::EncloseInBox("Description", m_desc_edit)); + + QWidget *reg_info = new QWidget(this); + QVBoxLayout *reg_info_layout = new QVBoxLayout; + reg_info_layout->addLayout(top_info_layout); + reg_info_layout->addStretch(0); + reg_info->setLayout(reg_info_layout); + + m_view_tab->addTab(reg_info, "Information"); + m_view_tab->addTab(m_fields_tab, "Fields"); + + QVBoxLayout *main_layout = new QVBoxLayout; + main_layout->addWidget(m_sexy_display2, 1); + main_layout->addWidget(m_view_tab, 2); + + m_delete_action = new QAction("&Delete", this); + m_delete_action->setIcon(QIcon::fromTheme("list-remove")); + m_new_action = new QAction("&New field", this); + m_new_action->setIcon(QIcon::fromTheme("list-add")); + + setLayout(main_layout); + + OnRegFieldActivated(QModelIndex()); + UpdateWidthRestrictions(); + + connect(m_sexy_display2, SIGNAL(clicked(const QModelIndex&)), this, + SLOT(OnRegFieldActivated(const QModelIndex&))); + connect(m_sexy_display2, SIGNAL(customContextMenuRequested(QPoint)), this, + SLOT(OnRegDisplayContextMenu(QPoint))); + connect(m_reg_size_group, SIGNAL(buttonClicked(int)), this, SLOT(OnWidthChanged(int))); + connect(m_delete_action, SIGNAL(triggered()), this, SLOT(OnRegFieldDelete())); + connect(m_new_action, SIGNAL(triggered()), this, SLOT(OnRegFieldNew())); + connect(m_variant_table, SIGNAL(itemActivated(QTableWidgetItem *)), this, + SLOT(OnVariantActivated(QTableWidgetItem *))); + connect(m_variant_table, SIGNAL(itemChanged(QTableWidgetItem *)), this, + SLOT(OnVariantValueChanged(QTableWidgetItem *))); + connect(m_desc_edit, SIGNAL(OnTextChanged()), this, SLOT(OnDescEdited())); + connect(m_fields_tab, SIGNAL(tabCloseRequested(int)), this, SLOT(OnFieldRemove(int))); + connect(m_fields_tab, SIGNAL(tabOpenRequested()), this, SLOT(OnFieldCreate())); } -void RegEditPanel::OnNameEdited(const QString& text) +void RegEditPanel::UpdateWidthRestrictions() { - m_ref.GetReg().name = text.toStdString(); - OnModified(m_name_edit->isModified()); + /* only allow width large enough to fit all fields */ + size_t max_bit = 0; + std::vector< soc_desc::field_ref_t > field_list = m_ref.fields(); + for(size_t i = 0; i < field_list.size(); i++) + { + soc_desc::field_t& f = *field_list[i].get(); + max_bit = std::max(max_bit, f.pos + f.width - 1); + } + /* update buttons */ + m_reg_size_group->button(8)->setEnabled(max_bit < 8); + m_reg_size_group->button(16)->setEnabled(max_bit < 16); + m_reg_size_group->button(32)->setEnabled(max_bit < 32); +} + +int RegEditPanel::IndexById(soc_id_t id) +{ + for(int i = 0; i < m_fields_tab->count(); i++) + { + RegFieldEditPanel *p = dynamic_cast< RegFieldEditPanel * >(m_fields_tab->widget(i)); + if(p->GetField().get()->id == id) + return i; + } + return -1; +} + +void RegEditPanel::OnWidthChanged(int w) +{ + m_ref.get()->width = w; + m_sexy_display2->setWidth(w); + for(int i = 0; i < m_fields_tab->count(); i++) + dynamic_cast< RegFieldEditPanel * >(m_fields_tab->widget(i))->UpdateWidth(); + OnModified(); } void RegEditPanel::OnDescEdited() { - m_ref.GetReg().desc = m_desc_edit->GetTextHtml().toStdString(); - OnModified(m_desc_edit->IsModified()); + m_ref.get()->desc = m_desc_edit->GetTextHtml().toStdString(); + OnModified(); } -void RegEditPanel::OnInstActivated(int row, int column) +void RegEditPanel::OnVariantActivated(QTableWidgetItem *item) { - if(column != 0) + if(item->type() == RegVariantEditPanelDelType) + { + int row = item->row(); + my_remove_at(m_ref.get()->variant, row); + m_variant_table->removeRow(row); + OnModified(); + } + else if(item->type() == RegVariantEditPanelAddType) + { + int row = m_ref.get()->variant.size(); + soc_desc::variant_t& variant = *m_ref.create_variant().get(); + variant.type = "untyped"; + variant.offset = 0; + m_variant_table->insertRow(row); + QTableWidgetItem *item = new QTableWidgetItem( + QIcon::fromTheme("list-remove"), "", RegVariantEditPanelDelType); + item->setFlags(Qt::ItemIsEnabled); + m_variant_table->setItem(row, 0, item); + item = new QTableWidgetItem(QString::fromStdString(variant.type)); + m_variant_table->setItem(row, 1, item); + item = new QTableWidgetItem(); + item->setData(Qt::EditRole, QVariant(variant.offset)); + m_variant_table->setItem(row, 2, item); + OnModified(); + } +} + +void RegEditPanel::OnVariantValueChanged(QTableWidgetItem *item) +{ + soc_desc::register_t& reg = *m_ref.get(); + if((size_t)item->row() >= reg.variant.size()) 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); - OnModified(true); - } - 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); - } + soc_desc::variant_t& var = reg.variant[item->row()]; + if(item->column() == 1) + var.type = item->text().toStdString(); + else if(item->column() == 2) + var.offset = item->data(Qt::EditRole).value< soc_word_t >(); + OnModified(); } -void RegEditPanel::OnInstChanged(int row, int column) +void RegEditPanel::OnRegFieldActivated(const QModelIndex& index) { - /* ignore extra row for addition */ - if(row >= (int)m_ref.GetReg().addr.size()) + if(!index.isValid()) return; - QTableWidgetItem *item = m_instances_table->item(row, column); - if(column == RegInstNameColumn) - { - m_ref.GetReg().addr[row].name = item->text().toStdString(); - OnModified(true); - } - else if(column == RegInstAddrColumn) - { - m_ref.GetReg().addr[row].addr = item->data(Qt::DisplayRole).toUInt(); - OnModified(true); - } + m_fields_tab->setCurrentIndex(IndexById(m_ref.get()->field[index.row()].id)); + m_view_tab->setCurrentIndex(1); } -/** - * FieldEditPanel - */ -FieldEditPanel::FieldEditPanel(SocFieldRef ref, QWidget *parent) - :QWidget(parent), m_ref(ref) +void RegEditPanel::OnFieldModified() { - 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); + int idx = m_fields_tab->currentIndex(); + RegFieldEditPanel *p = dynamic_cast< RegFieldEditPanel * >(m_fields_tab->widget(idx)); + m_fields_tab->setTabText(idx, QString::fromStdString(p->GetField().get()->name)); + DoModify(); } -void FieldEditPanel::UpdateDelegates() +void RegEditPanel::DoModify() { - 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(); + m_value_model->UpdateRegister(*m_ref.get()); + UpdateWidthRestrictions(); + OnModified(); } -void FieldEditPanel::UpdateWarning(int row) +void RegEditPanel::OnRegFieldDelete() { - 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) + QModelIndex current = m_sexy_display2->currentIndex(); + if(!current.isValid()) 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(); - OnModified(true); -} - -void FieldEditPanel::OnNameEdited(const QString& text) -{ - m_ref.GetField().name = text.toStdString(); - OnModified(m_name_edit->isModified()); -} - -void FieldEditPanel::OnDescEdited() -{ - m_ref.GetField().desc = m_desc_edit->GetTextHtml().toStdString(); - OnModified(m_desc_edit->IsModified()); -} - -void FieldEditPanel::OnValueActivated(int row, int column) -{ - if(column != 0) + QMessageBox msgbox(QMessageBox::Question, "Delete field ?", + "Are you sure you want to delete this field ?", + QMessageBox::Yes | QMessageBox::No, this); + msgbox.setDefaultButton(QMessageBox::No); + int ret = msgbox.exec(); + if(ret != QMessageBox::Yes) 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); - OnModified(true); - } - 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); - } + m_fields_tab->removeTab(IndexById(m_ref.get()->field[current.row()].id)); + my_remove_at(m_ref.get()->field, current.row()); + DoModify(); + OnRegFieldActivated(QModelIndex()); } -void FieldEditPanel::OnValueChanged(int row, int column) +void RegEditPanel::OnFieldRemove(int index) { - /* 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) + Q_UNUSED(index); +} + +int RegEditPanel::FindFreeBit(int preferred) +{ + int nr_bits = m_ref.get()->width; + soc_word_t free_mask = (nr_bits == 32) ? 0xffffffff : (1 << nr_bits) - 1; + soc_desc::register_t& reg = *m_ref.get(); + for(size_t i = 0; i < reg.field.size(); i++) + free_mask &= ~reg.field[i].bitmask(); + /* any space ? */ + if(free_mask == 0) + return -1; + int closest_bit = -1; + int closest_dist = nr_bits; + for(int bit = 0; bit < nr_bits; bit++) { - 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) + if(!(free_mask & (1 << bit))) + continue; + if(abs(bit - preferred) < closest_dist) { - fval = new_val; - UpdateWarning(row); + closest_bit = bit; + closest_dist = abs(bit - preferred); } } - else if(column == FieldValueDescColumn) - m_ref.GetField().value[row].desc = item->text().toStdString(); - OnModified(true); + return closest_bit; +} + +void RegEditPanel::OnRegFieldNew() +{ + int bit_col = m_sexy_display2->bitColumnAt(m_menu_point); + /* we need to make sure the created field does not overlap something */ + bit_col = FindFreeBit(bit_col); + if(bit_col == -1) + return; /* impossible to find a free position */ + soc_desc::field_ref_t ref = m_ref.create_field(); + soc_desc::field_t& field = *ref.get(); + field.pos = bit_col; + field.width = 1; + field.name = "UNNAMED"; + + RegFieldEditPanel *p = new RegFieldEditPanel(ref, this); + connect(p, SIGNAL(OnModified()), this, SLOT(OnFieldModified())); + m_fields_tab->addTab(p, QString::fromStdString(field.name)); + + DoModify(); +} + +void RegEditPanel::OnFieldCreate() +{ + OnRegFieldNew(); +} + +void RegEditPanel::OnRegDisplayContextMenu(QPoint point) +{ + m_menu_point = point; + QMenu *menu = new QMenu(this); + QModelIndex item = m_sexy_display2->indexAt(point); + menu->addAction(m_new_action); + if(item.isValid()) + menu->addAction(m_delete_action); + menu->popup(m_sexy_display2->viewport()->mapToGlobal(point)); } namespace @@ -780,119 +1308,29 @@ namespace enum { - SocTreeSocType = QTreeWidgetItem::UserType, - SocTreeDevType, - SocTreeRegType, - SocTreeFieldType, - SocTreeNewDevType, - SocTreeNewRegType, - SocTreeNewFieldType, + SocTreeSocType = QTreeWidgetItem::UserType, // SocRefRole -> node_ref_t to root + SocTreeNodeType, // SocRefRole -> node_ref_t + SocTreeRegType, // SocRefRole -> register_ref_t }; -/** - * SocTreeItem - */ - -class SocTreeItem : public QTreeWidgetItem +enum { -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; + SocRefRole = Qt::UserRole, }; -/** - * NewDevTreeItem - */ - -class NewDevTreeItem : public QTreeWidgetItem +template +T SocTreeItemVal(QTreeWidgetItem *item) { -public: - NewDevTreeItem(const QString& string, const SocRef& ref) - :QTreeWidgetItem(QStringList(string), SocTreeNewDevType), m_ref(ref) {} + return item->data(0, SocRefRole).value(); +} - const SocRef& GetRef() { return m_ref; } -private: - SocRef m_ref; -}; - -/** - * DevTreeItem - */ - -class DevTreeItem : public QTreeWidgetItem +template +QTreeWidgetItem *MakeSocTreeItem(int type, const T& val) { -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; -}; + QTreeWidgetItem *item = new QTreeWidgetItem(type); + item->setData(0, SocRefRole, QVariant::fromValue(val)); + return item; +} } @@ -903,8 +1341,7 @@ 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(); + QLabel *file_static = new QLabel("File:"); m_file_edit = new QLineEdit(this); m_file_edit->setReadOnly(true); m_file_open = new QToolButton(this); @@ -913,33 +1350,53 @@ RegEdit::RegEdit(Backend *backend, QWidget *parent) 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->setPopupMode(QToolButton::MenuButtonPopup); 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); + m_file_save->setPopupMode(QToolButton::MenuButtonPopup); 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); + + QHBoxLayout *file_group_layout = new QHBoxLayout(); + file_group_layout->addWidget(m_file_open); + file_group_layout->addWidget(m_file_save); + file_group_layout->addWidget(file_static); + 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_soc_tree->setContextMenuPolicy(Qt::ActionsContextMenu); - QAction *soc_tree_delete_action = new QAction("&Delete", this); - soc_tree_delete_action->setIcon(QIcon::fromTheme("list-remove")); - connect(soc_tree_delete_action, SIGNAL(triggered()), this, SLOT(OnSocItemDelete())); - m_soc_tree->addAction(soc_tree_delete_action); + m_soc_tree->setContextMenuPolicy(Qt::CustomContextMenu); + + m_delete_action = new QAction("&Delete", this); + m_delete_action->setIcon(QIcon::fromTheme("list-remove")); + m_new_action = new QAction("&New", this); + m_new_action->setIcon(QIcon::fromTheme("list-add")); + m_create_action = new QAction("&Create register", this); + m_create_action->setIcon(QIcon::fromTheme("folder-new")); + 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_msg = new MessageWidget(this); + QWidget *splitter_right = new QWidget(this); + m_right_panel_layout = new QVBoxLayout; + m_right_panel_layout->addWidget(m_msg, 0); + splitter_right->setLayout(m_right_panel_layout); + m_splitter->addWidget(splitter_right); + m_splitter->setStretchFactor(1, 2); + + m_msg_welcome_id = SetMessage(MessageWidget::Information, + "Open a description file to edit, or create a new file from scratch."); + m_msg_name_error_id = 0; + + m_vert_layout->addLayout(file_group_layout); m_vert_layout->addWidget(m_splitter, 1); setLayout(m_vert_layout); @@ -949,14 +1406,17 @@ RegEdit::RegEdit(Backend *backend, QWidget *parent) SetPanel(new EmptyEditPanel(this)); UpdateTabName(); + connect(m_soc_tree, SIGNAL(customContextMenuRequested(QPoint)), this, + SLOT(OnSocTreeContextMenu(QPoint))); + connect(m_delete_action, SIGNAL(triggered()), this, SLOT(OnSocItemDelete())); + connect(m_new_action, SIGNAL(triggered()), this, SLOT(OnSocItemNew())); + connect(m_create_action, SIGNAL(triggered()), this, SLOT(OnSocItemCreate())); 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))); } QWidget *RegEdit::GetWidget() @@ -968,6 +1428,16 @@ RegEdit::~RegEdit() { } +int RegEdit::SetMessage(MessageWidget::MessageType type, const QString& msg) +{ + return m_msg->SetMessage(type, msg); +} + +void RegEdit::HideMessage(int id) +{ + m_msg->HideMessage(id); +} + void RegEdit::OnSave() { SaveSoc(); @@ -1007,7 +1477,10 @@ 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 (*)"); + QStringList filters; + filters << "Description files (*.xml)"; + filters << "All files (*)"; + fd->setNameFilters(filters); fd->setDirectory(Settings::Get()->value("regedit/loaddescdir", QDir::currentPath()).toString()); if(fd->exec()) { @@ -1051,15 +1524,15 @@ void RegEdit::OnNew() bool RegEdit::SaveSocFile(const QString& filename) { - normalize(m_cur_socfile.GetSoc()); - if(!produce_xml(filename.toStdString(), m_cur_socfile.GetSoc())) + soc_desc::error_context_t ctx; + soc_desc::normalize(m_cur_socfile.GetSoc()); + if(!soc_desc::produce_xml(filename.toStdString(), m_cur_socfile.GetSoc(), ctx)) { QMessageBox::warning(this, "The description was not saved", "There was an error when saving the file"); return false; } - m_soc_tree->clear(); - FillSocTree(); + UpdateSocFile(); SetModified(false, false); return true; } @@ -1086,91 +1559,39 @@ void RegEdit::LoadSocFile(const QString& filename) SetModified(false, false); UpdateSocFile(); UpdateTabName(); + m_msg_welcome_id = SetMessage(MessageWidget::Information, + "Select items to edit in tree, or right-click on them to see available actions."); } -void RegEdit::CreateNewFieldItem(QTreeWidgetItem *_parent) +void RegEdit::FillNodeTreeItem(QTreeWidgetItem *item) { - 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++) + soc_desc::node_ref_t node = SocTreeItemVal< soc_desc::node_ref_t >(item); + soc_desc::register_ref_t reg = node.reg(); + /* put register if there, otherwise offer to create one */ + if(reg.valid() && reg.node() == node) { - 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); + QTreeWidgetItem *reg_item = MakeSocTreeItem(SocTreeRegType, reg); + FixupItem(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++) + std::vector< soc_desc::node_ref_t > list = node.children(); + for(size_t i = 0; i < list.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); + QTreeWidgetItem *node_item = MakeSocTreeItem(SocTreeNodeType, list[i]); + FixupItem(node_item); + FillNodeTreeItem(node_item); + item->addChild(node_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); + soc_desc::soc_ref_t ref = m_cur_socfile.GetSocRef(); + QTreeWidgetItem *root_item = MakeSocTreeItem(SocTreeSocType, ref.root()); + FixupItem(root_item); + FillNodeTreeItem(root_item); + m_soc_tree->addTopLevelItem(root_item); + root_item->setExpanded(true); } void RegEdit::MakeItalic(QTreeWidgetItem *item, bool it) @@ -1180,17 +1601,46 @@ void RegEdit::MakeItalic(QTreeWidgetItem *item, bool it) item->setFont(0, font); } -void RegEdit::FixupEmptyItem(QTreeWidgetItem *item) +QIcon RegEdit::GetIconFromType(int type) { - if(item->text(0).size() == 0) + switch(type) + { + case SocTreeSocType: return QIcon::fromTheme("computer"); + case SocTreeNodeType: return QIcon::fromTheme("cpu"); + case SocTreeRegType: return style()->standardIcon(QStyle::SP_ArrowRight); + default: return QIcon(); + } +} + +bool RegEdit::ValidateName(const QString& name) +{ + if(name.size() == 0) + return false; + for(int i = 0; i < name.size(); i++) + if(!name[i].isLetterOrNumber() && name[i] != QChar('_')) + return false; + return true; +} + +void RegEdit::FixupItem(QTreeWidgetItem *item) +{ + UpdateName(item); + if(!ValidateName(item->text(0))) { item->setIcon(0, QIcon::fromTheme("dialog-error")); - MakeItalic(item, true); - item->setText(0, "Unnamed"); + if(item->text(0).size() == 0) + { + MakeItalic(item, true); + item->setText(0, "Unnamed"); + } + m_msg_name_error_id = SetMessage(MessageWidget::Error, + "The item name is invalid. It must be non-empty and consists only " + "of alphanumerical or underscore characters"); } else { - item->setIcon(0, QIcon::fromTheme("cpu")); + HideMessage(m_msg_name_error_id); + item->setIcon(0, GetIconFromType(item->type())); MakeItalic(item, false); } } @@ -1206,9 +1656,9 @@ 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); + connect(m_right_panel, SIGNAL(OnModified()), this, + SLOT(OnSocModified())); + m_right_panel_layout->addWidget(m_right_panel, 1); } void RegEdit::SetModified(bool add, bool mod) @@ -1217,15 +1667,33 @@ void RegEdit::SetModified(bool add, bool mod) OnModified(mod); } -namespace +void RegEdit::OnSocItemNew() { - -template< typename T > -void my_remove_at(std::vector< T >& v, size_t at) -{ - v.erase(v.begin() + at); + QTreeWidgetItem *current = m_soc_tree->currentItem(); + if(current == 0) + return; + soc_desc::node_ref_t node = SocTreeItemVal< soc_desc::node_ref_t >(current); + node = node.create(); + node.get()->name = "unnamed"; + QTreeWidgetItem *node_item = MakeSocTreeItem(SocTreeNodeType, node); + FixupItem(node_item); + current->addChild(node_item); + m_soc_tree->setCurrentItem(node_item); } +void RegEdit::OnSocItemCreate() +{ + QTreeWidgetItem *current = m_soc_tree->currentItem(); + if(current == 0) + return; + soc_desc::register_t reg; + reg.width = 32; + soc_desc::node_ref_t node = SocTreeItemVal< soc_desc::node_ref_t >(current); + node.get()->register_.push_back(reg); + QTreeWidgetItem *reg_item = MakeSocTreeItem(SocTreeRegType, node.reg()); + FixupItem(reg_item); + current->insertChild(0, reg_item); + m_soc_tree->setCurrentItem(reg_item); } void RegEdit::OnSocItemDelete() @@ -1242,172 +1710,116 @@ void RegEdit::OnSocItemDelete() return; if(current->type() == SocTreeSocType) { - SocTreeItem *item = dynamic_cast< SocTreeItem * >(current); - item->GetRef().GetSoc().dev.clear(); - item->takeChildren(); - FillSocTreeItem(item); - m_soc_tree->expandItem(item); + SocTreeItemVal< soc_desc::node_ref_t >(current).remove(); + current->takeChildren(); + OnSocModified(); } - else if(current->type() == SocTreeDevType) + else if(current->type() == SocTreeNodeType) { - DevTreeItem *item = dynamic_cast< DevTreeItem * >(current); - my_remove_at(item->GetRef().GetSoc().dev, item->GetRef().GetDevIndex()); - QTreeWidgetItem *parent = item->parent(); - parent->takeChildren(); - FillSocTreeItem(parent); - m_soc_tree->expandItem(parent); + SocTreeItemVal< soc_desc::node_ref_t >(current).remove(); + current->parent()->removeChild(current); + OnSocModified(); } else if(current->type() == SocTreeRegType) { - RegTreeItem *item = dynamic_cast< RegTreeItem * >(current); - my_remove_at(item->GetRef().GetDev().reg, item->GetRef().GetRegIndex()); - QTreeWidgetItem *parent = item->parent(); - parent->takeChildren(); - FillDevTreeItem(parent); - m_soc_tree->expandItem(parent); - } - else if(current->type() == SocTreeFieldType) - { - FieldTreeItem *item = dynamic_cast< FieldTreeItem * >(current); - my_remove_at(item->GetRef().GetReg().field, item->GetRef().GetFieldIndex()); - QTreeWidgetItem *parent = item->parent(); - parent->takeChildren(); - FillRegTreeItem(parent); - m_soc_tree->expandItem(parent); + SocTreeItemVal< soc_desc::register_ref_t >(current).remove(); + current->parent()->removeChild(current); + OnSocModified(); } } -void RegEdit::OnSocModified(bool modified) +void RegEdit::OnSocModified() { // we might need to update the name in the tree - UpdateName(m_soc_tree->currentItem()); - if(modified) - SetModified(true, true); + FixupItem(m_soc_tree->currentItem()); + SetModified(true, true); } -void RegEdit::DisplaySoc(SocRef ref) +void RegEdit::DisplaySoc(const soc_desc::soc_ref_t& ref) { SetPanel(new SocEditPanel(ref, this)); } -void RegEdit::DisplayDev(SocDevRef ref) +void RegEdit::DisplayNode(const soc_desc::node_ref_t& ref) { - SetPanel(new DevEditPanel(ref, this)); + SetPanel(new NodeEditPanel(ref, this)); } -void RegEdit::DisplayReg(SocRegRef ref) +void RegEdit::DisplayReg(const soc_desc::register_ref_t& 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)); + current->setText(0, QString::fromStdString( + SocTreeItemVal< soc_desc::node_ref_t >(current).soc().get()->name)); } - else if(current->type() == SocTreeDevType) + else if(current->type() == SocTreeNodeType) { - DevTreeItem *item = dynamic_cast< DevTreeItem * >(current); - item->setText(0, QString::fromStdString(item->GetRef().GetDev().name)); + current->setText(0, QString::fromStdString( + SocTreeItemVal< soc_desc::node_ref_t >(current).get()->name)); } else if(current->type() == SocTreeRegType) { - RegTreeItem *item = dynamic_cast< RegTreeItem * >(current); - item->setText(0, QString::fromStdString(item->GetRef().GetReg().name)); + current->setText(0, "register"); } - else if(current->type() == SocTreeFieldType) +} + +void RegEdit::OnSocTreeContextMenu(QPoint point) +{ + HideMessage(m_msg_welcome_id); + QTreeWidgetItem *item = m_soc_tree->itemAt(point); + if(item == 0) + return; + /* customise messages with item */ + m_action_item = item; + QMenu *menu = new QMenu(this); + switch(item->type()) { - FieldTreeItem *item = dynamic_cast< FieldTreeItem * >(current); - item->setText(0, QString::fromStdString(item->GetRef().GetField().name)); + case SocTreeSocType: + m_new_action->setText("New node..."); + m_delete_action->setText("Delete all nodes..."); + menu->addAction(m_new_action); + menu->addAction(m_delete_action); + break; + case SocTreeNodeType: + { + m_new_action->setText("New node..."); + m_delete_action->setText("Delete node..."); + soc_desc::node_ref_t node = SocTreeItemVal< soc_desc::node_ref_t >(item); + if(node.reg().node() != node) + menu->addAction(m_create_action); + menu->addAction(m_new_action); + menu->addAction(m_delete_action); + break; + } + case SocTreeRegType: + m_delete_action->setText("Delete register..."); + menu->addAction(m_new_action); + menu->addAction(m_delete_action); + break; } - FixupEmptyItem(current); + menu->popup(m_soc_tree->viewport()->mapToGlobal(point)); } void RegEdit::OnSocItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous) { Q_UNUSED(previous); + HideMessage(m_msg_welcome_id); 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()); - } + DisplaySoc(SocTreeItemVal< soc_desc::node_ref_t >(current).soc()); + else if(current->type() == SocTreeNodeType) + DisplayNode(SocTreeItemVal< soc_desc::node_ref_t >(current)); 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); - OnModified(true); -} - -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); - OnModified(true); -} - -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); - OnModified(true); + DisplayReg(SocTreeItemVal< soc_desc::register_ref_t >(current)); } bool RegEdit::Quit() diff --git a/utils/regtools/qeditor/regedit.h b/utils/regtools/qeditor/regedit.h index c56f0d9026..2540500f29 100644 --- a/utils/regtools/qeditor/regedit.h +++ b/utils/regtools/qeditor/regedit.h @@ -38,6 +38,8 @@ #include #include #include +#include +#include #include "backend.h" #include "settings.h" #include "mainwindow.h" @@ -48,7 +50,7 @@ class AbstractRegEditPanel public: AbstractRegEditPanel() {} virtual ~AbstractRegEditPanel() {} - virtual void OnModified(bool mod) = 0; + virtual void OnModified() = 0; }; class EmptyEditPanel : public QWidget, public AbstractRegEditPanel @@ -58,7 +60,7 @@ public: EmptyEditPanel(QWidget *parent); signals: - void OnModified(bool mod); + void OnModified(); protected: }; @@ -67,178 +69,167 @@ class SocEditPanel : public QWidget, public AbstractRegEditPanel { Q_OBJECT public: - SocEditPanel(SocRef ref, QWidget *parent = 0); + SocEditPanel(const soc_desc::soc_ref_t& ref, QWidget *parent = 0); signals: - void OnModified(bool mod); + void OnModified(); protected slots: void OnTextEdited(); void OnNameEdited(const QString& text); + void OnTitleEdited(const QString& text); + void OnVersionEdited(const QString& text); + void OnIsaEdited(const QString& text); + void OnAuthorActivated(QTableWidgetItem *); + void OnAuthorChanged(QTableWidgetItem *); protected: - SocRef m_ref; - QGroupBox *m_name_group; - QLineEdit *m_name_edit; - QGroupBox *m_desc_group; + soc_desc::soc_ref_t m_ref; + QTableWidget *m_authors_list; MyTextEditor *m_desc_edit; }; -class DevEditPanel : public QWidget, public AbstractRegEditPanel +class NodeInstanceEditPanel : public QWidget { Q_OBJECT public: - DevEditPanel(SocDevRef ref, QWidget *parent = 0); + NodeInstanceEditPanel(const soc_desc::node_ref_t& ref, soc_id_t inst_id, + QWidget *parent = 0); + soc_id_t GetId(); + soc_desc::instance_t& GetInstance(); signals: - void OnModified(bool mod); + void OnModified(); 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(); + void OnTitleEdited(const QString& text); + void OnDescEdited(const QString& text); + void OnTypeChanged(int index); + void OnAddrChanged(uint addr); + void OnBaseChanged(uint base); + void OnStrideChanged(uint stride); + void OnFirstChanged(int first); + void OnCountChanged(int count); + void OnFormulaChanged(const QString& formula); + void OnVariableChanged(const QString& variable); + void OnAddressActivated(QTableWidgetItem *); + void OnAddressChanged(QTableWidgetItem *); protected: - void FillRow(int row, const soc_dev_addr_t& addr); - void CreateNewRow(int row); + void UpdateType(int type); - enum - { - DevInstDeleteType = QTableWidgetItem::UserType, - DevInstNewType - }; + soc_desc::node_ref_t m_ref; + soc_id_t m_id; + QComboBox *m_type_combo; + QWidget *m_single_group; + QWidget *m_range_group; + QWidget *m_formula_group; + QWidget *m_stride_group; + QWidget *m_list_group; + QStyledItemDelegate *m_table_delegate; + SocFieldEditorCreator *m_table_edit_factory; +}; - enum - { - DevInstIconColumn = 0, - DevInstNameColumn = 1, - DevInstAddrColumn = 2, - }; +class NodeEditPanel : public QWidget, public AbstractRegEditPanel +{ + Q_OBJECT +public: + NodeEditPanel(const soc_desc::node_ref_t& ref, QWidget *parent = 0); - 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; +signals: + void OnModified(); + +protected slots: + void OnNameEdited(const QString& text); + void OnTitleEdited(const QString& text); + void OnDescEdited(); + void OnInstRemove(int index); + void OnInstCreate(); + void OnInstModified(); + +protected: + soc_desc::instance_t *GetInstanceById(soc_id_t id); + soc_desc::instance_t *GetInstanceByRow(int row); + QString GuessName(); + + soc_desc::node_ref_t m_ref; MyTextEditor *m_desc_edit; + YTabWidget *m_instances_tab; +}; + +class RegFieldEditPanel : public QWidget +{ + Q_OBJECT +public: + RegFieldEditPanel(const soc_desc::field_ref_t& ref, QWidget *parent = 0); + soc_desc::field_ref_t GetField(); + void UpdateWidth(); + +signals: + void OnModified(); + +protected slots: + void OnFieldNameChanged(const QString& name); + void OnFieldRangeChanged(const QString& range); + void OnFieldDescChanged(const QString& name); + void OnFieldValueActivated(QTableWidgetItem *item); + void OnFieldValueChanged(QTableWidgetItem *item); + +protected: + + soc_desc::field_ref_t m_ref; + QLineEdit *m_name_edit; + QLineEdit *m_range_edit; + SocBitRangeValidator *m_range_validator; + MyTextEditor *m_desc_edit; + QTableWidget *m_enum_table; + SocFieldItemDelegate *m_enum_delegate; + SocFieldEditorCreator *m_enum_editor; }; class RegEditPanel : public QWidget, public AbstractRegEditPanel { Q_OBJECT public: - RegEditPanel(SocRegRef ref, QWidget *parent = 0); + RegEditPanel(const soc_desc::register_ref_t& ref, QWidget *parent = 0); signals: - void OnModified(bool mod); + void OnModified(); protected slots: - void OnInstActivated(int row, int column); - void OnInstChanged(int row, int column); - void OnNameEdited(const QString& text); + void OnRegFieldActivated(const QModelIndex& index); + void OnRegDisplayContextMenu(QPoint point); + void OnRegFieldDelete(); + void OnRegFieldNew(); + void OnWidthChanged(int size); + void OnFieldModified(); void OnDescEdited(); - void OnSctEdited(int state); - void OnFormulaChanged(int index); - void OnFormulaStringChanged(const QString& text); - void OnFormulaGenerate(bool checked); + void OnVariantActivated(QTableWidgetItem *item); + void OnVariantValueChanged(QTableWidgetItem *item); + void OnFieldRemove(int index); + void OnFieldCreate(); protected: - void CreateNewAddrRow(int row); - void FillRow(int row, const soc_reg_addr_t& addr); - void UpdateFormula(); - void UpdateWarning(int row); + void DoModify(); + int FindFreeBit(int preferred); + int IndexById(soc_id_t id); // tab index + void UpdateWidthRestrictions(); - 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; + MyTextEditor *m_desc_edit; + soc_desc::register_ref_t m_ref; 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; - Unscroll< RegSexyDisplay2 > *m_sexy_display2; - MyTextEditor *m_desc_edit; - QGroupBox *m_field_group; - QTableView *m_value_table; + Unscroll< YRegDisplay > *m_sexy_display2; RegFieldTableModel *m_value_model; - QStyledItemDelegate *m_table_delegate; -}; - -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; + YTabWidget *m_fields_tab; + QTabWidget *m_view_tab; + QTableWidget *m_variant_table; + QAction *m_new_action; + QAction *m_delete_action; + QPoint m_menu_point; + SocFieldItemDelegate *m_variant_delegate; + SocFieldEditorCreator *m_variant_editor; + QButtonGroup *m_reg_size_group; }; class RegEdit : public QWidget, public DocumentTab @@ -252,43 +243,50 @@ public: 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 OnSocModified(); void OnNew(); void OnSocItemDelete(); + void OnSocItemNew(); + void OnSocItemCreate(); + void OnSocTreeContextMenu(QPoint point); protected: void LoadSocFile(const QString& filename); void UpdateSocFile(); void FillSocTree(); - void FillSocTreeItem(QTreeWidgetItem *_item); - void FillDevTreeItem(QTreeWidgetItem *_item); - void FillRegTreeItem(QTreeWidgetItem *_item); + void FillNodeTreeItem(QTreeWidgetItem *item); void SetPanel(QWidget *panel); - void DisplaySoc(SocRef ref); - void DisplayDev(SocDevRef ref); - void DisplayReg(SocRegRef ref); - void DisplayField(SocFieldRef ref); + void DisplaySoc(const soc_desc::soc_ref_t& ref); + void DisplayNode(const soc_desc::node_ref_t& ref); + void DisplayReg(const soc_desc::register_ref_t& 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 FixupItem(QTreeWidgetItem *item); + QIcon GetIconFromType(int type); 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 CreateNewNodeItem(QTreeWidgetItem *parent); void CreateNewRegisterItem(QTreeWidgetItem *parent); void CreateNewFieldItem(QTreeWidgetItem *parent); void UpdateTabName(); + bool ValidateName(const QString& name); + int SetMessage(MessageWidget::MessageType type, const QString& msg); + void HideMessage(int id); + QAction *m_delete_action; + QAction *m_new_action; + QAction *m_create_action; + QTreeWidgetItem *m_action_item; QGroupBox *m_file_group; QToolButton *m_file_open; QToolButton *m_file_save; @@ -299,6 +297,10 @@ protected: bool m_modified; SocFile m_cur_socfile; QWidget *m_right_panel; + MessageWidget *m_msg; + QVBoxLayout *m_right_panel_layout; + int m_msg_welcome_id; + int m_msg_name_error_id; }; #endif /* REGEDIT_H */ diff --git a/utils/regtools/qeditor/regtab.cpp b/utils/regtools/qeditor/regtab.cpp index a82070e3f8..2653908d41 100644 --- a/utils/regtools/qeditor/regtab.cpp +++ b/utils/regtools/qeditor/regtab.cpp @@ -35,42 +35,7 @@ namespace enum { - RegTreeDevType = QTreeWidgetItem::UserType, - RegTreeRegType, - RegTreeSocType -}; - -class SocTreeItem : public QTreeWidgetItem -{ -public: - SocTreeItem(const QString& string, const SocRef& ref) - :QTreeWidgetItem(QStringList(string), RegTreeSocType), m_ref(ref) {} - - const SocRef& GetRef() { return m_ref; } -private: - SocRef m_ref; -}; - -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 -{ -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; + NodeInstRole = Qt::UserRole, }; } @@ -165,7 +130,8 @@ RegTab::RegTab(Backend *backend, QWidget *parent) connect(m_soc_selector, SIGNAL(currentIndexChanged(int)), this, SLOT(OnSocChanged(int))); - connect(m_backend, SIGNAL(OnSocListChanged()), this, SLOT(OnSocListChanged())); + connect(m_backend, SIGNAL(OnSocAdded(const SocFileRef&)), this, + SLOT(OnSocAdded(const SocFileRef&))); connect(m_reg_tree, SIGNAL(itemClicked(QTreeWidgetItem*, int)), this, SLOT(OnRegItemClicked(QTreeWidgetItem*, int))); connect(m_data_soc_label, SIGNAL(linkActivated(const QString&)), this, @@ -183,7 +149,9 @@ RegTab::RegTab(Backend *backend, QWidget *parent) "You can browse the registers. Select a data source to analyse the values."); m_msg_error_id = 0; - OnSocListChanged(); + QList< SocFileRef > socs = m_backend->GetSocFileList(); + for(int i = 0; i < socs.size(); i++) + OnSocAdded(socs[i]); SetDataSocName(""); UpdateTabName(); } @@ -286,21 +254,7 @@ void RegTab::OnRegItemClicked(QTreeWidgetItem *current, int col) Q_UNUSED(col); if(current == 0) return; - if(current->type() == RegTreeSocType) - { - SocTreeItem *item = dynamic_cast< SocTreeItem * >(current); - DisplaySoc(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()); - } + DisplayNode(NodeInst(current)); } void RegTab::OnAnalyserClicked(QListWidgetItem *current) @@ -311,19 +265,14 @@ void RegTab::OnAnalyserClicked(QListWidgetItem *current) SetPanel(ana->Create(m_cur_soc, m_io_backend)); } -void RegTab::DisplayRegister(const SocRegRef& ref) +void RegTab::DisplayNode(const soc_desc::node_inst_t& ref) { - SetPanel(new RegDisplayPanel(this, m_io_backend, ref)); -} - -void RegTab::DisplayDevice(const SocDevRef& ref) -{ - SetPanel(new DevDisplayPanel(this, ref)); -} - -void RegTab::DisplaySoc(const SocRef& ref) -{ - SetPanel(new SocDisplayPanel(this, ref)); + if(ref.node().is_root()) + SetPanel(new SocDisplayPanel(this, m_io_backend, ref.soc())); + else if(ref.node().reg().valid()) + SetPanel(new RegDisplayPanel(this, m_io_backend, ref)); + else + SetPanel(new NodeDisplayPanel(this, m_io_backend, ref)); } int RegTab::SetMessage(MessageWidget::MessageType type, const QString& msg) @@ -344,56 +293,45 @@ void RegTab::SetPanel(RegTabPanel *panel) m_right_panel->addWidget(m_right_content->GetWidget(), 1); } -void RegTab::OnSocListChanged() +void RegTab::OnSocAdded(const SocFileRef& ref) { - m_soc_selector->clear(); - QList< SocRef > socs = m_backend->GetSocList(); - for(int i = 0; i < socs.size(); i++) - { - QVariant v; - v.setValue(socs[i]); - m_soc_selector->addItem(QString::fromStdString(socs[i].GetSoc().name), v); - } + soc_desc::soc_ref_t soc = ref.GetSocFile()->GetSocRef(); + QVariant v; + v.setValue(soc); + m_soc_selector->addItem(QString::fromStdString(soc.get()->name), v); } -void RegTab::FillDevSubTree(QTreeWidgetItem *_item) +QTreeWidgetItem *RegTab::MakeNode(const soc_desc::node_inst_t& inst, const QString& s) { - 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]; - for(size_t j = 0; j < reg.addr.size(); j++) - { - RegTreeItem *reg_item = new RegTreeItem(reg.addr[j].name.c_str(), - SocRegRef(item->GetRef(), i, j)); - item->addChild(reg_item); - } - } + QTreeWidgetItem *item = new QTreeWidgetItem(QStringList(s)); + item->setData(0, NodeInstRole, QVariant::fromValue(inst)); + return item; } -void RegTab::FillSocSubTree(QTreeWidgetItem *_item) +soc_desc::node_inst_t RegTab::NodeInst(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++) + return item->data(0, NodeInstRole).value< soc_desc::node_inst_t >(); +} + +void RegTab::FillSubTree(QTreeWidgetItem *item) +{ + std::vector< soc_desc::node_inst_t > list = NodeInst(item).children(); + for(size_t i = 0; i < list.size(); i++) { - const soc_dev_t& dev = soc.dev[i]; - for(size_t j = 0; j < dev.addr.size(); j++) - { - DevTreeItem *dev_item = new DevTreeItem(dev.addr[j].name.c_str(), - SocDevRef(m_cur_soc, i, j)); - FillDevSubTree(dev_item); - item->addChild(dev_item); - } + QString name = QString::fromStdString(list[i].name()); + if(list[i].is_indexed()) + name = QString("%1[%2]").arg(name).arg(list[i].index()); + QTreeWidgetItem *child = MakeNode(list[i], name); + FillSubTree(child); + item->addChild(child); } } void RegTab::FillRegTree() { - SocTreeItem *soc_item = new SocTreeItem(m_cur_soc.GetSoc().name.c_str(), - m_cur_soc); - FillSocSubTree(soc_item); + QTreeWidgetItem *soc_item = MakeNode(m_cur_soc.root_inst(), + QString::fromStdString(m_cur_soc.get()->name)); + FillSubTree(soc_item); m_reg_tree->addTopLevelItem(soc_item); m_reg_tree->expandItem(soc_item); } @@ -401,7 +339,8 @@ void RegTab::FillRegTree() void RegTab::FillAnalyserList() { m_analysers_list->clear(); - m_analysers_list->addItems(AnalyserFactory::GetAnalysersForSoc(m_cur_soc.GetSoc().name.c_str())); + m_analysers_list->addItems(AnalyserFactory::GetAnalysersForSoc( + QString::fromStdString(m_cur_soc.get()->name))); } void RegTab::OnSocChanged(int index) @@ -409,7 +348,7 @@ void RegTab::OnSocChanged(int index) if(index == -1) return; m_reg_tree->clear(); - m_cur_soc = m_soc_selector->itemData(index).value< SocRef >(); + m_cur_soc = m_soc_selector->itemData(index).value< soc_desc::soc_ref_t >(); FillRegTree(); FillAnalyserList(); } @@ -426,7 +365,10 @@ void RegTab::OnDumpRegs(bool c) Q_UNUSED(c); QFileDialog *fd = new QFileDialog(this); fd->setAcceptMode(QFileDialog::AcceptSave); - fd->setFilter("Textual files (*.txt);;All files (*)"); + QStringList filters; + filters << "Textual files (*.txt)"; + filters << "All files (*)"; + fd->setNameFilters(filters); fd->setDirectory(Settings::Get()->value("regtab/loaddatadir", QDir::currentPath()).toString()); if(!fd->exec()) return; diff --git a/utils/regtools/qeditor/regtab.h b/utils/regtools/qeditor/regtab.h index a0fd5f305a..b56747f4d1 100644 --- a/utils/regtools/qeditor/regtab.h +++ b/utils/regtools/qeditor/regtab.h @@ -66,14 +66,13 @@ public: virtual QWidget *GetWidget(); protected: - void FillDevSubTree(QTreeWidgetItem *item); - void FillSocSubTree(QTreeWidgetItem *item); + QTreeWidgetItem *MakeNode(const soc_desc::node_inst_t& inst, const QString& s); + soc_desc::node_inst_t NodeInst(QTreeWidgetItem *item); + void FillSubTree(QTreeWidgetItem *item); void FillRegTree(); void FillAnalyserList(); void UpdateSocList(); - void DisplayRegister(const SocRegRef& ref); - void DisplayDevice(const SocDevRef& ref); - void DisplaySoc(const SocRef& ref); + void DisplayNode(const soc_desc::node_inst_t& ref); void SetDataSocName(const QString& socname); void SetPanel(RegTabPanel *panel); void UpdateSocFilename(); @@ -85,7 +84,7 @@ protected: BackendSelector *m_backend_selector; Backend *m_backend; QTreeWidget *m_reg_tree; - SocRef m_cur_soc; + soc_desc::soc_ref_t m_cur_soc; QVBoxLayout *m_right_panel; RegTabPanel *m_right_content; QCheckBox *m_readonly_check; @@ -102,7 +101,7 @@ protected: private slots: void SetReadOnlyIndicator(); void OnSocChanged(int index); - void OnSocListChanged(); + void OnSocAdded(const SocFileRef& ref); void OnRegItemClicked(QTreeWidgetItem *clicked, int col); void OnBackendSelect(IoBackend *backend); void OnDataChanged(); diff --git a/utils/regtools/qeditor/std_analysers.cpp b/utils/regtools/qeditor/std_analysers.cpp index 0fb2050cf0..05a90f9d5b 100644 --- a/utils/regtools/qeditor/std_analysers.cpp +++ b/utils/regtools/qeditor/std_analysers.cpp @@ -19,13 +19,44 @@ * ****************************************************************************/ #include "std_analysers.h" +#include + +/** + * AnalyserEx + */ + +AnalyserEx::AnalyserEx(const soc_desc::soc_ref_t& soc, IoBackend *backend) + :Analyser(soc, backend), m_helper(backend, soc) +{ +} + +bool AnalyserEx::ReadRegister(const QString& path, soc_word_t& val) +{ + return m_helper.ReadRegister(m_helper.ParsePath(path), val); +} + +bool AnalyserEx::ReadRegisterOld(const QString& dev, const QString& reg, soc_word_t& val) +{ + return ReadRegister(dev + "." + reg, val); +} + +bool AnalyserEx::ReadField(const QString& path, const QString& field, soc_word_t& val) +{ + return m_helper.ReadRegisterField(m_helper.ParsePath(path), field, val); +} + +bool AnalyserEx::ReadFieldOld(const QString& dev, const QString& reg, + const QString& field, soc_word_t& val) +{ + return ReadField(dev + "." + reg, field, val); +} /** * Clock analyser */ -ClockAnalyser::ClockAnalyser(const SocRef& soc, IoBackend *backend) - :Analyser(soc, backend) +ClockAnalyser::ClockAnalyser(const soc_desc::soc_ref_t& soc, IoBackend *backend) + :AnalyserEx(soc, backend) { m_group = new QGroupBox("Clock Analyser"); QVBoxLayout *layout = new QVBoxLayout; @@ -75,7 +106,8 @@ QString ClockAnalyser::GetFreq(unsigned freq) return QString().sprintf("%d Hz", freq); } -QTreeWidgetItem *ClockAnalyser::AddClock(QTreeWidgetItem *parent, const QString& name, int freq, int mul, int div) +QTreeWidgetItem *ClockAnalyser::AddClock(QTreeWidgetItem *parent, const QString& name, + int freq, int mul, int div) { if(freq == FROM_PARENT) { @@ -102,9 +134,9 @@ int ClockAnalyser::GetClockFreq(QTreeWidgetItem *item) void ClockAnalyser::FillTree() { m_tree_widget->clear(); - if(m_soc.GetSoc().name == "imx233") FillTreeIMX233(); - else if(m_soc.GetSoc().name == "rk27xx") FillTreeRK27XX(); - else if(m_soc.GetSoc().name == "atj213x") FillTreeATJ213X(); + if(m_soc.get()->name == "imx233") FillTreeIMX233(); + else if(m_soc.get()->name == "rk27xx") FillTreeRK27XX(); + else if(m_soc.get()->name == "atj213x") FillTreeATJ213X(); m_tree_widget->expandAll(); m_tree_widget->resizeColumnToContents(0); } @@ -113,17 +145,15 @@ void ClockAnalyser::FillTreeATJ213X() { soc_word_t pllbypass, pllclk, en, coreclks, tmp0, tmp1, tmp2, tmp3; - BackendHelper helper(m_io_backend, m_soc); - // system oscillators 32.768k and 24M QTreeWidgetItem *losc_clk = AddClock(0, "losc clk", 32768); QTreeWidgetItem *hosc_clk = AddClock(0, "hosc clk", 24000000); // core pll QTreeWidgetItem *corepll = 0; - if (helper.ReadRegisterField("CMU", "COREPLL", "CPEN", en) && - helper.ReadRegisterField("CMU", "COREPLL", "CPBY", pllbypass) && - helper.ReadRegisterField("CMU", "COREPLL", "CPCK", pllclk)) + if(ReadFieldOld("CMU", "COREPLL", "CPEN", en) && + ReadFieldOld("CMU", "COREPLL", "CPBY", pllbypass) && + ReadFieldOld("CMU", "COREPLL", "CPCK", pllclk)) { corepll = AddClock(hosc_clk, "core pll", en ? FROM_PARENT : DISABLED, pllbypass ? 1 : pllclk, pllbypass ? 1 : 4); @@ -135,8 +165,8 @@ void ClockAnalyser::FillTreeATJ213X() // dsp pll QTreeWidgetItem *dsppll = 0; - if (helper.ReadRegisterField("CMU", "DSPPLL", "DPEN", en) && - helper.ReadRegisterField("CMU", "DSPPLL", "DPCK", pllclk)) + if(ReadFieldOld("CMU", "DSPPLL", "DPEN", en) && + ReadFieldOld("CMU", "DSPPLL", "DPCK", pllclk)) { dsppll = AddClock(hosc_clk, "dsp pll", en ? FROM_PARENT : DISABLED, pllbypass ? 1 : pllclk, pllbypass ? 1 : 4); @@ -149,11 +179,11 @@ void ClockAnalyser::FillTreeATJ213X() // audio pll QTreeWidgetItem *adcpll = 0; QTreeWidgetItem *dacpll = 0; - if (helper.ReadRegisterField("CMU", "AUDIOPLL", "APEN", en) && - helper.ReadRegisterField("CMU", "AUDIOPLL", "ADCCLK", tmp0) && - helper.ReadRegisterField("CMU", "AUDIOPLL", "DACCLK", tmp1)) + if(ReadFieldOld("CMU", "AUDIOPLL", "APEN", en) && + ReadFieldOld("CMU", "AUDIOPLL", "ADCCLK", tmp0) && + ReadFieldOld("CMU", "AUDIOPLL", "DACCLK", tmp1)) { - if (en) + if(en) { adcpll = AddClock(hosc_clk, "audio adc pll", tmp0 ? 22579200 : 24576000); dacpll = AddClock(hosc_clk, "audio dac pll", tmp1 ? 22579200 : 24576000); @@ -173,8 +203,8 @@ void ClockAnalyser::FillTreeATJ213X() // audio clocks QTreeWidgetItem *adcclk = 0; QTreeWidgetItem *dacclk = 0; - if (helper.ReadRegisterField("CMU", "AUDIOPLL", "ADCCLK", tmp0) && - helper.ReadRegisterField("CMU", "AUDIOPLL", "DACCLK", tmp1)) + if(ReadFieldOld("CMU", "AUDIOPLL", "ADCCLK", tmp0) && + ReadFieldOld("CMU", "AUDIOPLL", "DACCLK", tmp1)) { adcclk = AddClock(adcpll, "audio adc clk", FROM_PARENT, 1, tmp0+1); dacclk = AddClock(dacpll, "audio dac clk", FROM_PARENT, 1, tmp1+1); @@ -187,14 +217,14 @@ void ClockAnalyser::FillTreeATJ213X() // cpu clock QTreeWidgetItem *cpuclk = 0; - if (helper.ReadRegisterField("CMU", "BUSCLK", "CORECLKS", coreclks) && - helper.ReadRegisterField("CMU", "BUSCLK", "CCLKDIV", tmp0)) + if(ReadFieldOld("CMU", "BUSCLK", "CORECLKS", coreclks) && + ReadFieldOld("CMU", "BUSCLK", "CCLKDIV", tmp0)) { - if (coreclks == 0) + if(coreclks == 0) cpuclk = AddClock(losc_clk, "cpu clk", FROM_PARENT, 1, tmp0+1); - else if (coreclks == 1) + else if(coreclks == 1) cpuclk = AddClock(hosc_clk, "cpu clk", FROM_PARENT, 1, tmp0+1); - else if (coreclks == 2) + else if(coreclks == 2) cpuclk = AddClock(corepll, "cpu clk", FROM_PARENT, 1, tmp0+1); else cpuclk = AddClock(corepll, "cpu clk", INVALID); @@ -206,24 +236,24 @@ void ClockAnalyser::FillTreeATJ213X() // system clock QTreeWidgetItem *sysclk = 0; - if (helper.ReadRegisterField("CMU", "BUSCLK", "SCLKDIV", tmp0)) + if(ReadFieldOld("CMU", "BUSCLK", "SCLKDIV", tmp0)) sysclk = AddClock(cpuclk, "system clk", FROM_PARENT, 1, tmp0+1); else sysclk = AddClock(cpuclk, "system clk", INVALID); // peripherial clk QTreeWidgetItem *pclk = 0; - if (helper.ReadRegisterField("CMU", "BUSCLK", "PCLKDIV", tmp0)) + if(ReadFieldOld("CMU", "BUSCLK", "PCLKDIV", tmp0)) pclk = AddClock(sysclk, "peripherial clk", FROM_PARENT, 1, tmp0 ? tmp0+1 : 2); else pclk = AddClock(sysclk, "peripherial clk", INVALID); // sdram clk QTreeWidgetItem *sdrclk = 0; - if (helper.ReadRegisterField("CMU", "DEVCLKEN", "SDRC", en) && - helper.ReadRegisterField("CMU", "DEVCLKEN", "SDRM", tmp0) && - helper.ReadRegisterField("SDR", "EN", "EN", tmp1) && - helper.ReadRegisterField("CMU", "SDRCLK", "SDRDIV", tmp2)) + if(ReadFieldOld("CMU", "DEVCLKEN", "SDRC", en) && + ReadFieldOld("CMU", "DEVCLKEN", "SDRM", tmp0) && + ReadFieldOld("SDR", "EN", "EN", tmp1) && + ReadFieldOld("CMU", "SDRCLK", "SDRDIV", tmp2)) { en &= tmp0 & tmp1; sdrclk = AddClock(sysclk, "sdram clk", en ? FROM_PARENT: DISABLED, 1, tmp2+1); @@ -233,18 +263,18 @@ void ClockAnalyser::FillTreeATJ213X() // nand clk QTreeWidgetItem *nandclk = 0; - if (helper.ReadRegisterField("CMU", "DEVCLKEN", "NAND", en) && - helper.ReadRegisterField("CMU", "NANDCLK", "NANDDIV", tmp0)) + if(ReadFieldOld("CMU", "DEVCLKEN", "NAND", en) && + ReadFieldOld("CMU", "NANDCLK", "NANDDIV", tmp0)) nandclk = AddClock(corepll, "nand clk", en ? FROM_PARENT : DISABLED, 1, tmp0+1); else nandclk = AddClock(corepll, "nand clk", INVALID); // sd clk QTreeWidgetItem *sdclk = 0; - if (helper.ReadRegisterField("CMU", "DEVCLKEN", "SD", tmp0) && - helper.ReadRegisterField("CMU", "SDCLK", "CKEN" , tmp1) && - helper.ReadRegisterField("CMU", "SDCLK", "D128" , tmp2) && - helper.ReadRegisterField("CMU", "SDCLK", "SDDIV" , tmp3)) + if(ReadFieldOld("CMU", "DEVCLKEN", "SD", tmp0) && + ReadFieldOld("CMU", "SDCLK", "CKEN" , tmp1) && + ReadFieldOld("CMU", "SDCLK", "D128" , tmp2) && + ReadFieldOld("CMU", "SDCLK", "SDDIV" , tmp3)) { en = tmp0 & tmp1; sdclk = AddClock(corepll, "sd clk", en ? FROM_PARENT : DISABLED, @@ -255,8 +285,8 @@ void ClockAnalyser::FillTreeATJ213X() // mha clk QTreeWidgetItem *mhaclk = 0; - if (helper.ReadRegisterField("CMU", "DEVCLKEN", "MHA", en) && - helper.ReadRegisterField("CMU", "MHACLK", "MHADIV", tmp1)) + if(ReadFieldOld("CMU", "DEVCLKEN", "MHA", en) && + ReadFieldOld("CMU", "MHACLK", "MHADIV", tmp1)) mhaclk = AddClock(corepll, "mha clk", en ? FROM_PARENT : DISABLED, 1, tmp1+1); else @@ -264,8 +294,8 @@ void ClockAnalyser::FillTreeATJ213X() // mca clk QTreeWidgetItem *mcaclk = 0; - if (helper.ReadRegisterField("CMU", "DEVCLKEN", "MCA", en) && - helper.ReadRegisterField("CMU", "MCACLK", "MCADIV", tmp1)) + if(ReadFieldOld("CMU", "DEVCLKEN", "MCA", en) && + ReadFieldOld("CMU", "MCACLK", "MCADIV", tmp1)) mcaclk = AddClock(corepll, "mca clk", en ? FROM_PARENT : DISABLED, 1, tmp1+1); else @@ -273,11 +303,11 @@ void ClockAnalyser::FillTreeATJ213X() // backlight pwm QTreeWidgetItem *pwmclk = 0; - if (helper.ReadRegisterField("CMU", "FMCLK", "BCKE", en) && - helper.ReadRegisterField("CMU", "FMCLK", "BCKS", tmp1) && - helper.ReadRegisterField("CMU", "FMCLK", "BCKCON", tmp2)) + if(ReadFieldOld("CMU", "FMCLK", "BCKE", en) && + ReadFieldOld("CMU", "FMCLK", "BCKS", tmp1) && + ReadFieldOld("CMU", "FMCLK", "BCKCON", tmp2)) { - if (tmp1) + if(tmp1) { // HOSC/8 input clk pwmclk = AddClock(hosc_clk, "pwm clk", en ? FROM_PARENT : DISABLED, @@ -296,9 +326,9 @@ void ClockAnalyser::FillTreeATJ213X() // i2c clk QTreeWidgetItem *i2c1clk = 0; QTreeWidgetItem *i2c2clk = 0; - if (helper.ReadRegisterField("CMU", "DEVCLKEN", "I2C", en) && - helper.ReadRegisterField("I2C1", "CTL", "EN", tmp0) && - helper.ReadRegisterField("I2C1", "CLKDIV", "CLKDIV", tmp1)) + if(ReadFieldOld("CMU", "DEVCLKEN", "I2C", en) && + ReadFieldOld("I2C1", "CTL", "EN", tmp0) && + ReadFieldOld("I2C1", "CLKDIV", "CLKDIV", tmp1)) { en &= tmp0; i2c1clk = AddClock(pclk, "i2c1 clk", en ? FROM_PARENT : DISABLED, @@ -309,16 +339,16 @@ void ClockAnalyser::FillTreeATJ213X() i2c1clk = AddClock(pclk, "i2c1 clk", INVALID); } - if (helper.ReadRegisterField("CMU", "DEVCLKEN", "I2C", en) && - helper.ReadRegisterField("I2C2", "CTL", "EN", tmp0) && - helper.ReadRegisterField("I2C2", "CLKDIV", "CLKDIV", tmp1)) + if(ReadFieldOld("CMU", "DEVCLKEN", "I2C", en) && + ReadFieldOld("I2C2", "CTL", "EN", tmp0) && + ReadFieldOld("I2C2", "CLKDIV", "CLKDIV", tmp1)) { en &= tmp0; i2c2clk = AddClock(pclk, "i2c2 clk", en ? FROM_PARENT : DISABLED, 1, 16*(tmp1+1)); } else - { + { i2c2clk = AddClock(pclk, "i2c2 clk", INVALID); } @@ -340,17 +370,15 @@ void ClockAnalyser::FillTreeRK27XX() soc_word_t value, value2, value3, value4; soc_word_t bypass, clkr, clkf, clkod, pll_off; - BackendHelper helper(m_io_backend, m_soc); - QTreeWidgetItem *xtal_clk = AddClock(0, "xtal clk", 24000000); // F = (Fref*F)/R/OD = (Fref*F)/R/OD QTreeWidgetItem *arm_pll = 0; - if (helper.ReadRegisterField("SCU", "PLLCON1", "ARM_PLL_BYPASS", bypass) && - helper.ReadRegisterField("SCU", "PLLCON1", "ARM_PLL_CLKR", clkr) && - helper.ReadRegisterField("SCU", "PLLCON1", "ARM_PLL_CLKF", clkf) && - helper.ReadRegisterField("SCU", "PLLCON1", "ARM_PLL_CLKOD", clkod) && - helper.ReadRegisterField("SCU", "PLLCON1", "ARM_PLL_POWERDOWN", pll_off)) + if(ReadFieldOld("SCU", "PLLCON1", "ARM_PLL_BYPASS", bypass) && + ReadFieldOld("SCU", "PLLCON1", "ARM_PLL_CLKR", clkr) && + ReadFieldOld("SCU", "PLLCON1", "ARM_PLL_CLKF", clkf) && + ReadFieldOld("SCU", "PLLCON1", "ARM_PLL_CLKOD", clkod) && + ReadFieldOld("SCU", "PLLCON1", "ARM_PLL_POWERDOWN", pll_off)) { arm_pll = AddClock(xtal_clk, "arm pll", pll_off ? DISABLED : FROM_PARENT, bypass ? 1 : clkf+1, bypass ? 1 : (clkr+1)*(clkod+1)); @@ -363,9 +391,9 @@ void ClockAnalyser::FillTreeRK27XX() QTreeWidgetItem *arm_clk = 0; QTreeWidgetItem *hclk = 0; QTreeWidgetItem *pclk = 0; - if(helper.ReadRegisterField("SCU", "DIVCON1", "ARM_SLOW_MODE", value) && - helper.ReadRegisterField("SCU", "DIVCON1", "ARM_CLK_DIV", value2) && - helper.ReadRegisterField("SCU", "DIVCON1", "PCLK_CLK_DIV", value3)) + if(ReadFieldOld("SCU", "DIVCON1", "ARM_SLOW_MODE", value) && + ReadFieldOld("SCU", "DIVCON1", "ARM_CLK_DIV", value2) && + ReadFieldOld("SCU", "DIVCON1", "PCLK_CLK_DIV", value3)) { arm_clk = AddClock(value ? xtal_clk : arm_pll, "arm clk", FROM_PARENT, 1, value2 ? 2 : 1); hclk = AddClock(arm_clk, "hclk", FROM_PARENT, 1, value2 ? 1 : 2); @@ -379,11 +407,11 @@ void ClockAnalyser::FillTreeRK27XX() } QTreeWidgetItem *dsp_pll = 0; - if (helper.ReadRegisterField("SCU", "PLLCON2", "DSP_PLL_BYPASS", bypass) && - helper.ReadRegisterField("SCU", "PLLCON2", "DSP_PLL_CLKR", clkr) && - helper.ReadRegisterField("SCU", "PLLCON2", "DSP_PLL_CLKF", clkf) && - helper.ReadRegisterField("SCU", "PLLCON2", "DSP_PLL_CLKOD", clkod) && - helper.ReadRegisterField("SCU", "PLLCON2", "DSP_PLL_POWERDOWN", pll_off)) + if(ReadFieldOld("SCU", "PLLCON2", "DSP_PLL_BYPASS", bypass) && + ReadFieldOld("SCU", "PLLCON2", "DSP_PLL_CLKR", clkr) && + ReadFieldOld("SCU", "PLLCON2", "DSP_PLL_CLKF", clkf) && + ReadFieldOld("SCU", "PLLCON2", "DSP_PLL_CLKOD", clkod) && + ReadFieldOld("SCU", "PLLCON2", "DSP_PLL_POWERDOWN", pll_off)) { dsp_pll = AddClock(xtal_clk, "dsp pll", pll_off ? DISABLED : FROM_PARENT, bypass ? 1 : clkf+1, bypass ? 1 : (clkr+1)*(clkod+1)); @@ -396,11 +424,11 @@ void ClockAnalyser::FillTreeRK27XX() QTreeWidgetItem *dsp_clk = AddClock(dsp_pll, "dsp clk", FROM_PARENT); QTreeWidgetItem *codec_pll = 0; - if (helper.ReadRegisterField("SCU", "PLLCON3", "CODEC_PLL_BYPASS", bypass) && - helper.ReadRegisterField("SCU", "PLLCON3", "CODEC_PLL_CLKR", clkr) && - helper.ReadRegisterField("SCU", "PLLCON3", "CODEC_PLL_CLKF", clkf) && - helper.ReadRegisterField("SCU", "PLLCON3", "CODEC_PLL_CLKOD", clkod) && - helper.ReadRegisterField("SCU", "PLLCON3", "CODEC_PLL_POWERDOWN", pll_off)) + if(ReadFieldOld("SCU", "PLLCON3", "CODEC_PLL_BYPASS", bypass) && + ReadFieldOld("SCU", "PLLCON3", "CODEC_PLL_CLKR", clkr) && + ReadFieldOld("SCU", "PLLCON3", "CODEC_PLL_CLKF", clkf) && + ReadFieldOld("SCU", "PLLCON3", "CODEC_PLL_CLKOD", clkod) && + ReadFieldOld("SCU", "PLLCON3", "CODEC_PLL_POWERDOWN", pll_off)) { codec_pll = AddClock(xtal_clk, "codec pll", pll_off ? DISABLED : FROM_PARENT, bypass ? 1 : clkf+1, bypass ? 1 : (clkr+1)*(clkod+1)); @@ -411,8 +439,8 @@ void ClockAnalyser::FillTreeRK27XX() } QTreeWidgetItem *codec_clk = 0; - if (helper.ReadRegisterField("SCU", "DIVCON1", "CODEC_CLK_SRC", value) && - helper.ReadRegisterField("SCU", "DIVCON1", "CODEC_CLK_DIV", value2)) + if(ReadFieldOld("SCU", "DIVCON1", "CODEC_CLK_SRC", value) && + ReadFieldOld("SCU", "DIVCON1", "CODEC_CLK_DIV", value2)) { codec_clk = AddClock(value ? xtal_clk : codec_pll, "codec clk", FROM_PARENT, 1, value ? 1 : (value2 + 1)); } @@ -422,7 +450,7 @@ void ClockAnalyser::FillTreeRK27XX() } QTreeWidgetItem *lsadc_clk = 0; - if (helper.ReadRegisterField("SCU", "DIVCON1", "LSADC_CLK_DIV", value)) + if(ReadFieldOld("SCU", "DIVCON1", "LSADC_CLK_DIV", value)) { lsadc_clk = AddClock(pclk, "lsadc clk", FROM_PARENT, 1, (value+1)); } @@ -432,11 +460,11 @@ void ClockAnalyser::FillTreeRK27XX() } QTreeWidgetItem *lcdc_clk = 0; - if (helper.ReadRegisterField("SCU", "DIVCON1", "LCDC_CLK", value) && - helper.ReadRegisterField("SCU", "DIVCON1", "LCDC_CLK_DIV", value2) && - helper.ReadRegisterField("SCU", "DIVCON1", "LCDC_CLK_DIV_SRC", value3)) + if(ReadFieldOld("SCU", "DIVCON1", "LCDC_CLK", value) && + ReadFieldOld("SCU", "DIVCON1", "LCDC_CLK_DIV", value2) && + ReadFieldOld("SCU", "DIVCON1", "LCDC_CLK_DIV_SRC", value3)) { - if (value) + if(value) { lcdc_clk = AddClock(xtal_clk, "lcdc clk", FROM_PARENT); } @@ -456,9 +484,9 @@ void ClockAnalyser::FillTreeRK27XX() } QTreeWidgetItem *pwm0_clk = 0; - if(helper.ReadRegisterField("PWM0", "LRC", "TR", value) && - helper.ReadRegisterField("PWM0", "CTRL", "PRESCALE", value3) && - helper.ReadRegisterField("PWM0", "CTRL", "PWM_EN", value4)) + if(ReadFieldOld("PWM0", "LRC", "TR", value) && + ReadFieldOld("PWM0", "CTRL", "PRESCALE", value3) && + ReadFieldOld("PWM0", "CTRL", "PWM_EN", value4)) { pwm0_clk = AddClock(pclk, "pwm0 clk", value4 ? FROM_PARENT : DISABLED, 1, 2*value*(1< g_clock_factory(true, "Clock Analyse /** * EMI analyser */ -EmiAnalyser::EmiAnalyser(const SocRef& soc, IoBackend *backend) - :Analyser(soc, backend) +EmiAnalyser::EmiAnalyser(const soc_desc::soc_ref_t& soc, IoBackend *backend) + :AnalyserEx(soc, backend) { m_display_mode = DisplayCycles; m_group = new QGroupBox("EMI Analyser"); @@ -870,26 +897,25 @@ void EmiAnalyser::FillTable() { while(m_panel->count() > 0) m_panel->removeItem(0); - BackendHelper helper(m_io_backend, m_soc); soc_word_t value; m_emi_freq = 0; - if(helper.ReadRegisterField("CLKCTRL", "CLKSEQ", "BYPASS_EMI", value)) + if(ReadFieldOld("CLKCTRL", "CLKSEQ", "BYPASS_EMI", value)) { bool ret; if(value) { m_emi_freq = 24000000; - ret = helper.ReadRegisterField("CLKCTRL", "EMI", "DIV_XTAL", value); + ret = ReadFieldOld("CLKCTRL", "EMI", "DIV_XTAL", value); } else { m_emi_freq = 480000000; - if(helper.ReadRegisterField("CLKCTRL", "FRAC", "EMIFRAC", value)) + if(ReadFieldOld("CLKCTRL", "FRAC", "EMIFRAC", value)) m_emi_freq = 18 * (int64_t)m_emi_freq / value; else m_emi_freq = 0; - ret = helper.ReadRegisterField("CLKCTRL", "EMI", "DIV_EMI", value); + ret = ReadFieldOld("CLKCTRL", "EMI", "DIV_EMI", value); } if(ret) m_emi_freq /= value; @@ -900,7 +926,7 @@ void EmiAnalyser::FillTable() m_emi_freq_label->setText(QString().sprintf("%.3f", m_emi_freq / 1000000.0)); NewGroup("Control Parameters"); - if(helper.ReadRegisterField("EMI", "CTRL", "PORT_PRIORITY_ORDER", value)) + if(ReadFieldOld("EMI", "CTRL", "PORT_PRIORITY_ORDER", value)) { QStringList ports; ports << "AXI0" << "AHB1" << "AHB2" << "AHB3"; @@ -913,38 +939,38 @@ void EmiAnalyser::FillTable() AddLine("Port Priority Order", value, "", order); } - if(helper.ReadRegisterField("EMI", "CTRL", "MEM_WIDTH", value)) + if(ReadFieldOld("EMI", "CTRL", "MEM_WIDTH", value)) AddLine("Memory Width", value ? 16 : 8, "-bit"); - if(helper.ReadRegisterField("DRAM", "CTL03", "AP", value)) + if(ReadFieldOld("DRAM", "CTL03", "AP", value)) AddLine("Auto Pre-Charge", NONE, value ? "Yes" : "No"); bool bypass_mode = false; - if(helper.ReadRegisterField("DRAM", "CTL04", "DLL_BYPASS_MODE", value)) + if(ReadFieldOld("DRAM", "CTL04", "DLL_BYPASS_MODE", value)) { bypass_mode = value == 1; AddLine("DLL Bypass Mode", NONE, value ? "Yes" : "No"); } - if(helper.ReadRegisterField("DRAM", "CTL05", "EN_LOWPOWER_MODE", value)) + if(ReadFieldOld("DRAM", "CTL05", "EN_LOWPOWER_MODE", value)) AddLine("Low Power Mode", NONE, value ? "Enabled" : "Disabled"); - if(helper.ReadRegisterField("DRAM", "CTL08", "SREFRESH", value)) + if(ReadFieldOld("DRAM", "CTL08", "SREFRESH", value)) AddLine("Self Refresh", NONE, value ? "Yes" : "No"); - if(helper.ReadRegisterField("DRAM", "CTL08", "SDR_MODE", value)) + if(ReadFieldOld("DRAM", "CTL08", "SDR_MODE", value)) AddLine("Mode", NONE, value ? "SDR" : "DDR"); - if(helper.ReadRegisterField("DRAM", "CTL10", "ADDR_PINS", value)) + if(ReadFieldOld("DRAM", "CTL10", "ADDR_PINS", value)) AddLine("Address Pins", 13 - value, ""); - if(helper.ReadRegisterField("DRAM", "CTL11", "COLUMN_SIZE", value)) + if(ReadFieldOld("DRAM", "CTL11", "COLUMN_SIZE", value)) AddLine("Column Size", 12 - value, "-bit"); - if(helper.ReadRegisterField("DRAM", "CTL11", "CASLAT", value)) + if(ReadFieldOld("DRAM", "CTL11", "CASLAT", value)) AddLine("Encoded CAS", value, "", "Memory device dependent"); - if(helper.ReadRegisterField("DRAM", "CTL14", "CS_MAP", value)) + if(ReadFieldOld("DRAM", "CTL14", "CS_MAP", value)) { QString v; for(int i = 0; i < 4; i++) @@ -957,12 +983,12 @@ void EmiAnalyser::FillTable() AddLine("Chip Select Pins", NONE, v, ""); } - if(helper.ReadRegisterField("DRAM", "CTL37", "TREF_ENABLE", value)) + if(ReadFieldOld("DRAM", "CTL37", "TREF_ENABLE", value)) AddLine("Refresh Commands", NONE, value ? "Enabled" : "Disabled", "Issue self-refresh every TREF cycles"); NewGroup("Frequency Parameters"); - if(helper.ReadRegisterField("DRAM", "CTL13", "CASLAT_LIN_GATE", value)) + if(ReadFieldOld("DRAM", "CTL13", "CASLAT_LIN_GATE", value)) { if(value >= 3 && value <= 10 && value != 9) { @@ -972,7 +998,7 @@ void EmiAnalyser::FillTable() else AddLine("CAS Gate", NONE, "Reserved", "Reserved value"); } - if(helper.ReadRegisterField("DRAM", "CTL13", "CASLAT_LIN", value)) + if(ReadFieldOld("DRAM", "CTL13", "CASLAT_LIN", value)) { if(value >= 3 && value <= 10 && value != 9) { @@ -983,97 +1009,97 @@ void EmiAnalyser::FillTable() AddLine("CAS Latency", NONE, "Reserved", "Reserved value"); } - if(helper.ReadRegisterField("DRAM", "CTL12", "TCKE", value)) + if(ReadFieldOld("DRAM", "CTL12", "TCKE", value)) AddCycleLine("tCKE", value, value, 0, "Minimum CKE pulse width"); - if(helper.ReadRegisterField("DRAM", "CTL15", "TDAL", value)) + if(ReadFieldOld("DRAM", "CTL15", "TDAL", value)) AddCycleLine("tDAL", value, value, 0, "Auto pre-charge write recovery time"); - if(helper.ReadRegisterField("DRAM", "CTL31", "TDLL", value)) + if(ReadFieldOld("DRAM", "CTL31", "TDLL", value)) AddCycleLine("tDLL", value, value, 0, "DLL lock time"); - if(helper.ReadRegisterField("DRAM", "CTL10", "TEMRS", value)) + if(ReadFieldOld("DRAM", "CTL10", "TEMRS", value)) AddCycleLine("tEMRS", value, value, 0, "Extended mode parameter set time"); - if(helper.ReadRegisterField("DRAM", "CTL34", "TINIT", value)) + if(ReadFieldOld("DRAM", "CTL34", "TINIT", value)) AddCycleLine("tINIT", value, value, 0, "Initialisation time"); - if(helper.ReadRegisterField("DRAM", "CTL16", "TMRD", value)) + if(ReadFieldOld("DRAM", "CTL16", "TMRD", value)) AddCycleLine("tMRD", value, value, 0, "Mode register set command time"); - if(helper.ReadRegisterField("DRAM", "CTL40", "TPDEX", value)) + if(ReadFieldOld("DRAM", "CTL40", "TPDEX", value)) AddCycleLine("tPDEX", value, value, 0, "Power down exit time"); - if(helper.ReadRegisterField("DRAM", "CTL32", "TRAS_MAX", value)) + if(ReadFieldOld("DRAM", "CTL32", "TRAS_MAX", value)) AddCycleLine("tRAS Max", value, value, 0, "Maximum row activate time"); - if(helper.ReadRegisterField("DRAM", "CTL20", "TRAS_MIN", value)) + if(ReadFieldOld("DRAM", "CTL20", "TRAS_MIN", value)) AddCycleLine("tRAS Min", value, value, 0, "Minimum row activate time"); - if(helper.ReadRegisterField("DRAM", "CTL17", "TRC", value)) + if(ReadFieldOld("DRAM", "CTL17", "TRC", value)) AddCycleLine("tRC", value, value, 0, "Activate to activate delay (same bank)"); - if(helper.ReadRegisterField("DRAM", "CTL20", "TRCD_INT", value)) + if(ReadFieldOld("DRAM", "CTL20", "TRCD_INT", value)) AddCycleLine("tRCD", value, value, 0, "RAS to CAS"); - if(helper.ReadRegisterField("DRAM", "CTL26", "TREF", value)) + if(ReadFieldOld("DRAM", "CTL26", "TREF", value)) AddCycleLine("tREF", value, value, 0, "Refresh to refresh time"); - if(helper.ReadRegisterField("DRAM", "CTL21", "TRFC", value)) + if(ReadFieldOld("DRAM", "CTL21", "TRFC", value)) AddCycleLine("tRFC", value, value, 0, "Refresh command time"); - if(helper.ReadRegisterField("DRAM", "CTL15", "TRP", value)) + if(ReadFieldOld("DRAM", "CTL15", "TRP", value)) AddCycleLine("tRP", value, value, 0, "Pre-charge command time"); - if(helper.ReadRegisterField("DRAM", "CTL12", "TRRD", value)) + if(ReadFieldOld("DRAM", "CTL12", "TRRD", value)) AddCycleLine("tRRD", value, value, 0, "Activate to activate delay (different banks)"); - if(helper.ReadRegisterField("DRAM", "CTL12", "TWR_INT", value)) + if(ReadFieldOld("DRAM", "CTL12", "TWR_INT", value)) AddCycleLine("tWR", value, value, 0, "Write recovery time"); - if(helper.ReadRegisterField("DRAM", "CTL13", "TWTR", value)) + if(ReadFieldOld("DRAM", "CTL13", "TWTR", value)) AddCycleLine("tWTR", value, value, 0, "Write to read delay"); - if(helper.ReadRegisterField("DRAM", "CTL32", "TXSNR", value)) + if(ReadFieldOld("DRAM", "CTL32", "TXSNR", value)) AddCycleLine("tXSNR", value, value, 0, ""); - if(helper.ReadRegisterField("DRAM", "CTL33", "TXSR", value)) + if(ReadFieldOld("DRAM", "CTL33", "TXSR", value)) AddCycleLine("tXSR", value, value, 0, "Self-refresh exit time"); NewGroup("DLL Parameters"); if(bypass_mode) { - if(helper.ReadRegisterField("DRAM", "CTL19", "DLL_DQS_DELAY_BYPASS_0", value)) + if(ReadFieldOld("DRAM", "CTL19", "DLL_DQS_DELAY_BYPASS_0", value)) AddLine("DLL DQS Delay 0", value, "", "In 1/128 fraction of a cycle (bypass mode)"); - if(helper.ReadRegisterField("DRAM", "CTL19", "DLL_DQS_DELAY_BYPASS_0", value)) + if(ReadFieldOld("DRAM", "CTL19", "DLL_DQS_DELAY_BYPASS_0", value)) AddLine("DLL DQS Delay 1", value, "", "In 1/128 fraction of a cycle (bypass mode)"); - if(helper.ReadRegisterField("DRAM", "CTL19", "DQS_OUT_SHIFT_BYPASS", value)) + if(ReadFieldOld("DRAM", "CTL19", "DQS_OUT_SHIFT_BYPASS", value)) AddLine("DQS Out Delay", value, "", "(bypass mode)"); - if(helper.ReadRegisterField("DRAM", "CTL20", "WR_DQS_SHIFT_BYPASS", value)) + if(ReadFieldOld("DRAM", "CTL20", "WR_DQS_SHIFT_BYPASS", value)) AddLine("DQS Write Delay", value, "", "(bypass mode)"); } else { - if(helper.ReadRegisterField("DRAM", "CTL17", "DLL_START_POINT", value)) + if(ReadFieldOld("DRAM", "CTL17", "DLL_START_POINT", value)) AddLine("DLL Start Point", value, "", "Initial delay count"); - if(helper.ReadRegisterField("DRAM", "CTL17", "DLL_INCREMENT", value)) + if(ReadFieldOld("DRAM", "CTL17", "DLL_INCREMENT", value)) AddLine("DLL Increment", value, "", "Delay increment"); - if(helper.ReadRegisterField("DRAM", "CTL18", "DLL_DQS_DELAY_0", value)) + if(ReadFieldOld("DRAM", "CTL18", "DLL_DQS_DELAY_0", value)) AddLine("DLL DQS Delay 0", value, "", "In 1/128 fraction of a cycle"); - if(helper.ReadRegisterField("DRAM", "CTL18", "DLL_DQS_DELAY_1", value)) + if(ReadFieldOld("DRAM", "CTL18", "DLL_DQS_DELAY_1", value)) AddLine("DLL DQS Delay 1", value, "", "In 1/128 fraction of a cycle"); - if(helper.ReadRegisterField("DRAM", "CTL19", "DQS_OUT_SHIFT", value)) + if(ReadFieldOld("DRAM", "CTL19", "DQS_OUT_SHIFT", value)) AddLine("DQS Out Delay", value, "", ""); - if(helper.ReadRegisterField("DRAM", "CTL20", "WR_DQS_SHIFT", value)) + if(ReadFieldOld("DRAM", "CTL20", "WR_DQS_SHIFT", value)) AddLine("DQS Write Delay", value, "", ""); } @@ -1090,8 +1116,8 @@ namespace pin_desc #include "../../imxtools/misc/map.h" } -PinAnalyser::PinAnalyser(const SocRef& soc, IoBackend *backend) - :Analyser(soc, backend) +PinAnalyser::PinAnalyser(const soc_desc::soc_ref_t& soc, IoBackend *backend) + :AnalyserEx(soc, backend) { m_group = new QGroupBox("Pin Analyser"); QVBoxLayout *layout = new QVBoxLayout; @@ -1129,7 +1155,6 @@ bool PinAnalyser::SupportSoc(const QString& soc_name) void PinAnalyser::FillList() { - BackendHelper helper(m_io_backend, m_soc); soc_word_t value; while(m_panel->count() > 0) @@ -1140,7 +1165,7 @@ void PinAnalyser::FillList() "bga169", "bga100", "lqfp100", "lqfp128", 0, 0, 0, 0 }; - if(!helper.ReadRegisterField("DIGCTL", "STATUS", "PACKAGE_TYPE", value)) + if(!ReadFieldOld("DIGCTL", "STATUS", "PACKAGE_TYPE", value)) { m_package_edit->setText(""); return; @@ -1199,21 +1224,21 @@ void PinAnalyser::FillList() uint32_t muxsel[2], drive[4], pull, in, out, oe; bool error = false; for(int i = 0; i < 2; i++) - if(!helper.ReadRegister("PINCTRL", QString("MUXSEL%1").arg(bank * 2 + i), muxsel[i])) + if(!ReadRegisterOld("PINCTRL", QString("MUXSELn[%1]").arg(bank * 2 + i), muxsel[i])) error = true; /* don't make an error for those since some do not exist */ for(int i = 0; i < 4; i++) - if(!helper.ReadRegister("PINCTRL", QString("DRIVE%1").arg(bank * 4 + i), drive[i])) + if(!ReadRegisterOld("PINCTRL", QString("DRIVEn[%1]").arg(bank * 4 + i), drive[i])) drive[i] = 0; if(error) continue; - if(!helper.ReadRegister("PINCTRL", QString("PULL%1").arg(bank), pull)) + if(!ReadRegisterOld("PINCTRL", QString("PULLn[%1]").arg(bank), pull)) pull = 0; - if(!helper.ReadRegister("PINCTRL", QString("DIN%1").arg(bank), in)) + if(!ReadRegisterOld("PINCTRL", QString("DINn[%1]").arg(bank), in)) in = 0; - if(!helper.ReadRegister("PINCTRL", QString("DOUT%1").arg(bank), out)) + if(!ReadRegisterOld("PINCTRL", QString("DOUTn[%1]").arg(bank), out)) out = 0; - if(!helper.ReadRegister("PINCTRL", QString("DOE%1").arg(bank), oe)) + if(!ReadRegisterOld("PINCTRL", QString("DOEn[%1]").arg(bank), oe)) oe = 0; for(int pin = 0; pin < 32; pin++) diff --git a/utils/regtools/qeditor/std_analysers.h b/utils/regtools/qeditor/std_analysers.h index 54e7b83862..030e010f58 100644 --- a/utils/regtools/qeditor/std_analysers.h +++ b/utils/regtools/qeditor/std_analysers.h @@ -35,14 +35,28 @@ #include #include "analyser.h" +class AnalyserEx : public Analyser +{ +public: + AnalyserEx(const soc_desc::soc_ref_t& soc, IoBackend *backend); +protected: + bool ReadRegister(const QString& path, soc_word_t& val); + bool ReadRegisterOld(const QString& dev, const QString& reg, soc_word_t& val); + bool ReadField(const QString& path, const QString& field, soc_word_t& val); + bool ReadFieldOld(const QString& dev, const QString& reg, const QString& field, + soc_word_t& val); + + BackendHelper m_helper; +}; + /** * Clock analyser */ -class ClockAnalyser : public Analyser +class ClockAnalyser : public AnalyserEx { public: - ClockAnalyser(const SocRef& soc, IoBackend *backend); + ClockAnalyser(const soc_desc::soc_ref_t& soc, IoBackend *backend); virtual ~ClockAnalyser(); virtual QWidget *GetWidget(); static bool SupportSoc(const QString& soc_name); @@ -72,11 +86,11 @@ private: /** * EMI analyser */ -class EmiAnalyser : public QObject, public Analyser +class EmiAnalyser : public QObject, public AnalyserEx { Q_OBJECT public: - EmiAnalyser(const SocRef& soc, IoBackend *backend); + EmiAnalyser(const soc_desc::soc_ref_t& soc, IoBackend *backend); virtual ~EmiAnalyser(); virtual QWidget *GetWidget(); @@ -116,10 +130,10 @@ private: /** * PINCTRL analyzer */ -class PinAnalyser : public Analyser +class PinAnalyser : public AnalyserEx { public: - PinAnalyser(const SocRef& soc, IoBackend *backend); + PinAnalyser(const soc_desc::soc_ref_t& soc, IoBackend *backend); virtual ~PinAnalyser(); virtual QWidget *GetWidget(); diff --git a/utils/regtools/qeditor/utils.cpp b/utils/regtools/qeditor/utils.cpp index 95b5a80c64..0d0a7de5ed 100644 --- a/utils/regtools/qeditor/utils.cpp +++ b/utils/regtools/qeditor/utils.cpp @@ -29,6 +29,7 @@ #include #include #include +#include /** * SocBitRangeValidator @@ -36,6 +37,7 @@ SocBitRangeValidator::SocBitRangeValidator(QObject *parent) :QValidator(parent) { + m_width = 32; } void SocBitRangeValidator::fixup(QString& input) const @@ -66,11 +68,11 @@ QValidator::State SocBitRangeValidator::parse(const QString& input, int& last, i // 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) + if(!ok || last < 0 || last >= m_width) return Invalid; } else - last = 31; + last = m_width - 1; // parse first bit if(pos < input.size() - 1) { @@ -88,6 +90,19 @@ QValidator::State SocBitRangeValidator::parse(const QString& input, int& last, i return Acceptable; } +void SocBitRangeValidator::setWidth(int nr_bits) +{ + m_width = nr_bits; +} + +QString SocBitRangeValidator::generate(int last_bit, int first_bit) const +{ + if(last_bit == first_bit) + return QString("%1").arg(first_bit); + else + return QString("%1:%2").arg(last_bit).arg(first_bit); +} + /** * SocFieldValidator */ @@ -95,11 +110,11 @@ QValidator::State SocBitRangeValidator::parse(const QString& input, int& last, i SocFieldValidator::SocFieldValidator(QObject *parent) :QValidator(parent) { - m_field.first_bit = 0; - m_field.last_bit = 31; + m_field.pos = 0; + m_field.width = 32; } -SocFieldValidator::SocFieldValidator(const soc_reg_field_t& field, QObject *parent) +SocFieldValidator::SocFieldValidator(const soc_desc::field_t& field, QObject *parent) :QValidator(parent), m_field(field) { } @@ -124,7 +139,7 @@ QValidator::State SocFieldValidator::parse(const QString& input, soc_word_t& val return Intermediate; // first check named values State state = Invalid; - foreach(const soc_reg_field_value_t& value, m_field.value) + foreach(const soc_desc::enum_t& value, m_field.enum_) { QString name = QString::fromLocal8Bit(value.name.c_str()); // cannot be a substring if too long or empty @@ -176,7 +191,7 @@ QValidator::State SocFieldValidator::parse(const QString& input, soc_word_t& val 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 nr_bits = m_field.width; unsigned long max = nr_bits == 32 ? 0xffffffff : (1 << nr_bits) - 1; if(v <= max) { @@ -308,14 +323,22 @@ QString SocFieldItemDelegate::displayText(const QVariant& value, const QLocale& return QStyledItemDelegate::displayText(value, locale); } +void SocFieldItemDelegate::setWidth(int bitcount) +{ + m_bitcount = bitcount; +} + /** * SocFieldEditor */ -SocFieldEditor::SocFieldEditor(const soc_reg_field_t& field, QWidget *parent) +SocFieldEditor::SocFieldEditor(const soc_desc::field_t& field, QWidget *parent) :QLineEdit(parent), m_reg_field(field) { m_validator = new SocFieldValidator(field); setValidator(m_validator); + connect(this, SIGNAL(editingFinished()), this, SLOT(editDone())); + setAlignment(Qt::AlignCenter); + setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Minimum); } SocFieldEditor::~SocFieldEditor() @@ -323,6 +346,11 @@ SocFieldEditor::~SocFieldEditor() delete m_validator; } +void SocFieldEditor::editDone() +{ + emit editingFinished(field()); +} + uint SocFieldEditor::field() const { soc_word_t v; @@ -336,11 +364,11 @@ uint SocFieldEditor::field() const void SocFieldEditor::setField(uint field) { m_field = field; - int digits = (m_reg_field.last_bit - m_reg_field.first_bit + 4) / 4; + int digits = (m_reg_field.width + 3) / 4; setText(QString("0x%1").arg(field, digits, 16, QChar('0'))); } -void SocFieldEditor::SetRegField(const soc_reg_field_t& field) +void SocFieldEditor::SetRegField(const soc_desc::field_t& field) { setValidator(0); delete m_validator; @@ -352,12 +380,30 @@ void SocFieldEditor::SetRegField(const soc_reg_field_t& field) /** * SocFieldCachedValue */ -SocFieldCachedValue::SocFieldCachedValue(const soc_reg_field_t& field, uint value) +SocFieldCachedValue::SocFieldCachedValue(const soc_desc::field_t& field, uint value) :m_field(field), m_value(value) { int idx = field.find_value(value); if(idx != -1) - m_name = QString::fromStdString(field.value[idx].name); + m_name = QString::fromStdString(field.enum_[idx].name); +} + +bool SocFieldCachedValue::operator<(const SocFieldCachedValue& o) const +{ + return m_value < o.m_value; +} + +/** + * SocFieldBitRange + */ + +bool SocFieldBitRange::operator<(const SocFieldBitRange& o) const +{ + if(m_first_bit < o.m_first_bit) + return true; + if(m_first_bit > o.m_first_bit) + return false; + return m_last_bit < o.m_last_bit; } /** @@ -372,11 +418,10 @@ SocFieldCachedItemDelegate::SocFieldCachedItemDelegate(QObject *parent) QString SocFieldCachedItemDelegate::displayText(const QVariant& value, const QLocale& locale) const { - // FIXME see QTBUG-30392 - if(value.type() == QVariant::UserType && value.userType() == qMetaTypeId< SocFieldCachedValue >()) + if(isUserType< SocFieldCachedValue >(value)) { const SocFieldCachedValue& v = value.value< SocFieldCachedValue >(); - int bitcount = v.field().last_bit - v.field().first_bit; + int bitcount = v.field().width; QString name = v.value_name(); QString strval = QString("0x%1").arg(v.value(), (bitcount + 3) / 4, 16, QChar('0')); switch(m_mode) @@ -410,7 +455,7 @@ QString SocFieldCachedItemDelegate::displayText(const QVariant& value, const QLo * SocFieldCachedEditor */ SocFieldCachedEditor::SocFieldCachedEditor(QWidget *parent) - :SocFieldEditor(soc_reg_field_t(), parent) + :SocFieldEditor(soc_desc::field_t(), parent) { } @@ -443,6 +488,11 @@ QByteArray SocFieldEditorCreator::valuePropertyName() const return QByteArray("field"); } +void SocFieldEditorCreator::setWidth(int bitcount) +{ + m_field.width = bitcount; +} + /** * SocFieldCachedEditorCreator */ @@ -478,8 +528,10 @@ int RegFieldTableModel::columnCount(const QModelIndex& /* parent */) const QVariant RegFieldTableModel::data(const QModelIndex& index, int role) const { + if(index.row() < 0 || (size_t)index.row() >= m_reg.field.size()) + return QVariant(); int section = index.column(); - const soc_reg_field_t& field = m_reg.field[index.row()]; + const soc_desc::field_t& field = m_reg.field[index.row()]; /* column independent code */ const RegThemeGroup *theme = 0; switch(m_status[index.row()]) @@ -609,7 +661,7 @@ void RegFieldTableModel::SetReadOnly(bool en) m_read_only = en; } -void RegFieldTableModel::SetRegister(const soc_reg_t& reg) +void RegFieldTableModel::SetRegister(const soc_desc::register_t& reg) { /* remove all rows */ beginResetModel(); @@ -622,6 +674,18 @@ void RegFieldTableModel::SetRegister(const soc_reg_t& reg) endInsertRows(); } +void RegFieldTableModel::UpdateRegister(const soc_desc::register_t& reg) +{ + m_reg = reg; + RecomputeTheme(); + emit dataChanged(index(0, 0), index(rowCount() - 1, columnCount() - 1)); +} + +soc_desc::register_t RegFieldTableModel::GetRegister() const +{ + return m_reg; +} + void RegFieldTableModel::SetValues(const QVector< QVariant >& values) { /* remove all value columns */ @@ -658,7 +722,7 @@ void RegFieldTableModel::RecomputeTheme() if(!m_theme.valid || m_value.size() == 0) continue; m_status[i] = Normal; - const soc_reg_field_t& field = m_reg.field[i]; + const soc_desc::field_t& field = m_reg.field[i]; QVariant val; for(int j = 0; j < m_value.size(); j++) { @@ -675,120 +739,269 @@ void RegFieldTableModel::RecomputeTheme() } /** - * RegSexyDisplay2 + * RegFieldProxyModel */ -RegSexyDisplay2::RegSexyDisplay2(QWidget *parent) +bool RegFieldProxyModel::lessThan(const QModelIndex& left, + const QModelIndex& right) const +{ + QVariant ldata = sourceModel()->data(left); + QVariant rdata = sourceModel()->data(right); + if(isUserType< SocFieldBitRange >(ldata) && + isUserType< SocFieldBitRange >(rdata)) + { + return ldata.value< SocFieldBitRange >() < + rdata.value< SocFieldBitRange >(); + } + else if(isUserType< SocFieldCachedValue >(ldata) && + isUserType< SocFieldCachedValue >(rdata)) + { + return ldata.value< SocFieldCachedValue >() < + rdata.value< SocFieldCachedValue >(); + } + else + return QSortFilterProxyModel::lessThan(left, right); +} + +/** + * YRegDisplayItemDelegate + */ + +YRegDisplayItemDelegate::YRegDisplayItemDelegate(QObject *parent) + :QStyledItemDelegate(parent) +{ +} + + void YRegDisplayItemDelegate::paint(QPainter *painter, + const QStyleOptionViewItem& option, const QModelIndex& index) const +{ + QStyleOptionViewItemV4 opt = option; + // default alignment is centered unless specified + opt.displayAlignment = Qt::AlignHCenter | Qt::AlignVCenter; + initStyleOption(&opt, index); + + painter->save(); + // draw everything rotated, requires careful manipulation of the + // rects involved + painter->translate(opt.rect.bottomLeft()); + painter->rotate(-90); + opt.rect = QRect(0, 0, opt.rect.height(), opt.rect.width()); + QStyle *style = opt.widget ? opt.widget->style() : QApplication::style(); + style->drawControl(QStyle::CE_ItemViewItem, &opt, painter, opt.widget); + painter->restore(); + +} + +QSize YRegDisplayItemDelegate::sizeHint(const QStyleOptionViewItem& option, + const QModelIndex& index) const +{ + Q_UNUSED(option); + Q_UNUSED(index); + return QSize(); +} + +/** + * YRegDisplay + */ + +YRegDisplay::YRegDisplay(QWidget *parent) :QAbstractItemView(parent) { m_is_dirty = true; + m_range_col = 0; + m_data_col = 1; + m_nr_bits = 32; // the frame around the register is ugly, disable it setFrameShape(QFrame::NoFrame); + setSelectionMode(SingleSelection); + setItemDelegate(new YRegDisplayItemDelegate()); } -QModelIndex RegSexyDisplay2::indexAt(const QPoint& point) const +void YRegDisplay::setWidth(int nr_bits) { - Q_UNUSED(point); + m_nr_bits = nr_bits; + m_is_dirty = true; + recomputeGeometry(); + updateGeometries(); +} + +int YRegDisplay::bitColumnAt(const QPoint& point, bool closest) const +{ + int wx = point.x() + horizontalScrollBar()->value(); + for(int bit = 0; bit < m_nr_bits; bit++) + { + int off = columnOffset(bitToColumn(bit)); + int w = columnWidth(bitToColumn(bit)); + if(wx >= off && wx < off + w) + return bit; + if(wx >= off + w && closest) + return bit; + } + return closest ? m_nr_bits - 1 : -1; +} + +QModelIndex YRegDisplay::indexAt(const QPoint& point) const +{ + if(!model()) + return QModelIndex(); + int wx = point.x() + horizontalScrollBar()->value(); + int wy = point.y() + verticalScrollBar()->value(); + + for(int i = 0; i < model()->rowCount(); i++) + { + QModelIndex index = model()->index(i, m_data_col, rootIndex()); + QRect r = itemRect(index); + if(!r.isValid()) + continue; + if(r.contains(wx, wy)) + return index; + } return QModelIndex(); } -void RegSexyDisplay2::scrollTo(const QModelIndex& index, ScrollHint hint) +void YRegDisplay::scrollTo(const QModelIndex& index, ScrollHint hint) { Q_UNUSED(index); Q_UNUSED(hint); } -QRect RegSexyDisplay2::visualRect(const QModelIndex& index) const +QRect YRegDisplay::visualRect(const QModelIndex &index) const { - Q_UNUSED(index); - return QRect(); + QRect rect = itemRect(index); + if(rect.isValid()) + return QRect(rect.left() - horizontalScrollBar()->value(), + rect.top() - verticalScrollBar()->value(), + rect.width(), rect.height()); + else + return rect; } -bool RegSexyDisplay2::isIndexHidden(const QModelIndex& index) const +bool YRegDisplay::isIndexHidden(const QModelIndex& index) const { Q_UNUSED(index); return false; } -QModelIndex RegSexyDisplay2::moveCursor(CursorAction cursorAction, Qt::KeyboardModifiers modifiers) +QModelIndex YRegDisplay::moveCursor(CursorAction cursorAction, Qt::KeyboardModifiers modifiers) { Q_UNUSED(cursorAction); Q_UNUSED(modifiers); return QModelIndex(); } -void RegSexyDisplay2::setSelection(const QRect& rect, QItemSelectionModel::SelectionFlags flags) +void YRegDisplay::setSelection(const QRect& r, QItemSelectionModel::SelectionFlags flags) { - Q_UNUSED(rect); - Q_UNUSED(flags); + if(!model()) + return; + QRect rect = r.translated(horizontalScrollBar()->value(), + verticalScrollBar()->value()).normalized(); + + QItemSelection sel; + for(int i = 0; i < model()->rowCount(); i++) + { + QModelIndex index = model()->index(i, m_data_col, rootIndex()); + QRect r = itemRect(index); + if(!r.isValid()) + continue; + if(r.intersects(rect)) + sel.select(index, index); + } + selectionModel()->select(sel, flags); } -int RegSexyDisplay2::verticalOffset() const +int YRegDisplay::verticalOffset() const { return verticalScrollBar()->value(); } -int RegSexyDisplay2::horizontalOffset() const +int YRegDisplay::horizontalOffset() const { return horizontalScrollBar()->value(); } -void RegSexyDisplay2::scrollContentsBy(int dx, int dy) +void YRegDisplay::scrollContentsBy(int dx, int dy) { viewport()->scroll(dx, dy); } -void RegSexyDisplay2::setModel(QAbstractItemModel *model) +void YRegDisplay::setModel(QAbstractItemModel *model) { QAbstractItemView::setModel(model); m_is_dirty = true; } -void RegSexyDisplay2::dataChanged(const QModelIndex &topLeft, +void YRegDisplay::dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight) { m_is_dirty = true; QAbstractItemView::dataChanged(topLeft, bottomRight); } -void RegSexyDisplay2::rowsInserted(const QModelIndex &parent, int start, int end) +void YRegDisplay::rowsInserted(const QModelIndex &parent, int start, int end) { m_is_dirty = true; QAbstractItemView::rowsInserted(parent, start, end); } -void RegSexyDisplay2::rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end) +void YRegDisplay::rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end) { m_is_dirty = true; QAbstractItemView::rowsAboutToBeRemoved(parent, start, end); } -int RegSexyDisplay2::GetSeparatorSize() const +int YRegDisplay::separatorSize() const { return 1; } -int RegSexyDisplay2::GetMarginSize() const +int YRegDisplay::marginSize() const { return viewOptions().fontMetrics.height() / 3; } -int RegSexyDisplay2::GetHeaderTextSep() const +int YRegDisplay::headerTextSep() const { - return GetMarginSize() / 2; + return marginSize() / 2; } -int RegSexyDisplay2::GetHeaderHeight() const +int YRegDisplay::headerHeight() const { - return 2 * GetMarginSize() + GetHeaderTextSep() + 2 * viewOptions().fontMetrics.height(); + return 2 * marginSize() + headerTextSep() + 2 * viewOptions().fontMetrics.height(); } -int RegSexyDisplay2::GetColumnWidth() const +int YRegDisplay::minColumnWidth() const { - return 2 * GetMarginSize() + viewOptions().fontMetrics.height(); + return 2 * marginSize() + viewOptions().fontMetrics.height(); } -int RegSexyDisplay2::GetMaxContentHeight() const +int YRegDisplay::maxColumnWidth() const +{ + return 2 * minColumnWidth(); +} + +int YRegDisplay::columnWidth(int col) const +{ + int avail = width() - (m_nr_bits + 1) * separatorSize(); + int small_w = qMin(avail / m_nr_bits, maxColumnWidth()); + int nr_big = avail - small_w * m_nr_bits; + if(col < nr_big) + return small_w + 1; + else + return small_w; +} + +int YRegDisplay::columnOffset(int col) const +{ + int off = separatorSize(); + for(int i = 0; i < col; i++) + off += columnWidth(i) + separatorSize(); + int all_w = off; + for(int i = col; i < m_nr_bits; i++) + all_w += columnWidth(i) + separatorSize(); + return off + (width() - all_w) / 2; +} + +int YRegDisplay::maxContentHeight() const { int max = 0; QFontMetrics metrics = viewOptions().fontMetrics; @@ -796,127 +1009,180 @@ int RegSexyDisplay2::GetMaxContentHeight() const { for(int i = 0; i < model()->rowCount(); i++) { - QModelIndex index = model()->index(i, 1, rootIndex()); + QModelIndex index = model()->index(i, m_data_col, rootIndex()); QString s = model()->data(index).toString(); max = qMax(max, metrics.boundingRect(s).width()); } } - return 2 * GetMarginSize() + max; + return 2 * marginSize() + max; } -int RegSexyDisplay2::GetGapHeight() const +int YRegDisplay::gapHeight() const { - return GetMarginSize() / 2; + return marginSize() / 2; } -QRegion RegSexyDisplay2::visualRegionForSelection(const QItemSelection& selection) const +int YRegDisplay::bitToColumn(int bit) const { - Q_UNUSED(selection); - return QRegion(); + return m_nr_bits - 1 - bit; } -void RegSexyDisplay2::paintEvent(QPaintEvent *event) +QRegion YRegDisplay::visualRegionForSelection(const QItemSelection& selection) const +{ + QRegion region; + foreach(const QItemSelectionRange &range, selection) + { + for(int row = range.top(); row <= range.bottom(); ++row) + { + for(int column = range.left(); column < range.right(); ++column) + { + QModelIndex index = model()->index(row, column, rootIndex()); + region += visualRect(index); + } + } + } + return region; +} + +QRect YRegDisplay::itemRect(const QModelIndex& index) const +{ + if(!index.isValid()) + return QRect(); + QVariant vrange = model()->data(model()->index(index.row(), m_range_col, rootIndex())); + if(!vrange.canConvert< SocFieldBitRange >()) + return QRect(); + SocFieldBitRange range = vrange.value< SocFieldBitRange >(); + return itemRect(range, index.column()); +} + +QRect YRegDisplay::itemRect(const SocFieldBitRange& range, int col) const +{ + int top, bot; + if(col == m_range_col) + { + top = separatorSize(); + bot = separatorSize() + headerHeight() - 1; + } + else if(col == m_data_col) + { + top = headerHeight() + 3 * separatorSize() + gapHeight(); + bot = height() - separatorSize() - 1; + } + else + return QRect(); + int first_col = bitToColumn(range.GetFirstBit()); + return QRect(QPoint(columnOffset(bitToColumn(range.GetLastBit())), top), + QPoint(columnOffset(first_col) + columnWidth(first_col) - 1, bot)); +} + +void YRegDisplay::paintEvent(QPaintEvent *event) { Q_UNUSED(event); - int txt_h = viewOptions().fontMetrics.height(); - int sep_sz = GetSeparatorSize(); - int w = qMax(m_minimum_width, viewport()->width()); - int h = qMax(m_minimum_height, viewport()->height()); - int nr_bits = 32; - int col_w = (w - (nr_bits + 1) * sep_sz) / nr_bits; - int hdr_h = GetHeaderHeight(); - int gap_h = GetGapHeight(); - int tot_w = (nr_bits + 1) * sep_sz + nr_bits * col_w; - int margin = GetMarginSize(); - int txt_sep = GetHeaderTextSep(); - int tot_hdr_sz = 2 * sep_sz + hdr_h; - - int x_shift = (w - tot_w) / 2; -#define ith_col_x(i) (x_shift + (i) * (sep_sz + col_w)) - QPainter painter(viewport()); painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing); painter.translate(-horizontalScrollBar()->value(), -verticalScrollBar()->value()); QStyleOptionViewItem option = viewOptions(); + int txt_h = option.fontMetrics.height(); + int grid_hint = style()->styleHint(QStyle::SH_Table_GridLineColor, &option, this); + QBrush grid_brush(static_cast< QRgb >(grid_hint)); QBrush back_brush = option.palette.base(); - QBrush line_brush = option.palette.dark(); + int sep_sz = separatorSize(); + QItemSelectionModel *selections = selectionModel(); - // fill interesting zone with base - painter.fillRect(event->rect(), option.palette.window()); - painter.fillRect(x_shift, 0, tot_w, h, back_brush); + // paint header + for(int bit = 0; bit < m_nr_bits; bit++) + { + QRect r = itemRect(SocFieldBitRange(bit, bit), m_range_col); + // paint background + painter.fillRect(r, back_brush); + // paint top digit + r.setTop(r.top() + marginSize()); + r.setBottom(r.top() + txt_h); + style()->drawItemText(&painter, r, Qt::AlignHCenter, option.palette, + true, QString("%1").arg(bit / 10), foregroundRole()); + // paint bottom digit + r.setTop(r.bottom() + headerTextSep()); + r.setBottom(r.top() + txt_h); + style()->drawItemText(&painter, r, Qt::AlignHCenter, option.palette, + true, QString("%1").arg(bit % 10), foregroundRole()); + } + // paint header grid + for(int bit = 1; bit < m_nr_bits; bit++) + { + QRect r = itemRect(SocFieldBitRange(bit, bit), m_range_col); + r.setCoords(r.right() + 1, r.top(), r.right() + sep_sz, r.bottom()); + if((bit % 4) == 0) + r.setCoords(r.left() - sep_sz, r.top(), r.right() + sep_sz, r.bottom()); + painter.fillRect(r, grid_brush); + } + QRect hdr_r = itemRect(SocFieldBitRange(0, m_nr_bits - 1), m_range_col); + painter.fillRect(QRect(hdr_r.left(), hdr_r.top() - sep_sz, hdr_r.width(), sep_sz), grid_brush); + painter.fillRect(QRect(hdr_r.left(), hdr_r.bottom() + 1, hdr_r.width(), sep_sz), grid_brush); + // paint header gap + QRect gap_r(hdr_r.left(), hdr_r.bottom() + sep_sz + 1, hdr_r.width(), gapHeight()); + painter.fillRect(gap_r, back_brush); + // paint header bottom line + painter.fillRect(QRect(gap_r.left(), gap_r.bottom() + 1, gap_r.width(), sep_sz), grid_brush); + // paint background + QRect data_r = itemRect(SocFieldBitRange(0, m_nr_bits - 1), m_data_col); + //painter.fillRect(data_r, back_brush); + // paint data bottom line + painter.fillRect(QRect(data_r.left(), data_r.bottom() + 1, data_r.width(), sep_sz), grid_brush); + // paint left/right lines + painter.fillRect(QRect(hdr_r.left() - sep_sz, hdr_r.top() - sep_sz, sep_sz, height()), grid_brush); + painter.fillRect(QRect(hdr_r.right() + 1, hdr_r.top() - sep_sz, sep_sz, height()), grid_brush); - // draw top and bottom lines - painter.setPen(QPen(line_brush, 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 < nr_bits; 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 < nr_bits; i++) + // paint model + if(!model()) + return; + + for(int i = 0; i < model()->rowCount(); i++) { - QRect r(ith_col_x(i), sep_sz + margin, col_w, txt_h); - painter.drawText(r, Qt::AlignCenter, QString("%1").arg((nr_bits - 1 - i) / 10)); - r.translate(0, txt_h + txt_sep); - painter.drawText(r, Qt::AlignCenter, QString("%1").arg((nr_bits - 1 - i) % 10)); + QModelIndex index = model()->index(i, m_data_col, rootIndex()); + QRect r = itemRect(index); + if(!r.isValid()) + continue; + QString name = index.data().toString(); + // paint background + QStyleOptionViewItem opt = viewOptions(); + opt.rect = r; + //opt.showDecorationSelected = true; + style()->drawPrimitive(QStyle::PE_PanelItemViewRow, &opt, &painter, this); + if(selections->isSelected(index)) + opt.state |= QStyle::State_Selected; + if(currentIndex() == index) + opt.state |= QStyle::State_HasFocus; + if(m_hover == index) + opt.state |= QStyle::State_MouseOver; + itemDelegate(index)->paint(&painter, opt, index); + // paint left/right lines + painter.fillRect(QRect(r.left() - sep_sz, r.top(), sep_sz, r.height()), grid_brush); + painter.fillRect(QRect(r.right() + 1, r.top(), sep_sz, r.height()), grid_brush); } - // display content - if(model()) - { - for(int i = 0; i < model()->rowCount(); i++) - { - QVariant vrange = model()->data(model()->index(i, 0, rootIndex())); - if(!vrange.canConvert< SocFieldBitRange >()) - continue; - SocFieldBitRange range = vrange.value< SocFieldBitRange >(); - QString name = model()->data(model()->index(i, 1, rootIndex())).toString(); - QRect r(QPoint(ith_col_x(nr_bits - 1 - range.GetLastBit()) + sep_sz, tot_hdr_sz), - QPoint(ith_col_x(nr_bits - range.GetFirstBit()), 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, name); - painter.restore(); - } - } -#undef ith_col_x } -void RegSexyDisplay2::RecomputeGeometry() +void YRegDisplay::recomputeGeometry() { if(!m_is_dirty) return; /* height: header + gap + sep + content + sep */ m_minimum_height = 0; - m_minimum_height += GetHeaderHeight() + GetGapHeight(); - m_minimum_height += 2 * GetSeparatorSize() + GetMaxContentHeight(); + m_minimum_height += headerHeight() + gapHeight(); + m_minimum_height += 2 * separatorSize() + maxContentHeight(); /* width: sep + (col + sep) * n */ - m_minimum_width = GetSeparatorSize() * 33 + GetColumnWidth() * 32; + m_minimum_width = separatorSize() * (m_nr_bits + 1) + minColumnWidth() * m_nr_bits; m_is_dirty = false; viewport()->update(); } -void RegSexyDisplay2::resizeEvent(QResizeEvent*) +void YRegDisplay::resizeEvent(QResizeEvent*) { m_is_dirty = true; - RecomputeGeometry(); + recomputeGeometry(); updateGeometries(); } -void RegSexyDisplay2::updateGeometries() +void YRegDisplay::updateGeometries() { horizontalScrollBar()->setSingleStep(1); horizontalScrollBar()->setPageStep(viewport()->width()); @@ -926,6 +1192,35 @@ void RegSexyDisplay2::updateGeometries() verticalScrollBar()->setRange(0, qMax(0, m_minimum_height - viewport()->height())); } +bool YRegDisplay::viewportEvent(QEvent *event) +{ + /* FIXME Apparently QAbstractItemView tracks the hovered index but keeps it + * in its private part which is not accessible, which makes it useless... + * This code reimplements it */ + switch (event->type()) + { + case QEvent::HoverEnter: + m_hover = indexAt(static_cast(event)->pos()); + update(m_hover); + break; + case QEvent::HoverLeave: + update(m_hover); // update old + m_hover = QModelIndex(); + break; + case QEvent::HoverMove: + { + QModelIndex old = m_hover; + m_hover = indexAt(static_cast(event)->pos()); + if(m_hover != old) + viewport()->update(visualRect(old)|visualRect(m_hover)); + break; + } + default: + break; + } + return QAbstractItemView::viewportEvent(event); +} + /** * GrowingTableView */ @@ -966,6 +1261,12 @@ MyTextEditor::MyTextEditor(QWidget *parent) QVBoxLayout *layout = new QVBoxLayout; m_toolbar = new QToolBar(this); m_edit = new QTextEdit(this); +#if QT_VERSION >= QT_VERSION_CHECK(5, 2, 0) + /* Qt 5.2 have a hardcoded sizeHint for QAbstractScrollArea which makes it + * hard to have a good behaviour for the text editor. Fortunately 5.2 introduces + * a new option to adjust this to the content. */ + m_edit->setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents); +#endif layout->addWidget(m_toolbar, 0); layout->addWidget(m_edit, 1); setLayout(layout); @@ -1000,8 +1301,11 @@ MyTextEditor::MyTextEditor(QWidget *parent) connect(m_edit, SIGNAL(currentCharFormatChanged(const QTextCharFormat&)), this, SLOT(OnCharFormatChanged(const QTextCharFormat&))); + m_edit->installEventFilter(this); + SetGrowingMode(false); SetReadOnly(false); + m_toolbar->hide(); } void MyTextEditor::SetReadOnly(bool en) @@ -1021,7 +1325,7 @@ void MyTextEditor::SetGrowingMode(bool en) { m_edit->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum); m_edit->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - OnTextChanged(); + OnInternalTextChanged(); } else { @@ -1036,10 +1340,11 @@ void MyTextEditor::OnInternalTextChanged() { 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->setMinimumHeight(content_size + m_edit->contentsMargins().top() + m_edit->contentsMargins().bottom()); } emit OnTextChanged(); + emit OnTextChanged(GetTextHtml()); } void MyTextEditor::OnTextBold(bool checked) @@ -1094,6 +1399,19 @@ bool MyTextEditor::IsModified() return m_edit->document()->isModified(); } +bool MyTextEditor::eventFilter(QObject *object, QEvent *event) +{ + if(object != m_edit) + return false; + if(m_read_only) + return false; + if(event->type() == QEvent::FocusIn) + m_toolbar->show(); + else if(event->type() == QEvent::FocusOut) + m_toolbar->hide(); + return false; +} + /** * BackendSelector */ @@ -1159,7 +1477,10 @@ void BackendSelector::OnDataSelChanged(int index) m_dev_selector->hide(); #endif QFileDialog *fd = new QFileDialog(m_data_selector); - fd->setFilter("Textual files (*.txt);;All files (*)"); + QStringList filters; + filters << "Textual files (*.txt)"; + filters << "All files (*)"; + fd->setNameFilters(filters); fd->setDirectory(Settings::Get()->value("regtab/loaddatadir", QDir::currentPath()).toString()); if(fd->exec()) { @@ -1251,6 +1572,47 @@ void BackendSelector::ChangeBackend(IoBackend *new_backend) m_io_backend = new_backend; } +/** + * YTabWidget + */ +YTabWidget::YTabWidget(QTabBar *bar, QWidget *parent) + :QTabWidget(parent) +{ + if(bar != 0) + setTabBar(bar); + m_tab_open_button = new QToolButton(this); + m_tab_open_button->setIcon(QIcon::fromTheme("list-add")); + m_tab_open_button->setAutoRaise(true); + m_tab_open_button->setPopupMode(QToolButton::InstantPopup); + /* the arrow with an icon only is pretty ugly and QToolButton has no way + * to remove the arrow programmaticaly, so use the CSS to do that */ + m_tab_open_button->setStyleSheet("QToolButton::menu-indicator { image: none; }"); + setCornerWidget(m_tab_open_button, Qt::TopLeftCorner); + setTabOpenable(false); + connect(m_tab_open_button, SIGNAL(clicked(bool)), this, SLOT(OnOpenButton(bool))); + /* there is a quirk in the default QStyle: if the tab bar is empty, it + * returns the minimum size of the corner widget, which is 0 for tool buttons */ + //setMinimumHeight(m_tab_open_button->height()); + //m_tab_open_button->setMinimumHeight(m_tab_open_button->sizeHint().height()); +} + +void YTabWidget::setTabOpenable(bool openable) +{ + m_tab_openable = openable; + m_tab_open_button->setVisible(openable); +} + +void YTabWidget::OnOpenButton(bool checked) +{ + Q_UNUSED(checked); + emit tabOpenRequested(); +} + +void YTabWidget::setTabOpenMenu(QMenu *menu) +{ + m_tab_open_button->setMenu(menu); +} + /** * MessageWidget */ @@ -1339,3 +1701,21 @@ void MessageWidget::OnClose(bool clicked) Q_UNUSED(clicked); hide(); } + +/** + * Misc + */ + +QGroupBox *Misc::EncloseInBox(const QString& name, QWidget *widget) +{ + QVBoxLayout *layout = new QVBoxLayout; + layout->addWidget(widget); + return Misc::EncloseInBox(name, layout); +} + +QGroupBox *Misc::EncloseInBox(const QString& name, QLayout *layout) +{ + QGroupBox *group = new QGroupBox(name); + group->setLayout(layout); + return group; +} diff --git a/utils/regtools/qeditor/utils.h b/utils/regtools/qeditor/utils.h index f3dbd15a22..026466fae0 100644 --- a/utils/regtools/qeditor/utils.h +++ b/utils/regtools/qeditor/utils.h @@ -38,9 +38,22 @@ #include #include #include +#include +#include #include "settings.h" #include "backend.h" +// FIXME see QTBUG-30392 +namespace +{ +template< typename T > +inline bool isUserType(const QVariant& var) +{ + return var.type() == QVariant::UserType && var.userType() == qMetaTypeId< T >(); +} + +} + class SocBitRangeValidator : public QValidator { Q_OBJECT @@ -51,6 +64,13 @@ public: 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; + /* create a valid string from range */ + QString generate(int last_bit, int first_bit) const; + /* set maximum width in bits */ + void setWidth(int nr_bits); + +protected: + int m_width; }; class SocFieldValidator : public QValidator @@ -58,7 +78,7 @@ class SocFieldValidator : public QValidator Q_OBJECT public: SocFieldValidator(QObject *parent = 0); - SocFieldValidator(const soc_reg_field_t& field, QObject *parent = 0); + SocFieldValidator(const soc_desc::field_t& field, QObject *parent = 0); virtual void fixup(QString& input) const; virtual State validate(QString& input, int& pos) const; @@ -66,7 +86,7 @@ public: State parse(const QString& input, soc_word_t& val) const; protected: - soc_reg_field_t m_field; + soc_desc::field_t m_field; }; class RegLineEdit : public QWidget @@ -112,10 +132,11 @@ 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) {} + SocFieldItemDelegate(const soc_desc::field_t& field, QObject *parent = 0) + :QStyledItemDelegate(parent), m_bitcount(field.width) {} virtual QString displayText(const QVariant& value, const QLocale& locale) const; + void setWidth(int bitcount); protected: int m_bitcount; }; @@ -125,44 +146,54 @@ 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); + SocFieldEditor(const soc_desc::field_t& field, QWidget *parent = 0); virtual ~SocFieldEditor(); uint field() const; void setField(uint field); - void SetRegField(const soc_reg_field_t& field); + void SetRegField(const soc_desc::field_t& field); + +signals: + void editingFinished(uint value); + +protected slots: + void editDone(); protected: SocFieldValidator *m_validator; uint m_field; - soc_reg_field_t m_reg_field; + soc_desc::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) {} + SocFieldEditorCreator() { m_field.pos = 0; m_field.width = 32; } + SocFieldEditorCreator(const soc_desc::field_t& field):m_field(field) {} virtual QWidget *createWidget(QWidget *parent) const; virtual QByteArray valuePropertyName() const; + void setWidth(int bitcount); + protected: - soc_reg_field_t m_field; + soc_desc::field_t m_field; }; class SocFieldCachedValue { public: SocFieldCachedValue():m_value(0) {} - SocFieldCachedValue(const soc_reg_field_t& field, uint value); + SocFieldCachedValue(const soc_desc::field_t& field, uint value); virtual ~SocFieldCachedValue() {} - const soc_reg_field_t& field() const { return m_field; } + const soc_desc::field_t& field() const { return m_field; } uint value() const { return m_value; } /* return empty string if there no match */ QString value_name() const { return m_name; } + + bool operator<(const SocFieldCachedValue& o) const; protected: - soc_reg_field_t m_field; + soc_desc::field_t m_field; uint m_value; QString m_name; }; @@ -172,11 +203,14 @@ Q_DECLARE_METATYPE(SocFieldCachedValue) class SocFieldBitRange { public: - SocFieldBitRange():m_first_bit(0),m_last_bit(0) {} - SocFieldBitRange(const soc_reg_field_t& field) - :m_first_bit(field.first_bit), m_last_bit(field.last_bit) {} + SocFieldBitRange():m_first_bit(0), m_last_bit(0) {} + SocFieldBitRange(const soc_desc::field_t& field) + :m_first_bit(field.pos), m_last_bit(field.pos + field.width - 1) {} + SocFieldBitRange(int first, int last):m_first_bit(first), m_last_bit(last) {} unsigned GetFirstBit() const { return m_first_bit; } unsigned GetLastBit() const { return m_last_bit; } + + bool operator<(const SocFieldBitRange& o) const; protected: unsigned m_first_bit, m_last_bit; }; @@ -248,14 +282,16 @@ class RegFieldTableModel : public QAbstractTableModel Q_OBJECT public: RegFieldTableModel(QObject *parent); - virtual int rowCount(const QModelIndex & parent = QModelIndex()) const; - virtual int columnCount(const QModelIndex & parent = QModelIndex()) const; - virtual QVariant data(const QModelIndex & index, int role) const; + virtual int rowCount(const QModelIndex& parent = QModelIndex()) const; + virtual int columnCount(const QModelIndex& parent = QModelIndex()) const; + virtual QVariant data(const QModelIndex& index, int role) const; virtual QVariant headerData(int section, Qt::Orientation orientation, int role) const; - virtual Qt::ItemFlags flags (const QModelIndex & index) const; + virtual Qt::ItemFlags flags(const QModelIndex& index) const; virtual bool setData(const QModelIndex& index, const QVariant& value, int role); - void SetRegister(const soc_reg_t& reg); + void SetRegister(const soc_desc::register_t& reg); + void UpdateRegister(const soc_desc::register_t& reg); + soc_desc::register_t GetRegister() const; /* values can either be an invalid QVariant() (means no value/error), or a * QVariant containing a soc_word_t */ void SetValues(const QVector< QVariant >& values); @@ -286,22 +322,44 @@ protected: Error }; - soc_reg_t m_reg; + soc_desc::register_t m_reg; QVector< QVariant > m_value; QVector< ColorStatus > m_status; RegTheme m_theme; bool m_read_only; }; -class RegSexyDisplay2 : public QAbstractItemView +class RegFieldProxyModel : public QSortFilterProxyModel +{ +public: + RegFieldProxyModel(QObject *parent):QSortFilterProxyModel(parent) {} +protected: + bool lessThan(const QModelIndex& left, const QModelIndex& right) const; +}; + +class YRegDisplayItemDelegate : public QStyledItemDelegate +{ +public: + YRegDisplayItemDelegate(QObject *parent = 0); + virtual void paint(QPainter * painter, const QStyleOptionViewItem& option, + const QModelIndex & index) const; + virtual QSize sizeHint(const QStyleOptionViewItem& option, + const QModelIndex & index) const; +}; + +class YRegDisplay : public QAbstractItemView { Q_OBJECT public: - RegSexyDisplay2(QWidget *parent = 0); + YRegDisplay(QWidget *parent = 0); virtual QModelIndex indexAt(const QPoint& point) const; virtual void scrollTo(const QModelIndex& index, ScrollHint hint = EnsureVisible); - virtual QRect visualRect(const QModelIndex& index ) const; + virtual QRect visualRect(const QModelIndex& index) const; virtual void setModel(QAbstractItemModel *model); + /* specify the number of bits to display */ + void setWidth(int nr_bits); + /* returns the bit column at a point, or -1 if none except if closest=true */ + int bitColumnAt(const QPoint& point, bool closest = true) const; protected slots: virtual void dataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight); @@ -311,14 +369,20 @@ protected slots: virtual void updateGeometries(); protected: - int GetMarginSize() const; // margin in cells - int GetSeparatorSize() const; // size of lines betweens cells - int GetColumnWidth() const; // width of a 1-bit column (excluding separators) - int GetHeaderHeight() const; // height of the header (excluding separators) - int GetGapHeight() const; // height of gap between header and fields - int GetMaxContentHeight() const; // maximum height of field columns - int GetHeaderTextSep() const; // height between digits in header - void RecomputeGeometry(); + int marginSize() const; // margin in cells + int separatorSize() const; // size of lines betweens cells + int minColumnWidth() const; // minimum width of a column (excluding separators) + int maxColumnWidth() const; // maximum width of a column (excluding separators) + int columnWidth(int col) const; // width of a 1-bit column (excluding separators) + int headerHeight() const; // height of the header (excluding separators) + int gapHeight() const; // height of gap between header and fields + int maxContentHeight() const; // maximum height of field columns + int headerTextSep() const; // height between digits in header + int columnOffset(int col) const; // column offset + int bitToColumn(int bit) const; // bit -> column + void recomputeGeometry(); + QRect itemRect(const SocFieldBitRange& range, int col) const; + QRect itemRect(const QModelIndex& index) const; virtual bool isIndexHidden(const QModelIndex& index) const; virtual QModelIndex moveCursor(CursorAction cursorAction, Qt::KeyboardModifiers modifiers); @@ -328,9 +392,13 @@ protected: virtual QRegion visualRegionForSelection(const QItemSelection& selection) const; virtual void paintEvent(QPaintEvent *event); virtual void resizeEvent(QResizeEvent* event); + virtual bool viewportEvent(QEvent * event); bool m_is_dirty; int m_minimum_width, m_minimum_height; + int m_range_col, m_data_col; + int m_nr_bits; + QModelIndex m_hover; }; /** @@ -387,8 +455,10 @@ public: void SetTextHtml(const QString& text); QString GetTextHtml(); bool IsModified(); + signals: void OnTextChanged(); + void OnTextChanged(const QString& text_html); protected slots: void OnInternalTextChanged(); @@ -398,6 +468,8 @@ protected slots: void OnCharFormatChanged(const QTextCharFormat& fmt); protected: + virtual bool eventFilter(QObject *object, QEvent *event); + bool m_growing_mode; bool m_read_only; QToolBar *m_toolbar; @@ -483,4 +555,35 @@ private slots: void OnClose(bool clicked); }; +Q_DECLARE_METATYPE(QModelIndex) + +class YTabWidget : public QTabWidget +{ + Q_OBJECT + Q_PROPERTY(bool tabOpenable READ tabOpenable WRITE setTabOpenable) +public: + YTabWidget(QTabBar *tabbar = 0, QWidget *parent = 0); + + inline bool tabOpenable() const { return m_tab_openable; } + void setTabOpenable(bool openable); + void setTabOpenMenu(QMenu *menu); + +signals: + void tabOpenRequested(); + +protected slots: + void OnOpenButton(bool checked); + +protected: + bool m_tab_openable; + QToolButton *m_tab_open_button; +}; + +class Misc +{ +public: + static QGroupBox *EncloseInBox(const QString& name, QWidget *widget); + static QGroupBox *EncloseInBox(const QString& name, QLayout *layout); +}; + #endif /* AUX_H */