summaryrefslogtreecommitdiff
path: root/utils
diff options
context:
space:
mode:
authorAmaury Pouly <amaury.pouly@gmail.com>2016-02-07 21:48:40 +0000
committerAmaury Pouly <amaury.pouly@gmail.com>2016-04-08 18:46:46 +0100
commit5ac0166388ac9a493491a30fbc3570f23950dc51 (patch)
tree8fe2019a8d3376042d1f92b7a2127bd73d3c97e3 /utils
parentcc4c9b70bcac048fc388d0f553b7621f52449526 (diff)
downloadrockbox-5ac0166388ac9a493491a30fbc3570f23950dc51.tar.gz
rockbox-5ac0166388ac9a493491a30fbc3570f23950dc51.zip
qeditor: port to the new hwstub library and add features
This commit adds support for the version of the hwstub library, which requires a lot of changes. It also adds some editing features, such as register access and much better editing of fields using the mouse (double click on a field to be able to resize and move it). Change-Id: I3c4e4cc855cb44911c72bc8127bad841b68efe52
Diffstat (limited to 'utils')
-rw-r--r--utils/imxtools/misc/map.h2
-rw-r--r--utils/regtools/qeditor/backend.cpp553
-rw-r--r--utils/regtools/qeditor/backend.h141
-rw-r--r--utils/regtools/qeditor/mainwindow.cpp38
-rw-r--r--utils/regtools/qeditor/qeditor.pro3
-rw-r--r--utils/regtools/qeditor/regdisplaypanel.cpp35
-rw-r--r--utils/regtools/qeditor/regedit.cpp136
-rw-r--r--utils/regtools/qeditor/regedit.h5
-rw-r--r--utils/regtools/qeditor/regtab.cpp38
-rw-r--r--utils/regtools/qeditor/utils.cpp594
-rw-r--r--utils/regtools/qeditor/utils.h178
11 files changed, 1394 insertions, 329 deletions
diff --git a/utils/imxtools/misc/map.h b/utils/imxtools/misc/map.h
index b94875ff6d..6143f91912 100644
--- a/utils/imxtools/misc/map.h
+++ b/utils/imxtools/misc/map.h
@@ -79,7 +79,7 @@ struct soc_t
79#define PIN_GROUP_PREFIX_NONE "" 79#define PIN_GROUP_PREFIX_NONE ""
80 80
81#define R(group,name,block) {PIN_GROUP_PREFIX_##group name, PIN_GROUP_##group, block} 81#define R(group,name,block) {PIN_GROUP_PREFIX_##group name, PIN_GROUP_##group, block}
82#define Q(group,block,name) R(group,STR(block)"_"name, block) 82#define Q(group,block,name) R(group,STR(block) "_" name, block)
83#define P(group,name) R(group,name,PIN_NO_BLOCK) 83#define P(group,name) R(group,name,PIN_NO_BLOCK)
84 84
85#define IO P(GPIO,"gpio") 85#define IO P(GPIO,"gpio")
diff --git a/utils/regtools/qeditor/backend.cpp b/utils/regtools/qeditor/backend.cpp
index 5f006b0aa7..a8264c6e50 100644
--- a/utils/regtools/qeditor/backend.cpp
+++ b/utils/regtools/qeditor/backend.cpp
@@ -22,6 +22,7 @@
22#include <QTextStream> 22#include <QTextStream>
23#include <QDebug> 23#include <QDebug>
24#include <QFileInfo> 24#include <QFileInfo>
25#include <QFont>
25#include "backend.h" 26#include "backend.h"
26 27
27/** 28/**
@@ -337,110 +338,436 @@ QString FileIoBackend::GetFileName()
337 338
338#ifdef HAVE_HWSTUB 339#ifdef HAVE_HWSTUB
339/** 340/**
340 * HWStubDevice 341 * HWStubManager
341 */ 342 */
342HWStubDevice::HWStubDevice(struct libusb_device *dev) 343HWStubManager *HWStubManager::g_inst = nullptr;
344
345HWStubManager::HWStubManager()
343{ 346{
344 Init(dev); 347 Add("Default", QString::fromStdString(hwstub::uri::default_uri().full_uri()));
345} 348}
346 349
347HWStubDevice::HWStubDevice(const HWStubDevice *dev) 350HWStubManager::~HWStubManager()
348{ 351{
349 Init(dev->m_dev);
350} 352}
351 353
352void HWStubDevice::Init(struct libusb_device *dev) 354HWStubManager *HWStubManager::Get()
353{ 355{
354 libusb_ref_device(dev); 356 if(g_inst == nullptr)
355 m_dev = dev; 357 g_inst = new HWStubManager();
356 m_handle = 0; 358 return g_inst;
357 m_hwdev = 0;
358 m_valid = Probe();
359} 359}
360 360
361HWStubDevice::~HWStubDevice() 361bool HWStubManager::Add(const QString& name, const QString& uri)
362{
363 struct Context ctx;
364 ctx.name = name;
365 ctx.uri = uri;
366 ctx.context = hwstub::uri::create_context(uri.toStdString());
367 if(!ctx.context)
368 return false;
369 ctx.context->start_polling();
370 beginInsertRows(QModelIndex(), m_list.size(), m_list.size());
371 m_list.push_back(ctx);
372 endInsertRows();
373 return true;
374}
375
376void HWStubManager::Clear()
362{ 377{
363 Close(); 378 m_list.clear();
364 libusb_unref_device(m_dev);
365} 379}
366 380
367int HWStubDevice::GetBusNumber() 381int HWStubManager::rowCount(const QModelIndex& parent) const
368{ 382{
369 return libusb_get_bus_number(m_dev); 383 Q_UNUSED(parent);
384 return m_list.size();
370} 385}
371 386
372int HWStubDevice::GetDevAddress() 387int HWStubManager::columnCount(const QModelIndex& parent) const
373{ 388{
374 return libusb_get_device_address(m_dev); 389 Q_UNUSED(parent);
390 return 2;
375} 391}
376 392
377bool HWStubDevice::Probe() 393std::shared_ptr< hwstub::context > HWStubManager::GetContext(int row)
378{ 394{
379 if(!Open()) 395 if(row < 0 || (size_t)row >= m_list.size())
380 return false; 396 return std::shared_ptr< hwstub::context >();
381 // get target 397 else
382 int ret = hwstub_get_desc(m_hwdev, HWSTUB_DT_TARGET, &m_hwdev_target, sizeof(m_hwdev_target)); 398 return m_list[row].context;
383 if(ret != sizeof(m_hwdev_target)) 399}
384 goto Lerr; 400
385 // get STMP information 401QVariant HWStubManager::data(const QModelIndex& index, int role) const
386 if(m_hwdev_target.dID == HWSTUB_TARGET_STMP) 402{
403 if(index.row() < 0 || (size_t)index.row() >= m_list.size())
404 return QVariant();
405 int section = index.column();
406 const Context& ctx = m_list[index.row()];
407 if(section == GetNameColumn())
387 { 408 {
388 ret = hwstub_get_desc(m_hwdev, HWSTUB_DT_STMP, &m_hwdev_stmp, sizeof(m_hwdev_stmp)); 409 if(role == Qt::DisplayRole || role == Qt::EditRole)
389 if(ret != sizeof(m_hwdev_stmp)) 410 return QVariant(ctx.name);
390 goto Lerr;
391 } 411 }
392 else if(m_hwdev_target.dID == HWSTUB_TARGET_PP) 412 else if(section == GetUriColumn())
393 { 413 {
394 ret = hwstub_get_desc(m_hwdev, HWSTUB_DT_PP, &m_hwdev_pp, sizeof(m_hwdev_pp)); 414 if(role == Qt::DisplayRole)
395 if(ret != sizeof(m_hwdev_pp)) 415 return QVariant(ctx.uri);
396 goto Lerr;
397 } 416 }
398 Close(); 417 return QVariant();
399 return true; 418}
400 419
401 Lerr: 420QVariant HWStubManager::headerData(int section, Qt::Orientation orientation, int role) const
402 Close(); 421{
403 return false; 422 if(orientation == Qt::Vertical)
423 return QVariant();
424 if(role != Qt::DisplayRole)
425 return QVariant();
426 if(section == GetNameColumn())
427 return QVariant("Name");
428 else if(section == GetUriColumn())
429 return QVariant("URI");
430 return QVariant();
431}
432
433Qt::ItemFlags HWStubManager::flags(const QModelIndex& index) const
434{
435 Qt::ItemFlags flags = Qt::ItemIsSelectable | Qt::ItemIsEnabled;
436 int section = index.column();
437 if(section == GetNameColumn())
438 flags |= Qt::ItemIsEditable;
439 return flags;
404} 440}
405 441
406bool HWStubDevice::Open() 442bool HWStubManager::setData(const QModelIndex& index, const QVariant& value, int role)
407{ 443{
408 if(libusb_open(m_dev, &m_handle)) 444 if(role != Qt::EditRole)
409 return false; 445 return false;
410 m_hwdev = hwstub_open(m_handle); 446 if(index.row() < 0 || (size_t)index.row() >= m_list.size())
411 if(m_hwdev == 0)
412 {
413 libusb_close(m_handle);
414 m_handle = 0;
415 return false; 447 return false;
416 } 448 if(index.column() != GetNameColumn())
449 return false;
450 m_list[index.row()].name = value.toString();
451 emit dataChanged(index, index);
417 return true; 452 return true;
418} 453}
419 454
420void HWStubDevice::Close() 455int HWStubManager::GetNameColumn() const
421{ 456{
422 if(m_hwdev) 457 return 0;
423 hwstub_release(m_hwdev);
424 m_hwdev = 0;
425 if(m_handle)
426 libusb_close(m_handle);
427 m_handle = 0;
428} 458}
429 459
430bool HWStubDevice::ReadMem(soc_addr_t addr, size_t length, void *buffer) 460int HWStubManager::GetUriColumn() const
461{
462 return 1;
463}
464
465QString HWStubManager::GetFriendlyName(std::shared_ptr< hwstub::device > device)
466{
467 /* try to open the device */
468 std::shared_ptr< hwstub::handle > handle;
469 hwstub::error err = device->open(handle);
470 if(err != hwstub::error::SUCCESS)
471 goto Lfallback;
472 /* get target descriptor */
473 struct hwstub_target_desc_t target_desc;
474 err = handle->get_target_desc(target_desc);
475 if(err != hwstub::error::SUCCESS)
476 goto Lfallback;
477 return QString::fromStdString(target_desc.bName);
478
479 /* fallback: don't open the device */
480Lfallback:
481 hwstub::usb::device *udev = dynamic_cast< hwstub::usb::device* >(device.get());
482 if(udev)
483 {
484 return QString("USB Bus %1 Device %2: ID %3:%4")
485 .arg(udev->get_bus_number()).arg(udev->get_address(), 3, 10, QChar('0'))
486 .arg(udev->get_vid(), 4, 16, QChar('0')).arg(udev->get_pid(), 4, 16, QChar('0'));
487 }
488 else
489 return QString("<Unknown device>");
490}
491
492/**
493 * HWStubContextModel
494 */
495HWStubContextModel::HWStubContextModel(QObject *parent)
496 :QAbstractTableModel(parent), m_has_dummy(false)
497{
498}
499
500HWStubContextModel::~HWStubContextModel()
501{
502 SetContext(std::shared_ptr< hwstub::context >());
503}
504
505void HWStubContextModel::SetContext(std::shared_ptr< hwstub::context > context)
506{
507 int first_row = m_has_dummy ? 1: 0;
508 /* clear previous model if any */
509 if(m_list.size() > 0)
510 {
511 beginRemoveRows(QModelIndex(), first_row, first_row + m_list.size() - 1);
512 m_list.clear();
513 endRemoveRows();
514 }
515 /* don't forget to unregister callback if context still exists */
516 std::shared_ptr< hwstub::context > ctx = m_context.lock();
517 if(ctx)
518 ctx->unregister_callback(m_callback_ref);
519 /* get new context */
520 m_context = context;
521 if(context)
522 {
523 /* register new callback */
524 m_callback_ref = context->register_callback(
525 std::bind(&HWStubContextModel::OnDevChangeLow, this, std::placeholders::_1,
526 std::placeholders::_2, std::placeholders::_3));
527 /* get dev list */
528 std::vector< std::shared_ptr< hwstub::device > > list;
529 hwstub::error err = context->get_device_list(list);
530 if(err == hwstub::error::SUCCESS)
531 {
532 beginInsertRows(QModelIndex(), first_row, first_row + list.size() - 1);
533 for(auto& d : list)
534 {
535 Device dev;
536 dev.name = GetFriendlyName(d);
537 dev.device = d;
538 m_list.push_back(dev);
539 }
540 endInsertRows();
541 }
542 }
543}
544
545void HWStubContextModel::EnableDummy(bool en, const QString& text)
546{
547 /* if needed, create/remove raw */
548 if(m_has_dummy && !en)
549 {
550 /* remove row */
551 beginRemoveRows(QModelIndex(), 0, 0);
552 m_has_dummy = false;
553 endRemoveRows();
554 }
555 else if(!m_has_dummy && en)
556 {
557 /* add row */
558 beginInsertRows(QModelIndex(), 0, 0);
559 m_has_dummy = true;
560 m_dummy_text = text;
561 endInsertRows();
562 }
563 else if(en)
564 {
565 /* text change only */
566 emit dataChanged(index(0, GetNameColumn()), index(0, GetNameColumn()));
567 }
568}
569
570int HWStubContextModel::rowCount(const QModelIndex& parent) const
571{
572 Q_UNUSED(parent);
573 return m_list.size() + (m_has_dummy ? 1 : 0);
574}
575
576int HWStubContextModel::columnCount(const QModelIndex& parent) const
577{
578 Q_UNUSED(parent);
579 return 1;
580}
581
582QVariant HWStubContextModel::data(const QModelIndex& index, int role) const
583{
584 int first_row = m_has_dummy ? 1: 0;
585 /* special case for dummy */
586 if(m_has_dummy && index.row() == 0)
587 {
588 int section = index.column();
589 if(section == GetNameColumn())
590 {
591 if(role == Qt::DisplayRole)
592 return QVariant(m_dummy_text);
593 else if(role == Qt::FontRole)
594 {
595 QFont font;
596 font.setItalic(true);
597 return QVariant(font);
598 }
599 }
600 return QVariant();
601 }
602
603 if(index.row() < first_row || (size_t)index.row() >= first_row + m_list.size())
604 return QVariant();
605 int section = index.column();
606 if(section == GetNameColumn())
607 {
608 if(role == Qt::DisplayRole)
609 return QVariant(m_list[index.row() - first_row].name);
610 }
611 return QVariant();
612}
613
614QVariant HWStubContextModel::headerData(int section, Qt::Orientation orientation, int role) const
615{
616 if(orientation == Qt::Vertical)
617 return QVariant();
618 if(role != Qt::DisplayRole)
619 return QVariant();
620 if(section == GetNameColumn())
621 return QVariant("Friendly name");
622 return QVariant();
623}
624
625Qt::ItemFlags HWStubContextModel::flags(const QModelIndex& index) const
626{
627 Q_UNUSED(index);
628 return Qt::ItemIsSelectable | Qt::ItemIsEnabled;
629}
630
631int HWStubContextModel::GetNameColumn() const
632{
633 return 0;
634}
635
636std::shared_ptr< hwstub::device > HWStubContextModel::GetDevice(int row)
637{
638 int first_row = m_has_dummy ? 1: 0;
639 /* special case for dummy */
640 if(row < first_row || (size_t)row >= first_row + m_list.size())
641 return std::shared_ptr< hwstub::device >();
642 else
643 return m_list[row - first_row].device;
644}
645
646QString HWStubContextModel::GetFriendlyName(std::shared_ptr< hwstub::device > device)
431{ 647{
432 if(!m_hwdev) 648 return HWStubManager::GetFriendlyName(device);
649}
650
651namespace
652{
653 struct dev_change_t
654 {
655 std::shared_ptr< hwstub::context > ctx;
656 bool arrived;
657 std::shared_ptr< hwstub::device > device;
658 };
659}
660
661void HWStubContextModel::OnDevChangeLow(std::shared_ptr< hwstub::context > ctx,
662 bool arrived, std::shared_ptr< hwstub::device > device)
663{
664 /* calling Qt function from non-Qt thread is unsafe. Since the polling thread
665 * is a pthread, the safest way to use Qt invoke mecanism to make it run
666 * on the event loop */
667 dev_change_t *evt = new dev_change_t;
668 evt->ctx = ctx;
669 evt->arrived = arrived;
670 evt->device = device;
671 QMetaObject::invokeMethod(this, "OnDevChangeUnsafe", Q_ARG(void *, (void *)evt));
672}
673
674void HWStubContextModel::OnDevChangeUnsafe(void *data)
675{
676 dev_change_t *evt = (dev_change_t *)data;
677 OnDevChange(evt->ctx, evt->arrived, evt->device);
678 delete evt;
679}
680
681void HWStubContextModel::OnDevChange(std::shared_ptr< hwstub::context > ctx, bool arrived,
682 std::shared_ptr< hwstub::device > device)
683{
684 int first_row = m_has_dummy ? 1: 0;
685 Q_UNUSED(ctx);
686 if(arrived)
687 {
688 Device dev;
689 dev.name = GetFriendlyName(device);
690 dev.device = device;
691 beginInsertRows(QModelIndex(), first_row + m_list.size(),
692 first_row + m_list.size());
693 m_list.push_back(dev);
694 endInsertRows();
695 }
696 else
697 {
698 /* find device in the list */
699 auto it = m_list.begin();
700 int idx = 0;
701 for(; it != m_list.end(); ++it, ++idx)
702 if(it->device == device)
703 break;
704 if(it == m_list.end())
705 return;
706 /* remove it */
707 beginRemoveRows(QModelIndex(), first_row + idx, first_row + idx);
708 m_list.erase(it);
709 endRemoveRows();
710 }
711}
712
713/**
714 * HWStubDevice
715 */
716HWStubDevice::HWStubDevice(std::shared_ptr< hwstub::device > device)
717{
718 m_valid = Probe(device);
719}
720
721HWStubDevice::~HWStubDevice()
722{
723}
724
725bool HWStubDevice::Probe(std::shared_ptr<hwstub::device> device)
726{
727 if(!device)
433 return false; 728 return false;
434 int ret = hwstub_rw_mem_atomic(m_hwdev, 1, addr, buffer, length); 729 hwstub::error err = device->open(m_handle);
435 return ret >= 0 && (size_t)ret == length; 730 if(err != hwstub::error::SUCCESS)
731 return false;
732 // get target information
733 err = m_handle->get_target_desc(m_hwdev_target);
734 if(err != hwstub::error::SUCCESS)
735 return false;
736 // get STMP/PP information
737 if(m_hwdev_target.dID == HWSTUB_TARGET_STMP)
738 {
739 err = m_handle->get_stmp_desc(m_hwdev_stmp);
740 if(err != hwstub::error::SUCCESS)
741 return false;
742 }
743 else if(m_hwdev_target.dID == HWSTUB_TARGET_PP)
744 {
745 err = m_handle->get_pp_desc(m_hwdev_pp);
746 if(err != hwstub::error::SUCCESS)
747 return false;
748 }
749 else if(m_hwdev_target.dID == HWSTUB_TARGET_JZ)
750 {
751 err = m_handle->get_jz_desc(m_hwdev_jz);
752 if(err != hwstub::error::SUCCESS)
753 return false;
754 }
755 m_name = HWStubManager::GetFriendlyName(device);
756 return true;
757}
758
759bool HWStubDevice::ReadMem(soc_addr_t addr, size_t length, void *buffer)
760{
761 size_t len = length;
762 hwstub::error err = m_handle->read(addr, buffer, len, true);
763 return err == hwstub::error::SUCCESS && len == length;
436} 764}
437 765
438bool HWStubDevice::WriteMem(soc_addr_t addr, size_t length, void *buffer) 766bool HWStubDevice::WriteMem(soc_addr_t addr, size_t length, void *buffer)
439{ 767{
440 if(!m_hwdev) 768 size_t len = length;
441 return false; 769 hwstub::error err = m_handle->write(addr, buffer, len, true);
442 int ret = hwstub_rw_mem_atomic(m_hwdev, 0, addr, buffer, length); 770 return err == hwstub::error::SUCCESS && len == length;
443 return ret >= 0 && (size_t)ret == length;
444} 771}
445 772
446bool HWStubDevice::IsValid() 773bool HWStubDevice::IsValid()
@@ -448,6 +775,10 @@ bool HWStubDevice::IsValid()
448 return m_valid; 775 return m_valid;
449} 776}
450 777
778QString HWStubDevice::GetFriendlyName()
779{
780 return m_name;
781}
451 782
452/** 783/**
453 * HWStubIoBackend 784 * HWStubIoBackend
@@ -456,7 +787,7 @@ bool HWStubDevice::IsValid()
456HWStubIoBackend::HWStubIoBackend(HWStubDevice *dev) 787HWStubIoBackend::HWStubIoBackend(HWStubDevice *dev)
457{ 788{
458 m_dev = dev; 789 m_dev = dev;
459 m_dev->Open(); 790
460 struct hwstub_target_desc_t target = m_dev->GetTargetInfo(); 791 struct hwstub_target_desc_t target = m_dev->GetTargetInfo();
461 if(target.dID == HWSTUB_TARGET_STMP) 792 if(target.dID == HWSTUB_TARGET_STMP)
462 { 793 {
@@ -470,6 +801,13 @@ HWStubIoBackend::HWStubIoBackend(HWStubDevice *dev)
470 else 801 else
471 m_soc = QString("stmp%1").arg(stmp.wChipID, 4, 16, QChar('0')); 802 m_soc = QString("stmp%1").arg(stmp.wChipID, 4, 16, QChar('0'));
472 } 803 }
804 else if(target.dID == HWSTUB_TARGET_JZ)
805 {
806 struct hwstub_jz_desc_t jz = m_dev->GetJZInfo();
807 m_soc = QString("jz%1").arg(jz.wChipID, 4, 16, QChar('0'));
808 if(jz.bRevision != 0)
809 m_soc.append(QChar(jz.bRevision).toLower());
810 }
473 else if(target.dID == HWSTUB_TARGET_RK27) 811 else if(target.dID == HWSTUB_TARGET_RK27)
474 m_soc = "rk27x"; 812 m_soc = "rk27x";
475 else if(target.dID == HWSTUB_TARGET_PP) 813 else if(target.dID == HWSTUB_TARGET_PP)
@@ -549,95 +887,6 @@ bool HWStubIoBackend::Reload()
549 return true; 887 return true;
550} 888}
551 889
552/**
553 * HWStubBackendHelper
554 */
555HWStubBackendHelper::HWStubBackendHelper()
556{
557#ifdef LIBUSB_NO_HOTPLUG
558 m_hotplug = false;
559#else
560 m_hotplug = libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG);
561 if(m_hotplug)
562 {
563 int evt = LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED |
564 LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT;
565 m_hotplug = LIBUSB_SUCCESS == libusb_hotplug_register_callback(
566 NULL, (libusb_hotplug_event)evt, LIBUSB_HOTPLUG_ENUMERATE,
567 LIBUSB_HOTPLUG_MATCH_ANY, LIBUSB_HOTPLUG_MATCH_ANY, LIBUSB_HOTPLUG_MATCH_ANY,
568 &HWStubBackendHelper::HotPlugCallback, reinterpret_cast< void* >(this),
569 &m_hotplug_handle);
570 }
571#endif /* LIBUSB_NO_HOTPLUG */
572}
573
574HWStubBackendHelper::~HWStubBackendHelper()
575{
576#ifndef LIBUSB_NO_HOTPLUG
577 if(m_hotplug)
578 libusb_hotplug_deregister_callback(NULL, m_hotplug_handle);
579#endif /* LIBUSB_NO_HOTPLUG */
580}
581
582QList< HWStubDevice* > HWStubBackendHelper::GetDevList()
583{
584 QList< HWStubDevice* > list;
585 libusb_device **dev_list;
586 ssize_t cnt = hwstub_get_device_list(NULL, &dev_list);
587 for(int i = 0; i < cnt; i++)
588 {
589 HWStubDevice *dev = new HWStubDevice(dev_list[i]);
590 /* filter out non-hwstub devices */
591 if(dev->IsValid())
592 list.push_back(dev);
593 else
594 delete dev;
595 }
596 libusb_free_device_list(dev_list, 1);
597 return list;
598}
599
600#ifndef LIBUSB_NO_HOTPLUG
601void HWStubBackendHelper::OnHotPlug(bool arrived, struct libusb_device *dev)
602{
603 /* signal it */
604 emit OnDevListChanged(arrived, dev);
605}
606
607int HWStubBackendHelper::HotPlugCallback(struct libusb_context *ctx, struct libusb_device *dev,
608 libusb_hotplug_event event, void *user_data)
609{
610 Q_UNUSED(ctx);
611 HWStubBackendHelper *helper = reinterpret_cast< HWStubBackendHelper* >(user_data);
612 switch(event)
613 {
614 case LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED: helper->OnHotPlug(true, dev); break;
615 case LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT: helper->OnHotPlug(false, dev); break;
616 default: break;
617 }
618 return 0;
619}
620#endif /* LIBUSB_NO_HOTPLUG */
621
622bool HWStubBackendHelper::HasHotPlugSupport()
623{
624 return m_hotplug;
625}
626
627namespace
628{
629class lib_usb_init
630{
631public:
632 lib_usb_init()
633 {
634 libusb_init(NULL);
635 }
636};
637
638lib_usb_init __lib_usb_init;
639}
640
641#endif /* HAVE_HWSTUB */ 890#endif /* HAVE_HWSTUB */
642 891
643/** 892/**
diff --git a/utils/regtools/qeditor/backend.h b/utils/regtools/qeditor/backend.h
index 17eeb44533..19e2cb5616 100644
--- a/utils/regtools/qeditor/backend.h
+++ b/utils/regtools/qeditor/backend.h
@@ -28,7 +28,9 @@
28#include <QMetaType> 28#include <QMetaType>
29#include <QAbstractItemModel> 29#include <QAbstractItemModel>
30#ifdef HAVE_HWSTUB 30#ifdef HAVE_HWSTUB
31#include "hwstub.h" 31#include "hwstub.hpp"
32#include "hwstub_usb.hpp"
33#include "hwstub_uri.hpp"
32#endif 34#endif
33#include "soc_desc.hpp" 35#include "soc_desc.hpp"
34 36
@@ -139,41 +141,124 @@ protected:
139}; 141};
140 142
141#ifdef HAVE_HWSTUB 143#ifdef HAVE_HWSTUB
144/* HWStub context manager: provides a centralized place to add/remove/get
145 * contexts */
146class HWStubManager : public QAbstractTableModel
147{
148 Q_OBJECT
149protected:
150 HWStubManager();
151public:
152 virtual ~HWStubManager();
153 /* Get manager */
154 static HWStubManager *Get();
155 /* Clear the context list */
156 void Clear();
157 bool Add(const QString& name, const QString& uri);
158 /* Model */
159 virtual int rowCount(const QModelIndex& parent = QModelIndex()) const;
160 virtual int columnCount(const QModelIndex& parent = QModelIndex()) const;
161 virtual QVariant data(const QModelIndex& index, int role) const;
162 virtual QVariant headerData(int section, Qt::Orientation orientation, int role) const;
163 virtual Qt::ItemFlags flags(const QModelIndex& index) const;
164 virtual bool setData(const QModelIndex& index, const QVariant& value, int role);
165 /* return predefined columns */
166 int GetNameColumn() const;
167 int GetUriColumn() const;
168 std::shared_ptr< hwstub::context > GetContext(int row);
169 /* return a friendly name for a device */
170 static QString GetFriendlyName(std::shared_ptr< hwstub::device > device);
171
172protected:
173 struct Context
174 {
175 std::shared_ptr< hwstub::context > context;
176 QString name;
177 QString uri;
178 };
179
180 std::vector< Context > m_list; /* list of context */
181 static HWStubManager *g_inst; /* unique instance */
182};
183
184/* HWStub context model: provides access to the device list using Qt MVC model. */
185class HWStubContextModel : public QAbstractTableModel
186{
187 Q_OBJECT
188public:
189 HWStubContextModel(QObject *parent = 0);
190 virtual ~HWStubContextModel();
191 void SetContext(std::shared_ptr< hwstub::context > context);
192 /* Model */
193 virtual int rowCount(const QModelIndex& parent = QModelIndex()) const;
194 virtual int columnCount(const QModelIndex& parent = QModelIndex()) const;
195 virtual QVariant data(const QModelIndex& index, int role) const;
196 virtual QVariant headerData(int section, Qt::Orientation orientation, int role) const;
197 virtual Qt::ItemFlags flags(const QModelIndex& index) const;
198 /* return predefined columns */
199 int GetNameColumn() const;
200 std::shared_ptr< hwstub::device > GetDevice(int row);
201 /* Add an entry in the model for "no selection", which will correspond to
202 * a dummy device. This function also allows the text to be customised. */
203 void EnableDummy(bool en, const QString& text = "");
204
205private slots:
206 void OnDevChangeUnsafe(void *data);
207protected:
208 QString GetFriendlyName(std::shared_ptr< hwstub::device > device);
209 void OnDevChangeLow(std::shared_ptr< hwstub::context > ctx, bool arrived,
210 std::shared_ptr< hwstub::device > device);
211 void OnDevChange(std::shared_ptr< hwstub::context > ctx, bool arrived,
212 std::shared_ptr< hwstub::device > device);
213
214 struct Device
215 {
216 QString name;
217 std::shared_ptr< hwstub::device > device;
218 };
219
220 std::vector< Device > m_list;
221 std::weak_ptr< hwstub::context > m_context;
222 hwstub::context::callback_ref_t m_callback_ref;
223 bool m_has_dummy;
224 QString m_dummy_text;
225};
226
227/* Abstract Virtual Class from where TCP and USB backend
228 * child classes are derived
229 */
142class HWStubDevice 230class HWStubDevice
143{ 231{
144public: 232public:
145 HWStubDevice(struct libusb_device *dev); 233 HWStubDevice(std::shared_ptr<hwstub::device> device);
146 HWStubDevice(const HWStubDevice *dev); 234 virtual ~HWStubDevice();
147 ~HWStubDevice(); 235
236 QString GetFriendlyName();
148 bool IsValid(); 237 bool IsValid();
149 bool Open(); 238 /* Calls below are cached */
150 void Close();
151 int GetBusNumber();
152 int GetDevAddress();
153 /* Calls below are cached and do not require the device to be opened */
154 inline struct hwstub_version_desc_t GetVersionInfo() { return m_hwdev_ver; } 239 inline struct hwstub_version_desc_t GetVersionInfo() { return m_hwdev_ver; }
155 inline struct hwstub_target_desc_t GetTargetInfo() { return m_hwdev_target; } 240 inline struct hwstub_target_desc_t GetTargetInfo() { return m_hwdev_target; }
156 inline struct hwstub_stmp_desc_t GetSTMPInfo() { return m_hwdev_stmp; } 241 inline struct hwstub_stmp_desc_t GetSTMPInfo() { return m_hwdev_stmp; }
157 inline struct hwstub_pp_desc_t GetPPInfo() { return m_hwdev_pp; } 242 inline struct hwstub_pp_desc_t GetPPInfo() { return m_hwdev_pp; }
158 /* Calls below require the device to be opened */ 243 inline struct hwstub_jz_desc_t GetJZInfo() { return m_hwdev_jz; }
159 bool ReadMem(soc_addr_t addr, size_t length, void *buffer); 244 bool ReadMem(soc_addr_t addr, size_t length, void *buffer);
160 bool WriteMem(soc_addr_t addr, size_t length, void *buffer); 245 bool WriteMem(soc_addr_t addr, size_t length, void *buffer);
161 246
162protected: 247protected:
163 bool Probe(); 248 bool Probe(std::shared_ptr<hwstub::device> device);
164 void Init(struct libusb_device *dev);
165 249
250 std::shared_ptr<hwstub::handle> m_handle;
166 bool m_valid; 251 bool m_valid;
167 struct libusb_device *m_dev;
168 libusb_device_handle *m_handle;
169 struct hwstub_device_t *m_hwdev; 252 struct hwstub_device_t *m_hwdev;
170 struct hwstub_version_desc_t m_hwdev_ver; 253 struct hwstub_version_desc_t m_hwdev_ver;
171 struct hwstub_target_desc_t m_hwdev_target; 254 struct hwstub_target_desc_t m_hwdev_target;
172 struct hwstub_stmp_desc_t m_hwdev_stmp; 255 struct hwstub_stmp_desc_t m_hwdev_stmp;
173 struct hwstub_pp_desc_t m_hwdev_pp; 256 struct hwstub_pp_desc_t m_hwdev_pp;
257 struct hwstub_jz_desc_t m_hwdev_jz;
258 QString m_name;
174}; 259};
175 260
176/** NOTE the HWStub backend is never dirty: all writes are immediately committed */ 261/** NOTE the HWStub backend is never dirty: all wrnew ites are immediately committed */
177class HWStubIoBackend : public IoBackend 262class HWStubIoBackend : public IoBackend
178{ 263{
179 Q_OBJECT 264 Q_OBJECT
@@ -197,32 +282,6 @@ protected:
197 QString m_soc; 282 QString m_soc;
198 HWStubDevice *m_dev; 283 HWStubDevice *m_dev;
199}; 284};
200
201#if LIBUSB_API_VERSION < 0x01000102
202#define LIBUSB_NO_HOTPLUG
203#endif
204
205class HWStubBackendHelper : public QObject
206{
207 Q_OBJECT
208public:
209 HWStubBackendHelper();
210 ~HWStubBackendHelper();
211 bool HasHotPlugSupport();
212 QList< HWStubDevice* > GetDevList();
213
214signals:
215 void OnDevListChanged(bool arrived, struct libusb_device *dev);
216
217protected:
218#ifndef LIBUSB_NO_HOTPLUG
219 void OnHotPlug(bool arrived, struct libusb_device *dev);
220 static int HotPlugCallback(struct libusb_context *ctx, struct libusb_device *dev,
221 libusb_hotplug_event event, void *user_data);
222 libusb_hotplug_callback_handle m_hotplug_handle;
223#endif
224 bool m_hotplug;
225};
226#endif 285#endif
227 286
228class SocFile 287class SocFile
diff --git a/utils/regtools/qeditor/mainwindow.cpp b/utils/regtools/qeditor/mainwindow.cpp
index 8b83be6bae..69138a91b7 100644
--- a/utils/regtools/qeditor/mainwindow.cpp
+++ b/utils/regtools/qeditor/mainwindow.cpp
@@ -107,12 +107,18 @@ void DocumentTabWidget::OnCloseTab(int index)
107MainWindow::MainWindow(Backend *backend) 107MainWindow::MainWindow(Backend *backend)
108 :m_backend(backend) 108 :m_backend(backend)
109{ 109{
110 QAction *new_regtab_act = new QAction(QIcon::fromTheme("document-new"), tr("Register &Tab"), this); 110 QAction *new_regtab_act = new QAction(YIconManager::Get()->GetIcon(YIconManager::DocumentNew),
111 QAction *new_regedit_act = new QAction(QIcon::fromTheme("document-edit"), tr("Register &Editor"), this); 111 tr("Register &Tab"), this);
112 QAction *load_desc_act = new QAction(QIcon::fromTheme("document-open"), tr("&Soc Description"), this); 112 QAction *new_regedit_act = new QAction(YIconManager::Get()->GetIcon(YIconManager::DocumentEdit),
113 QAction *quit_act = new QAction(QIcon::fromTheme("application-exit"), tr("&Quit"), this); 113 tr("Register &Editor"), this);
114 QAction *about_act = new QAction(QIcon::fromTheme("help-about"), tr("&About"), this); 114 QAction *load_desc_act = new QAction(YIconManager::Get()->GetIcon(YIconManager::DocumentOpen),
115 QAction *about_qt_act = new QAction(QIcon::fromTheme("help-about"), tr("About &Qt"), this); 115 tr("&Soc Description"), this);
116 QAction *quit_act = new QAction(YIconManager::Get()->GetIcon(YIconManager::ApplicationExit),
117 tr("&Quit"), this);
118 QAction *about_act = new QAction(YIconManager::Get()->GetIcon(YIconManager::HelpAbout),
119 tr("&About"), this);
120 QAction *about_qt_act = new QAction(YIconManager::Get()->GetIcon(YIconManager::HelpAbout),
121 tr("About &Qt"), this);
116 122
117 connect(new_regtab_act, SIGNAL(triggered()), this, SLOT(OnNewRegTab())); 123 connect(new_regtab_act, SIGNAL(triggered()), this, SLOT(OnNewRegTab()));
118 connect(new_regedit_act, SIGNAL(triggered()), this, SLOT(OnNewRegEdit())); 124 connect(new_regedit_act, SIGNAL(triggered()), this, SLOT(OnNewRegEdit()));
@@ -121,9 +127,10 @@ MainWindow::MainWindow(Backend *backend)
121 connect(about_act, SIGNAL(triggered()), this, SLOT(OnAbout())); 127 connect(about_act, SIGNAL(triggered()), this, SLOT(OnAbout()));
122 connect(about_qt_act, SIGNAL(triggered()), this, SLOT(OnAboutQt())); 128 connect(about_qt_act, SIGNAL(triggered()), this, SLOT(OnAboutQt()));
123 129
124 QMenu *file_menu = menuBar()->addMenu(tr("&File")); 130 QMenu *app_menu = new QMenu;
125 QMenu *new_submenu = file_menu->addMenu(QIcon::fromTheme("document-new"), "&New"); 131 QMenu *file_menu = app_menu->addMenu(tr("&File"));
126 QMenu *load_submenu = file_menu->addMenu(QIcon::fromTheme("document-open"), "&Load"); 132 QMenu *new_submenu = file_menu->addMenu(YIconManager::Get()->GetIcon(YIconManager::DocumentNew), "&New");
133 QMenu *load_submenu = file_menu->addMenu(YIconManager::Get()->GetIcon(YIconManager::DocumentOpen), "&Load");
127 file_menu->addAction(quit_act); 134 file_menu->addAction(quit_act);
128 135
129 new_submenu->addAction(new_regtab_act); 136 new_submenu->addAction(new_regtab_act);
@@ -131,17 +138,24 @@ MainWindow::MainWindow(Backend *backend)
131 138
132 load_submenu->addAction(load_desc_act); 139 load_submenu->addAction(load_desc_act);
133 140
134 QMenu *about_menu = menuBar()->addMenu(tr("&About")); 141 QMenu *about_menu = app_menu->addMenu(tr("&About"));
135 about_menu->addAction(about_act); 142 about_menu->addAction(about_act);
136 about_menu->addAction(about_qt_act); 143 about_menu->addAction(about_qt_act);
137 144
138 m_tab = new DocumentTabWidget(); 145 m_tab = new DocumentTabWidget();
139 m_tab->setTabOpenable(true); 146 m_tab->setTabOpenable(true);
140 m_tab->setTabOpenMenu(new_submenu); 147 m_tab->setTabOpenMenu(new_submenu);
148 m_tab->setOtherMenu(app_menu);
141 149
142 setCentralWidget(m_tab); 150 setCentralWidget(m_tab);
143 151
144 ReadSettings(); 152 ReadSettings();
153#ifdef HAVE_HWSTUB
154 /* acquire hwstub manager */
155 HWStubManager::Get()->setParent(this);
156#endif
157 /* acquire icon manager */
158 YIconManager::Get()->setParent(this);
145 159
146 OnNewRegTab(); 160 OnNewRegTab();
147} 161}
@@ -167,12 +181,12 @@ void MainWindow::OnAbout()
167 .arg(soc_desc::MINOR_VERSION).arg(soc_desc::REVISION_VERSION); 181 .arg(soc_desc::MINOR_VERSION).arg(soc_desc::REVISION_VERSION);
168 QMessageBox::about(this, "About", 182 QMessageBox::about(this, "About",
169 "<h1>QEditor</h1>" 183 "<h1>QEditor</h1>"
170 "<h2>Version "APP_VERSION"</h2>" 184 "<h2>Version " APP_VERSION "</h2>"
171 "<p>Written by Amaury Pouly</p>" 185 "<p>Written by Amaury Pouly</p>"
172 "<p>Libraries:</p>" 186 "<p>Libraries:</p>"
173 "<ul><li>soc_desc: " + soc_desc_ver + "</li>" 187 "<ul><li>soc_desc: " + soc_desc_ver + "</li>"
174#ifdef HAVE_HWSTUB 188#ifdef HAVE_HWSTUB
175 "<li>hwstub: "HWSTUB_VERSION"</li>" 189 "<li>hwstub: " HWSTUB_VERSION "</li>"
176#else 190#else
177 "<li>hwstub: not compiled in</li>" 191 "<li>hwstub: not compiled in</li>"
178#endif 192#endif
diff --git a/utils/regtools/qeditor/qeditor.pro b/utils/regtools/qeditor/qeditor.pro
index 0ec7c3dde1..5414f34e72 100644
--- a/utils/regtools/qeditor/qeditor.pro
+++ b/utils/regtools/qeditor/qeditor.pro
@@ -5,8 +5,9 @@ HEADERS += mainwindow.h backend.h regtab.h analyser.h settings.h \
5SOURCES += main.cpp mainwindow.cpp regtab.cpp backend.cpp analyser.cpp \ 5SOURCES += main.cpp mainwindow.cpp regtab.cpp backend.cpp analyser.cpp \
6 std_analysers.cpp settings.cpp utils.cpp regdisplaypanel.cpp regedit.cpp 6 std_analysers.cpp settings.cpp utils.cpp regdisplaypanel.cpp regedit.cpp
7LIBS += -L../lib/ -lsocdesc -lxml2 7LIBS += -L../lib/ -lsocdesc -lxml2
8INCLUDEPATH += ../include/ ../../hwstub/lib 8INCLUDEPATH += ../include/ ../../hwstub/include
9DEPENDPATH += ../ 9DEPENDPATH += ../
10CONFIG += c++11
10 11
11libsocdesc.commands = cd ../lib && make 12libsocdesc.commands = cd ../lib && make
12QMAKE_EXTRA_TARGETS += libsocdesc 13QMAKE_EXTRA_TARGETS += libsocdesc
diff --git a/utils/regtools/qeditor/regdisplaypanel.cpp b/utils/regtools/qeditor/regdisplaypanel.cpp
index a72d280d6c..1c2f1db9a9 100644
--- a/utils/regtools/qeditor/regdisplaypanel.cpp
+++ b/utils/regtools/qeditor/regdisplaypanel.cpp
@@ -46,7 +46,7 @@ SocDisplayPanel::SocDisplayPanel(QWidget *parent, IoBackend *io_backend,
46 right_layout->addWidget(m_desc, 0); 46 right_layout->addWidget(m_desc, 0);
47 right_layout->addStretch(1); 47 right_layout->addStretch(1);
48 48
49 setTitle("System-on-Chip Description"); 49 setTitle("");
50 setLayout(right_layout); 50 setLayout(right_layout);
51} 51}
52 52
@@ -108,7 +108,7 @@ NodeDisplayPanel::NodeDisplayPanel(QWidget *parent, IoBackend *io_backend,
108 right_layout->addWidget(m_inst_desc, 0); 108 right_layout->addWidget(m_inst_desc, 0);
109 right_layout->addStretch(1); 109 right_layout->addStretch(1);
110 110
111 setTitle("Device Description"); 111 setTitle("");
112 setLayout(right_layout); 112 setLayout(right_layout);
113} 113}
114 114
@@ -126,6 +126,21 @@ QWidget *NodeDisplayPanel::GetWidget()
126 * RegDisplayPanel 126 * RegDisplayPanel
127 */ 127 */
128 128
129namespace
130{
131 QString access_string(soc_desc::access_t acc, QString dflt = "")
132 {
133 switch(acc)
134 {
135 case soc_desc::UNSPECIFIED: return dflt;
136 case soc_desc::READ_ONLY: return "Read only";
137 case soc_desc::READ_WRITE: return "Read-write";
138 case soc_desc::WRITE_ONLY: return "Write-only";
139 default: return "";
140 }
141 }
142}
143
129RegDisplayPanel::RegDisplayPanel(QWidget *parent, IoBackend *io_backend, 144RegDisplayPanel::RegDisplayPanel(QWidget *parent, IoBackend *io_backend,
130 const soc_desc::node_inst_t& ref) 145 const soc_desc::node_inst_t& ref)
131 :QGroupBox(parent), m_io_backend(io_backend), m_node(ref), m_reg_font(font()) 146 :QGroupBox(parent), m_io_backend(io_backend), m_node(ref), m_reg_font(font())
@@ -139,16 +154,18 @@ RegDisplayPanel::RegDisplayPanel(QWidget *parent, IoBackend *io_backend,
139 m_reg_font.setKerning(false); 154 m_reg_font.setKerning(false);
140 155
141 QString reg_name = helper.GetPath(ref); 156 QString reg_name = helper.GetPath(ref);
142 QStringList names; 157 QStringList names, access;
143 QVector< soc_addr_t > addresses; 158 QVector< soc_addr_t > addresses;
144 names.append(reg_name); 159 names.append(reg_name);
145 addresses.append(ref.addr()); 160 addresses.append(ref.addr());
161 access.append(access_string(ref.node().reg().get()->access));
146 162
147 std::vector< soc_desc::variant_ref_t > variants = ref.node().reg().variants(); 163 std::vector< soc_desc::variant_ref_t > variants = ref.node().reg().variants();
148 for(size_t i = 0; i < variants.size(); i++) 164 for(size_t i = 0; i < variants.size(); i++)
149 { 165 {
150 names.append(reg_name + "/" + QString::fromStdString(variants[i].get()->type)); 166 names.append(reg_name + "/" + QString::fromStdString(variants[i].get()->type));
151 addresses.append(ref.addr() + variants[i].get()->offset); 167 addresses.append(ref.addr() + variants[i].get()->offset);
168 access.append(access_string(ref.node().reg().get()->access, access[0]));
152 } 169 }
153 170
154 QString str; 171 QString str;
@@ -169,10 +186,20 @@ RegDisplayPanel::RegDisplayPanel(QWidget *parent, IoBackend *io_backend,
169 label_addr->setTextFormat(Qt::RichText); 186 label_addr->setTextFormat(Qt::RichText);
170 label_addr->setText(str_addr); 187 label_addr->setText(str_addr);
171 188
189 QString str_acc;
190 str_acc += "<table align=left>";
191 for(int i = 0; i < names.size(); i++)
192 str_acc += "<tr><td><b>" + access[i] + "</b></td></tr>";
193 str_acc += "</table>";
194 QLabel *label_access = new QLabel;
195 label_access->setTextFormat(Qt::RichText);
196 label_access->setText(str_acc);
197
172 QHBoxLayout *top_layout = new QHBoxLayout; 198 QHBoxLayout *top_layout = new QHBoxLayout;
173 top_layout->addStretch(); 199 top_layout->addStretch();
174 top_layout->addWidget(label_names); 200 top_layout->addWidget(label_names);
175 top_layout->addWidget(label_addr); 201 top_layout->addWidget(label_addr);
202 top_layout->addWidget(label_access);
176 top_layout->addStretch(); 203 top_layout->addStretch();
177 204
178 m_raw_val_name = new QLabel; 205 m_raw_val_name = new QLabel;
@@ -250,7 +277,7 @@ RegDisplayPanel::RegDisplayPanel(QWidget *parent, IoBackend *io_backend,
250 right_layout->addWidget(m_value_table); 277 right_layout->addWidget(m_value_table);
251 right_layout->addStretch(); 278 right_layout->addStretch();
252 279
253 setTitle("Register Description"); 280 setTitle("");
254 m_viewport = new QWidget; 281 m_viewport = new QWidget;
255 m_viewport->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); 282 m_viewport->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
256 m_viewport->setLayout(right_layout); 283 m_viewport->setLayout(right_layout);
diff --git a/utils/regtools/qeditor/regedit.cpp b/utils/regtools/qeditor/regedit.cpp
index 826452fdbd..bf86792c1e 100644
--- a/utils/regtools/qeditor/regedit.cpp
+++ b/utils/regtools/qeditor/regedit.cpp
@@ -107,14 +107,15 @@ SocEditPanel::SocEditPanel(const soc_desc::soc_ref_t& ref, QWidget *parent)
107 for(size_t i = 0; i < authors.size(); i++) 107 for(size_t i = 0; i < authors.size(); i++)
108 { 108 {
109 QTableWidgetItem *item = new QTableWidgetItem( 109 QTableWidgetItem *item = new QTableWidgetItem(
110 QIcon::fromTheme("list-remove"), "", SocEditPanelDelType); 110 YIconManager::Get()->GetIcon(YIconManager::ListRemove), "", SocEditPanelDelType);
111 item->setToolTip("Remove this author");
111 item->setFlags(Qt::ItemIsEnabled); 112 item->setFlags(Qt::ItemIsEnabled);
112 m_authors_list->setItem(i, 0, item); 113 m_authors_list->setItem(i, 0, item);
113 item = new QTableWidgetItem(QString::fromStdString(authors[i])); 114 item = new QTableWidgetItem(QString::fromStdString(authors[i]));
114 m_authors_list->setItem(i, 1, item); 115 m_authors_list->setItem(i, 1, item);
115 } 116 }
116 QTableWidgetItem *new_item = new QTableWidgetItem( 117 QTableWidgetItem *new_item = new QTableWidgetItem(
117 QIcon::fromTheme("list-add"), "", SocEditPanelAddType); 118 YIconManager::Get()->GetIcon(YIconManager::ListAdd), "", SocEditPanelAddType);
118 new_item->setFlags(Qt::ItemIsEnabled); 119 new_item->setFlags(Qt::ItemIsEnabled);
119 m_authors_list->setItem(authors.size(), 0, new_item); 120 m_authors_list->setItem(authors.size(), 0, new_item);
120 new_item = new QTableWidgetItem("New author...", QTableWidgetItem::UserType); 121 new_item = new QTableWidgetItem("New author...", QTableWidgetItem::UserType);
@@ -188,7 +189,8 @@ void SocEditPanel::OnAuthorActivated(QTableWidgetItem *item)
188 m_ref.get()->author.push_back("Anonymous"); 189 m_ref.get()->author.push_back("Anonymous");
189 m_authors_list->insertRow(row); 190 m_authors_list->insertRow(row);
190 QTableWidgetItem *item = new QTableWidgetItem( 191 QTableWidgetItem *item = new QTableWidgetItem(
191 QIcon::fromTheme("list-remove"), "", SocEditPanelDelType); 192 YIconManager::Get()->GetIcon(YIconManager::ListRemove), "", SocEditPanelDelType);
193 item->setToolTip("Remove this author");
192 item->setFlags(Qt::ItemIsEnabled); 194 item->setFlags(Qt::ItemIsEnabled);
193 m_authors_list->setItem(row, 0, item); 195 m_authors_list->setItem(row, 0, item);
194 item = new QTableWidgetItem(QString::fromStdString(m_ref.get()->author.back())); 196 item = new QTableWidgetItem(QString::fromStdString(m_ref.get()->author.back()));
@@ -386,7 +388,8 @@ NodeInstanceEditPanel::NodeInstanceEditPanel(const soc_desc::node_ref_t& ref,
386 for(size_t i = 0; i < addrs.size(); i++) 388 for(size_t i = 0; i < addrs.size(); i++)
387 { 389 {
388 QTableWidgetItem *item = new QTableWidgetItem( 390 QTableWidgetItem *item = new QTableWidgetItem(
389 QIcon::fromTheme("list-remove"), "", NodeInstEditPanelDelType); 391 YIconManager::Get()->GetIcon(YIconManager::ListRemove), "", NodeInstEditPanelDelType);
392 item->setToolTip("Remove this address");
390 item->setFlags(Qt::ItemIsEnabled); 393 item->setFlags(Qt::ItemIsEnabled);
391 addr_list->setItem(i, 0, item); 394 addr_list->setItem(i, 0, item);
392 item = new QTableWidgetItem(); 395 item = new QTableWidgetItem();
@@ -394,7 +397,7 @@ NodeInstanceEditPanel::NodeInstanceEditPanel(const soc_desc::node_ref_t& ref,
394 addr_list->setItem(i, 1, item); 397 addr_list->setItem(i, 1, item);
395 } 398 }
396 QTableWidgetItem *new_item = new QTableWidgetItem( 399 QTableWidgetItem *new_item = new QTableWidgetItem(
397 QIcon::fromTheme("list-add"), "", NodeInstEditPanelAddType); 400 YIconManager::Get()->GetIcon(YIconManager::ListAdd), "", NodeInstEditPanelAddType);
398 new_item->setFlags(Qt::ItemIsEnabled); 401 new_item->setFlags(Qt::ItemIsEnabled);
399 addr_list->setItem(addrs.size(), 0, new_item); 402 addr_list->setItem(addrs.size(), 0, new_item);
400 new_item = new QTableWidgetItem("New address...", QTableWidgetItem::UserType); 403 new_item = new QTableWidgetItem("New address...", QTableWidgetItem::UserType);
@@ -535,7 +538,8 @@ void NodeInstanceEditPanel::OnAddressActivated(QTableWidgetItem *item)
535 GetInstance().range.list.push_back(new_addr); 538 GetInstance().range.list.push_back(new_addr);
536 table->insertRow(row); 539 table->insertRow(row);
537 QTableWidgetItem *item = new QTableWidgetItem( 540 QTableWidgetItem *item = new QTableWidgetItem(
538 QIcon::fromTheme("list-remove"), "", NodeInstEditPanelDelType); 541 YIconManager::Get()->GetIcon(YIconManager::ListRemove), "", NodeInstEditPanelDelType);
542 item->setToolTip("Remove this address");
539 item->setFlags(Qt::ItemIsEnabled); 543 item->setFlags(Qt::ItemIsEnabled);
540 table->setItem(row, 0, item); 544 table->setItem(row, 0, item);
541 item = new QTableWidgetItem(); 545 item = new QTableWidgetItem();
@@ -828,7 +832,8 @@ RegFieldEditPanel::RegFieldEditPanel(const soc_desc::field_ref_t& ref, QWidget *
828 for(size_t i = 0; i < field.enum_.size(); i++) 832 for(size_t i = 0; i < field.enum_.size(); i++)
829 { 833 {
830 QTableWidgetItem *item = new QTableWidgetItem( 834 QTableWidgetItem *item = new QTableWidgetItem(
831 QIcon::fromTheme("list-remove"), "", RegFieldEditPanelDelType); 835 YIconManager::Get()->GetIcon(YIconManager::ListRemove), "", RegFieldEditPanelDelType);
836 item->setToolTip("Remove this enum");
832 item->setFlags(Qt::ItemIsEnabled); 837 item->setFlags(Qt::ItemIsEnabled);
833 m_enum_table->setItem(i, 0, item); 838 m_enum_table->setItem(i, 0, item);
834 item = new QTableWidgetItem(QString::fromStdString(field.enum_[i].name)); 839 item = new QTableWidgetItem(QString::fromStdString(field.enum_[i].name));
@@ -840,7 +845,7 @@ RegFieldEditPanel::RegFieldEditPanel(const soc_desc::field_ref_t& ref, QWidget *
840 m_enum_table->setItem(i, 3, item); 845 m_enum_table->setItem(i, 3, item);
841 } 846 }
842 QTableWidgetItem *new_item = new QTableWidgetItem( 847 QTableWidgetItem *new_item = new QTableWidgetItem(
843 QIcon::fromTheme("list-add"), "", RegFieldEditPanelAddType); 848 YIconManager::Get()->GetIcon(YIconManager::ListAdd), "", RegFieldEditPanelAddType);
844 new_item->setFlags(Qt::ItemIsEnabled); 849 new_item->setFlags(Qt::ItemIsEnabled);
845 m_enum_table->setItem(field.enum_.size(), 0, new_item); 850 m_enum_table->setItem(field.enum_.size(), 0, new_item);
846 new_item = new QTableWidgetItem("New field..."); 851 new_item = new QTableWidgetItem("New field...");
@@ -875,6 +880,13 @@ void RegFieldEditPanel::UpdateWidth()
875 m_range_validator->setWidth(m_ref.reg().get()->width); 880 m_range_validator->setWidth(m_ref.reg().get()->width);
876} 881}
877 882
883void RegFieldEditPanel::UpdateRange()
884{
885 soc_desc::field_t *field = m_ref.get();
886 m_range_edit->setText(m_range_validator->generate(
887 field->pos + field->width - 1, field->pos));
888}
889
878void RegFieldEditPanel::OnFieldValueActivated(QTableWidgetItem *item) 890void RegFieldEditPanel::OnFieldValueActivated(QTableWidgetItem *item)
879{ 891{
880 if(item->type() == RegFieldEditPanelDelType) 892 if(item->type() == RegFieldEditPanelDelType)
@@ -895,7 +907,8 @@ void RegFieldEditPanel::OnFieldValueActivated(QTableWidgetItem *item)
895 field.enum_.push_back(new_enum); 907 field.enum_.push_back(new_enum);
896 m_enum_table->insertRow(row); 908 m_enum_table->insertRow(row);
897 QTableWidgetItem *item = new QTableWidgetItem( 909 QTableWidgetItem *item = new QTableWidgetItem(
898 QIcon::fromTheme("list-remove"), "", RegFieldEditPanelDelType); 910 YIconManager::Get()->GetIcon(YIconManager::ListRemove), "", RegFieldEditPanelDelType);
911 item->setToolTip("Remove this enum");
899 item->setFlags(Qt::ItemIsEnabled); 912 item->setFlags(Qt::ItemIsEnabled);
900 m_enum_table->setItem(row, 0, item); 913 m_enum_table->setItem(row, 0, item);
901 item = new QTableWidgetItem(QString::fromStdString(new_enum.name)); 914 item = new QTableWidgetItem(QString::fromStdString(new_enum.name));
@@ -977,7 +990,7 @@ RegEditPanel::RegEditPanel(const soc_desc::register_ref_t& ref, QWidget *parent)
977 990
978 m_value_model = new RegFieldTableModel(this); // view takes ownership 991 m_value_model = new RegFieldTableModel(this); // view takes ownership
979 m_value_model->SetRegister(*ref.get()); 992 m_value_model->SetRegister(*ref.get());
980 m_value_model->SetReadOnly(true); 993 m_value_model->SetReadOnly(false);
981 994
982 m_sexy_display2 = new Unscroll<YRegDisplay>(this); 995 m_sexy_display2 = new Unscroll<YRegDisplay>(this);
983 m_sexy_display2->setFont(m_reg_font); 996 m_sexy_display2->setFont(m_reg_font);
@@ -1016,29 +1029,61 @@ RegEditPanel::RegEditPanel(const soc_desc::register_ref_t& ref, QWidget *parent)
1016 width_group_layout->addWidget(reg_size_32); 1029 width_group_layout->addWidget(reg_size_32);
1017 width_group_layout->addWidget(reg_size_16); 1030 width_group_layout->addWidget(reg_size_16);
1018 width_group_layout->addWidget(reg_size_8); 1031 width_group_layout->addWidget(reg_size_8);
1019 width_group_layout->addStretch(0);
1020 QGroupBox *width_group = new QGroupBox("Width"); 1032 QGroupBox *width_group = new QGroupBox("Width");
1021 width_group->setLayout(width_group_layout); 1033 width_group->setLayout(width_group_layout);
1022 1034
1035 m_reg_access_group = new QButtonGroup(this);
1036 QRadioButton *reg_dflt = new QRadioButton("Unspecified");
1037 QRadioButton *reg_rw = new QRadioButton("Read-Write");
1038 QRadioButton *reg_ro = new QRadioButton("Read-Only");
1039 QRadioButton *reg_wo = new QRadioButton("Write-Only");
1040 m_reg_access_group->addButton(reg_dflt, soc_desc::UNSPECIFIED);
1041 m_reg_access_group->addButton(reg_rw, soc_desc::READ_WRITE);
1042 m_reg_access_group->addButton(reg_ro, soc_desc::READ_ONLY);
1043 m_reg_access_group->addButton(reg_wo, soc_desc::WRITE_ONLY);
1044 if(m_reg_access_group->button(m_ref.get()->access))
1045 m_reg_access_group->button(m_ref.get()->access)->click();
1046 QVBoxLayout *access_group_layout = new QVBoxLayout;
1047 access_group_layout->addWidget(reg_dflt);
1048 access_group_layout->addWidget(reg_rw);
1049 access_group_layout->addWidget(reg_ro);
1050 access_group_layout->addWidget(reg_wo);
1051 QGroupBox *access_group = new QGroupBox("Access");
1052 access_group->setLayout(access_group_layout);
1053
1054 QVBoxLayout *width_access_layout = new QVBoxLayout;
1055 width_access_layout->addWidget(width_group);
1056 width_access_layout->addWidget(access_group);
1057 width_access_layout->addStretch(0);
1058
1023 m_variant_table = new QTableWidget; 1059 m_variant_table = new QTableWidget;
1024 m_variant_table->setColumnCount(3); 1060 m_variant_table->setColumnCount(4);
1025 m_variant_table->setHorizontalHeaderItem(0, new QTableWidgetItem("")); 1061 m_variant_table->setHorizontalHeaderItem(0, new QTableWidgetItem(""));
1026 m_variant_table->setHorizontalHeaderItem(1, new QTableWidgetItem("Type")); 1062 m_variant_table->setHorizontalHeaderItem(1, new QTableWidgetItem("Type"));
1027 m_variant_table->setHorizontalHeaderItem(2, new QTableWidgetItem("Offset")); 1063 m_variant_table->setHorizontalHeaderItem(2, new QTableWidgetItem("Offset"));
1064 m_variant_table->setHorizontalHeaderItem(3, new QTableWidgetItem("Access"));
1028 m_variant_table->verticalHeader()->setVisible(false); 1065 m_variant_table->verticalHeader()->setVisible(false);
1029 m_variant_table->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); 1066 m_variant_table->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
1030 m_variant_delegate = new SocFieldItemDelegate(this); 1067 m_variant_delegate = new SocFieldItemDelegate(this);
1031 m_variant_delegate->setItemEditorFactory(new QItemEditorFactory); 1068 m_variant_delegate->setItemEditorFactory(new QItemEditorFactory);
1032 m_variant_editor = new SocFieldEditorCreator; 1069 m_variant_delegate->itemEditorFactory()->registerEditor(QVariant::UInt,
1033 m_variant_delegate->itemEditorFactory()->registerEditor(QVariant::UInt, m_variant_editor); 1070 new SocFieldEditorCreator);
1034 m_variant_table->setItemDelegate(m_variant_delegate); 1071 m_variant_table->setItemDelegate(m_variant_delegate);
1072 m_access_delegate = new SocAccessItemDelegate("Unspecified", this);
1073 m_access_delegate->setItemEditorFactory(new QItemEditorFactory);
1074 // FIXME see QTBUG-30392
1075 m_access_delegate->itemEditorFactory()->registerEditor(
1076 (QVariant::Type)qMetaTypeId< soc_desc::access_t >(),
1077 new SocAccessEditorCreator);
1078 m_variant_table->setItemDelegateForColumn(3, m_access_delegate);
1035 1079
1036 std::vector< soc_desc::variant_ref_t > variants = m_ref.variants(); 1080 std::vector< soc_desc::variant_ref_t > variants = m_ref.variants();
1037 m_variant_table->setRowCount(variants.size() + 1); 1081 m_variant_table->setRowCount(variants.size() + 1);
1038 for(size_t i = 0; i < variants.size(); i++) 1082 for(size_t i = 0; i < variants.size(); i++)
1039 { 1083 {
1040 QTableWidgetItem *item = new QTableWidgetItem( 1084 QTableWidgetItem *item = new QTableWidgetItem(
1041 QIcon::fromTheme("list-remove"), "", RegVariantEditPanelDelType); 1085 YIconManager::Get()->GetIcon(YIconManager::ListRemove), "", RegVariantEditPanelDelType);
1086 item->setToolTip("Remove this variant");
1042 item->setFlags(Qt::ItemIsEnabled); 1087 item->setFlags(Qt::ItemIsEnabled);
1043 m_variant_table->setItem(i, 0, item); 1088 m_variant_table->setItem(i, 0, item);
1044 item = new QTableWidgetItem(QString::fromStdString(variants[i].get()->type)); 1089 item = new QTableWidgetItem(QString::fromStdString(variants[i].get()->type));
@@ -1046,9 +1091,12 @@ RegEditPanel::RegEditPanel(const soc_desc::register_ref_t& ref, QWidget *parent)
1046 item = new QTableWidgetItem(); 1091 item = new QTableWidgetItem();
1047 item->setData(Qt::EditRole, QVariant(variants[i].get()->offset)); 1092 item->setData(Qt::EditRole, QVariant(variants[i].get()->offset));
1048 m_variant_table->setItem(i, 2, item); 1093 m_variant_table->setItem(i, 2, item);
1094 item = new QTableWidgetItem();
1095 item->setData(Qt::EditRole, QVariant::fromValue(variants[i].get()->access));
1096 m_variant_table->setItem(i, 3, item);
1049 } 1097 }
1050 QTableWidgetItem *new_item = new QTableWidgetItem( 1098 QTableWidgetItem *new_item = new QTableWidgetItem(
1051 QIcon::fromTheme("list-add"), "", RegVariantEditPanelAddType); 1099 YIconManager::Get()->GetIcon(YIconManager::ListAdd), "", RegVariantEditPanelAddType);
1052 new_item->setFlags(Qt::ItemIsEnabled); 1100 new_item->setFlags(Qt::ItemIsEnabled);
1053 m_variant_table->setItem(variants.size(), 0, new_item); 1101 m_variant_table->setItem(variants.size(), 0, new_item);
1054 new_item = new QTableWidgetItem("New variant..."); 1102 new_item = new QTableWidgetItem("New variant...");
@@ -1069,7 +1117,7 @@ RegEditPanel::RegEditPanel(const soc_desc::register_ref_t& ref, QWidget *parent)
1069 m_desc_edit->SetTextHtml(QString::fromStdString(ref.get()->desc)); 1117 m_desc_edit->SetTextHtml(QString::fromStdString(ref.get()->desc));
1070 1118
1071 QHBoxLayout *top_info_layout = new QHBoxLayout; 1119 QHBoxLayout *top_info_layout = new QHBoxLayout;
1072 top_info_layout->addWidget(width_group); 1120 top_info_layout->addLayout(width_access_layout);
1073 top_info_layout->addWidget(Misc::EncloseInBox("Variants", m_variant_table)); 1121 top_info_layout->addWidget(Misc::EncloseInBox("Variants", m_variant_table));
1074 top_info_layout->addWidget(Misc::EncloseInBox("Description", m_desc_edit)); 1122 top_info_layout->addWidget(Misc::EncloseInBox("Description", m_desc_edit));
1075 1123
@@ -1087,9 +1135,9 @@ RegEditPanel::RegEditPanel(const soc_desc::register_ref_t& ref, QWidget *parent)
1087 main_layout->addWidget(m_view_tab, 2); 1135 main_layout->addWidget(m_view_tab, 2);
1088 1136
1089 m_delete_action = new QAction("&Delete", this); 1137 m_delete_action = new QAction("&Delete", this);
1090 m_delete_action->setIcon(QIcon::fromTheme("list-remove")); 1138 m_delete_action->setIcon(YIconManager::Get()->GetIcon(YIconManager::ListRemove));
1091 m_new_action = new QAction("&New field", this); 1139 m_new_action = new QAction("&New field", this);
1092 m_new_action->setIcon(QIcon::fromTheme("list-add")); 1140 m_new_action->setIcon(YIconManager::Get()->GetIcon(YIconManager::ListAdd));
1093 1141
1094 setLayout(main_layout); 1142 setLayout(main_layout);
1095 1143
@@ -1101,6 +1149,7 @@ RegEditPanel::RegEditPanel(const soc_desc::register_ref_t& ref, QWidget *parent)
1101 connect(m_sexy_display2, SIGNAL(customContextMenuRequested(QPoint)), this, 1149 connect(m_sexy_display2, SIGNAL(customContextMenuRequested(QPoint)), this,
1102 SLOT(OnRegDisplayContextMenu(QPoint))); 1150 SLOT(OnRegDisplayContextMenu(QPoint)));
1103 connect(m_reg_size_group, SIGNAL(buttonClicked(int)), this, SLOT(OnWidthChanged(int))); 1151 connect(m_reg_size_group, SIGNAL(buttonClicked(int)), this, SLOT(OnWidthChanged(int)));
1152 connect(m_reg_access_group, SIGNAL(buttonClicked(int)), this, SLOT(OnAccessChanged(int)));
1104 connect(m_delete_action, SIGNAL(triggered()), this, SLOT(OnRegFieldDelete())); 1153 connect(m_delete_action, SIGNAL(triggered()), this, SLOT(OnRegFieldDelete()));
1105 connect(m_new_action, SIGNAL(triggered()), this, SLOT(OnRegFieldNew())); 1154 connect(m_new_action, SIGNAL(triggered()), this, SLOT(OnRegFieldNew()));
1106 connect(m_variant_table, SIGNAL(itemActivated(QTableWidgetItem *)), this, 1155 connect(m_variant_table, SIGNAL(itemActivated(QTableWidgetItem *)), this,
@@ -1110,6 +1159,7 @@ RegEditPanel::RegEditPanel(const soc_desc::register_ref_t& ref, QWidget *parent)
1110 connect(m_desc_edit, SIGNAL(OnTextChanged()), this, SLOT(OnDescEdited())); 1159 connect(m_desc_edit, SIGNAL(OnTextChanged()), this, SLOT(OnDescEdited()));
1111 connect(m_fields_tab, SIGNAL(tabCloseRequested(int)), this, SLOT(OnFieldRemove(int))); 1160 connect(m_fields_tab, SIGNAL(tabCloseRequested(int)), this, SLOT(OnFieldRemove(int)));
1112 connect(m_fields_tab, SIGNAL(tabOpenRequested()), this, SLOT(OnFieldCreate())); 1161 connect(m_fields_tab, SIGNAL(tabOpenRequested()), this, SLOT(OnFieldCreate()));
1162 connect(m_value_model, SIGNAL(OnBitrangeModified(int)), this, SLOT(OnBitrangeModified(int)));
1113} 1163}
1114 1164
1115void RegEditPanel::UpdateWidthRestrictions() 1165void RegEditPanel::UpdateWidthRestrictions()
@@ -1148,6 +1198,22 @@ void RegEditPanel::OnWidthChanged(int w)
1148 OnModified(); 1198 OnModified();
1149} 1199}
1150 1200
1201void RegEditPanel::OnBitrangeModified(int index)
1202{
1203 soc_desc::register_t reg = m_value_model->GetRegister();
1204 m_ref.get()->field[index].pos = reg.field[index].pos;
1205 m_ref.get()->field[index].width = reg.field[index].width;
1206 for(int i = 0; i < m_fields_tab->count(); i++)
1207 dynamic_cast< RegFieldEditPanel * >(m_fields_tab->widget(i))->UpdateRange();
1208 OnModified();
1209}
1210
1211void RegEditPanel::OnAccessChanged(int acc)
1212{
1213 m_ref.get()->access = (soc_desc::access_t)acc;
1214 OnModified();
1215}
1216
1151void RegEditPanel::OnDescEdited() 1217void RegEditPanel::OnDescEdited()
1152{ 1218{
1153 m_ref.get()->desc = m_desc_edit->GetTextHtml().toStdString(); 1219 m_ref.get()->desc = m_desc_edit->GetTextHtml().toStdString();
@@ -1169,9 +1235,11 @@ void RegEditPanel::OnVariantActivated(QTableWidgetItem *item)
1169 soc_desc::variant_t& variant = *m_ref.create_variant().get(); 1235 soc_desc::variant_t& variant = *m_ref.create_variant().get();
1170 variant.type = "untyped"; 1236 variant.type = "untyped";
1171 variant.offset = 0; 1237 variant.offset = 0;
1238 variant.access = soc_desc::UNSPECIFIED;
1172 m_variant_table->insertRow(row); 1239 m_variant_table->insertRow(row);
1173 QTableWidgetItem *item = new QTableWidgetItem( 1240 QTableWidgetItem *item = new QTableWidgetItem(
1174 QIcon::fromTheme("list-remove"), "", RegVariantEditPanelDelType); 1241 YIconManager::Get()->GetIcon(YIconManager::ListRemove), "", RegVariantEditPanelDelType);
1242 item->setToolTip("Remove this variant");
1175 item->setFlags(Qt::ItemIsEnabled); 1243 item->setFlags(Qt::ItemIsEnabled);
1176 m_variant_table->setItem(row, 0, item); 1244 m_variant_table->setItem(row, 0, item);
1177 item = new QTableWidgetItem(QString::fromStdString(variant.type)); 1245 item = new QTableWidgetItem(QString::fromStdString(variant.type));
@@ -1179,6 +1247,9 @@ void RegEditPanel::OnVariantActivated(QTableWidgetItem *item)
1179 item = new QTableWidgetItem(); 1247 item = new QTableWidgetItem();
1180 item->setData(Qt::EditRole, QVariant(variant.offset)); 1248 item->setData(Qt::EditRole, QVariant(variant.offset));
1181 m_variant_table->setItem(row, 2, item); 1249 m_variant_table->setItem(row, 2, item);
1250 item = new QTableWidgetItem();
1251 item->setData(Qt::EditRole, QVariant::fromValue(variant.access));
1252 m_variant_table->setItem(row, 3, item);
1182 OnModified(); 1253 OnModified();
1183 } 1254 }
1184} 1255}
@@ -1193,6 +1264,8 @@ void RegEditPanel::OnVariantValueChanged(QTableWidgetItem *item)
1193 var.type = item->text().toStdString(); 1264 var.type = item->text().toStdString();
1194 else if(item->column() == 2) 1265 else if(item->column() == 2)
1195 var.offset = item->data(Qt::EditRole).value< soc_word_t >(); 1266 var.offset = item->data(Qt::EditRole).value< soc_word_t >();
1267 else if(item->column() == 3)
1268 var.access = item->data(Qt::EditRole).value< soc_desc::access_t >();
1196 OnModified(); 1269 OnModified();
1197} 1270}
1198 1271
@@ -1346,20 +1419,22 @@ RegEdit::RegEdit(Backend *backend, QWidget *parent)
1346 m_file_edit->setReadOnly(true); 1419 m_file_edit->setReadOnly(true);
1347 m_file_open = new QToolButton(this); 1420 m_file_open = new QToolButton(this);
1348 m_file_open->setText("Open"); 1421 m_file_open->setText("Open");
1349 m_file_open->setIcon(QIcon::fromTheme("document-open")); 1422 m_file_open->setIcon(YIconManager::Get()->GetIcon(YIconManager::DocumentOpen));
1350 m_file_open->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); 1423 m_file_open->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
1351 QMenu *file_open_menu = new QMenu(this); 1424 QMenu *file_open_menu = new QMenu(this);
1352 QAction *new_act = file_open_menu->addAction(QIcon::fromTheme("document-new"), "New..."); 1425 QAction *new_act = file_open_menu->addAction(YIconManager::Get()->GetIcon(YIconManager::DocumentNew),
1426 "New...");
1353 m_file_open->setPopupMode(QToolButton::MenuButtonPopup); 1427 m_file_open->setPopupMode(QToolButton::MenuButtonPopup);
1354 m_file_open->setMenu(file_open_menu); 1428 m_file_open->setMenu(file_open_menu);
1355 1429
1356 m_file_save = new QToolButton(this); 1430 m_file_save = new QToolButton(this);
1357 m_file_save->setText("Save"); 1431 m_file_save->setText("Save");
1358 m_file_save->setIcon(QIcon::fromTheme("document-save")); 1432 m_file_save->setIcon(YIconManager::Get()->GetIcon(YIconManager::DocumentSave));
1359 m_file_save->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); 1433 m_file_save->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
1360 m_file_save->setPopupMode(QToolButton::MenuButtonPopup); 1434 m_file_save->setPopupMode(QToolButton::MenuButtonPopup);
1361 QMenu *file_save_menu = new QMenu(this); 1435 QMenu *file_save_menu = new QMenu(this);
1362 QAction *saveas_act = file_save_menu->addAction(QIcon::fromTheme("document-save-as"), "Save as..."); 1436 QAction *saveas_act = file_save_menu->addAction(YIconManager::Get()->GetIcon(YIconManager::DocumentSaveAs),
1437 "Save as...");
1363 m_file_save->setMenu(file_save_menu); 1438 m_file_save->setMenu(file_save_menu);
1364 1439
1365 QHBoxLayout *file_group_layout = new QHBoxLayout(); 1440 QHBoxLayout *file_group_layout = new QHBoxLayout();
@@ -1375,11 +1450,11 @@ RegEdit::RegEdit(Backend *backend, QWidget *parent)
1375 m_soc_tree->setContextMenuPolicy(Qt::CustomContextMenu); 1450 m_soc_tree->setContextMenuPolicy(Qt::CustomContextMenu);
1376 1451
1377 m_delete_action = new QAction("&Delete", this); 1452 m_delete_action = new QAction("&Delete", this);
1378 m_delete_action->setIcon(QIcon::fromTheme("list-remove")); 1453 m_delete_action->setIcon(YIconManager::Get()->GetIcon(YIconManager::ListRemove));
1379 m_new_action = new QAction("&New", this); 1454 m_new_action = new QAction("&New", this);
1380 m_new_action->setIcon(QIcon::fromTheme("list-add")); 1455 m_new_action->setIcon(YIconManager::Get()->GetIcon(YIconManager::ListAdd));
1381 m_create_action = new QAction("&Create register", this); 1456 m_create_action = new QAction("&Create register", this);
1382 m_create_action->setIcon(QIcon::fromTheme("folder-new")); 1457 m_create_action->setIcon(YIconManager::Get()->GetIcon(YIconManager::FolderNew));
1383 1458
1384 m_splitter->addWidget(m_soc_tree); 1459 m_splitter->addWidget(m_soc_tree);
1385 m_splitter->setStretchFactor(0, 0); 1460 m_splitter->setStretchFactor(0, 0);
@@ -1605,8 +1680,8 @@ QIcon RegEdit::GetIconFromType(int type)
1605{ 1680{
1606 switch(type) 1681 switch(type)
1607 { 1682 {
1608 case SocTreeSocType: return QIcon::fromTheme("computer"); 1683 case SocTreeSocType: return YIconManager::Get()->GetIcon(YIconManager::Computer);
1609 case SocTreeNodeType: return QIcon::fromTheme("cpu"); 1684 case SocTreeNodeType: return YIconManager::Get()->GetIcon(YIconManager::Cpu);
1610 case SocTreeRegType: return style()->standardIcon(QStyle::SP_ArrowRight); 1685 case SocTreeRegType: return style()->standardIcon(QStyle::SP_ArrowRight);
1611 default: return QIcon(); 1686 default: return QIcon();
1612 } 1687 }
@@ -1627,7 +1702,7 @@ void RegEdit::FixupItem(QTreeWidgetItem *item)
1627 UpdateName(item); 1702 UpdateName(item);
1628 if(!ValidateName(item->text(0))) 1703 if(!ValidateName(item->text(0)))
1629 { 1704 {
1630 item->setIcon(0, QIcon::fromTheme("dialog-error")); 1705 item->setIcon(0, YIconManager::Get()->GetIcon(YIconManager::DialogError));
1631 if(item->text(0).size() == 0) 1706 if(item->text(0).size() == 0)
1632 { 1707 {
1633 MakeItalic(item, true); 1708 MakeItalic(item, true);
@@ -1688,6 +1763,7 @@ void RegEdit::OnSocItemCreate()
1688 return; 1763 return;
1689 soc_desc::register_t reg; 1764 soc_desc::register_t reg;
1690 reg.width = 32; 1765 reg.width = 32;
1766 reg.access = soc_desc::UNSPECIFIED;
1691 soc_desc::node_ref_t node = SocTreeItemVal< soc_desc::node_ref_t >(current); 1767 soc_desc::node_ref_t node = SocTreeItemVal< soc_desc::node_ref_t >(current);
1692 node.get()->register_.push_back(reg); 1768 node.get()->register_.push_back(reg);
1693 QTreeWidgetItem *reg_item = MakeSocTreeItem(SocTreeRegType, node.reg()); 1769 QTreeWidgetItem *reg_item = MakeSocTreeItem(SocTreeRegType, node.reg());
diff --git a/utils/regtools/qeditor/regedit.h b/utils/regtools/qeditor/regedit.h
index 2540500f29..893ec73421 100644
--- a/utils/regtools/qeditor/regedit.h
+++ b/utils/regtools/qeditor/regedit.h
@@ -165,6 +165,7 @@ public:
165 RegFieldEditPanel(const soc_desc::field_ref_t& ref, QWidget *parent = 0); 165 RegFieldEditPanel(const soc_desc::field_ref_t& ref, QWidget *parent = 0);
166 soc_desc::field_ref_t GetField(); 166 soc_desc::field_ref_t GetField();
167 void UpdateWidth(); 167 void UpdateWidth();
168 void UpdateRange();
168 169
169signals: 170signals:
170 void OnModified(); 171 void OnModified();
@@ -203,12 +204,14 @@ protected slots:
203 void OnRegFieldDelete(); 204 void OnRegFieldDelete();
204 void OnRegFieldNew(); 205 void OnRegFieldNew();
205 void OnWidthChanged(int size); 206 void OnWidthChanged(int size);
207 void OnAccessChanged(int access);
206 void OnFieldModified(); 208 void OnFieldModified();
207 void OnDescEdited(); 209 void OnDescEdited();
208 void OnVariantActivated(QTableWidgetItem *item); 210 void OnVariantActivated(QTableWidgetItem *item);
209 void OnVariantValueChanged(QTableWidgetItem *item); 211 void OnVariantValueChanged(QTableWidgetItem *item);
210 void OnFieldRemove(int index); 212 void OnFieldRemove(int index);
211 void OnFieldCreate(); 213 void OnFieldCreate();
214 void OnBitrangeModified(int index);
212 215
213protected: 216protected:
214 void DoModify(); 217 void DoModify();
@@ -228,8 +231,10 @@ protected:
228 QAction *m_delete_action; 231 QAction *m_delete_action;
229 QPoint m_menu_point; 232 QPoint m_menu_point;
230 SocFieldItemDelegate *m_variant_delegate; 233 SocFieldItemDelegate *m_variant_delegate;
234 SocAccessItemDelegate *m_access_delegate;
231 SocFieldEditorCreator *m_variant_editor; 235 SocFieldEditorCreator *m_variant_editor;
232 QButtonGroup *m_reg_size_group; 236 QButtonGroup *m_reg_size_group;
237 QButtonGroup *m_reg_access_group;
233}; 238};
234 239
235class RegEdit : public QWidget, public DocumentTab 240class RegEdit : public QWidget, public DocumentTab
diff --git a/utils/regtools/qeditor/regtab.cpp b/utils/regtools/qeditor/regtab.cpp
index 2653908d41..c6a1f41ee9 100644
--- a/utils/regtools/qeditor/regtab.cpp
+++ b/utils/regtools/qeditor/regtab.cpp
@@ -75,10 +75,11 @@ RegTab::RegTab(Backend *backend, QWidget *parent)
75 QVBoxLayout *left_layout = new QVBoxLayout; 75 QVBoxLayout *left_layout = new QVBoxLayout;
76 left->setLayout(left_layout); 76 left->setLayout(left_layout);
77 77
78 QGroupBox *top_group = new QGroupBox("SOC selection"); 78 QGroupBox *top_group = new QGroupBox("");
79 QVBoxLayout *top_group_layout = new QVBoxLayout; 79 QHBoxLayout *top_group_layout = new QHBoxLayout;
80 m_soc_selector = new QComboBox; 80 m_soc_selector = new QComboBox;
81 top_group_layout->addWidget(m_soc_selector); 81 top_group_layout->addWidget(new QLabel("SOC:"));
82 top_group_layout->addWidget(m_soc_selector, 1);
82 top_group->setLayout(top_group_layout); 83 top_group->setLayout(top_group_layout);
83 84
84 m_reg_tree = new QTreeWidget(); 85 m_reg_tree = new QTreeWidget();
@@ -96,7 +97,7 @@ RegTab::RegTab(Backend *backend, QWidget *parent)
96 left_layout->addWidget(m_type_selector); 97 left_layout->addWidget(m_type_selector);
97 98
98 m_right_panel = new QVBoxLayout; 99 m_right_panel = new QVBoxLayout;
99 QGroupBox *data_sel_group = new QGroupBox("Data selection"); 100 QGroupBox *data_sel_group = new QGroupBox("");
100 QHBoxLayout *data_sel_layout = new QHBoxLayout; 101 QHBoxLayout *data_sel_layout = new QHBoxLayout;
101 m_backend_selector = new BackendSelector(m_backend, this); 102 m_backend_selector = new BackendSelector(m_backend, this);
102 m_backend_selector->SetNothingMessage("<i>Select a data source to analyse its content.</i>"); 103 m_backend_selector->SetNothingMessage("<i>Select a data source to analyse its content.</i>");
@@ -108,6 +109,7 @@ RegTab::RegTab(Backend *backend, QWidget *parent)
108 m_data_sel_reload = new QPushButton(this); 109 m_data_sel_reload = new QPushButton(this);
109 m_data_sel_reload->setIcon(QIcon::fromTheme("view-refresh")); 110 m_data_sel_reload->setIcon(QIcon::fromTheme("view-refresh"));
110 m_data_sel_reload->setToolTip("Reload data"); 111 m_data_sel_reload->setToolTip("Reload data");
112 data_sel_layout->addWidget(new QLabel("Data:"));
111 data_sel_layout->addWidget(m_backend_selector); 113 data_sel_layout->addWidget(m_backend_selector);
112 data_sel_layout->addWidget(m_readonly_check); 114 data_sel_layout->addWidget(m_readonly_check);
113 data_sel_layout->addWidget(m_data_soc_label); 115 data_sel_layout->addWidget(m_data_soc_label);
@@ -146,7 +148,9 @@ RegTab::RegTab(Backend *backend, QWidget *parent)
146 connect(m_type_selector, SIGNAL(currentChanged(int)), this, SLOT(OnTypeChanged(int))); 148 connect(m_type_selector, SIGNAL(currentChanged(int)), this, SLOT(OnTypeChanged(int)));
147 149
148 m_msg_select_id = SetMessage(MessageWidget::Information, 150 m_msg_select_id = SetMessage(MessageWidget::Information,
149 "You can browse the registers. Select a data source to analyse the values."); 151 "You can browse the registers using the left panel. "
152 "Select a data source at the top to analyse the values. "
153 "You can also use the analyzers available in the left panel, if any.");
150 m_msg_error_id = 0; 154 m_msg_error_id = 0;
151 155
152 QList< SocFileRef > socs = m_backend->GetSocFileList(); 156 QList< SocFileRef > socs = m_backend->GetSocFileList();
@@ -215,8 +219,7 @@ void RegTab::UpdateTabName()
215 else if(hwstub) 219 else if(hwstub)
216 { 220 {
217 HWStubDevice *dev = hwstub->GetDevice(); 221 HWStubDevice *dev = hwstub->GetDevice();
218 SetTabName(QString("HWStub %1.%2").arg(dev->GetBusNumber()) 222 SetTabName(dev->GetFriendlyName());
219 .arg(dev->GetDevAddress()));
220 } 223 }
221#endif 224#endif
222 else 225 else
@@ -231,11 +234,21 @@ void RegTab::OnBackendSelect(IoBackend *backend)
231 HideMessage(m_msg_select_id); 234 HideMessage(m_msg_select_id);
232 HideMessage(m_msg_error_id); 235 HideMessage(m_msg_error_id);
233 m_io_backend = backend; 236 m_io_backend = backend;
234 SetReadOnlyIndicator(); 237 /* Check if the backend is valid, otherwise it might confuse the user */
235 SetDataSocName(m_io_backend->GetSocName()); 238 if(m_io_backend->IsValid())
236 OnDataSocActivated(m_io_backend->GetSocName()); 239 {
237 OnDataChanged(); 240 SetReadOnlyIndicator();
238 UpdateTabName(); 241 SetDataSocName(m_io_backend->GetSocName());
242 OnDataSocActivated(m_io_backend->GetSocName());
243 OnDataChanged();
244 UpdateTabName();
245 }
246 /* But don't display it for the dummy backend either */
247 else if(dynamic_cast< DummyIoBackend * >(m_io_backend) == 0)
248 {
249 m_msg_error_id = SetMessage(MessageWidget::Error,
250 "Data source is not available.");
251 }
239} 252}
240 253
241void RegTab::SetReadOnlyIndicator() 254void RegTab::SetReadOnlyIndicator()
@@ -267,6 +280,7 @@ void RegTab::OnAnalyserClicked(QListWidgetItem *current)
267 280
268void RegTab::DisplayNode(const soc_desc::node_inst_t& ref) 281void RegTab::DisplayNode(const soc_desc::node_inst_t& ref)
269{ 282{
283 HideMessage(m_msg_select_id);
270 if(ref.node().is_root()) 284 if(ref.node().is_root())
271 SetPanel(new SocDisplayPanel(this, m_io_backend, ref.soc())); 285 SetPanel(new SocDisplayPanel(this, m_io_backend, ref.soc()));
272 else if(ref.node().reg().valid()) 286 else if(ref.node().reg().valid())
diff --git a/utils/regtools/qeditor/utils.cpp b/utils/regtools/qeditor/utils.cpp
index 0d0a7de5ed..748a989512 100644
--- a/utils/regtools/qeditor/utils.cpp
+++ b/utils/regtools/qeditor/utils.cpp
@@ -30,6 +30,9 @@
30#include <QXmlStreamWriter> 30#include <QXmlStreamWriter>
31#include <QTextBlock> 31#include <QTextBlock>
32#include <QApplication> 32#include <QApplication>
33#include <QPushButton>
34#include <QMessageBox>
35#include <QStandardItemModel>
33 36
34/** 37/**
35 * SocBitRangeValidator 38 * SocBitRangeValidator
@@ -406,6 +409,11 @@ bool SocFieldBitRange::operator<(const SocFieldBitRange& o) const
406 return m_last_bit < o.m_last_bit; 409 return m_last_bit < o.m_last_bit;
407} 410}
408 411
412bool SocFieldBitRange::operator!=(const SocFieldBitRange& o) const
413{
414 return m_first_bit != o.m_first_bit || m_last_bit != o.m_last_bit;
415}
416
409/** 417/**
410 * SocFieldCachedItemDelegate 418 * SocFieldCachedItemDelegate
411 */ 419 */
@@ -476,6 +484,53 @@ void SocFieldCachedEditor::setValue(SocFieldCachedValue val)
476} 484}
477 485
478/** 486/**
487 * SocAccessItemDelegate
488 */
489QString SocAccessItemDelegate::displayText(const QVariant& value, const QLocale& locale) const
490{
491 if(isUserType< soc_desc::access_t >(value))
492 {
493 soc_desc::access_t acc = value.value< soc_desc::access_t >();
494 switch(acc)
495 {
496 case soc_desc::UNSPECIFIED: return m_unspec_text;
497 case soc_desc::READ_ONLY: return "Read-Only";
498 case soc_desc::READ_WRITE: return "Read-Write";
499 case soc_desc::WRITE_ONLY: return "Write-Only";
500 default: return "<bug>";
501 }
502 }
503 else
504 return QStyledItemDelegate::displayText(value, locale);
505}
506
507/**
508 * SocAccessEditor
509 */
510SocAccessEditor::SocAccessEditor(const QString& unspec_text, QWidget *parent)
511 :QComboBox(parent)
512{
513 addItem(unspec_text, QVariant::fromValue(soc_desc::UNSPECIFIED));
514 addItem("Read-Only", QVariant::fromValue(soc_desc::READ_ONLY));
515 addItem("Read-Write", QVariant::fromValue(soc_desc::READ_WRITE));
516 addItem("Write-Only", QVariant::fromValue(soc_desc::WRITE_ONLY));
517}
518
519SocAccessEditor::~SocAccessEditor()
520{
521}
522
523soc_desc::access_t SocAccessEditor::access() const
524{
525 return itemData(currentIndex()).value< soc_desc::access_t >();
526}
527
528void SocAccessEditor::setAccess(soc_desc::access_t acc)
529{
530 setCurrentIndex(findData(QVariant::fromValue(acc)));
531}
532
533/**
479 * SocFieldEditorCreator 534 * SocFieldEditorCreator
480 */ 535 */
481QWidget *SocFieldEditorCreator::createWidget(QWidget *parent) const 536QWidget *SocFieldEditorCreator::createWidget(QWidget *parent) const
@@ -494,6 +549,19 @@ void SocFieldEditorCreator::setWidth(int bitcount)
494} 549}
495 550
496/** 551/**
552 * SocAccessEditorCreator
553 */
554QWidget *SocAccessEditorCreator::createWidget(QWidget *parent) const
555{
556 return new SocAccessEditor(m_unspec_text, parent);
557}
558
559QByteArray SocAccessEditorCreator::valuePropertyName() const
560{
561 return QByteArray("access");
562}
563
564/**
497 * SocFieldCachedEditorCreator 565 * SocFieldCachedEditorCreator
498 */ 566 */
499QWidget *SocFieldCachedEditorCreator::createWidget(QWidget *parent) const 567QWidget *SocFieldCachedEditorCreator::createWidget(QWidget *parent) const
@@ -602,8 +670,22 @@ bool RegFieldTableModel::setData(const QModelIndex& idx, const QVariant& value,
602 if(role != Qt::EditRole) 670 if(role != Qt::EditRole)
603 return false; 671 return false;
604 int section = idx.column(); 672 int section = idx.column();
673 if(section == BitRangeColumn)
674 {
675 if(idx.row() < 0 || idx.row() >= rowCount())
676 return false;
677 if(value.type() != QVariant::UserType && value.userType() == qMetaTypeId< SocFieldBitRange >())
678 return false;
679 SocFieldBitRange bitrange = value.value< SocFieldBitRange >();
680 m_reg.field[idx.row()].pos = bitrange.GetFirstBit();
681 m_reg.field[idx.row()].width = bitrange.GetLastBit() - bitrange.GetFirstBit() + 1;
682 emit OnBitrangeModified(idx.row());
683 }
605 if(section < FirstValueColumn || section >= FirstValueColumn + m_value.size()) 684 if(section < FirstValueColumn || section >= FirstValueColumn + m_value.size())
685 {
686 qDebug() << "ignore setData to column " << section;
606 return false; 687 return false;
688 }
607 section -= FirstValueColumn; 689 section -= FirstValueColumn;
608 const SocFieldCachedValue& v = value.value< SocFieldCachedValue >(); 690 const SocFieldCachedValue& v = value.value< SocFieldCachedValue >();
609 if(!m_value[section].isValid()) 691 if(!m_value[section].isValid())
@@ -622,7 +704,12 @@ Qt::ItemFlags RegFieldTableModel::flags(const QModelIndex& index) const
622 Qt::ItemFlags flags = Qt::ItemIsSelectable | Qt::ItemIsEnabled; 704 Qt::ItemFlags flags = Qt::ItemIsSelectable | Qt::ItemIsEnabled;
623 int section = index.column(); 705 int section = index.column();
624 if(section < FirstValueColumn || section >= FirstValueColumn + m_value.size()) 706 if(section < FirstValueColumn || section >= FirstValueColumn + m_value.size())
707 {
708 /* bitrange or name */
709 if(!m_read_only)
710 flags |= Qt::ItemIsEditable;
625 return flags; 711 return flags;
712 }
626 section -= FirstValueColumn; 713 section -= FirstValueColumn;
627 if(m_value[section].isValid() && !m_read_only) 714 if(m_value[section].isValid() && !m_read_only)
628 flags |= Qt::ItemIsEditable; 715 flags |= Qt::ItemIsEditable;
@@ -764,6 +851,207 @@ bool RegFieldProxyModel::lessThan(const QModelIndex& left,
764} 851}
765 852
766/** 853/**
854 * YRegDisplayItemEditor
855 */
856YRegDisplayItemEditor::YRegDisplayItemEditor(QWidget *parent, YRegDisplay *display,
857 YRegDisplayItemDelegate *delegate, QModelIndex bitrange_index,
858 QModelIndex name_index)
859 :QWidget(parent), m_display_delegate(delegate),
860 m_display(display), m_state(Idle)
861{
862 m_col_width = m_display->BitrangeRect(SocFieldBitRange(0, 0)).width();
863 m_resize_margin = m_col_width / 4;
864 setEditorData(bitrange_index, name_index);
865 setMouseTracking(true);
866 setAutoFillBackground(true);
867 setFocusPolicy(Qt::StrongFocus); // QItemDelegate says it's important
868}
869
870void YRegDisplayItemEditor::setEditorData(QModelIndex bitrange_index, QModelIndex name_index)
871{
872 if(m_state != Idle)
873 {
874 m_state = Idle;
875 QApplication::restoreOverrideCursor();
876 }
877 m_bitrange_index = bitrange_index;
878 m_name_index = name_index;
879 m_bitrange = bitrange_index.data().value< SocFieldBitRange >();
880}
881
882void YRegDisplayItemEditor::getEditorData(QVariant& name, QVariant& bitrange)
883{
884 name = QVariant(); /* don't touch the name */
885 bitrange = QVariant::fromValue(m_bitrange);
886}
887
888YRegDisplayItemEditor::~YRegDisplayItemEditor()
889{
890 /* make sure to restore cursor if modified */
891 if(m_state != Idle)
892 {
893 m_state = Idle;
894 QApplication::restoreOverrideCursor();
895 }
896}
897
898YRegDisplayItemEditor::Zone YRegDisplayItemEditor::GetZone(const QPoint& pt)
899{
900 if(!rect().contains(pt))
901 return NoZone;
902 if(pt.x() >= 0 && pt.x() <= m_resize_margin)
903 return ResizeLeftZone;
904 if(pt.x() >= width() - m_resize_margin && pt.x() <= width())
905 return ResizeRightZone;
906 return MoveZone;
907}
908
909void YRegDisplayItemEditor::mouseMoveEvent(QMouseEvent *event)
910{
911 Zone zone = GetZone(event->pos());
912 bool in_resize_zone = (zone == ResizeLeftZone || zone == ResizeRightZone);
913 /* resizing/moving has priority */
914 if(m_state == ResizingLeft || m_state == ResizingRight || m_state == Moving)
915 {
916 SocFieldBitRange new_bitrange = m_bitrange;
917 if(m_state == Moving)
918 {
919 /* Compute new bitrange: we know the offset of the mouse relative to the
920 * left of the register: use that offset to compute the new position of
921 * the MSB bit. To make it more natural, add half of a column of margin
922 * so that the register does not move until half of a bit column displacement
923 * was made */
924 int bit = m_display->bitColumnAt(mapTo(m_display,
925 event->pos() - QPoint(m_move_offset - m_col_width / 2, 0)));
926 new_bitrange.SetLastBit(bit);
927 int w = m_bitrange.GetLastBit() - m_bitrange.GetFirstBit();
928 /* make sure range is valid */
929 if(bit - w < 0)
930 return;
931 new_bitrange.SetFirstBit(bit - w);
932 }
933 else
934 {
935 /* Compute new bitrange. To make it more natural, add quarter of a column of margin
936 * so that the register does not resize until quarter of a bit column displacement
937 * was made */
938 int bit = m_display->bitColumnAt(mapTo(m_display, event->pos()
939 + QPoint(m_col_width / 4, 0)));
940 if(m_state == ResizingLeft)
941 new_bitrange.SetLastBit(bit);
942 else
943 new_bitrange.SetFirstBit(bit);
944 /* make sure range is valid */
945 if(new_bitrange.GetLastBit() < new_bitrange.GetFirstBit())
946 return;
947 }
948 /* make sure range does not overlap with other fields */
949 /* TODO */
950 /* update current bitrange (display only) and resize widget */
951 if(m_bitrange != new_bitrange)
952 {
953 m_bitrange = new_bitrange;
954 /* resize widget */
955 QRect rect = m_display->BitrangeRect(m_bitrange);
956 rect.moveTopLeft(parentWidget()->mapFromGlobal(m_display->mapToGlobal(rect.topLeft())));
957 setGeometry(rect);
958 }
959 }
960 /* any zone -> resize zone */
961 else if(in_resize_zone)
962 {
963 /* don't do unnecessary changes */
964 if(m_state != InResizeZone)
965 {
966 /* restore old cursor if needed */
967 if(m_state != Idle)
968 QApplication::restoreOverrideCursor();
969 m_state = InResizeZone;
970 QApplication::setOverrideCursor(QCursor(Qt::SizeHorCursor));
971 }
972 }
973 /* any zone -> move zone */
974 else if(zone == MoveZone)
975 {
976 /* don't do unnecessary changes */
977 if(m_state != InMoveZone)
978 {
979 /* restore old cursor if needed */
980 if(m_state != Idle)
981 QApplication::restoreOverrideCursor();
982 m_state = InMoveZone;
983 QApplication::setOverrideCursor(QCursor(Qt::SizeAllCursor));
984 }
985 }
986 /* any zone -> no zone */
987 else if(zone == NoZone)
988 {
989 if(m_state != Idle)
990 {
991 m_state = Idle;
992 QApplication::restoreOverrideCursor();
993 }
994 }
995}
996
997void YRegDisplayItemEditor::leaveEvent(QEvent *event)
998{
999 Q_UNUSED(event);
1000 if(m_state == InResizeZone)
1001 {
1002 m_state = Idle;
1003 QApplication::restoreOverrideCursor();
1004 }
1005}
1006
1007void YRegDisplayItemEditor::mousePressEvent(QMouseEvent *event)
1008{
1009 /* just in case the mouseMove event was not done */
1010 mouseMoveEvent(event);
1011 /* we need to track mouse outside of widget but Qt already grabs the mouse
1012 * for us on mouse press in widget */
1013 if(m_state == InResizeZone)
1014 {
1015 if(GetZone(event->pos()) == ResizeLeftZone)
1016 m_state = ResizingLeft;
1017 else
1018 m_state = ResizingRight;
1019 }
1020 else if(m_state == InMoveZone)
1021 {
1022 m_state = Moving;
1023 /* store offset from the left, to keep relative position of the register
1024 * with respect to the mouse */
1025 m_move_offset = event->pos().x();
1026 }
1027}
1028
1029void YRegDisplayItemEditor::mouseReleaseEvent(QMouseEvent *event)
1030{
1031 if(m_state == ResizingLeft || m_state == ResizingRight || m_state == Moving)
1032 {
1033 QApplication::restoreOverrideCursor();
1034 m_state = Idle;
1035 /* update cursor */
1036 mouseMoveEvent(event);
1037 }
1038}
1039
1040void YRegDisplayItemEditor::paintEvent(QPaintEvent *event)
1041{
1042 Q_UNUSED(event);
1043 QPainter painter(this);
1044 /* reuse delegate code to paint */
1045 QStyleOptionViewItemV4 opt = m_display->viewOptions();
1046 opt.state |= QStyle::State_HasFocus | QStyle::State_Selected | QStyle::State_Active;
1047 opt.displayAlignment = Qt::AlignHCenter | Qt::AlignVCenter;
1048 opt.rect = rect();
1049 opt.showDecorationSelected = true;
1050 m_display_delegate->initStyleOption(&opt, m_name_index);
1051 m_display_delegate->MyPaint(&painter, opt);
1052}
1053
1054/**
767 * YRegDisplayItemDelegate 1055 * YRegDisplayItemDelegate
768 */ 1056 */
769 1057
@@ -772,14 +1060,9 @@ YRegDisplayItemDelegate::YRegDisplayItemDelegate(QObject *parent)
772{ 1060{
773} 1061}
774 1062
775 void YRegDisplayItemDelegate::paint(QPainter *painter, 1063void YRegDisplayItemDelegate::MyPaint(QPainter *painter, const QStyleOptionViewItemV4& option) const
776 const QStyleOptionViewItem& option, const QModelIndex& index) const
777{ 1064{
778 QStyleOptionViewItemV4 opt = option; 1065 QStyleOptionViewItemV4 opt = option;
779 // default alignment is centered unless specified
780 opt.displayAlignment = Qt::AlignHCenter | Qt::AlignVCenter;
781 initStyleOption(&opt, index);
782
783 painter->save(); 1066 painter->save();
784 // draw everything rotated, requires careful manipulation of the 1067 // draw everything rotated, requires careful manipulation of the
785 // rects involved 1068 // rects involved
@@ -789,17 +1072,58 @@ YRegDisplayItemDelegate::YRegDisplayItemDelegate(QObject *parent)
789 QStyle *style = opt.widget ? opt.widget->style() : QApplication::style(); 1072 QStyle *style = opt.widget ? opt.widget->style() : QApplication::style();
790 style->drawControl(QStyle::CE_ItemViewItem, &opt, painter, opt.widget); 1073 style->drawControl(QStyle::CE_ItemViewItem, &opt, painter, opt.widget);
791 painter->restore(); 1074 painter->restore();
1075}
1076
1077void YRegDisplayItemDelegate::paint(QPainter *painter,
1078 const QStyleOptionViewItem& option, const QModelIndex& index) const
1079{
1080 QStyleOptionViewItemV4 opt = option;
1081 // default alignment is centered unless specified
1082 opt.displayAlignment = Qt::AlignHCenter | Qt::AlignVCenter;
1083 initStyleOption(&opt, index);
1084
1085 MyPaint(painter, opt);
792 1086
793} 1087}
794 1088
795QSize YRegDisplayItemDelegate::sizeHint(const QStyleOptionViewItem& option, 1089QSize YRegDisplayItemDelegate::sizeHint(const QStyleOptionViewItem& option,
796 const QModelIndex& index) const 1090 const QModelIndex& index) const
797{ 1091{
1092 /* useless in our case, the view ignores this */
798 Q_UNUSED(option); 1093 Q_UNUSED(option);
799 Q_UNUSED(index); 1094 Q_UNUSED(index);
800 return QSize(); 1095 return QSize();
801} 1096}
802 1097
1098QWidget *YRegDisplayItemDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem& option,
1099 const QModelIndex& index) const
1100{
1101 Q_UNUSED(option);
1102 Q_UNUSED(index);
1103 YRegDisplay *display = dynamic_cast< YRegDisplay* >(parent->parent());
1104 Q_ASSERT(display != nullptr);
1105 /* column 0 is name, column 1 is range */
1106 return new YRegDisplayItemEditor(parent, display, const_cast< YRegDisplayItemDelegate* >(this),
1107 index.sibling(index.row(), 0), index.sibling(index.row(), 1));
1108}
1109
1110void YRegDisplayItemDelegate::setEditorData(QWidget *editor, const QModelIndex& index) const
1111{
1112 dynamic_cast< YRegDisplayItemEditor* >(editor)->setEditorData(
1113 index.sibling(index.row(), 0), index.sibling(index.row(), 1));
1114}
1115
1116void YRegDisplayItemDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,
1117 const QModelIndex& index) const
1118{
1119 QVariant name, bitrange;
1120 dynamic_cast< YRegDisplayItemEditor* >(editor)->getEditorData(name, bitrange);
1121 if(name.isValid())
1122 model->setData(index.sibling(index.row(), 1), name);
1123 if(bitrange.isValid())
1124 model->setData(index.sibling(index.row(), 0), bitrange);
1125}
1126
803/** 1127/**
804 * YRegDisplay 1128 * YRegDisplay
805 */ 1129 */
@@ -814,7 +1138,8 @@ YRegDisplay::YRegDisplay(QWidget *parent)
814 // the frame around the register is ugly, disable it 1138 // the frame around the register is ugly, disable it
815 setFrameShape(QFrame::NoFrame); 1139 setFrameShape(QFrame::NoFrame);
816 setSelectionMode(SingleSelection); 1140 setSelectionMode(SingleSelection);
817 setItemDelegate(new YRegDisplayItemDelegate()); 1141 setEditTriggers(QAbstractItemView::DoubleClicked | QAbstractItemView::SelectedClicked);
1142 setItemDelegate(new YRegDisplayItemDelegate(this));
818} 1143}
819 1144
820void YRegDisplay::setWidth(int nr_bits) 1145void YRegDisplay::setWidth(int nr_bits)
@@ -1055,6 +1380,11 @@ QRect YRegDisplay::itemRect(const QModelIndex& index) const
1055 return itemRect(range, index.column()); 1380 return itemRect(range, index.column());
1056} 1381}
1057 1382
1383QRect YRegDisplay::BitrangeRect(const SocFieldBitRange& range) const
1384{
1385 return itemRect(range, m_data_col);
1386}
1387
1058QRect YRegDisplay::itemRect(const SocFieldBitRange& range, int col) const 1388QRect YRegDisplay::itemRect(const SocFieldBitRange& range, int col) const
1059{ 1389{
1060 int top, bot; 1390 int top, bot;
@@ -1276,17 +1606,17 @@ MyTextEditor::MyTextEditor(QWidget *parent)
1276 m_edit->setAutoFormatting(QTextEdit::AutoAll); 1606 m_edit->setAutoFormatting(QTextEdit::AutoAll);
1277 1607
1278 m_bold_button = new QToolButton(this); 1608 m_bold_button = new QToolButton(this);
1279 m_bold_button->setIcon(QIcon::fromTheme("format-text-bold")); 1609 m_bold_button->setIcon(YIconManager::Get()->GetIcon(YIconManager::FormatTextBold));
1280 m_bold_button->setText("bold"); 1610 m_bold_button->setText("bold");
1281 m_bold_button->setCheckable(true); 1611 m_bold_button->setCheckable(true);
1282 1612
1283 m_italic_button = new QToolButton(this); 1613 m_italic_button = new QToolButton(this);
1284 m_italic_button->setIcon(QIcon::fromTheme("format-text-italic")); 1614 m_italic_button->setIcon(YIconManager::Get()->GetIcon(YIconManager::FormatTextItalic));
1285 m_italic_button->setText("italic"); 1615 m_italic_button->setText("italic");
1286 m_italic_button->setCheckable(true); 1616 m_italic_button->setCheckable(true);
1287 1617
1288 m_underline_button = new QToolButton(this); 1618 m_underline_button = new QToolButton(this);
1289 m_underline_button->setIcon(QIcon::fromTheme("format-text-underline")); 1619 m_underline_button->setIcon(YIconManager::Get()->GetIcon(YIconManager::FormatTextUnderline));
1290 m_underline_button->setText("underline"); 1620 m_underline_button->setText("underline");
1291 m_underline_button->setCheckable(true); 1621 m_underline_button->setCheckable(true);
1292 1622
@@ -1419,10 +1749,13 @@ BackendSelector::BackendSelector(Backend *backend, QWidget *parent)
1419 :QWidget(parent), m_backend(backend) 1749 :QWidget(parent), m_backend(backend)
1420{ 1750{
1421 m_data_selector = new QComboBox(this); 1751 m_data_selector = new QComboBox(this);
1422 m_data_selector->addItem(QIcon::fromTheme("text-x-generic"), "Nothing...", QVariant(DataSelNothing)); 1752 m_data_selector->addItem(YIconManager::Get()->GetIcon(YIconManager::TextGeneric),
1423 m_data_selector->addItem(QIcon::fromTheme("document-open"), "File...", QVariant(DataSelFile)); 1753 "Nothing...", QVariant(DataSelNothing));
1754 m_data_selector->addItem(YIconManager::Get()->GetIcon(YIconManager::DocumentOpen),
1755 "File...", QVariant(DataSelFile));
1424#ifdef HAVE_HWSTUB 1756#ifdef HAVE_HWSTUB
1425 m_data_selector->addItem(QIcon::fromTheme("multimedia-player"), "Device...", QVariant(DataSelDevice)); 1757 m_data_selector->addItem(YIconManager::Get()->GetIcon(YIconManager::MultimediaPlayer),
1758 "USB Device...", QVariant(DataSelDevice));
1426#endif 1759#endif
1427 m_data_sel_edit = new QLineEdit(this); 1760 m_data_sel_edit = new QLineEdit(this);
1428 m_data_sel_edit->setReadOnly(true); 1761 m_data_sel_edit->setReadOnly(true);
@@ -1435,7 +1768,18 @@ BackendSelector::BackendSelector(Backend *backend, QWidget *parent)
1435 data_sel_layout->addStretch(0); 1768 data_sel_layout->addStretch(0);
1436#ifdef HAVE_HWSTUB 1769#ifdef HAVE_HWSTUB
1437 m_dev_selector = new QComboBox; 1770 m_dev_selector = new QComboBox;
1771 m_ctx_model = new HWStubContextModel;
1772 m_ctx_model->EnableDummy(true, "Please select a device...");
1773 m_dev_selector->setModel(m_ctx_model); /* m_dev_selector will delete m_ctx_model */
1774 m_ctx_selector = new QComboBox;
1775 m_ctx_manager = HWStubManager::Get();
1776 m_ctx_selector->setModel(m_ctx_manager);
1777 m_ctx_manage_button = new QPushButton();
1778 m_ctx_manage_button->setIcon(YIconManager::Get()->GetIcon(YIconManager::Preferences));
1779 m_ctx_manage_button->setToolTip("Manage contexts");
1438 data_sel_layout->addWidget(m_dev_selector, 1); 1780 data_sel_layout->addWidget(m_dev_selector, 1);
1781 data_sel_layout->addWidget(m_ctx_selector);
1782 data_sel_layout->addWidget(m_ctx_manage_button);
1439#endif 1783#endif
1440 1784
1441 m_io_backend = m_backend->CreateDummyIoBackend(); 1785 m_io_backend = m_backend->CreateDummyIoBackend();
@@ -1443,18 +1787,25 @@ BackendSelector::BackendSelector(Backend *backend, QWidget *parent)
1443 connect(m_data_selector, SIGNAL(activated(int)), 1787 connect(m_data_selector, SIGNAL(activated(int)),
1444 this, SLOT(OnDataSelChanged(int))); 1788 this, SLOT(OnDataSelChanged(int)));
1445#ifdef HAVE_HWSTUB 1789#ifdef HAVE_HWSTUB
1446 connect(m_dev_selector, SIGNAL(currentIndexChanged(int)), 1790 connect(m_ctx_selector, SIGNAL(currentIndexChanged(int)), this,
1447 this, SLOT(OnDevChanged(int))); 1791 SLOT(OnContextSelChanged(int)));
1448 connect(&m_hwstub_helper, SIGNAL(OnDevListChanged(bool, struct libusb_device *)), 1792 connect(m_dev_selector, SIGNAL(currentIndexChanged(int)), this,
1449 this, SLOT(OnDevListChanged2(bool, struct libusb_device *))); 1793 SLOT(OnDeviceSelChanged(int)));
1794 connect(m_dev_selector, SIGNAL(activated(int)), this,
1795 SLOT(OnDeviceSelActivated(int)));
1796#endif
1797
1798#ifdef HAVE_HWSTUB
1799 OnContextSelChanged(0);
1450#endif 1800#endif
1451 OnDataSelChanged(0); 1801 OnDataSelChanged(0);
1452} 1802}
1453 1803
1454BackendSelector::~BackendSelector() 1804BackendSelector::~BackendSelector()
1455{ 1805{
1806 /* avoid m_ctx_selector from deleting HWStubManager */
1456#ifdef HAVE_HWSTUB 1807#ifdef HAVE_HWSTUB
1457 ClearDevList(); 1808 m_ctx_selector->setModel(new QStandardItemModel());
1458#endif 1809#endif
1459 delete m_io_backend; 1810 delete m_io_backend;
1460} 1811}
@@ -1475,6 +1826,8 @@ void BackendSelector::OnDataSelChanged(int index)
1475 m_data_sel_edit->show(); 1826 m_data_sel_edit->show();
1476#ifdef HAVE_HWSTUB 1827#ifdef HAVE_HWSTUB
1477 m_dev_selector->hide(); 1828 m_dev_selector->hide();
1829 m_ctx_selector->hide();
1830 m_ctx_manage_button->hide();
1478#endif 1831#endif
1479 QFileDialog *fd = new QFileDialog(m_data_selector); 1832 QFileDialog *fd = new QFileDialog(m_data_selector);
1480 QStringList filters; 1833 QStringList filters;
@@ -1496,7 +1849,10 @@ void BackendSelector::OnDataSelChanged(int index)
1496 m_nothing_text->hide(); 1849 m_nothing_text->hide();
1497 m_data_sel_edit->hide(); 1850 m_data_sel_edit->hide();
1498 m_dev_selector->show(); 1851 m_dev_selector->show();
1499 OnDevListChanged(); 1852 m_ctx_selector->show();
1853 m_ctx_manage_button->show();
1854 /* explicitely change the backend now */
1855 OnDeviceSelActivated(m_dev_selector->currentIndex());
1500 } 1856 }
1501#endif 1857#endif
1502 else 1858 else
@@ -1505,83 +1861,68 @@ void BackendSelector::OnDataSelChanged(int index)
1505 m_nothing_text->show(); 1861 m_nothing_text->show();
1506#ifdef HAVE_HWSTUB 1862#ifdef HAVE_HWSTUB
1507 m_dev_selector->hide(); 1863 m_dev_selector->hide();
1864 m_ctx_selector->hide();
1865 m_ctx_manage_button->hide();
1508#endif 1866#endif
1509 1867
1510 ChangeBackend(m_backend->CreateDummyIoBackend()); 1868 ChangeBackend(m_backend->CreateDummyIoBackend());
1511 } 1869 }
1512} 1870}
1513 1871
1514#ifdef HAVE_HWSTUB 1872IoBackend *BackendSelector::GetBackend()
1515void BackendSelector::OnDevListChanged2(bool arrived, struct libusb_device *dev)
1516{ 1873{
1517 Q_UNUSED(arrived); 1874 return m_io_backend;
1518 Q_UNUSED(dev);
1519 OnDevListChanged();
1520} 1875}
1521 1876
1522void BackendSelector::OnDevListChanged() 1877void BackendSelector::ChangeBackend(IoBackend *new_backend)
1523{ 1878{
1524 ClearDevList(); 1879 /* WARNING: delete old backend *after* calling the signal, otherwise the old backend
1525 QList< HWStubDevice* > list = m_hwstub_helper.GetDevList(); 1880 * might get used after delete */
1526 foreach(HWStubDevice *dev, list) 1881 emit OnSelect(new_backend);
1527 { 1882 delete m_io_backend;
1528 QString name = QString("Bus %1 Device %2: %3").arg(dev->GetBusNumber()) 1883 m_io_backend = new_backend;
1529 .arg(dev->GetDevAddress()).arg(dev->GetTargetInfo().bName);
1530 m_dev_selector->addItem(QIcon::fromTheme("multimedia-player"), name,
1531 QVariant::fromValue((void *)dev));
1532 }
1533 if(list.size() > 0)
1534 m_dev_selector->setCurrentIndex(0);
1535} 1884}
1536 1885
1537void BackendSelector::OnDevChanged(int index) 1886#ifdef HAVE_HWSTUB
1887void BackendSelector::OnContextSelChanged(int index)
1538{ 1888{
1889 m_ctx_model->SetContext(m_ctx_manager->GetContext(index));
1890 m_dev_selector->setCurrentIndex(0);
1891}
1892
1893void BackendSelector::OnDeviceSelChanged(int index)
1894{
1895 /* if current selection is -1, because device was removed or a new context
1896 * was selected, select entry 0, which is dummy. Not that this will not
1897 * call activate(), we don't want to change the current backend if the user
1898 * is using another type of backend. */
1539 if(index == -1) 1899 if(index == -1)
1540 return; 1900 m_dev_selector->setCurrentIndex(0);
1541 HWStubDevice *dev = reinterpret_cast< HWStubDevice* >(m_dev_selector->itemData(index).value< void* >());
1542 delete m_io_backend;
1543 /* NOTE: make a copy of the HWStubDevice device because the one in the list
1544 * might get destroyed when clearing the list while the backend is still
1545 * active: this would result in a double free when the backend is also destroyed */
1546 m_io_backend = m_backend->CreateHWStubIoBackend(new HWStubDevice(dev));
1547 emit OnSelect(m_io_backend);
1548} 1901}
1549 1902
1550void BackendSelector::ClearDevList() 1903void BackendSelector::OnDeviceSelActivated(int index)
1551{ 1904{
1552 while(m_dev_selector->count() > 0) 1905 auto dev = new HWStubDevice(m_ctx_model->GetDevice(index));
1906 if(!dev->IsValid())
1553 { 1907 {
1554 HWStubDevice *dev = reinterpret_cast< HWStubDevice* >(m_dev_selector->itemData(0).value< void* >());
1555 delete dev; 1908 delete dev;
1556 m_dev_selector->removeItem(0); 1909 ChangeBackend(m_backend->CreateDummyIoBackend());
1557 } 1910 }
1911 else
1912 ChangeBackend(new HWStubIoBackend(dev));
1558} 1913}
1559#endif 1914#endif
1560 1915
1561IoBackend *BackendSelector::GetBackend()
1562{
1563 return m_io_backend;
1564}
1565
1566void BackendSelector::ChangeBackend(IoBackend *new_backend)
1567{
1568 /* WARNING: delete old backend *after* calling the signal, otherwise the old backend
1569 * might get used after delete */
1570 emit OnSelect(new_backend);
1571 delete m_io_backend;
1572 m_io_backend = new_backend;
1573}
1574
1575/** 1916/**
1576 * YTabWidget 1917 * YTabWidget
1577 */ 1918 */
1578YTabWidget::YTabWidget(QTabBar *bar, QWidget *parent) 1919YTabWidget::YTabWidget(QTabBar *bar, QWidget *parent)
1579 :QTabWidget(parent) 1920 :QTabWidget(parent), m_other_button(0)
1580{ 1921{
1581 if(bar != 0) 1922 if(bar != 0)
1582 setTabBar(bar); 1923 setTabBar(bar);
1583 m_tab_open_button = new QToolButton(this); 1924 m_tab_open_button = new QToolButton(this);
1584 m_tab_open_button->setIcon(QIcon::fromTheme("list-add")); 1925 m_tab_open_button->setIcon(YIconManager::Get()->GetIcon(YIconManager::ListAdd));
1585 m_tab_open_button->setAutoRaise(true); 1926 m_tab_open_button->setAutoRaise(true);
1586 m_tab_open_button->setPopupMode(QToolButton::InstantPopup); 1927 m_tab_open_button->setPopupMode(QToolButton::InstantPopup);
1587 /* the arrow with an icon only is pretty ugly and QToolButton has no way 1928 /* the arrow with an icon only is pretty ugly and QToolButton has no way
@@ -1592,8 +1933,8 @@ YTabWidget::YTabWidget(QTabBar *bar, QWidget *parent)
1592 connect(m_tab_open_button, SIGNAL(clicked(bool)), this, SLOT(OnOpenButton(bool))); 1933 connect(m_tab_open_button, SIGNAL(clicked(bool)), this, SLOT(OnOpenButton(bool)));
1593 /* there is a quirk in the default QStyle: if the tab bar is empty, it 1934 /* there is a quirk in the default QStyle: if the tab bar is empty, it
1594 * returns the minimum size of the corner widget, which is 0 for tool buttons */ 1935 * returns the minimum size of the corner widget, which is 0 for tool buttons */
1595 //setMinimumHeight(m_tab_open_button->height()); 1936 m_tab_open_button->setMinimumSize(m_tab_open_button->sizeHint());
1596 //m_tab_open_button->setMinimumHeight(m_tab_open_button->sizeHint().height()); 1937 setMinimumSize(m_tab_open_button->sizeHint());
1597} 1938}
1598 1939
1599void YTabWidget::setTabOpenable(bool openable) 1940void YTabWidget::setTabOpenable(bool openable)
@@ -1613,6 +1954,28 @@ void YTabWidget::setTabOpenMenu(QMenu *menu)
1613 m_tab_open_button->setMenu(menu); 1954 m_tab_open_button->setMenu(menu);
1614} 1955}
1615 1956
1957void YTabWidget::setOtherMenu(QMenu *menu)
1958{
1959 if(menu == nullptr)
1960 {
1961 if(m_other_button)
1962 delete m_other_button;
1963 m_other_button = nullptr;
1964 }
1965 else
1966 {
1967 if(m_other_button == nullptr)
1968 {
1969 m_other_button = new QToolButton(this);
1970 m_other_button->setText("Menu");
1971 m_other_button->setAutoRaise(true);
1972 m_other_button->setPopupMode(QToolButton::InstantPopup);
1973 setCornerWidget(m_other_button, Qt::TopRightCorner);
1974 }
1975 m_other_button->setMenu(menu);
1976 }
1977}
1978
1616/** 1979/**
1617 * MessageWidget 1980 * MessageWidget
1618 */ 1981 */
@@ -1625,6 +1988,7 @@ MessageWidget::MessageWidget(QWidget *parent)
1625 m_icon->hide(); 1988 m_icon->hide();
1626 m_text = new QLabel(this); 1989 m_text = new QLabel(this);
1627 m_text->setTextFormat(Qt::RichText); 1990 m_text->setTextFormat(Qt::RichText);
1991 m_text->setWordWrap(true);
1628 m_close = new QToolButton(this); 1992 m_close = new QToolButton(this);
1629 m_close->setText("close"); 1993 m_close->setText("close");
1630 m_close->setIcon(style()->standardIcon(QStyle::SP_DialogCloseButton)); 1994 m_close->setIcon(style()->standardIcon(QStyle::SP_DialogCloseButton));
@@ -1702,6 +2066,102 @@ void MessageWidget::OnClose(bool clicked)
1702 hide(); 2066 hide();
1703} 2067}
1704 2068
2069/*
2070 * YIconManager
2071 */
2072YIconManager *YIconManager::m_singleton = nullptr;
2073
2074YIconManager::YIconManager()
2075{
2076 m_icon_name[ListAdd] = "list-add";
2077 m_icon_name[ListRemove] = "list-remove";
2078 m_icon_name[DocumentNew] = "document-new";
2079 m_icon_name[DocumentEdit] = "document-edit";
2080 m_icon_name[DocumentOpen] = "document-open";
2081 m_icon_name[DocumentSave] = "document-save";
2082 m_icon_name[DocumentSaveAs] = "document-save-as";
2083 m_icon_name[Preferences] = "preferences-system";
2084 m_icon_name[FolderNew] = "folder-new";
2085 m_icon_name[Computer] = "computer";
2086 m_icon_name[Cpu] = "cpu";
2087 m_icon_name[DialogError] = "dialog-error";
2088 m_icon_name[ViewRefresh] = "view-refresh";
2089 m_icon_name[SytemRun] = "system-run";
2090 m_icon_name[ApplicationExit] = "application-exit";
2091 m_icon_name[HelpAbout] = "help-about";
2092 m_icon_name[FormatTextBold] = "format-text-bold";
2093 m_icon_name[FormatTextItalic] = "format-text-italic";
2094 m_icon_name[FormatTextUnderline] = "format-text-underline";
2095 m_icon_name[TextGeneric] = "text-x-generic";
2096 m_icon_name[MultimediaPlayer] = "multimedia-player";
2097}
2098
2099YIconManager::~YIconManager()
2100{
2101}
2102
2103YIconManager *YIconManager::Get()
2104{
2105 if(m_singleton == nullptr)
2106 m_singleton = new YIconManager();
2107 return m_singleton;
2108}
2109
2110QIcon YIconManager::GetIcon(IconType type)
2111{
2112 if(type < 0 || type >= MaxIcon)
2113 return QIcon();
2114 if(QIcon::hasThemeIcon(m_icon_name[type]))
2115 return QIcon::fromTheme(m_icon_name[type]);
2116 /* render icon if needed */
2117 if(m_icon[type].isNull())
2118 Render(type);
2119 return m_icon[type];
2120}
2121
2122namespace
2123{
2124 void RenderListAdd(QIcon& icon)
2125 {
2126 QPixmap pix(64, 64);
2127 pix.fill(Qt::transparent);
2128 QPainter paint(&pix);
2129 paint.fillRect(30, 12, 4, 40, QColor(255, 0, 0));
2130 paint.fillRect(12, 30, 40, 4, QColor(255, 0, 0));
2131 icon = QIcon(pix);
2132 }
2133
2134 void RenderListRemove(QIcon& icon)
2135 {
2136 QPixmap pix(64, 64);
2137 pix.fill(Qt::transparent);
2138 QPainter paint(&pix);
2139 paint.setPen(QColor(255, 0, 0));
2140 paint.drawLine(12, 12, 52, 52);
2141 paint.drawLine(12, 52, 52, 16);
2142 icon = QIcon(pix);
2143 }
2144
2145 void RenderUnknown(QIcon& icon)
2146 {
2147 QPixmap pix(64, 64);
2148 pix.fill();
2149 QPainter paint(&pix);
2150 paint.fillRect(0, 0, 64, 64, QColor(255, 0, 0));
2151 icon = QIcon(pix);
2152 }
2153}
2154
2155void YIconManager::Render(IconType type)
2156{
2157 switch(type)
2158 {
2159 case ListAdd: RenderListAdd(m_icon[type]); break;
2160 case ListRemove: RenderListRemove(m_icon[type]); break;
2161 default: RenderUnknown(m_icon[type]); break;
2162 }
2163}
2164
1705/** 2165/**
1706 * Misc 2166 * Misc
1707 */ 2167 */
diff --git a/utils/regtools/qeditor/utils.h b/utils/regtools/qeditor/utils.h
index 026466fae0..83992274b7 100644
--- a/utils/regtools/qeditor/utils.h
+++ b/utils/regtools/qeditor/utils.h
@@ -40,6 +40,7 @@
40#include <QScrollBar> 40#include <QScrollBar>
41#include <QGroupBox> 41#include <QGroupBox>
42#include <QSortFilterProxyModel> 42#include <QSortFilterProxyModel>
43#include <QDebug>
43#include "settings.h" 44#include "settings.h"
44#include "backend.h" 45#include "backend.h"
45 46
@@ -180,6 +181,50 @@ protected:
180 soc_desc::field_t m_field; 181 soc_desc::field_t m_field;
181}; 182};
182 183
184Q_DECLARE_METATYPE(soc_desc::access_t)
185
186class SocAccessItemDelegate: public QStyledItemDelegate
187{
188public:
189 SocAccessItemDelegate(const QString& unspec_text, QObject *parent = 0)
190 :QStyledItemDelegate(parent), m_unspec_text(unspec_text) {}
191
192 virtual QString displayText(const QVariant& value, const QLocale& locale) const;
193protected:
194 QString m_unspec_text;
195};
196
197class SocAccessEditor : public QComboBox
198{
199 Q_OBJECT
200 Q_PROPERTY(soc_desc::access_t access READ access WRITE setAccess USER true)
201public:
202 SocAccessEditor(const QString& unspec_text, QWidget *parent = 0);
203 virtual ~SocAccessEditor();
204
205 soc_desc::access_t access() const;
206 void setAccess(soc_desc::access_t acc);
207
208protected slots:
209 /* bla */
210
211protected:
212 soc_desc::access_t m_access;
213};
214
215class SocAccessEditorCreator : public QItemEditorCreatorBase
216{
217public:
218 SocAccessEditorCreator(const QString& unspec_text = "Unspecified")
219 :m_unspec_text(unspec_text) {}
220
221 virtual QWidget *createWidget(QWidget *parent) const;
222 virtual QByteArray valuePropertyName() const;
223
224protected:
225 QString m_unspec_text;
226};
227
183class SocFieldCachedValue 228class SocFieldCachedValue
184{ 229{
185public: 230public:
@@ -209,8 +254,11 @@ public:
209 SocFieldBitRange(int first, int last):m_first_bit(first), m_last_bit(last) {} 254 SocFieldBitRange(int first, int last):m_first_bit(first), m_last_bit(last) {}
210 unsigned GetFirstBit() const { return m_first_bit; } 255 unsigned GetFirstBit() const { return m_first_bit; }
211 unsigned GetLastBit() const { return m_last_bit; } 256 unsigned GetLastBit() const { return m_last_bit; }
257 void SetFirstBit(unsigned bit) { m_first_bit = bit; }
258 void SetLastBit(unsigned bit) { m_last_bit = bit; }
212 259
213 bool operator<(const SocFieldBitRange& o) const; 260 bool operator<(const SocFieldBitRange& o) const;
261 bool operator!=(const SocFieldBitRange& o) const;
214protected: 262protected:
215 unsigned m_first_bit, m_last_bit; 263 unsigned m_first_bit, m_last_bit;
216}; 264};
@@ -301,6 +349,7 @@ public:
301 349
302signals: 350signals:
303 void OnValueModified(int index); 351 void OnValueModified(int index);
352 void OnBitrangeModified(int index);
304 353
305protected: 354protected:
306 void RecomputeTheme(); 355 void RecomputeTheme();
@@ -337,19 +386,79 @@ protected:
337 bool lessThan(const QModelIndex& left, const QModelIndex& right) const; 386 bool lessThan(const QModelIndex& left, const QModelIndex& right) const;
338}; 387};
339 388
389class YRegDisplay;
390class YRegDisplayItemDelegate;
391
392class YRegDisplayItemEditor : public QWidget
393{
394 Q_OBJECT
395public:
396 YRegDisplayItemEditor(QWidget *parent, YRegDisplay *display,
397 YRegDisplayItemDelegate *delegate, QModelIndex bitrange_index,
398 QModelIndex name_index);
399 virtual ~YRegDisplayItemEditor();
400 void setEditorData(QModelIndex bitrange_index, QModelIndex name_index);
401 void getEditorData(QVariant& name, QVariant& birange);
402
403protected:
404 virtual void paintEvent(QPaintEvent *event);
405 virtual void mouseMoveEvent(QMouseEvent *event);
406 virtual void mousePressEvent(QMouseEvent *event);
407 virtual void mouseReleaseEvent(QMouseEvent *event);
408 virtual void leaveEvent(QEvent *event);
409
410 enum Zone
411 {
412 NoZone,
413 MoveZone,
414 ResizeLeftZone,
415 ResizeRightZone
416 };
417
418 Zone GetZone(const QPoint& pt);
419
420 YRegDisplayItemDelegate *m_display_delegate;
421 YRegDisplay *m_display;
422 QModelIndex m_bitrange_index, m_name_index;
423 enum
424 {
425 Idle,
426 InResizeZone,
427 InMoveZone,
428 Moving,
429 ResizingLeft,
430 ResizingRight,
431 }m_state;
432 int m_col_width;
433 int m_resize_margin;
434 int m_move_offset;
435 SocFieldBitRange m_bitrange;
436};
437
340class YRegDisplayItemDelegate : public QStyledItemDelegate 438class YRegDisplayItemDelegate : public QStyledItemDelegate
341{ 439{
440 Q_OBJECT
441 friend class YRegDisplayItemEditor;
342public: 442public:
343 YRegDisplayItemDelegate(QObject *parent = 0); 443 YRegDisplayItemDelegate(QObject *parent = 0);
344 virtual void paint(QPainter * painter, const QStyleOptionViewItem& option, 444 virtual void paint(QPainter *painter, const QStyleOptionViewItem& option,
345 const QModelIndex & index) const; 445 const QModelIndex& index) const;
446 virtual void MyPaint(QPainter *painter, const QStyleOptionViewItemV4& option) const;
346 virtual QSize sizeHint(const QStyleOptionViewItem& option, 447 virtual QSize sizeHint(const QStyleOptionViewItem& option,
347 const QModelIndex & index) const; 448 const QModelIndex& index) const;
449 /* don't bother using the item factory and such, we only use this delegate
450 * for very specific models anyway */
451 virtual QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem& option,
452 const QModelIndex& index) const;
453 virtual void setEditorData(QWidget *editor, const QModelIndex& index) const;
454 virtual void setModelData(QWidget *editor, QAbstractItemModel *model,
455 const QModelIndex& index) const;
348}; 456};
349 457
350class YRegDisplay : public QAbstractItemView 458class YRegDisplay : public QAbstractItemView
351{ 459{
352 Q_OBJECT 460 Q_OBJECT
461 friend class YRegDisplayItemEditor;
353public: 462public:
354 YRegDisplay(QWidget *parent = 0); 463 YRegDisplay(QWidget *parent = 0);
355 virtual QModelIndex indexAt(const QPoint& point) const; 464 virtual QModelIndex indexAt(const QPoint& point) const;
@@ -360,6 +469,8 @@ public:
360 void setWidth(int nr_bits); 469 void setWidth(int nr_bits);
361 /* returns the bit column at a point, or -1 if none except if closest=true */ 470 /* returns the bit column at a point, or -1 if none except if closest=true */
362 int bitColumnAt(const QPoint& point, bool closest = true) const; 471 int bitColumnAt(const QPoint& point, bool closest = true) const;
472 /* return rect for a bitrange */
473 QRect BitrangeRect(const SocFieldBitRange& range) const;
363 474
364protected slots: 475protected slots:
365 virtual void dataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight); 476 virtual void dataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight);
@@ -509,18 +620,20 @@ protected:
509 QLineEdit *m_data_sel_edit; 620 QLineEdit *m_data_sel_edit;
510#ifdef HAVE_HWSTUB 621#ifdef HAVE_HWSTUB
511 QComboBox *m_dev_selector; 622 QComboBox *m_dev_selector;
512 HWStubBackendHelper m_hwstub_helper; 623 QComboBox *m_ctx_selector;
624 QPushButton *m_ctx_manage_button;
625 HWStubContextModel *m_ctx_model;
626 HWStubManager *m_ctx_manager;
513#endif 627#endif
514 QLabel *m_nothing_text; 628 QLabel *m_nothing_text;
515 629
516private slots: 630private slots:
631 void OnDataSelChanged(int index);
517#ifdef HAVE_HWSTUB 632#ifdef HAVE_HWSTUB
518 void OnDevListChanged(); 633 void OnContextSelChanged(int index);
519 void OnDevChanged(int index); 634 void OnDeviceSelChanged(int index);
520 void OnDevListChanged2(bool, struct libusb_device *); 635 void OnDeviceSelActivated(int index);
521 void ClearDevList();
522#endif 636#endif
523 void OnDataSelChanged(int index);
524}; 637};
525 638
526class MessageWidget : public QFrame 639class MessageWidget : public QFrame
@@ -567,6 +680,7 @@ public:
567 inline bool tabOpenable() const { return m_tab_openable; } 680 inline bool tabOpenable() const { return m_tab_openable; }
568 void setTabOpenable(bool openable); 681 void setTabOpenable(bool openable);
569 void setTabOpenMenu(QMenu *menu); 682 void setTabOpenMenu(QMenu *menu);
683 void setOtherMenu(QMenu *menu);
570 684
571signals: 685signals:
572 void tabOpenRequested(); 686 void tabOpenRequested();
@@ -577,6 +691,52 @@ protected slots:
577protected: 691protected:
578 bool m_tab_openable; 692 bool m_tab_openable;
579 QToolButton *m_tab_open_button; 693 QToolButton *m_tab_open_button;
694 QToolButton *m_other_button;
695};
696
697class YIconManager : public QObject
698{
699 Q_OBJECT
700protected:
701 YIconManager();
702public:
703 virtual ~YIconManager();
704 /* list of icons */
705 enum IconType
706 {
707 ListAdd = 0,
708 ListRemove,
709 DocumentNew,
710 DocumentEdit,
711 DocumentOpen,
712 DocumentSave,
713 DocumentSaveAs,
714 Preferences,
715 FolderNew,
716 Computer,
717 Cpu,
718 DialogError,
719 ViewRefresh,
720 SytemRun,
721 ApplicationExit,
722 HelpAbout,
723 FormatTextBold,
724 FormatTextItalic,
725 FormatTextUnderline,
726 TextGeneric,
727 MultimediaPlayer,
728 MaxIcon
729 };
730 /* return instance */
731 static YIconManager *Get();
732 QIcon GetIcon(IconType it);
733
734protected:
735 void Render(IconType type);
736
737 static YIconManager *m_singleton; // single instance
738 QIcon m_icon[MaxIcon]; /* list add icon */
739 QString m_icon_name[MaxIcon]; /* icon name from theme */
580}; 740};
581 741
582class Misc 742class Misc