From 41fb51f4208c994893e97309ac703e90d6cbb3c0 Mon Sep 17 00:00:00 2001 From: David Heremans Date: Tue, 19 Apr 2022 13:28:51 +0200 Subject: [PATCH 01/63] Adding al the files from BlendSplitter project These are already slightly adjust to be in a flat subdirectory. Original code can be found at https://github.com/marekdedic/BlendSplitter and was MIT licensed when converted. --- src/blendsplitter/BlendSplitter.cpp | 76 ++++ src/blendsplitter/BlendSplitter.h | 96 ++++++ src/blendsplitter/Expander.cpp | 90 +++++ src/blendsplitter/Expander.h | 25 ++ src/blendsplitter/ExpanderCorner.cpp | 419 +++++++++++++++++++++++ src/blendsplitter/ExpanderCorner.h | 49 +++ src/blendsplitter/Global.h | 8 + src/blendsplitter/Overlay.cpp | 143 ++++++++ src/blendsplitter/Overlay.h | 28 ++ src/blendsplitter/RegistryItem.cpp | 3 + src/blendsplitter/RegistryItem.h | 36 ++ src/blendsplitter/SplitterDecorator.cpp | 16 + src/blendsplitter/SplitterDecorator.h | 17 + src/blendsplitter/SplitterHandle.cpp | 51 +++ src/blendsplitter/SplitterHandle.h | 27 ++ src/blendsplitter/SwitchingBar.cpp | 47 +++ src/blendsplitter/SwitchingBar.h | 38 ++ src/blendsplitter/SwitchingCombo.cpp | 28 ++ src/blendsplitter/SwitchingCombo.h | 15 + src/blendsplitter/SwitchingWidget.cpp | 41 +++ src/blendsplitter/SwitchingWidget.h | 36 ++ src/blendsplitter/WidgetDecorator.cpp | 108 ++++++ src/blendsplitter/WidgetDecorator.h | 40 +++ src/blendsplitter/WidgetRegistry.cpp | 94 +++++ src/blendsplitter/WidgetRegistry.h | 114 ++++++ src/blendsplitter/resources/expander.png | Bin 0 -> 6077 bytes 26 files changed, 1645 insertions(+) create mode 100644 src/blendsplitter/BlendSplitter.cpp create mode 100644 src/blendsplitter/BlendSplitter.h create mode 100644 src/blendsplitter/Expander.cpp create mode 100644 src/blendsplitter/Expander.h create mode 100644 src/blendsplitter/ExpanderCorner.cpp create mode 100644 src/blendsplitter/ExpanderCorner.h create mode 100644 src/blendsplitter/Global.h create mode 100644 src/blendsplitter/Overlay.cpp create mode 100644 src/blendsplitter/Overlay.h create mode 100644 src/blendsplitter/RegistryItem.cpp create mode 100644 src/blendsplitter/RegistryItem.h create mode 100644 src/blendsplitter/SplitterDecorator.cpp create mode 100644 src/blendsplitter/SplitterDecorator.h create mode 100644 src/blendsplitter/SplitterHandle.cpp create mode 100644 src/blendsplitter/SplitterHandle.h create mode 100644 src/blendsplitter/SwitchingBar.cpp create mode 100644 src/blendsplitter/SwitchingBar.h create mode 100644 src/blendsplitter/SwitchingCombo.cpp create mode 100644 src/blendsplitter/SwitchingCombo.h create mode 100644 src/blendsplitter/SwitchingWidget.cpp create mode 100644 src/blendsplitter/SwitchingWidget.h create mode 100644 src/blendsplitter/WidgetDecorator.cpp create mode 100644 src/blendsplitter/WidgetDecorator.h create mode 100644 src/blendsplitter/WidgetRegistry.cpp create mode 100644 src/blendsplitter/WidgetRegistry.h create mode 100644 src/blendsplitter/resources/expander.png diff --git a/src/blendsplitter/BlendSplitter.cpp b/src/blendsplitter/BlendSplitter.cpp new file mode 100644 index 00000000..a4bfb579 --- /dev/null +++ b/src/blendsplitter/BlendSplitter.cpp @@ -0,0 +1,76 @@ +#include "BlendSplitter.h" + +#include "WidgetRegistry.h" +#include "RegistryItem.h" +#include "SplitterDecorator.h" +#include "SplitterHandle.h" +#include "WidgetDecorator.h" + +int BlendSplitter::expanderSize{12}; +int BlendSplitter::switchingBarHeight{36}; +QString BlendSplitter::expanderImage{":/BlendSplitter/Expander"}; + +BlendSplitter::BlendSplitter(QWidget* (*defaultWidget) (), Qt::Orientation orientation) : QSplitter{orientation, nullptr}, defaultWidget{defaultWidget} +{ +// Q_INIT_RESOURCE(BlendSplitterResources); + setChildrenCollapsible(false); + setHandleWidth(1); + setStyleSheet("QSplitter::handle{background: black;}"); +} + +void BlendSplitter::addWidget() +{ + addWidget((*defaultWidget) ()); +} + +void BlendSplitter::addWidget(QWidget* widget) +{ + insertWidget(-1, widget); +} + +void BlendSplitter::addWidget(RegistryItem* item) +{ + insertWidget(-1, item); +} + +void BlendSplitter::insertWidget(int index) +{ + insertWidget(index, (*defaultWidget) ()); +} + +void BlendSplitter::insertWidget(int index, QWidget* widget) +{ + WidgetDecorator* decorator{new WidgetDecorator{widget}}; + QSplitter::insertWidget(index, decorator); +} + +void BlendSplitter::insertWidget(int index, RegistryItem* item) +{ + insertWidget(index, new SwitchingWidget{item}); +} + +void BlendSplitter::addDecoratedWidget(WidgetDecorator* widget) +{ + insertDecoratedWidget(-1, widget); +} + +void BlendSplitter::insertDecoratedWidget(int index, WidgetDecorator* widget) +{ + QSplitter::insertWidget(index, widget); +} + +void BlendSplitter::addSplitter(BlendSplitter *splitter) +{ + insertSplitter(-1, splitter); +} + +void BlendSplitter::insertSplitter(int index, BlendSplitter* splitter) +{ + SplitterDecorator* decorator{new SplitterDecorator{splitter}}; + QSplitter::insertWidget(index, decorator); +} + +QSplitterHandle* BlendSplitter::createHandle() +{ + return new SplitterHandle(orientation(), this); +} diff --git a/src/blendsplitter/BlendSplitter.h b/src/blendsplitter/BlendSplitter.h new file mode 100644 index 00000000..bfb61de9 --- /dev/null +++ b/src/blendsplitter/BlendSplitter.h @@ -0,0 +1,96 @@ +#pragma once + +#include + +#include "RegistryItem.h" +#include "SwitchingBar.h" +#include "SwitchingWidget.h" +#include "WidgetRegistry.h" + +class Expander; +class ExpanderCorner; +class ExpanderBottom; +class ExpanderTop; +class WidgetDecorator; + +/** \brief A user-defined Splitter + * + * This widget implements the functionality of Blender (Open-source 3D modelling software) widget management. This widget displays a splitter similar to QSplitter. However, each widget in BlendSplitter has a pair of Expanders (one in top right and one in bottom left corner). By dragging from these Expanders inwards a new widget is created in the direction of the drag. If the direction is different to that of the BlendSplitter, a new BlendSplitter with parallel direction is created in place of the widget with the widget and the new widget in it. By dragging from these expanders outwards, a neighbouring widget (or a collection of widgets) can be closed. While the mouse is held, the widgets to be closed are marked with black overlay. When the mouse is released, they are closed. BlendSplitter can be used like any other QWidget, although setting one as the central widget is recommended. A BlendSplitter can contain any QWidget, but to achieve best results, use it together with SwitchingWidget. + * + * BlendSplitter provides 3 static variables that allow some customization of the library design. These are expanderSize, switchingBarHeight and expanderImage. These are all initialized with default values. The default Expander image is provided by the library. + * + * The default Expander image: + * + * ![The default Expander](resources/expander.png) + */ +class BlendSplitter : public QSplitter +{ + Q_OBJECT + Q_DISABLE_COPY(BlendSplitter) +public: + static int expanderSize; /**< Size of the expanders in the corners. Default value: 12 */ + static int switchingBarHeight; /**< Height of the SwitchingBar. Default value: 36 */ + static QString expanderImage; /**< The image to be used for the top left expander. The bottom right one will rotate this by pi (180 degrees). Default value: \":/BlendSplitter/Expander\" */ + /** \brief BlendSplitter class constructor + * \param defaultWidget A pointer to function constructing the default widget. This function is called when a new widget is added to BlendSplitter. + * \param orientation Orientation of the main BlendSplitter + */ + BlendSplitter(QWidget* (*defaultWidget) () = []()->QWidget* {return new SwitchingWidget{};}, Qt::Orientation orientation = Qt::Horizontal); + /** \brief Add a widget to the BlendSplitter + * + * Adds the default widget to the very bottom/right of the BlendSplitter. + */ + void addWidget(); + /** \brief Add a widget to the BlendSplitter + * + * Adds the specified widget to the very bottom/right of the BlendSplitter + * \param widget A pointer to the widget to be added + */ + void addWidget(QWidget* widget); + /** \brief Add a widget to the BlendSplitter + * + * Adds the specified widget from the WidgetRegistry to the very bottom/right of the BlendSplitter + * \param item A RegistryItem to be added (inside a SwitchingWidget). + */ + void addWidget(RegistryItem* item); + /** \brief Insert a widget into the BlendSplitter + * + * Inserts the default widget into the BlendSplitter at the given position counting from top/left (counting starts at 0). This function should NOT be called with a BlendSplitter as a parameter. + * \param index The desired position + */ + void insertWidget(int index); + /** \brief Insert a widget into the BlendSplitter + * + * Inserts the specified widget into the BlendSplitter at the given position counting from top/left (counting starts at 0). This function should NOT be called with a BlendSplitter as a parameter. + * \param index The desired position + * \param widget A pointer to the widget to be inserted + */ + void insertWidget(int index, QWidget* widget); + /** \brief Insert a widget into the BlendSplitter + * + * Inserts the specified widget from WidgetRegistry into the BlendSplitter at the given position counting from top/left (counting starts at 0). This function should NOT be called with a BlendSplitter as a parameter. + * \param index The desired position + * \param item A RegistryItem to be added (inside a SwitchingWidget). + */ + void insertWidget(int index, RegistryItem* item); + /** \brief Add another BlendSplitter to this BlendSplitter + * + * Adds a BlendSplitter (usually with parallel orientation) to the BlendSplitter + * \param splitter A pointer to the BlendSplitter to be added + */ + void addSplitter(BlendSplitter* splitter); + /** \brief Insert another BlendSplitter into this BlendSplitter + * + * Inserts a BlendSplitter (usually with parallel orientation) into the BlendSplitter at the given position counting from top/left (counting starts at 0). + * \param index The desired position + * \param splitter A pointer to the BlendSplitter to be inserted + */ + void insertSplitter(int index, BlendSplitter* splitter); +private: + friend Expander; + friend ExpanderCorner; + QWidget* (*defaultWidget) (); + virtual QSplitterHandle* createHandle() override; + void addDecoratedWidget(WidgetDecorator* widget); + void insertDecoratedWidget(int index, WidgetDecorator* widget); +}; diff --git a/src/blendsplitter/Expander.cpp b/src/blendsplitter/Expander.cpp new file mode 100644 index 00000000..a1488330 --- /dev/null +++ b/src/blendsplitter/Expander.cpp @@ -0,0 +1,90 @@ +#include "Expander.h" + +#include "BlendSplitter.h" +#include "Overlay.h" +#include "WidgetDecorator.h" + +Expander::Expander(WidgetDecorator* parent) : QLabel(parent), pixmap{new QPixmap{BlendSplitter::expanderImage}}, overlay{nullptr} +{ + *pixmap = pixmap->scaledToHeight(BlendSplitter::expanderSize, Qt::FastTransformation); + setPixmap(*pixmap); + resize(BlendSplitter::expanderSize, BlendSplitter::expanderSize); + setCursor(Qt::SizeAllCursor); +} + +void Expander::reposition() +{ + raise(); +} + +void Expander::mousePressEvent(QMouseEvent* event) +{ + if(event->button() == Qt::LeftButton) + { + event->accept(); // No-op + } + else + { + releaseMouse(); + event->ignore(); // Propagate event + } +} + +void Expander::mouseReleaseEvent(QMouseEvent* event) +{ + if(event->button() == Qt::LeftButton and overlay != nullptr) + { + WidgetDecorator* parentDecorator{qobject_cast(parentWidget())}; + if(parentDecorator == 0) + { + qCritical("A BlendSplitter library error occurred. Error code: 1"); + return; + } + BlendSplitter* parentSplitter{qobject_cast(overlay->parentWidget()->parentWidget())}; + if(parentSplitter == 0) + { + qCritical("A BlendSplitter library error occurred. Error code: 2"); + return; + } + QList sizes{parentSplitter->sizes()}; + int parentIndex{parentSplitter->indexOf(parentDecorator)}; + int overlayIndex{parentSplitter->indexOf(overlay->parentWidget())}; + sizes[parentIndex] += sizes[overlayIndex] + 1; + sizes.removeAt(overlayIndex); + delete parentSplitter->widget(overlayIndex); + if(parentSplitter->count() == 1 and parentSplitter->parentWidget()->inherits("SplitterDecorator")) + { + BlendSplitter* newParent{qobject_cast(parentSplitter->parentWidget()->parentWidget())}; + if(newParent == 0) + { + qCritical("A BlendSplitter library error occurred. Error code: 3"); + return; + } + QList sizes2{newParent->sizes()}; + newParent->insertDecoratedWidget(newParent->indexOf(parentSplitter->parentWidget()), parentDecorator); + delete parentSplitter->parentWidget(); + newParent->setSizes(sizes2); + } + else + { + parentSplitter->setSizes(sizes); + } + overlay = nullptr; + } +} + +Expander::~Expander() +{ + delete pixmap; +} + + +//void Expander::enterEvent(QEvent *event) +//{ +// setCursor(Qt::SizeAllCursor); +//} + +//void Expander::leaveEvent(QEvent *event) +//{ +// setCursor(Qt::ArrowCursor); +//} diff --git a/src/blendsplitter/Expander.h b/src/blendsplitter/Expander.h new file mode 100644 index 00000000..15cfa07a --- /dev/null +++ b/src/blendsplitter/Expander.h @@ -0,0 +1,25 @@ +#pragma once + +#include "Global.h" + +class Overlay; +class WidgetDecorator; + +class Expander : public QLabel +{ + Q_OBJECT + Q_DISABLE_COPY(Expander) +protected: + QPixmap* pixmap; + Overlay* overlay; + Expander() = delete; + explicit Expander(WidgetDecorator* parent); + virtual void reposition() ; //= 0 ; + ~Expander(); +protected slots: +// virtual void enterEvent(QEvent* event) override final; +// virtual void leaveEvent(QEvent* event) override final; + virtual void mousePressEvent(QMouseEvent* event) override; + virtual void mouseMoveEvent(QMouseEvent* event) override = 0; + virtual void mouseReleaseEvent(QMouseEvent* event) override; +}; diff --git a/src/blendsplitter/ExpanderCorner.cpp b/src/blendsplitter/ExpanderCorner.cpp new file mode 100644 index 00000000..bc3afd56 --- /dev/null +++ b/src/blendsplitter/ExpanderCorner.cpp @@ -0,0 +1,419 @@ +#include "ExpanderCorner.h" + +#include "BlendSplitter.h" +#include "Overlay.h" +#include "WidgetDecorator.h" +#include "SplitterDecorator.h" + +#include + +ExpanderCorner::ExpanderCorner(WidgetDecorator* parent,Qt::Corner location) : Expander{parent} , + corner{location},unitX{1},unitY{1},hotspotX{0},hotspotY{0},dragaction{undecidedDrag}, + dragorientation{Qt::Horizontal},internalOverlay{nullptr},externalOverlay{nullptr}, + externalJoinWidget{nullptr},joinarrow{Qt::NoArrow} +{ + //now do some masking and pixmap rotating depending on location + //also set out unit steps + QPolygon mask; + switch (location) { + case Qt::TopLeftCorner: { + QTransform rot; + *pixmap = pixmap->transformed(rot.rotate(-90), Qt::FastTransformation); + setPixmap(*pixmap); + mask << QPoint{BlendSplitter::expanderSize, 0} + << QPoint{BlendSplitter::expanderSize, BlendSplitter::expanderSize/10} + << QPoint{BlendSplitter::expanderSize / 10, BlendSplitter::expanderSize} + << QPoint{0, BlendSplitter::expanderSize} + << QPoint{0, 0}; +// done by constructor unitX=1; +// done by constructor unitY=1; + }; + break; + case Qt::TopRightCorner: { + QTransform rot; + *pixmap = pixmap->transformed(rot.rotate(0), Qt::FastTransformation); + setPixmap(*pixmap); + mask << QPoint{0, 0} + << QPoint{0, BlendSplitter::expanderSize/10} + << QPoint{BlendSplitter::expanderSize * 9 / 10, BlendSplitter::expanderSize} + << QPoint{BlendSplitter::expanderSize, BlendSplitter::expanderSize} + << QPoint{BlendSplitter::expanderSize, 0}; + unitX=-1; +// done by constructor unitY=1; + hotspotX=BlendSplitter::expanderSize-1; + }; + break; + case Qt::BottomLeftCorner: { + QTransform rot; + *pixmap = pixmap->transformed(rot.rotate(180), Qt::FastTransformation); + setPixmap(*pixmap); + mask << QPoint{0, 0} + << QPoint{BlendSplitter::expanderSize/10, 0} + << QPoint{BlendSplitter::expanderSize, BlendSplitter::expanderSize * 9 / 10} + << QPoint{BlendSplitter::expanderSize, BlendSplitter::expanderSize} + << QPoint{0, BlendSplitter::expanderSize}; +// done by constructor unitX=1; + unitY=-1; + hotspotY=BlendSplitter::expanderSize-1; + }; + break; + case Qt::BottomRightCorner: { + QTransform rot; + *pixmap = pixmap->transformed(rot.rotate(90), Qt::FastTransformation); + setPixmap(*pixmap); + mask << QPoint{BlendSplitter::expanderSize, 0} + << QPoint{BlendSplitter::expanderSize * 9 /10, 0} + << QPoint{0, BlendSplitter::expanderSize * 9 / 10} + << QPoint{0, BlendSplitter::expanderSize} + << QPoint{BlendSplitter::expanderSize, BlendSplitter::expanderSize}; + }; + unitX=-1; + unitY=-1; + hotspotX=BlendSplitter::expanderSize-1; + hotspotY=BlendSplitter::expanderSize-1; + default: + break; + + } + setMask(QRegion{mask}); +} + +/** + * @brief ExpanderCorner::reposition + * + * If the parent WidgetDecorator/SplitterDecorator gets resized, this method + * makes sure that we end up in the new correct location. + * + */ +void ExpanderCorner::reposition() +{ + switch (corner) { + case Qt::TopLeftCorner: + move(0, 0); + break; + case Qt::TopRightCorner: + move(parentWidget()->width() - width(), 0); + break; + case Qt::BottomLeftCorner: + move(0, parentWidget()->height()-height()); + break; + case Qt::BottomRightCorner: + move(parentWidget()->width() - width(), parentWidget()->height()-height()); + break; + default: + break; + } + raise(); +} + +bool ExpanderCorner::isOnTrailingHandler(BlendSplitter* parentSplitter) +{ + return (parentSplitter->orientation()==Qt::Horizontal)? unitX<0 : unitY<0; +} + +/** + * @brief ExpanderCorner::performInnerSplit + * @param parentDecorator + * @param parentSplitter + * @param splitorientation + * + * This will split the widget. + * If the orientation of the split corresponds to the splitter we simply add an item + * If the orietation is orthogonal we replace the widget with a new splitter and have the widget added to the new splitter + */ +void ExpanderCorner::performInnerSplit(WidgetDecorator* parentDecorator, BlendSplitter* parentSplitter, Qt::Orientation splitorientation) +{ + if (parentSplitter->orientation() == splitorientation){ + + QList sizes{parentSplitter->sizes()}; + int index{parentSplitter->indexOf(parentDecorator)}; + if (!isOnTrailingHandler(parentSplitter)){ + sizes.insert(index, BlendSplitter::expanderSize); + sizes[index + 1] -= BlendSplitter::expanderSize + 1; + parentSplitter->insertWidget(index); + } else { + sizes.insert(index +1, BlendSplitter::expanderSize); + sizes[index] -= BlendSplitter::expanderSize + 1; + parentSplitter->insertWidget(index+1); + } + parentSplitter->setSizes(sizes); + parentSplitter->handle(index + 1)->grabMouse(); + } else { + //add a new splitter orthogonal to the current one + Qt::Orientation newOrientation{parentSplitter->orientation()==Qt::Horizontal?Qt::Vertical:Qt::Horizontal}; + BlendSplitter* newSplitter{new BlendSplitter{parentSplitter->defaultWidget, newOrientation}}; + QList sizes{parentSplitter->sizes()}; + parentSplitter->insertSplitter(parentSplitter->indexOf(parentDecorator), newSplitter); + // add a widget in current splitter but on the correct side + bool after = (newOrientation==Qt::Horizontal)? unitX>0 : unitY>0; + + if (after){ + newSplitter->addWidget(); + newSplitter->addDecoratedWidget(parentDecorator); + } else { + newSplitter->addDecoratedWidget(parentDecorator); + newSplitter->addWidget(); + } + parentSplitter->setSizes(sizes); + newSplitter->handle(1)->grabMouse(); + } +} + +void ExpanderCorner::setupJoiners(WidgetDecorator *parentDecorator, BlendSplitter *parentSplitter, int x, int y, Qt::Orientation /*splitorientation*/) +{ + Q_ASSERT(dragaction ==undecidedDrag); + Q_ASSERT(externalOverlay == nullptr); + Q_ASSERT(internalOverlay == nullptr); + if(isInContinuationOfSplitter(parentSplitter,pos().x()+x,pos().y()+y) ){ + QWidget* wdgt = nullptr; + if( isOnTrailingHandler(parentSplitter) and + parentSplitter->indexOf(parentDecorator) + 1 < parentSplitter->count()) { + + wdgt = parentSplitter->widget(parentSplitter->indexOf(parentDecorator) + 1); + //do not join if the target widget is also splitted + if (!wdgt->inherits("SplitterDecorator")){ + joinarrow=parentSplitter->orientation()==Qt::Horizontal?Qt::RightArrow:Qt::DownArrow; + externalOverlay = new Overlay{wdgt,joinarrow}; + } + } else if (!isOnTrailingHandler(parentSplitter) and + parentSplitter->indexOf(parentDecorator) > 0) { + + wdgt = parentSplitter->widget(parentSplitter->indexOf(parentDecorator) - 1); + //do not join if the target widget is also splitted + if (!wdgt->inherits("SplitterDecorator")){ + joinarrow=parentSplitter->orientation()==Qt::Horizontal?Qt::LeftArrow:Qt::UpArrow; + externalOverlay = new Overlay{wdgt,joinarrow}; + } + }; + + //now show overlay if we started a valid joindrag + if (externalOverlay){ + externalOverlay->show(); + externalJoinWidget=wdgt; + internalOverlay=new Overlay{parentDecorator,Overlay::invertArrow(joinarrow)}; + internalOverlay->hide(); + dragaction=joinDrag; + } + } +} +int ExpanderCorner::pickCoordinate(int x,int y,Qt::Orientation orient) +{ + return orient==Qt::Horizontal?x:y; +} + +int ExpanderCorner::pickSize(const QSize &size, Qt::Orientation orient) +{ + return (orient == Qt::Horizontal) ? size.width() : size.height(); +} + +void ExpanderCorner::followDragJoiners(WidgetDecorator *parentDecorator, BlendSplitter *parentSplitter, int x, int y, Qt::Orientation /*splitorientation*/) +{ + x=pos().x()+x; + y=pos().y()+y; + + if (isInContinuationOfSplitter(parentSplitter,x,y)){ + // already an overlay and we are still dragging 'inside' of the splitter, so + externalOverlay->show(); + // maybe we need to change direction of the join ? + qDebug() << "overlay->parentWidget()!=externalJoinWidget" << externalOverlay->parentWidget() << " " <orientation(); + if ((isOnTrailingHandler(parentSplitter) and pickCoordinate(x,y,o)>pickSize(parentDecorator->size(),o)) + or (!isOnTrailingHandler(parentSplitter) and pickCoordinate(x,y,o)<0) + ) { + externalOverlay->show(); + internalOverlay->hide(); + } else if ((isOnTrailingHandler(parentSplitter) and pickCoordinate(x,y,o)<=pickSize(parentDecorator->size(),o)) + or (!isOnTrailingHandler(parentSplitter) and pickCoordinate(x,y,o)>=0) + ) { + externalOverlay->hide(); + internalOverlay->show(); + } + } else { + // hide all overlay since we dragged 'to the side' of the splitter + externalOverlay->hide(); + internalOverlay->hide(); + } +} + + + +bool ExpanderCorner::isInContinuationOfSplitter(BlendSplitter *parentSplitter, int x, int y) +{ + if (parentSplitter->orientation() == Qt::Horizontal + and y > 0 and y < parentSplitter->height() + ) { + return true; + }; + if (parentSplitter->orientation() == Qt::Vertical + and x > 0 and x < parentSplitter->width() + ) { + return true; + }; + return false; +} + +/** + * @brief ExpanderCorner::decideDragAction + * @param event + * + *If a drag is just started this function helps determine if we drag inwards + *our outward and if it is a horizontal or vertical drag. + */ +void ExpanderCorner::decideDragAction(QMouseEvent *event, WidgetDecorator* parentDecorator, BlendSplitter* parentSplitter) +{ + int x=event->x()-hotspotX; + int y=event->y()-hotspotY; + + if (abs(x) < BlendSplitter::expanderSize and abs(y) < BlendSplitter::expanderSize ){ + return; + }; + + // we dragged far enough + dragorientation= (abs(x) > abs(y)) ? Qt::Horizontal : Qt::Vertical ; + + // but did we drag inwards? + // (and als prefent splitting if widget already too small!) + if ( x*unitX >0 and y*unitY>0 and ( + (dragorientation==Qt::Horizontal and parentDecorator->width()>2*BlendSplitter::expanderSize) or + (dragorientation==Qt::Vertical and parentDecorator->height()>2*BlendSplitter::expanderSize)) + ) + { + dragaction=splitDrag; // we dragged inwards + performInnerSplit(parentDecorator,parentSplitter,dragorientation); + } + // do we join widgets together? + else if (dragorientation == parentSplitter->orientation()){ + setupJoiners(parentDecorator,parentSplitter,x,y,dragorientation); + } else { + //here we could start a relocationdrag.... + } +} + +void ExpanderCorner::mouseMoveEvent(QMouseEvent *event) +{ + if( !(event->buttons() & Qt::LeftButton)){ + return; + } + + //get our parentdecorator and our immediate blendSplitter + WidgetDecorator* parentDecorator{qobject_cast(parentWidget())}; + if(parentDecorator == 0) + { + qCritical("A BlendSplitter library error occurred. Error code: 4"); + return; + } + BlendSplitter* parentSplitter{qobject_cast(parentDecorator->parentWidget())}; + if(parentSplitter == 0) + { + qCritical("A BlendSplitter library error occurred. Error code: 5"); + return; + } + + switch (dragaction) { + case undecidedDrag: + decideDragAction(event,parentDecorator,parentSplitter); + break; + case joinDrag: + { + int x=event->x()-hotspotX; + int y=event->y()-hotspotY; + followDragJoiners(parentDecorator,parentSplitter,x,y,(abs(x) > abs(y)) ? Qt::Horizontal : Qt::Vertical); + }; + break; + case splitDrag: + default: + break; + } +} + +void ExpanderCorner::mousePressEvent(QMouseEvent *event) +{ + if(event->button() == Qt::LeftButton) + { + dragaction=undecidedDrag; //start of drag + event->accept(); // No-op + } + else + { + releaseMouse(); + event->ignore(); // Propagate event + } +} + +void ExpanderCorner::mouseReleaseEvent(QMouseEvent *event) +{ + if(event->button() != Qt::LeftButton or dragaction != joinDrag){ + return; + }; + //correct button and we have an overlay, so continue... + if(externalOverlay->isVisible() && internalOverlay->isVisible()) + { + qCritical("A BlendSplitter library error occurred. Error code: 8"); + return; + } + + + QWidget* widgetToRemove=nullptr; //improved readability later on + if (externalOverlay->isHidden()){ + externalOverlay->deleteLater(); + } else { + widgetToRemove=externalOverlay->parentWidget(); + }; + + if (internalOverlay->isHidden()){ + internalOverlay->deleteLater(); + } else { + widgetToRemove=internalOverlay->parentWidget(); + }; + + + + //first get our decorator and the parent blendSplitter + WidgetDecorator* parentDecorator{qobject_cast(parentWidget())}; + if(parentDecorator == 0) + { + qCritical("A BlendSplitter library error occurred. Error code: 1"); + return; + } + BlendSplitter* parentSplitter{qobject_cast(externalOverlay->parentWidget()->parentWidget())}; + if(parentSplitter == 0) + { + qCritical("A BlendSplitter library error occurred. Error code: 2"); + return; + } + + + //now delete the item with the overlay from the splitter + + QList sizes{parentSplitter->sizes()}; + int parentIndex{parentSplitter->indexOf(parentDecorator)}; + int overlayIndex{parentSplitter->indexOf(widgetToRemove)}; + sizes[parentIndex] += sizes[overlayIndex] + 1; + sizes.removeAt(overlayIndex); + delete parentSplitter->widget(overlayIndex); + externalOverlay = nullptr; + externalJoinWidget = nullptr; + + // if we now have a blendSplitter with a single item, which is inside + // another blendSplitter then we remove this singular-item splitter + if(parentSplitter->count() == 1 and + parentSplitter->parentWidget()->inherits("SplitterDecorator")) + { + BlendSplitter* newParent{qobject_cast(parentSplitter->parentWidget()->parentWidget())}; + if(newParent == nullptr) + { + qCritical("A BlendSplitter library error occurred. Error code: 3"); + return; + } + QList sizes2{newParent->sizes()}; + newParent->insertDecoratedWidget(newParent->indexOf(parentSplitter->parentWidget()), parentDecorator); + delete parentSplitter->parentWidget(); + newParent->setSizes(sizes2); + } + else + { + parentSplitter->setSizes(sizes); + } + +} diff --git a/src/blendsplitter/ExpanderCorner.h b/src/blendsplitter/ExpanderCorner.h new file mode 100644 index 00000000..3dd31c6d --- /dev/null +++ b/src/blendsplitter/ExpanderCorner.h @@ -0,0 +1,49 @@ +#pragma once + +#include "Global.h" + +#include "Expander.h" +class WidgetDecorator; +class BlendSplitter; + +class ExpanderCorner final : public Expander +{ + Q_OBJECT + Q_DISABLE_COPY(ExpanderCorner) +public: + ExpanderCorner() = delete; + explicit ExpanderCorner(WidgetDecorator* parent,Qt::Corner location); + virtual void reposition() override; +protected slots: + virtual void mouseMoveEvent(QMouseEvent* event) override; + virtual void mousePressEvent(QMouseEvent* event) override final; + virtual void mouseReleaseEvent(QMouseEvent* event) override final; + +private: + Qt::Corner corner; + //next variables are used to see if we have mouseMovements inwards or outwards of our decorating widget + int unitX; // x-step to centrum of WidgetDecorator (1 or -1) + int unitY; // y-step to centrum of WidgetDecorator (1 or -1) + int hotspotX; + int hotspotY; + enum { + undecidedDrag, + joinDrag, + splitDrag, + } dragaction; + Qt::Orientation dragorientation; + + void decideDragAction(QMouseEvent *event, WidgetDecorator *parentDecorator, BlendSplitter *parentSplitter); + void performInnerSplit(WidgetDecorator *parentDecorator, BlendSplitter *parentSplitter, Qt::Orientation splitorientation); + void setupJoiners(WidgetDecorator *parentDecorator, BlendSplitter *parentSplitter, int x, int y, Qt::Orientation splitorientation); + void followDragJoiners(WidgetDecorator *parentDecorator, BlendSplitter *parentSplitter, int x, int y, Qt::Orientation splitorientation); + bool isInContinuationOfSplitter(BlendSplitter *parentSplitter, int x, int y); + bool isOnTrailingHandler(BlendSplitter *parentSplitter); + + Overlay* internalOverlay; + Overlay* externalOverlay; + QWidget* externalJoinWidget; + Qt::ArrowType joinarrow; + int pickCoordinate(int x,int y,Qt::Orientation orient); + int pickSize(const QSize &size, Qt::Orientation orient); +}; diff --git a/src/blendsplitter/Global.h b/src/blendsplitter/Global.h new file mode 100644 index 00000000..176ac66b --- /dev/null +++ b/src/blendsplitter/Global.h @@ -0,0 +1,8 @@ +#pragma once + +#include +#include +#include +#include +#include +#include diff --git a/src/blendsplitter/Overlay.cpp b/src/blendsplitter/Overlay.cpp new file mode 100644 index 00000000..49b24536 --- /dev/null +++ b/src/blendsplitter/Overlay.cpp @@ -0,0 +1,143 @@ +#include "Overlay.h" +#include +#include +#include + +Overlay::Overlay(QWidget* parent, Qt::ArrowType direction) : QLabel(parent),arrow(),arrowtype(direction) +{ + move(0, 0); + reposition(); + // setStyleSheet("background-color: rgba(0, 0, 0, 128);"); +} + +void Overlay::setArrowshape(Qt::ArrowType arrow) +{ + arrowtype=arrow; + //makeArrowshape(); + //update(); +} + +Qt::ArrowType Overlay::arrowshape() +{ + return arrowtype; +} + +Qt::ArrowType Overlay::invertArrow(Qt::ArrowType arrow) +{ + switch (arrow) { + case Qt::UpArrow: + return Qt::DownArrow; + break; + case Qt::DownArrow: + return Qt::UpArrow; + break; + case Qt::LeftArrow: + return Qt::RightArrow; + break; + case Qt::RightArrow: + return Qt::LeftArrow; + break; + case Qt::NoArrow: + default: + return Qt::NoArrow; + break; + } +} + +void Overlay::reposition() +{ + resize(parentWidget()->width(), parentWidget()->height()); + raise(); + makeArrowshape(); + update(); +} + +void Overlay::makeArrowshape() +{ + if (arrowtype == Qt::NoArrow){ + arrow.clear(); + return; + } + + int unit,midpoint; + int height=parentWidget()->height(); + int width=parentWidget()->width(); + + switch(arrowtype){ + case Qt::DownArrow: + case Qt::UpArrow: + //create vertical pointing arrow + midpoint=width/2; + unit=std::min(midpoint , height/2) /4; + break; + case Qt::LeftArrow: + case Qt::RightArrow: + //create horizontal pointing arrow + midpoint=height/2; + unit=std::min(midpoint , width/2) /4; + case Qt::NoArrow: + default: + break; + } + + switch(arrowtype){ + case Qt::DownArrow: + arrow.setPoints(7, + midpoint+unit,0, + midpoint+unit,2*unit, + midpoint+2*unit,2*unit, + midpoint, 4*unit, + midpoint-2*unit,2*unit, + midpoint-unit,2*unit, + midpoint-unit,0 + ); + break; + case Qt::UpArrow: + arrow.setPoints(7, + midpoint+unit,height, + midpoint+unit,height-2*unit, + midpoint+2*unit,height-2*unit, + midpoint, height-4*unit, + midpoint-2*unit,height-2*unit, + midpoint-unit,height-2*unit, + midpoint-unit,height + ); + break; + case Qt::RightArrow: + arrow.setPoints(7, + 0,midpoint+unit, + 2*unit,midpoint+unit, + 2*unit,midpoint+2*unit, + 4*unit,midpoint, + 2*unit,midpoint-2*unit, + 2*unit,midpoint-unit, + 0,midpoint-unit + ); + break; + case Qt::LeftArrow: + arrow.setPoints(7, + width,midpoint+unit, + width-2*unit,midpoint+unit, + width-2*unit,midpoint+2*unit, + width-4*unit,midpoint, + width-2*unit,midpoint-2*unit, + width-2*unit,midpoint-unit, + width,midpoint-unit + ); + case Qt::NoArrow: + default: + break; + }; + + +} + +void Overlay::paintEvent(QPaintEvent *) +{ + QPainter qp(this); + qp.setBrush(QColor(0,0,0,128)); + qp.setPen(Qt::NoPen); + qp.drawRect(0,0,size().width(),size().height() ); + qp.setBrush(QColor(255,255,255,128)); + qp.drawPolygon(arrow); +} diff --git a/src/blendsplitter/Overlay.h b/src/blendsplitter/Overlay.h new file mode 100644 index 00000000..f22b6c3e --- /dev/null +++ b/src/blendsplitter/Overlay.h @@ -0,0 +1,28 @@ +#pragma once + +#include "Global.h" + +class Overlay final : public QLabel +{ + Q_OBJECT + Q_DISABLE_COPY(Overlay) +public: + Overlay() = delete; + explicit Overlay(QWidget* parent, Qt::ArrowType direction=Qt::NoArrow); + + static Qt::ArrowType invertArrow(Qt::ArrowType arrow); + + void setArrowshape(Qt::ArrowType arrow); + Qt::ArrowType arrowshape(); + void reposition(); + +private: + void makeArrowshape(); + + QPolygon arrow; + + Qt::ArrowType arrowtype; + +protected: + void paintEvent(QPaintEvent *) override; +}; diff --git a/src/blendsplitter/RegistryItem.cpp b/src/blendsplitter/RegistryItem.cpp new file mode 100644 index 00000000..e32780be --- /dev/null +++ b/src/blendsplitter/RegistryItem.cpp @@ -0,0 +1,3 @@ +#include "RegistryItem.h" + +RegistryItem::RegistryItem(QString name, QWidget* (*widget) (), void (*populateBar) (SwitchingBar*, QWidget*)) : name{name}, widget{widget}, populateBar{populateBar} {} diff --git a/src/blendsplitter/RegistryItem.h b/src/blendsplitter/RegistryItem.h new file mode 100644 index 00000000..a4134440 --- /dev/null +++ b/src/blendsplitter/RegistryItem.h @@ -0,0 +1,36 @@ +#pragma once + +#include + +class SwitchingBar; + +/** \brief An item intended to be put into WidgetRegistry + * + * Each RegistryItem corresponds to one widget that can be displayed in a BlendSplitter. It describes how this widget should be constructed, what is its name and what items should be in the SwitchingBar when this widget is selected. + */ +class RegistryItem +{ +public: + QString name; /**< The name of the widget, used in the SwitchingBar combo box. */ + /** \brief A function constructing the widget + * + * A pointer to a function returning QWidget*. This function is called to construct the widget each time it is selected in any SwitchingWidget. Usually in this function the widget is dynamically created using `new` operator and the pointer is returned. + * \return A pointer to the newly-created QWidget + */ + QWidget* (*widget) (); + /** \brief A function populating the SwitchingBar + * + * A pointer to a function populating the SwitchingBar. This function is called each time this widget is selected in any SwitchingWidget. Usually this function makes use of the interface provided by SwitchingBar to populate it. + * \param A pointer to the SwitchingBar to be populated + * \param A pointer to the newly-created widget in the SwitchingWidget + */ + void (*populateBar) (SwitchingBar*, QWidget*); + /** \brief A constructor setting all the internal values + * + * This constructor takes 3 parameters corresponding to the 3 members of the RegistryItem class. See their desription for more details. + * \param name The name of the widget, used in the SwitchingBar combo box + * \param widget A pointer to a function constructing the widget + * \param populateBar A pointer to a function populating the SwitchingBar + */ + RegistryItem(QString name = "Default", QWidget* (*widget) () = []()->QWidget* {return new QLabel{"Default Widget"};}, void (*populateBar) (SwitchingBar*, QWidget*) = [](SwitchingBar*, QWidget*)->void {}); +}; diff --git a/src/blendsplitter/SplitterDecorator.cpp b/src/blendsplitter/SplitterDecorator.cpp new file mode 100644 index 00000000..d13d73a8 --- /dev/null +++ b/src/blendsplitter/SplitterDecorator.cpp @@ -0,0 +1,16 @@ +#include "SplitterDecorator.h" + +#include "BlendSplitter.h" + +SplitterDecorator::SplitterDecorator(BlendSplitter* splitter) : QWidget{}, splitter{splitter} +{ + QHBoxLayout* layout{new QHBoxLayout{}}; + layout->addWidget(splitter); + layout->setMargin(0); + setLayout(layout); +} + +SplitterDecorator::~SplitterDecorator() +{ + delete layout(); +} diff --git a/src/blendsplitter/SplitterDecorator.h b/src/blendsplitter/SplitterDecorator.h new file mode 100644 index 00000000..9b9edae5 --- /dev/null +++ b/src/blendsplitter/SplitterDecorator.h @@ -0,0 +1,17 @@ +#pragma once + +#include "Global.h" + +class BlendSplitter; + +class SplitterDecorator : public QWidget +{ + Q_OBJECT + Q_DISABLE_COPY(SplitterDecorator) +public: + SplitterDecorator() = delete; + explicit SplitterDecorator(BlendSplitter* splitter); + ~SplitterDecorator(); +private: + BlendSplitter* splitter; +}; diff --git a/src/blendsplitter/SplitterHandle.cpp b/src/blendsplitter/SplitterHandle.cpp new file mode 100644 index 00000000..2c3bc815 --- /dev/null +++ b/src/blendsplitter/SplitterHandle.cpp @@ -0,0 +1,51 @@ +#include "SplitterHandle.h" +#include +#include +#include + +SplitterHandle::SplitterHandle(Qt::Orientation orientation, QSplitter* parent) : QSplitterHandle(orientation, parent) +{ + popupmenu= new QMenu(this); + splitAction= popupmenu->addAction(tr("Split")); + joinAction= popupmenu->addAction(tr("Join")); +} + +SplitterHandle::~SplitterHandle() +{ + delete popupmenu; //Qmenu has ownership of the actions +} + +void SplitterHandle::mousePressEvent(QMouseEvent *event) +{ + + if (event->button() == Qt::RightButton){ + QPoint pos=event->globalPos(); + // When positioning a menu with exec() or popup(), bear in mind that you + // cannot rely on the menu's current size(). For performance reasons, + // the menu adapts its size only when necessary, so in many cases, the + // size before and after the show is different. Instead, use sizeHint() + // which calculates the proper size depending on the menu's current + // contents. + pos.setX(pos.x() - popupmenu->sizeHint().width() / 2); // + QAction* act=popupmenu->exec(pos); + if (act==joinAction){ + //not yet implemented + } else if (act==splitAction){ + //not yet implemented + } +// setFocus(); +// grabMouse(); + } + QSplitterHandle::mousePressEvent(event); +} +void SplitterHandle::mouseReleaseEvent(QMouseEvent* event) +{ + QSplitterHandle::mouseReleaseEvent(event); + releaseMouse(); +} + +bool SplitterHandle::event(QEvent *event) +{ +// qDebug() << " SplitterHandle::event " << event ; + return QSplitterHandle::event(event); +} diff --git a/src/blendsplitter/SplitterHandle.h b/src/blendsplitter/SplitterHandle.h new file mode 100644 index 00000000..fb07b50b --- /dev/null +++ b/src/blendsplitter/SplitterHandle.h @@ -0,0 +1,27 @@ +#pragma once + +#include "Global.h" + +class BlendSplitter; +class QAction; +class QMenu; + +class SplitterHandle final : public QSplitterHandle +{ + Q_OBJECT + Q_DISABLE_COPY(SplitterHandle) +public: + SplitterHandle() = delete; + SplitterHandle(Qt::Orientation orientation, QSplitter* parent); + ~SplitterHandle(); + +protected slots: + virtual void mousePressEvent(QMouseEvent* event) override; + virtual void mouseReleaseEvent(QMouseEvent* event) override; + virtual bool event(QEvent *event) override; + +private: + QMenu* popupmenu; + QAction* joinAction; + QAction* splitAction; +}; diff --git a/src/blendsplitter/SwitchingBar.cpp b/src/blendsplitter/SwitchingBar.cpp new file mode 100644 index 00000000..9a57072b --- /dev/null +++ b/src/blendsplitter/SwitchingBar.cpp @@ -0,0 +1,47 @@ +#include "SwitchingBar.h" + +#include +#include "BlendSplitter.h" +#include "SwitchingCombo.h" + +void SwitchingBar::addMenu(QMenu* menu) +{ + QMenuBar* menuBar{new QMenuBar}; + menuBar->setDefaultUp(true); + layout->insertWidget(layout->count() - 1, menuBar); + layout->setAlignment(menuBar, Qt::AlignVCenter); + setStyleSheet("QMenuBar{background-color: transparent;}"); + menuBar->addMenu(menu); +} + +void SwitchingBar::addWidget(QWidget* widget) +{ + layout->insertWidget(layout->count() - 1, widget); +} + +SwitchingBar::SwitchingBar(QWidget* parent) : QWidget(parent), layout{new QHBoxLayout{}}, combo{new SwitchingCombo{}} +{ + layout->setContentsMargins(BlendSplitter::expanderSize * 3 / 4, 0, 0, 0); + setLayout(layout); + setMinimumHeight(BlendSplitter::switchingBarHeight); + setMaximumHeight(BlendSplitter::switchingBarHeight); + layout->addWidget(combo); + layout->addStretch(); +} + +void SwitchingBar::reconstruct(void (*populateBar) (SwitchingBar*, QWidget*), QWidget* widget) +{ + int count{layout->count() - 1}; + for(int i = 1; i < count; i++) + { + QLayoutItem* it{layout->takeAt(1)}; + delete it->widget(); + delete it; + } + (*populateBar) (this, widget); +} + +SwitchingBar::~SwitchingBar() +{ + delete layout; +} diff --git a/src/blendsplitter/SwitchingBar.h b/src/blendsplitter/SwitchingBar.h new file mode 100644 index 00000000..239d0c6c --- /dev/null +++ b/src/blendsplitter/SwitchingBar.h @@ -0,0 +1,38 @@ +#pragma once + +#include +#include +#include + +class SwitchingWidget; +class SwitchingCombo; + +/** \brief A menu bar which is always found on the bottom of SwitchingWidget + * + * This menu bar is similar to the built-in QMenuBar, but can also contain plain QWidgets. The first item on the left is always a combo box for selecting which widget should be displayed in the SwitchingWidget. + */ +class SwitchingBar : public QWidget +{ + Q_OBJECT + Q_DISABLE_COPY(SwitchingBar) +public: + /** \brief Add a QMenu + * + * This function adds a QMenu to the very right of the SwitchingBar. The menu is wrapped in an invisible QMenuBar. + * \param menu A pointer to the QMenu to be added + */ + void addMenu(QMenu* menu); + /** \brief Add a QWidget + * + * This function adds a QWidget to the very right of the SwitchingBar. The widget is placed in a QHBoxLayout. + * @param widget A pointer to the QWidget to be added + */ + void addWidget(QWidget* widget); +private: + friend SwitchingWidget; + QHBoxLayout* layout; + SwitchingCombo* combo; + explicit SwitchingBar(QWidget* parent = nullptr); + void reconstruct(void (*populateBar) (SwitchingBar*, QWidget*), QWidget* widget); + ~SwitchingBar(); +}; diff --git a/src/blendsplitter/SwitchingCombo.cpp b/src/blendsplitter/SwitchingCombo.cpp new file mode 100644 index 00000000..a8ff75ad --- /dev/null +++ b/src/blendsplitter/SwitchingCombo.cpp @@ -0,0 +1,28 @@ +#include "SwitchingCombo.h" + +#include "WidgetRegistry.h" +#include "RegistryItem.h" + +SwitchingCombo::SwitchingCombo() +{ + connect(WidgetRegistry::getRegistry(), &WidgetRegistry::registryChanged, this, &SwitchingCombo::repopulate); + repopulate(); +} + +void SwitchingCombo::repopulate() +{ + RegistryItem* current{WidgetRegistry::getRegistry()->item(currentIndex())}; + clear(); + for(int i{0}; i < WidgetRegistry::getRegistry()->size(); i++) + { + QComboBox::addItem(WidgetRegistry::getRegistry()->item(i)->name); + } + if(current != 0) + { + setCurrentIndex(findText(current->name)); + } + else + { + setCurrentIndex(findText(WidgetRegistry::getRegistry()->getDefault()->name)); + } +} diff --git a/src/blendsplitter/SwitchingCombo.h b/src/blendsplitter/SwitchingCombo.h new file mode 100644 index 00000000..225a5d6f --- /dev/null +++ b/src/blendsplitter/SwitchingCombo.h @@ -0,0 +1,15 @@ +#pragma once + +#include "Global.h" + +class SwitchingBar; + +class SwitchingCombo : public QComboBox +{ + Q_OBJECT + Q_DISABLE_COPY(SwitchingCombo) +public: + SwitchingCombo(); +public slots: + void repopulate(); +}; diff --git a/src/blendsplitter/SwitchingWidget.cpp b/src/blendsplitter/SwitchingWidget.cpp new file mode 100644 index 00000000..777d13f9 --- /dev/null +++ b/src/blendsplitter/SwitchingWidget.cpp @@ -0,0 +1,41 @@ +#include "SwitchingWidget.h" + +#include "WidgetRegistry.h" +#include "RegistryItem.h" +#include "SwitchingBar.h" +#include "SwitchingCombo.h" + +SwitchingWidget::SwitchingWidget(RegistryItem* item, QWidget* parent) : QSplitter(Qt::Vertical, parent), bar{new SwitchingBar{}} +{ + setChildrenCollapsible(true); + setHandleWidth(1); + setStyleSheet("QSplitter::handle{background: grey;}"); + addWidget((*WidgetRegistry::getRegistry()->getDefault()->widget) ()); + addWidget(bar); + bar->reconstruct(*WidgetRegistry::getRegistry()->getDefault()->populateBar, widget(0)); + connect(bar->combo, static_cast(&QComboBox::activated), this, &SwitchingWidget::changeCurrentWidget); + setCurrentWidget(item); +} + +void SwitchingWidget::setCurrentWidget(RegistryItem *item) +{ + if(item == nullptr) + { + item = WidgetRegistry::getRegistry()->getDefault(); + } + if(WidgetRegistry::getRegistry()->indexOf(item) >= 0) + { + delete widget(0); + insertWidget(0, (*item->widget) ()); + bar->reconstruct(*item->populateBar, widget(0)); + bar->combo->setCurrentIndex(bar->combo->findText(item->name)); + } +} + +void SwitchingWidget::changeCurrentWidget(int index) +{ + if(index >= 0) + { + setCurrentWidget(WidgetRegistry::getRegistry()->item(index)); + } +} diff --git a/src/blendsplitter/SwitchingWidget.h b/src/blendsplitter/SwitchingWidget.h new file mode 100644 index 00000000..1947b105 --- /dev/null +++ b/src/blendsplitter/SwitchingWidget.h @@ -0,0 +1,36 @@ +#pragma once + +#include + +class SwitchingBar; +class RegistryItem; + +/** \brief A widget whose actual content can be selected from a combo box + * + * This widget displays a Widget with a SwitchingBar on the bottom. The widget displayed is one from WidgetRegistry and it can be selected using a combo box in the SwitchingBar. + * + * Note that constructing an object of this class when WidgetRegistry is empty will cause a default RegistryItem to be added to it. The height of the SwitchingBar can be modified by changing BlendSplitter::switchingBarHeight. + */ +class SwitchingWidget : public QSplitter +{ + Q_OBJECT + Q_DISABLE_COPY(SwitchingWidget) +public: + /** \brief A default constructor similar to that of QWidget + * + * Creates a SwitchingWidget containg the default widget specified in WidgetRegistry + * \param item A RegistryItem to display in the widget. If nullptr, then WidgetRegistry::getDefault() is used. + * \param parent A parent widget + */ + SwitchingWidget(RegistryItem* item = nullptr, QWidget* parent = nullptr); + /** \brief Set the current Widget displayed. + * + * Sets the current widget to be the item + * \param item A RegistryItem to display in the widget. If nullptr, then WidgetRegistry::getDefault() is used. + */ + void setCurrentWidget(RegistryItem* item = nullptr); +private slots: + void changeCurrentWidget(int index); +private: + SwitchingBar* bar; +}; diff --git a/src/blendsplitter/WidgetDecorator.cpp b/src/blendsplitter/WidgetDecorator.cpp new file mode 100644 index 00000000..1562dcf4 --- /dev/null +++ b/src/blendsplitter/WidgetDecorator.cpp @@ -0,0 +1,108 @@ +#include "WidgetDecorator.h" + +#include "BlendSplitter.h" +#include "ExpanderCorner.h" +#include +#include +#include + +WidgetDecorator::WidgetDecorator(QWidget* widget) : QWidget{}, widget{widget}, +// expanderBottom{new ExpanderBottom{this}}, +// expanderTop{new ExpanderTop{this}}, + expanderCorner1{new ExpanderCorner{this,Qt::TopLeftCorner}}, + expanderCorner2{new ExpanderCorner{this,Qt::BottomRightCorner}}, + expanderCorner3{new ExpanderCorner{this,Qt::TopRightCorner}}, + expanderCorner4{new ExpanderCorner{this,Qt::BottomLeftCorner}}, + dropzone(dropregions::center) +{ + QHBoxLayout* layout{new QHBoxLayout{}}; + layout->addWidget(widget); + layout->setMargin(0); + setLayout(layout); + setMinimumSize(2 * BlendSplitter::expanderSize, 2 * BlendSplitter::expanderSize); + +} + +WidgetDecorator::~WidgetDecorator() +{ + delete layout(); +} + +void WidgetDecorator::resizeEvent(QResizeEvent*) +{ +// expanderBottom->reposition(); +// expanderTop->reposition(); + expanderCorner1->reposition(); + expanderCorner2->reposition(); + expanderCorner3->reposition(); + expanderCorner4->reposition(); +} + +//void WidgetDecorator::mouseMoveEvent(QMouseEvent* event) +//{ +// determineDropZone(event->pos()); +// update(); +//} + +void WidgetDecorator::determineDropZone(QPoint pos) +{ + int x=width()/3; + int y=height()/3; + if (pos.x()>x && pos.x()<(width()-x) && pos.y()>y && pos.y()<(height()-y) ){ + dropzone=dropregions::center; + return; + } + // now if we are not center then use the diagonals of the rect to see in which of the 4 triangles we are + + //normal on diagnal (0,0) -> (width,height) + x=-height(); + y=width(); + //we use the sign of the dot product to determine if we are above/below the diagonal + int side=(x*pos.x()+y*pos.y())>0?1:0; + + //normal on diagnal (0,height) -> (width,0) == (0,0)-(width,-height) + x=height(); + y=width(); + //we use the sign of the dot product to determine if we are above/below the diagonal + side+=(x*pos.x()+y*(pos.y()-height()))>0?2:0; + dropzone=static_cast(side); +} + +//void WidgetDecorator::paintEvent(QPaintEvent *event) +//{ +// QWidget::paintEvent(event); + +//// qDebug() << "WidgetDecorator::paintEvent"; + +// QPainter painter(this); +// painter.setPen(Qt::black); +// painter.setBrush(Qt::NoBrush); +// int x=width()/3; +// int y=height()/3; +// painter.drawLine(0,0,x,y); +// painter.drawLine(width(),0,width()-x,y); +// painter.drawLine(0,height(),x,height()-y); +// painter.drawLine(width(),height(),width()-x,height()-y); +// painter.drawRect(x,y,x,y); + +// switch (dropzone) { +// case dropregions::top: +// painter.drawText(QRect(x,0,x,y),Qt::AlignCenter,"top"); +// break; +// case dropregions::left: +// painter.drawText(QRect(0,y,x,y),Qt::AlignCenter,"left"); +// break; +// case dropregions::right: +// painter.drawText(QRect(width()-x,y,x,y),Qt::AlignCenter,"right"); +// break; +// case dropregions::bottom: +// painter.drawText(QRect(x,height()-y,x,y),Qt::AlignCenter,"bottom"); +// break; +// case dropregions::center: +// painter.drawText(QRect(x,y,x,y),Qt::AlignCenter,"center"); +// break; +// default: +// break; +// } +// setMouseTracking(true); +//} diff --git a/src/blendsplitter/WidgetDecorator.h b/src/blendsplitter/WidgetDecorator.h new file mode 100644 index 00000000..e672c850 --- /dev/null +++ b/src/blendsplitter/WidgetDecorator.h @@ -0,0 +1,40 @@ +#pragma once + +#include "Global.h" + +class BlendSplitter; +class ExpanderCorner; + +class WidgetDecorator final : public QWidget +{ + Q_OBJECT + Q_DISABLE_COPY(WidgetDecorator) +public: + WidgetDecorator() = delete; + explicit WidgetDecorator(QWidget* widget); + ~WidgetDecorator(); +private: + QWidget* widget; + ExpanderCorner* expanderCorner1; + ExpanderCorner* expanderCorner2; + ExpanderCorner* expanderCorner3; + ExpanderCorner* expanderCorner4; + + enum class dropregions { + top=0, + left=1, + right=2, + bottom=3, + center=4 + }; + + dropregions dropzone; + + void determineDropZone(QPoint pos); + +protected slots: + virtual void resizeEvent(QResizeEvent*) override; +// virtual void mouseMoveEvent(QMouseEvent* event) override; +// virtual void paintEvent(QPaintEvent* event) override; + +}; diff --git a/src/blendsplitter/WidgetRegistry.cpp b/src/blendsplitter/WidgetRegistry.cpp new file mode 100644 index 00000000..b33d0cdf --- /dev/null +++ b/src/blendsplitter/WidgetRegistry.cpp @@ -0,0 +1,94 @@ +#include "WidgetRegistry.h" + +#include "RegistryItem.h" + +WidgetRegistry* WidgetRegistry::theRegistry; + +WidgetRegistry* WidgetRegistry::getRegistry() +{ + if(theRegistry == nullptr) + { + theRegistry = new WidgetRegistry{}; + } + return theRegistry; +} + +RegistryItem* WidgetRegistry::item(int i) const +{ + return list.value(i); +} + +int WidgetRegistry::indexOf(RegistryItem* item) const +{ + return list.indexOf(item); +} + +RegistryItem* WidgetRegistry::getDefault() +{ + if(defaultItem == nullptr) + { + if(list.size() == 0) + { + addItem(); + } + defaultItem = item(0); + } + return defaultItem; +} + +void WidgetRegistry::setDefault(RegistryItem* item) +{ + if(!list.contains(item)) + { + addItem(item); + } + defaultItem = item; +} + +void WidgetRegistry::setDefault(int index) +{ + if(index < size()) + { + setDefault(item(index)); + } +} + +void WidgetRegistry::addItem(RegistryItem* item) +{ + list.append(item); + emit registryChanged(); +} + +void WidgetRegistry::addItem(QString name, QWidget* (*widget) (), void (*populateBar) (SwitchingBar*, QWidget*)) +{ + addItem(new RegistryItem{name, widget, populateBar}); +} + +void WidgetRegistry::insertItem(int index, RegistryItem* item) +{ + list.insert(index, item); + emit registryChanged(); +} + +void WidgetRegistry::insertItem(int index, QString name, QWidget* (*widget) (), void (*populateBar) (SwitchingBar*, QWidget*)) +{ + insertItem(index, new RegistryItem{name, widget, populateBar}); +} + +void WidgetRegistry::removeItem(RegistryItem* item) +{ + removeItem(indexOf(item)); +} + +void WidgetRegistry::removeItem(int index) +{ + list.removeAt(index); + emit registryChanged(); +} + +int WidgetRegistry::size() const +{ + return list.size(); +} + +WidgetRegistry::WidgetRegistry() : list{}, defaultItem{nullptr} {} diff --git a/src/blendsplitter/WidgetRegistry.h b/src/blendsplitter/WidgetRegistry.h new file mode 100644 index 00000000..ec99a561 --- /dev/null +++ b/src/blendsplitter/WidgetRegistry.h @@ -0,0 +1,114 @@ +#pragma once + +#include + +class RegistryItem; +class SwitchingBar; + +/** \brief A registry of all widgets that can be displayed in a SwitchingWidget + * + * This singleton-class acts as a registry of widgets that can be displayed in a SwitchingWidget by selecting from a combo box in the SwitchingBar. Each item is represented as one RegistryItem. The Registry also contains a pointer to the default RegistryItem, which is shown when a new SwitchingWidget is created. + */ +class WidgetRegistry : public QObject +{ + Q_OBJECT + Q_DISABLE_COPY(WidgetRegistry) +public: + /** \brief Registry getter + * + * This is a singleton class, i. e. you can't construct any object yourself. To get the one-and-only instance of this class, you need to call WidgetRegistry::getRegistry(). The function will create the object if neccessary (= when called for the first time) and return a pointer to it. + * \return A pointer to the one-and-only instance of WidgetRegistry + */ + static WidgetRegistry* getRegistry(); + /** \brief Get the item at position i. + * + * This function gives you the item at position i (counting starts at 0). + * \param i Index of the item to be returned + * \return A pointer to the RegistryItem at position i + */ + RegistryItem* item(int i) const; + /** \brief Get the position of an item in WidgetRegistry + * + * Get the index (counting starts at 0) of an item. Often used together with item(int i) const. + * \param item A pointer to the item whose index is to be returned + * \return Index of the item + */ + int indexOf(RegistryItem* item) const; + /** \brief Get the default RegistryItem + * + * This function gives you the default RegistryItem. Note that if no item was set as default, the currently first item is set as default by this function. If the registry is empty, a RegistryItem is added to the registry (using the default constructor) and set as default. + * \return A pointer to the default RegistryItem + */ + RegistryItem* getDefault(); + /** \brief Set the default RegistryItem + * + * This function sets the default RegistryItem. Note that if the item is not in WidgetRegistry, it is added as the last entry. The default item is used when a new SwitchingWidget is created as the displayed widget. + * \param item A pointer to the RegistryItem to be set as default + */ + void setDefault(RegistryItem* item); + /** \brief Set the default RegistryItem + * + * This function sets the default RegistryItem to be the RegistryItem at given index. This is equal to calling setDefault(item(index)). + * \param index Index of the RegistryItem to be set as default (counting starts at 0) + */ + void setDefault(int index = 0); + /** \brief Add an item to WidgetRegistry + * + * Adds a given RegistryItem at the end of WidgetRegistry. + * \param item A pointer to the RegistryItem to be added + */ + void addItem(RegistryItem* item); + /** \brief Add an item to WidgetRegistry + * + * Adds a RegistryItem constructed with the given parameters at the end of WidgetRegistry. This is equal to calling addItem(new RegistryItem{name, widget, populateBar}). + * \param name The name of the widget, used in the SwitchingBar combo box + * \param widget A pointer to a function constructing the widget + * \param populateBar A pointer to a function populating the SwitchingBar + */ + void addItem(QString name = "Default", QWidget* (*widget) () = []()->QWidget* {return new QLabel{"Default widget"};}, void (*populateBar) (SwitchingBar*, QWidget*) = [](SwitchingBar*, QWidget*)->void {}); + /** \brief Insert an item into WidgetRegistry + * + * Inserts a given RegistryItem into WidgetRegistry at a given index. + * \param index The desired index of the inserted RegistryItem (counting starts at 0) + * \param item A pointer to the RegistryItem to be added + */ + void insertItem(int index, RegistryItem* item); + /** \brief Insert an item into widgetRegistry + * + * Inserts a RegistryItem constructed with the given parameters into WidgetRegistry at a given index. This is equal to calling insertItem(index, new RegistryItem{name, widget, populateBar}). + * \param index The desired index of the inserted RegistryItem (counting starts at 0) + * \param name The name of the widget, used in the SwitchingBar combo box + * \param widget A pointer to a function constructing the widget + * \param populateBar A pointer to a function populating the SwitchingBar + */ + void insertItem(int index, QString name = "Default", QWidget* (*widget) () = []()->QWidget* {return new QLabel{"Default widget"};}, void (*populateBar) (SwitchingBar*, QWidget*) = [](SwitchingBar*, QWidget*)->void {}); + /** \brief Remove a RegistryItem from WidgetRegistry + * + * Removes a given RegistryItem from WidgetRegistry. If this is also the default RegistryItem, the first RegistryItem is set as default if it exists. This is equal to calling removeItem(indexOf(item)). + * \param item + */ + void removeItem(RegistryItem* item); + /** \brief Remove a RegistryItem from WidgetRegistry + * + * Removes the RegistryItem at position index (counting starts at 0) from WidgetRegistry. If this is also the default RegistryItem, the first RegistryItem is set as default if it exists. + * \param index Index of the RegistryItem to be removed + */ + void removeItem(int index); + /** \brief Get the size of WidgetRegistry + * + * This function returns the number of RegistryItems currently in WidgetRegistry. Note that these are indexed as 0, ..., (size() - 1). + * \return Number of RegistryItems in WidgetRegistry + */ + int size() const; +signals: + /** \brief Signal emited when WidgetRegistry changes its contents + * + * This signal is emited when a RegistryItem is added, inserted or removed from WidgetRegistry. It is NOT emited when the default item is changed unless this change requires adding a RegistryItem. + */ + void registryChanged(); +private: + static WidgetRegistry* theRegistry; + QList list; + RegistryItem* defaultItem; + WidgetRegistry(); +}; diff --git a/src/blendsplitter/resources/expander.png b/src/blendsplitter/resources/expander.png new file mode 100644 index 0000000000000000000000000000000000000000..96047a3e7afc7de7ada17707651c561f9a024035 GIT binary patch literal 6077 zcmW+)1ys}D7yoYbXrvL`=olT+5*tXj(mkXb0jbfW1`-qLMnZ*wpn!Br3c?RmaHNO= z0~IBdKmN}<_q=;Q@0`zlH_myHW@@ZU3*m$S06?pE8)1GmqyGsdIRJp#mCPKj402Zk zT?BCXZ&bXl&$~jX0&m-d008y1e*yxEO4zSJicmcxBn1J)!z!(`G_tF61#x>>T8C-} z`1zsyL$6E#&<;kqgreM`;a;JhP+dJEQ+Ejz1pu(Y^bnes5%2dM>_V>V-T8YK`>^(* z-wGa;tu{FWPFZz%WWb(6=5hZ98Vv^kq;z($FBCB_$#lK%hP{$}$X!I4BYB zh%V)RKGxx`*CDaG7xlg3(A25Esj;c6sjI8@4JIA;uCY1KsZ8~>G*74vO==*!a|ocT zqEF9(wTFkXp#FgI!#)}UNoNAnt#jZ66iwDI3(SHp=+Wh5#8RM_j!+E5^7L~9mwR^r zpu6W(3@8KtRzTC+OppL^6ohi%f*0Kl{2h4;L?2rKeQ(OkTXM@ui4H*Tn@@3c{l%hb zcD(>$mMl*YeG4EKU;KffoxrAaUkk#43jwh<{lBK7@lMwW&aTsuf`u2%#ovE=v9Jry zT2Jtx$AG_}eiM@4bin0xtBF{kzg%hhbp2(~85s~KS^(9*_HpMM__zGq$JQ*K0yhdr zaUSfUvk@_Ig}g|S5q=|3qj44z_?h#`N$eI0Aso@!30z2{&oBNcpl^X&xZUa1!9)pk zD$q+#VD8UxIB~jOAYXMEa1mRTz=+lbVwwB1gO+1SE0E{J@^&&5&^M@WY_Ha$zqbAJ zw&-b?{&9BxHxg_ju8D$=4ww4w=kwNFtlVcV-~j-+?%Z2TLkI_5lmX}J=spH#?Xd*; z&#<7=oZJ%q5NusmGGp1K(@Hgp|V2y zh1ku5&Ti1uExGKQI*RGPJjE>BFZcXIismZGvULGJ=~AzU&Vr&-6ppz&+{=k^hLd3s z!ntrW3{OqyJN<)MJyu6^^9D1apjgcCT|IMkqum>T;%4Flpcm;DMnm|X^ocZ5QCgN%YbI0GHb~Szhfc#T*UFQ*UL~l4iBw@*V-3yXj9bOuium@%qb%=m%ga&`AjdGq z$o{`^(4kJDHxIPVi5!qXz}f!x+>-`u4|4m$XQqs#^_mq#p@=PBiaT-&7n}A}0g=M& zQG#GgqQZ+QA1j!h!u>`a--CaPeC_no?Y;eJSeOiAZ7-6yiAyu(inLMCGAEs@aHP>b zYc&?_ew;MibPA6Q z6P}61IU^)0o-sqWY8oX|ks2MCr*0()0lPUCyK9A?uEw_%GCo(iKB>~~-HmY7fQ4h; zDO~pfS3Af<0#jKU8R{=$5-q-otGj2HKaX&5)AnbI*MQj@M2yBgGsSc#-FHe- z+&C0Wf*oa+r@FuUFXD1qivPl}mC9`UA|@NGc5TEGrjC4>(1@IG;ulKFyqcqQD46tt#cPQn~M5op?F^_S&ILGYx7J*mIn%YYvgg({9mPyiSfp_RQe_O0ws zU5Gbp8}GYm z`8!uAr`Tqy5VP+~N{}TcL3qo8D?KB0_9h2JJ!r6xS{%8B8qt@I_b=|mx)wEBP)0bH zu3d7*9R?9gx-undEIDA-_hR^#f($AAY^x{pT^wAS1hpk6`b(WQJ2~QCn!w1nOmE1N zpL?gXh-8$XDC`HMWnHp9UuA&432pjRLvwQk6q)(`Cz?$USf3$r^G4=jxBOn&Ph)ZEA0L~t+v*XWy zmQU+%O8GTSDvO-~?SKbyDO-J6^^4_Xh=G0Enfvf(jA?Rp>w72F?X0ly4L~{zk~Oj& zInacJE&X=3nEd)JOA6}9Fn71PTLQV!L3xf zgbla_J)s=sAoEjHa2=AijMXUA>Dl@uY7d%AX(sa=F8dhAt36bO?xb|j`}MO*2eS!2 zqDubK(kp*5s_^_L1N6alI^65u=~{PCnZ-|!7BE=PZ6V^ZtYNjksmgPV%K_iO;+uy_ zCgsNqI3r(3yNIv0FXC=8k%Kd}xf`zbz|QhRsl0N}nA`^CT2*NIIz~|pNyp}IP8U@zs>S}t>U^M9Pv8O_p)b`{HE-v-f0Gwz6=RONowW>Q z|0?t6{_j7EKEPlEg2GXG)N1|oD`R1;*KmA9m9AWw?jXsi3u7fb<0$1^(Ihs~z}|yo zFD|GzQW!2}@!6_cO^L5Xt)@pgPoeTXvxk!3(r(L`$?5n008x8|tBo|`uNA)1HuVN2 zc^^dde)h}#Jz&3_VnaipD^$ST8*a|@nw{xe_P}28TXg;0xk+Gw!yv| zs?o1!F1bd50U0A-Gk21;lNw>@@}1h7!b9Y!mSsn8fO%xPov;<=JybZT%UGdR8L*)$ zw#6D>vR6WxwaQ$6DX8??OIt_;xCl;aWL~Oj6gc}}6x*kQL|2hYbVxtG=Pow7aGVKO z^cK^gHGeO-%>i|~=0iBx=( z-wc={ydcyTS&!m4`0d>2=SiEYb#r_J>=M;%bIH|DK$@r)sk;Tg*tX+z^gI)saD_2T zr*rbLoM#FuKNx!UTvt4h?-K*8H{xr5%O&|-6pov}^| zAl{RG7F#40s%69Ss$LL^MYyTxfe79S33E9|*4O%#K|=$*T+}9Wi^W~^M2ObiEn$lT zvEz#rPs5v7K}6b>$8}SdO0KG+YK9?2CI;GyM)r;rPpw=1fy5HNpNU6=El$yg~~nlv7(DZOCt;y>mfCs?_PQ{C8e3X=BqyWUWuA}?9S}8 zN%7;RY(t*+lnob?Y?jE#T}ySV(i=w?#&eqlkX{I@J@!8;C55YX#b=iUy4+>4iM7y4XBCc$alJ(oo!Q;B-H`oUq#+3Faso;`2MfV0tw@6{E z2{S%l1Yq#_RGJ9S8U__5!%+~8t1K*r7Z&_enempTdGG>mT~9?nMfZn7>#K2Hk+r?0-APRCxZ@7AG>+&5&UP( zXL zGL$VBwLqd$5?GzQX|fCWrs%|I(dB}kRhA25@q5U{B&+xGb?y_q2Arslxn(J=i~S3~ z5S{QvsVx@MEFxVAa-;{z<@lRJK(VUi`!!74Ee*_ zlwsvFBCCPZck)T=KdzGct!T{Y`6%nxLAG>%RRS+S(82j~enfW$au(i>F#}AES}cT~ zeLozd!T#1smSh6zs943-Yu?y}j{j)*b;cQ$3a zd*{}Ro*|SKK-LR&9)LMMn93HPS|Y6oGxX;ahg1YH!whUjvG`2sNVb zv7@R`i&;8yFas48fI+r2OSCytw^6qBxIRC8Y2)`d7G6Dn->=c@ol=Cu&LMtQ7=b{J zo3pA-j;msE(Ty);e4G~&ZTKgHV@TET5+{5u5Oq)K62sfgEMX%mKbkArbZce9-tmUb83Rox<>-YM92 zf-;tv=<($1Uv8h7EL`A)o3k3dQ452cQ?K2TDCS9b4e~yYenBb!P?{wpXG=^ljG2=t z{#YoLH(GP&qdW&y7}cI!i5dGMYSNZf?PD`VKq^j9NGl&GR7Gf>P85B=$^VqntH-tN zFiHD^jIKAcKVfR3>+n;wr&>i24>l(mzE|3gp!)W+9QPkhkeCmaIug0T#d6~p<9G6< zd3{G!{92K z=zD!mX_{T5m6~{<@mCm{vvGFNMw*Yujli``%I-aXpd6;Pz&92$CwpI^1Z{5h8{zva z=;8CiuutKB9!J(Y1}fl2DBhf*IrXP#^E>z_NKcieb!%o*7QId~h2doR1lt@h7!#dMuj{fTrn@zw8u&mfNNNWgLH>g4>qe%N7TYA%0sOTNLn~; z(pH!5_Nd%8ajBy^0U=T-j^34G!aDKhDw()$Z{bL~A%;wjwKJ9sc5cydR)#xC3}bJ3M}%J@`zIET2^% zgQ>q)n~tI|*#4wZv|sMg^fZWFsoIp@qG96pyXw==RKh5cNkw05pC^Pt028v4IoO&x zh@bsf;-TU77H`i5H@x(QOpG1Gb-3;sOUt30<@}w0#Sp@_oDt0uGMyRWo|u86OJzQsZzGy;Z_wBe0O5$XyP_7NpZ#n8;SV z3#v<#ebq(8#hHw(TGG1}ifPDzYI`rr1$45rt>$gcXT?Y<>Rn zc3GIBBO)=F%-T>x&qU-ct$+`c&ATVAjY_~PFkHQ2tIXUy_@gdg#*Vsz)CUgzE6_`0 zLZM){sd-wyU7pNI15+vnKt{V?GUe!{RK> zx^DP!jMXu&uiBsN=C9VY36?%fe8QFAOk|*gF17H_>)487RUd1OJEqTom9Fd}q215w zb!9C1Vj3NwS~@}P>3h;({R0tL?CcfYgm^+3^&FPLG+0T?s2S~q2+9}hAE6Rnxnz@y z Date: Tue, 19 Apr 2022 13:36:52 +0200 Subject: [PATCH 02/63] Move BlendSplitter icon Simply moved the expander.png in our already existing qrc file. Mainly since I didn't feel like working out how to incorporate 2 qrc files in our buildsystem :-) --- resources/expander.png | Bin 0 -> 6077 bytes resources/resources.qrc | 3 +++ 2 files changed, 3 insertions(+) create mode 100644 resources/expander.png diff --git a/resources/expander.png b/resources/expander.png new file mode 100644 index 0000000000000000000000000000000000000000..96047a3e7afc7de7ada17707651c561f9a024035 GIT binary patch literal 6077 zcmW+)1ys}D7yoYbXrvL`=olT+5*tXj(mkXb0jbfW1`-qLMnZ*wpn!Br3c?RmaHNO= z0~IBdKmN}<_q=;Q@0`zlH_myHW@@ZU3*m$S06?pE8)1GmqyGsdIRJp#mCPKj402Zk zT?BCXZ&bXl&$~jX0&m-d008y1e*yxEO4zSJicmcxBn1J)!z!(`G_tF61#x>>T8C-} z`1zsyL$6E#&<;kqgreM`;a;JhP+dJEQ+Ejz1pu(Y^bnes5%2dM>_V>V-T8YK`>^(* z-wGa;tu{FWPFZz%WWb(6=5hZ98Vv^kq;z($FBCB_$#lK%hP{$}$X!I4BYB zh%V)RKGxx`*CDaG7xlg3(A25Esj;c6sjI8@4JIA;uCY1KsZ8~>G*74vO==*!a|ocT zqEF9(wTFkXp#FgI!#)}UNoNAnt#jZ66iwDI3(SHp=+Wh5#8RM_j!+E5^7L~9mwR^r zpu6W(3@8KtRzTC+OppL^6ohi%f*0Kl{2h4;L?2rKeQ(OkTXM@ui4H*Tn@@3c{l%hb zcD(>$mMl*YeG4EKU;KffoxrAaUkk#43jwh<{lBK7@lMwW&aTsuf`u2%#ovE=v9Jry zT2Jtx$AG_}eiM@4bin0xtBF{kzg%hhbp2(~85s~KS^(9*_HpMM__zGq$JQ*K0yhdr zaUSfUvk@_Ig}g|S5q=|3qj44z_?h#`N$eI0Aso@!30z2{&oBNcpl^X&xZUa1!9)pk zD$q+#VD8UxIB~jOAYXMEa1mRTz=+lbVwwB1gO+1SE0E{J@^&&5&^M@WY_Ha$zqbAJ zw&-b?{&9BxHxg_ju8D$=4ww4w=kwNFtlVcV-~j-+?%Z2TLkI_5lmX}J=spH#?Xd*; z&#<7=oZJ%q5NusmGGp1K(@Hgp|V2y zh1ku5&Ti1uExGKQI*RGPJjE>BFZcXIismZGvULGJ=~AzU&Vr&-6ppz&+{=k^hLd3s z!ntrW3{OqyJN<)MJyu6^^9D1apjgcCT|IMkqum>T;%4Flpcm;DMnm|X^ocZ5QCgN%YbI0GHb~Szhfc#T*UFQ*UL~l4iBw@*V-3yXj9bOuium@%qb%=m%ga&`AjdGq z$o{`^(4kJDHxIPVi5!qXz}f!x+>-`u4|4m$XQqs#^_mq#p@=PBiaT-&7n}A}0g=M& zQG#GgqQZ+QA1j!h!u>`a--CaPeC_no?Y;eJSeOiAZ7-6yiAyu(inLMCGAEs@aHP>b zYc&?_ew;MibPA6Q z6P}61IU^)0o-sqWY8oX|ks2MCr*0()0lPUCyK9A?uEw_%GCo(iKB>~~-HmY7fQ4h; zDO~pfS3Af<0#jKU8R{=$5-q-otGj2HKaX&5)AnbI*MQj@M2yBgGsSc#-FHe- z+&C0Wf*oa+r@FuUFXD1qivPl}mC9`UA|@NGc5TEGrjC4>(1@IG;ulKFyqcqQD46tt#cPQn~M5op?F^_S&ILGYx7J*mIn%YYvgg({9mPyiSfp_RQe_O0ws zU5Gbp8}GYm z`8!uAr`Tqy5VP+~N{}TcL3qo8D?KB0_9h2JJ!r6xS{%8B8qt@I_b=|mx)wEBP)0bH zu3d7*9R?9gx-undEIDA-_hR^#f($AAY^x{pT^wAS1hpk6`b(WQJ2~QCn!w1nOmE1N zpL?gXh-8$XDC`HMWnHp9UuA&432pjRLvwQk6q)(`Cz?$USf3$r^G4=jxBOn&Ph)ZEA0L~t+v*XWy zmQU+%O8GTSDvO-~?SKbyDO-J6^^4_Xh=G0Enfvf(jA?Rp>w72F?X0ly4L~{zk~Oj& zInacJE&X=3nEd)JOA6}9Fn71PTLQV!L3xf zgbla_J)s=sAoEjHa2=AijMXUA>Dl@uY7d%AX(sa=F8dhAt36bO?xb|j`}MO*2eS!2 zqDubK(kp*5s_^_L1N6alI^65u=~{PCnZ-|!7BE=PZ6V^ZtYNjksmgPV%K_iO;+uy_ zCgsNqI3r(3yNIv0FXC=8k%Kd}xf`zbz|QhRsl0N}nA`^CT2*NIIz~|pNyp}IP8U@zs>S}t>U^M9Pv8O_p)b`{HE-v-f0Gwz6=RONowW>Q z|0?t6{_j7EKEPlEg2GXG)N1|oD`R1;*KmA9m9AWw?jXsi3u7fb<0$1^(Ihs~z}|yo zFD|GzQW!2}@!6_cO^L5Xt)@pgPoeTXvxk!3(r(L`$?5n008x8|tBo|`uNA)1HuVN2 zc^^dde)h}#Jz&3_VnaipD^$ST8*a|@nw{xe_P}28TXg;0xk+Gw!yv| zs?o1!F1bd50U0A-Gk21;lNw>@@}1h7!b9Y!mSsn8fO%xPov;<=JybZT%UGdR8L*)$ zw#6D>vR6WxwaQ$6DX8??OIt_;xCl;aWL~Oj6gc}}6x*kQL|2hYbVxtG=Pow7aGVKO z^cK^gHGeO-%>i|~=0iBx=( z-wc={ydcyTS&!m4`0d>2=SiEYb#r_J>=M;%bIH|DK$@r)sk;Tg*tX+z^gI)saD_2T zr*rbLoM#FuKNx!UTvt4h?-K*8H{xr5%O&|-6pov}^| zAl{RG7F#40s%69Ss$LL^MYyTxfe79S33E9|*4O%#K|=$*T+}9Wi^W~^M2ObiEn$lT zvEz#rPs5v7K}6b>$8}SdO0KG+YK9?2CI;GyM)r;rPpw=1fy5HNpNU6=El$yg~~nlv7(DZOCt;y>mfCs?_PQ{C8e3X=BqyWUWuA}?9S}8 zN%7;RY(t*+lnob?Y?jE#T}ySV(i=w?#&eqlkX{I@J@!8;C55YX#b=iUy4+>4iM7y4XBCc$alJ(oo!Q;B-H`oUq#+3Faso;`2MfV0tw@6{E z2{S%l1Yq#_RGJ9S8U__5!%+~8t1K*r7Z&_enempTdGG>mT~9?nMfZn7>#K2Hk+r?0-APRCxZ@7AG>+&5&UP( zXL zGL$VBwLqd$5?GzQX|fCWrs%|I(dB}kRhA25@q5U{B&+xGb?y_q2Arslxn(J=i~S3~ z5S{QvsVx@MEFxVAa-;{z<@lRJK(VUi`!!74Ee*_ zlwsvFBCCPZck)T=KdzGct!T{Y`6%nxLAG>%RRS+S(82j~enfW$au(i>F#}AES}cT~ zeLozd!T#1smSh6zs943-Yu?y}j{j)*b;cQ$3a zd*{}Ro*|SKK-LR&9)LMMn93HPS|Y6oGxX;ahg1YH!whUjvG`2sNVb zv7@R`i&;8yFas48fI+r2OSCytw^6qBxIRC8Y2)`d7G6Dn->=c@ol=Cu&LMtQ7=b{J zo3pA-j;msE(Ty);e4G~&ZTKgHV@TET5+{5u5Oq)K62sfgEMX%mKbkArbZce9-tmUb83Rox<>-YM92 zf-;tv=<($1Uv8h7EL`A)o3k3dQ452cQ?K2TDCS9b4e~yYenBb!P?{wpXG=^ljG2=t z{#YoLH(GP&qdW&y7}cI!i5dGMYSNZf?PD`VKq^j9NGl&GR7Gf>P85B=$^VqntH-tN zFiHD^jIKAcKVfR3>+n;wr&>i24>l(mzE|3gp!)W+9QPkhkeCmaIug0T#d6~p<9G6< zd3{G!{92K z=zD!mX_{T5m6~{<@mCm{vvGFNMw*Yujli``%I-aXpd6;Pz&92$CwpI^1Z{5h8{zva z=;8CiuutKB9!J(Y1}fl2DBhf*IrXP#^E>z_NKcieb!%o*7QId~h2doR1lt@h7!#dMuj{fTrn@zw8u&mfNNNWgLH>g4>qe%N7TYA%0sOTNLn~; z(pH!5_Nd%8ajBy^0U=T-j^34G!aDKhDw()$Z{bL~A%;wjwKJ9sc5cydR)#xC3}bJ3M}%J@`zIET2^% zgQ>q)n~tI|*#4wZv|sMg^fZWFsoIp@qG96pyXw==RKh5cNkw05pC^Pt028v4IoO&x zh@bsf;-TU77H`i5H@x(QOpG1Gb-3;sOUt30<@}w0#Sp@_oDt0uGMyRWo|u86OJzQsZzGy;Z_wBe0O5$XyP_7NpZ#n8;SV z3#v<#ebq(8#hHw(TGG1}ifPDzYI`rr1$45rt>$gcXT?Y<>Rn zc3GIBBO)=F%-T>x&qU-ct$+`c&ATVAjY_~PFkHQ2tIXUy_@gdg#*Vsz)CUgzE6_`0 zLZM){sd-wyU7pNI15+vnKt{V?GUe!{RK> zx^DP!jMXu&uiBsN=C9VY36?%fe8QFAOk|*gF17H_>)487RUd1OJEqTom9Fd}q215w zb!9C1Vj3NwS~@}P>3h;({R0tL?CcfYgm^+3^&FPLG+0T?s2S~q2+9}hAE6Rnxnz@y zicons/symfil.png overlay.png + + expander.png + From 975952a6f008b27f10f15e21736c23addda68317 Mon Sep 17 00:00:00 2001 From: David Heremans Date: Tue, 19 Apr 2022 13:50:43 +0200 Subject: [PATCH 03/63] Improved stackviewer Better coloring when widget disabled. Highlight current SP address. --- src/StackViewer.cpp | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/StackViewer.cpp b/src/StackViewer.cpp index d38e90d2..970cdb46 100644 --- a/src/StackViewer.cpp +++ b/src/StackViewer.cpp @@ -117,7 +117,7 @@ void StackViewer::paintEvent(QPaintEvent* e) int d = fontMetrics().descent(); // set font - p.setPen(Qt::black); +// p.setPen(palette().color(QPalette::Text)); // calc and set drawing bounds QRect r(e->rect()); @@ -132,16 +132,25 @@ void StackViewer::paintEvent(QPaintEvent* e) // calc layout (not optimal) int xAddr = frameL + 8; - int xStack = xAddr + fontMetrics().horizontalAdvance("FFFFF"); + int xStack = xAddr + fontMetrics().horizontalAdvance("FFFFFF"); int y = frameT + h - 1; int address = topAddress; for (int i = 0; i < int(ceil(visibleLines)); ++i) { + // draw background + if (address==stackPointer){ +// p.fillRect(frameL,y-h,width() - frameL- frameR, h, +// palette().color(QPalette::Highlight)); + p.setPen(palette().color(QPalette::LinkVisited)); + } else { + p.setPen(palette().color(QPalette::Text)); + }; // print address QString hexStr; - hexStr = QString("%1").arg(address, 4, 16, QChar('0')).toUpper(); + hexStr = QString("%1").arg(isEnabled()?address:0, 4, 16, QChar('0')).toUpper(); p.drawText(xAddr, y - d, hexStr); - hexStr = QString("%1").arg(memory[address + 1] << 8 | memory[address], 4, 16, QChar('0')).toUpper(); + int val=isEnabled()?(memory[address + 1] << 8 | memory[address]):0; + hexStr = QString("%1").arg(val, 4, 16, QChar('0')).toUpper(); p.drawText(xStack, y - d, hexStr); y += h; address += 2; From fb5f050673291e7c0b1be7b8365f66f3c56eda70 Mon Sep 17 00:00:00 2001 From: David Heremans Date: Tue, 19 Apr 2022 13:53:51 +0200 Subject: [PATCH 04/63] First working version with blendsplitter Currently the old view is in a splitter visible on first workspace. The old code had a lot of direct signals/slots and calls between DebuggerForm and all the *Viewer code To decouple this the SignalDispatcher was created as a central way to forward signals to all views that registers. Also the CPU registers state code now also lives in the SignalDispatcher. This means that now we can have multiple DisasmViewers since the code doesn't rely on one and exactly one disasmView to exist. As a side effect the QAction that would toggle breakpoints are now disabled, since that code can no longer as the cursorAdress from the one-and-only disasmView the old code assumed. --- src/CPURegsViewer.h | 7 +- src/DebugSession.cpp | 11 + src/DebugSession.h | 10 +- src/DebuggableViewer.cpp | 5 + src/DebuggableViewer.h | 2 + src/DebuggerForm.cpp | 545 ++++++++++++++++++++++---- src/DebuggerForm.h | 62 ++- src/DisasmViewer.cpp | 2 +- src/DisasmViewer.h | 2 +- src/MainMemoryViewer.cpp | 18 +- src/MainMemoryViewer.h | 4 +- src/SignalDispatcher.cpp | 122 ++++++ src/SignalDispatcher.h | 74 ++++ src/SlotViewer.cpp | 3 + src/SlotViewer.h | 2 +- src/blendsplitter/BlendSplitter.cpp | 9 +- src/blendsplitter/SwitchingBar.cpp | 7 +- src/blendsplitter/SwitchingWidget.cpp | 41 +- src/blendsplitter/SwitchingWidget.h | 8 +- src/node.mk | 11 +- 20 files changed, 833 insertions(+), 112 deletions(-) create mode 100644 src/SignalDispatcher.cpp create mode 100644 src/SignalDispatcher.h diff --git a/src/CPURegsViewer.h b/src/CPURegsViewer.h index 4c8fa751..9fabadc6 100644 --- a/src/CPURegsViewer.h +++ b/src/CPURegsViewer.h @@ -11,11 +11,13 @@ class CPURegsViewer : public QFrame public: CPURegsViewer(QWidget* parent = nullptr); - void setData(unsigned char* datPtr); int readRegister(int id); - QSize sizeHint() const override; +public slots: + void setData(unsigned char* datPtr); + void setRegister(int id, int value); + private: void resizeEvent(QResizeEvent* e) override; void paintEvent(QPaintEvent* e) override; @@ -37,7 +39,6 @@ class CPURegsViewer : public QFrame int cursorLoc; void drawValue(QPainter& p, int id, int x, int y); - void setRegister(int id, int value); void getRegister(int id, unsigned char* data); void applyModifications(); void cancelModifications(); diff --git a/src/DebugSession.cpp b/src/DebugSession.cpp index dea642ad..b1e2f940 100644 --- a/src/DebugSession.cpp +++ b/src/DebugSession.cpp @@ -4,6 +4,8 @@ #include #include +DebugSession* DebugSession::theDebugSession = nullptr; + DebugSession::DebugSession() : modified(false) { @@ -38,6 +40,15 @@ SymbolTable& DebugSession::symbolTable() return symTable; } + +DebugSession *DebugSession::getDebugSession() +{ + if(theDebugSession == nullptr){ + theDebugSession = new DebugSession{}; + } + return theDebugSession; +} + void DebugSession::clear() { // clear everything diff --git a/src/DebugSession.h b/src/DebugSession.h index 7ddc3f5e..7d3e1822 100644 --- a/src/DebugSession.h +++ b/src/DebugSession.h @@ -10,8 +10,9 @@ class QXmlStreamReader; class DebugSession : public QObject { Q_OBJECT + Q_DISABLE_COPY(DebugSession) public: - DebugSession(); + static DebugSession* getDebugSession(); // session void clear(); @@ -25,6 +26,9 @@ class DebugSession : public QObject Breakpoints& breakpoints(); SymbolTable& symbolTable(); +public slots: + void sessionModified(); + private: void skipUnknownElement(QXmlStreamReader& ses); @@ -33,8 +37,8 @@ class DebugSession : public QObject QString fileName; bool modified; -public slots: - void sessionModified(); + static DebugSession* theDebugSession; + DebugSession(); }; #endif // DEBUGSESSION_H diff --git a/src/DebuggableViewer.cpp b/src/DebuggableViewer.cpp index 9c7ad22b..5f96566d 100644 --- a/src/DebuggableViewer.cpp +++ b/src/DebuggableViewer.cpp @@ -83,4 +83,9 @@ void DebuggableViewer::setDebuggables(const QMap& list) debuggableList->setCurrentIndex(select); hexView->setLocation(lastLocation); } + if (!list.empty() && select == -1) { + hexView->setLocation(0); + debuggableList->setCurrentIndex(0); + } + } diff --git a/src/DebuggableViewer.h b/src/DebuggableViewer.h index 45a92d8e..3662f3b6 100644 --- a/src/DebuggableViewer.h +++ b/src/DebuggableViewer.h @@ -26,6 +26,8 @@ public slots: private slots: void debuggableSelected(int index); void locationChanged(int loc); + +friend class DebuggerForm; // to get to debuggableSelected from the widgetFactory }; #endif // DEBUGGABLEVIEWER_H diff --git a/src/DebuggerForm.cpp b/src/DebuggerForm.cpp index 1e601fd4..b60961bc 100644 --- a/src/DebuggerForm.cpp +++ b/src/DebuggerForm.cpp @@ -23,6 +23,9 @@ #include "VDPCommandRegViewer.h" #include "Settings.h" #include "Version.h" +#include "SignalDispatcher.h" +#include "blendsplitter/BlendSplitter.h" +#include "blendsplitter/WidgetRegistry.h" #include #include #include @@ -31,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -40,6 +44,9 @@ #include #include #include + +QMap DebuggerForm::debuggables; + class QueryPauseHandler : public SimpleCommand { public: @@ -95,6 +102,7 @@ class CPURegRequest : public ReadDebugBlockCommand { copyData(message); form.regsView->setData(buf); + SignalDispatcher::getDispatcher()->setData(buf); delete this; } @@ -148,12 +156,14 @@ int DebuggerForm::counter = 0; DebuggerForm::DebuggerForm(QWidget* parent) : QMainWindow(parent) - , comm(CommClient::instance()) + , comm(CommClient::instance()),enableWidgetStatus(false) { VDPRegView = nullptr; VDPStatusRegView = nullptr; VDPCommandRegView = nullptr; + session = DebugSession::getDebugSession(); + createActions(); createMenus(); createToolbars(); @@ -163,7 +173,7 @@ DebuggerForm::DebuggerForm(QWidget* parent) recentFiles = Settings::get().value("MainWindow/RecentFiles").toStringList(); updateRecentFiles(); - connect(&session.symbolTable(), &SymbolTable::symbolFileChanged, this, &DebuggerForm::symbolFileChanged); + connect(&(session->symbolTable()), &SymbolTable::symbolFileChanged, this, &DebuggerForm::symbolFileChanged); } void DebuggerForm::createActions() @@ -325,19 +335,37 @@ void DebuggerForm::createActions() connect(this, &DebuggerForm::breakStateEntered, [this]{ executeRunToAction->setEnabled(true); }); breakpointToggleAction = new QAction(tr("Toggle"), this); - breakpointToggleAction->setShortcut(tr("F5")); - breakpointToggleAction->setStatusTip(tr("Toggle breakpoint on/off at cursor")); - breakpointToggleAction->setIcon(QIcon(":/icons/break.png")); - breakpointToggleAction->setEnabled(false); + //now that we have possible multiple disasmviewers the disasmview->getCursorAddr() will not work anymore +// breakpointToggleAction->setShortcut(tr("F5")); +// breakpointToggleAction->setStatusTip(tr("Toggle breakpoint on/off at cursor")); +// breakpointToggleAction->setIcon(QIcon(":/icons/break.png")); +// breakpointToggleAction->setEnabled(false); breakpointAddAction = new QAction(tr("Add ..."), this); - breakpointAddAction->setShortcut(tr("CTRL+B")); - breakpointAddAction->setStatusTip(tr("Add a breakpoint at a location")); - breakpointAddAction->setEnabled(false); + //now that we have possible multiple disasmviewers the disasmview->getCursorAddr() will not work anymore +// breakpointAddAction->setShortcut(tr("CTRL+B")); +// breakpointAddAction->setStatusTip(tr("Add a breakpoint at a location")); +// breakpointAddAction->setEnabled(false); helpAboutAction = new QAction(tr("&About"), this); executeRunToAction->setStatusTip(tr("Show the application information")); + addVDPRegsWorkspaceAction = new QAction(tr("VDP &Regs"), this); + addVDPRegsWorkspaceAction->setStatusTip(tr("Show the regular VDP registers")); + + addVDPTilesWorkspaceAction = new QAction(tr("VDP &Tiles"), this); + addVDPTilesWorkspaceAction->setStatusTip(tr("Show the VRAM in tiles")); + + addVDPBitmapWorkspaceAction = new QAction(tr("VDP &Bitmap"), this); + addVDPBitmapWorkspaceAction->setStatusTip(tr("Show the VRAM in bitmap mode")); + + addEmptyWorkspaceAction = new QAction(tr("&Empty workspace"), this); + addEmptyWorkspaceAction->setStatusTip(tr("create an almost empty workspace")); + + addFloatingSwitchingWidgetAction = new QAction(tr("&Create floating item"), this); + addFloatingSwitchingWidgetAction->setStatusTip(tr("Create item in seperate window")); + + connect(fileNewSessionAction, &QAction::triggered, this, &DebuggerForm::fileNewSession); connect(fileOpenSessionAction, &QAction::triggered, this, &DebuggerForm::fileOpenSession); connect(fileSaveSessionAction, &QAction::triggered, this, &DebuggerForm::fileSaveSession); @@ -370,9 +398,14 @@ void DebuggerForm::createActions() connect(executeRunToAction, &QAction::triggered, this, &DebuggerForm::executeRunTo); connect(executeStepOutAction, &QAction::triggered, this, &DebuggerForm::executeStepOut); connect(executeStepBackAction, &QAction::triggered, this, &DebuggerForm::executeStepBack); - connect(breakpointToggleAction, &QAction::triggered, this, &DebuggerForm::toggleBreakpoint); - connect(breakpointAddAction, &QAction::triggered, this, &DebuggerForm::addBreakpoint); + //connect(breakpointToggleAction, &QAction::triggered, this, &DebuggerForm::toggleBreakpoint); + //connect(breakpointAddAction, &QAction::triggered, this, &DebuggerForm::addBreakpoint); connect(helpAboutAction, &QAction::triggered, this, &DebuggerForm::showAbout); + connect(addVDPRegsWorkspaceAction, &QAction::triggered, this, &DebuggerForm::addVDPRegsWorkspace); + connect(addVDPTilesWorkspaceAction, &QAction::triggered, this, &DebuggerForm::addVDPTilesWorkspace); + connect(addVDPBitmapWorkspaceAction, &QAction::triggered, this, &DebuggerForm::addVDPBitmapWorkspace); + connect(addEmptyWorkspaceAction, &QAction::triggered, this, &DebuggerForm::addEmptyWorkspace); + connect(addFloatingSwitchingWidgetAction, &QAction::triggered, this, &DebuggerForm::addFloatingSwitchingWidget); } void DebuggerForm::createMenus() @@ -447,7 +480,7 @@ void DebuggerForm::createMenus() // create breakpoint menu breakpointMenu = menuBar()->addMenu(tr("&Breakpoint")); - breakpointMenu->addAction(breakpointToggleAction); + //breakpointMenu->addAction(breakpointToggleAction); breakpointMenu->addAction(breakpointAddAction); // create help menu @@ -484,13 +517,259 @@ void DebuggerForm::createStatusbar() statusBar()->showMessage("No emulation running."); } +void DebuggerForm::createWidgetRegistry() +{ + //0: register the disasm viewer widget + RegistryItem *item = new RegistryItem{ + tr("Code view"), + []()->QWidget* {return widgetFactory(disasmViewer);} + }; + WidgetRegistry::getRegistry()->addItem(item); + + //1: register the memory view widget + item = new RegistryItem{ + tr("Main memory"), + []()->QWidget* {return widgetFactory(mainMemoryViewer);} + }; + WidgetRegistry::getRegistry()->addItem(item); + + //2: register the register viewer + item = new RegistryItem{ + tr("CPU registers"), + []()->QWidget* {return widgetFactory(cpuRegsViewer);} + }; + WidgetRegistry::getRegistry()->addItem(item); + + //3: register the flags viewer + item = new RegistryItem{ + tr("Flags"), + []()->QWidget* {return widgetFactory(flagsViewer);} + }; + WidgetRegistry::getRegistry()->addItem(item); + + //4: register the stack viewer + item = new RegistryItem{ + tr("Stack"), + []()->QWidget* {return widgetFactory(stackViewer);} + }; + WidgetRegistry::getRegistry()->addItem(item); + + //5: register the slot viewer + item = new RegistryItem{ + tr("Memory layout"), + []()->QWidget* {return widgetFactory(slotViewer);} + }; + WidgetRegistry::getRegistry()->addItem(item); + + //6: register the breakpoints viewer + item = new RegistryItem{ + tr("Debug list"), + []()->QWidget* {return widgetFactory(breakpointViewer);} + }; + WidgetRegistry::getRegistry()->addItem(item); + + //7: register the debuggable viewer + item = new RegistryItem{ + tr("Debuggable hex view"), + []()->QWidget* {return widgetFactory(debuggableViewer);} + }; + //WidgetRegistry::getRegistry()->addItem(item); + WidgetRegistry::getRegistry()->setDefault(item); + + //8: register the VDP Status Registers + item = new RegistryItem{ + tr("VDP status registers"), + []()->QWidget* {return widgetFactory(vdpStatusRegViewer);} + }; + WidgetRegistry::getRegistry()->addItem(item); + + //9: register the VDP command registers view + item = new RegistryItem{ + tr("VDP command registers "), + []()->QWidget* {return widgetFactory(vdpCommandRegViewer);} + }; + WidgetRegistry::getRegistry()->addItem(item); + + //10: register the Bitmapped VRAM View + item = new RegistryItem{ + tr("VRAM as bitmap"), + []()->QWidget* {return widgetFactory(bitMapViewer);} + }; + WidgetRegistry::getRegistry()->addItem(item); + + //11: register the Tile VRAM View + item = new RegistryItem{ + tr("VRAM as tiles"), + []()->QWidget* {return widgetFactory(tileViewer);} + }; + WidgetRegistry::getRegistry()->addItem(item); + + //12: register the Sprites View + item = new RegistryItem{ + tr("Sprites View"), + []()->QWidget* {return widgetFactory(spriteViewer);} + }; + WidgetRegistry::getRegistry()->addItem(item); + + //13: register the general VDP registers + item = new RegistryItem{ + tr("VDP registers"), + []()->QWidget* {return widgetFactory(vdpRegisters);} +}; + WidgetRegistry::getRegistry()->addItem(item); + +} +BlendSplitter* DebuggerForm::createWorkspaceCPU() +{ + BlendSplitter* split = new BlendSplitter([]()->QWidget* {return new SwitchingWidget{};},Qt::Horizontal); + split->addWidget(WidgetRegistry::getRegistry()->item(2)); //2: the register viewer + split->addWidget(WidgetRegistry::getRegistry()->item(3)); //3: the flags viewer + split->addWidget(WidgetRegistry::getRegistry()->item(5)); //5: the slot viewer + + BlendSplitter* split2 = new BlendSplitter([]()->QWidget* {return new SwitchingWidget{};},Qt::Vertical); + split2->addSplitter(split); + split2->addWidget(WidgetRegistry::getRegistry()->item(1)); //1: the memory view widget + split2->addWidget(WidgetRegistry::getRegistry()->item(6)); //6: the breakpoints viewer + + BlendSplitter* split3 = new BlendSplitter([]()->QWidget* {return new SwitchingWidget{};},Qt::Horizontal); + split3->addWidget(WidgetRegistry::getRegistry()->item(0)); //0: the disasm viewer + split3->addSplitter(split2); + split3->addWidget(WidgetRegistry::getRegistry()->item(4)); //4: the stack viewer + + return split3; +} + +BlendSplitter* DebuggerForm::createWorkspaceVDPRegs() +{ + BlendSplitter* split2 = new BlendSplitter([]()->QWidget* {return new SwitchingWidget{};},Qt::Vertical); + split2->addWidget(WidgetRegistry::getRegistry()->item(8)); //8: the VDP Status Registers + split2->addWidget(WidgetRegistry::getRegistry()->item(9)); //9: the VDP command registers view + + BlendSplitter* split3 = new BlendSplitter([]()->QWidget* {return new SwitchingWidget{};},Qt::Horizontal); + split3->addWidget(WidgetRegistry::getRegistry()->item(13)); //13: the general VDP registers + split3->addSplitter(split2); + + return split3; +} + +BlendSplitter *DebuggerForm::createWorkspaceVDPTiles() +{ + BlendSplitter* split3 = new BlendSplitter([]()->QWidget* {return new SwitchingWidget{};},Qt::Horizontal); + split3->addWidget(WidgetRegistry::getRegistry()->item(11)); //11: the Tile VRAM View + split3->addWidget(WidgetRegistry::getRegistry()->item(12)); //12: the Sprites View + + return split3; +} + +BlendSplitter *DebuggerForm::createWorkspaceVDPBitmap() +{ + BlendSplitter* split3 = new BlendSplitter([]()->QWidget* {return new SwitchingWidget{};},Qt::Horizontal); + split3->addWidget(WidgetRegistry::getRegistry()->item(10)); //10: the Bitmapped VRAM View + split3->addWidget(WidgetRegistry::getRegistry()->item(12)); //12: the Sprites View + + return split3; +} + +void DebuggerForm::tabCloseRequest(int index) +{ + if((index < 0) || (index >= workspaces->count())){ + return; + }; + //index 0 is the CPU workspace, refuse to delete this one for now + //Also this way at least one workspace remains, altough we could do this diferently in the future + if (index > 0){ + QWidget *splitter=workspaces->widget(index); + workspaces->removeTab(index); + delete splitter; + } +} + +void DebuggerForm::addVDPRegsWorkspace(){ + workspaces->addTab(createWorkspaceVDPRegs(),"VDP Registers"); +} +void DebuggerForm::addVDPTilesWorkspace(){ + workspaces->addTab(createWorkspaceVDPTiles(),"VDP tiles"); +} +void DebuggerForm::addVDPBitmapWorkspace(){ + workspaces->addTab(createWorkspaceVDPBitmap(),"VDP bitmap"); +} + +void DebuggerForm::addEmptyWorkspace() +{ + BlendSplitter* split = new BlendSplitter([]()->QWidget* {return new SwitchingWidget{};},Qt::Horizontal); + split->addWidget(); + workspaces->addTab(split,"custom"); +} + +void DebuggerForm::addFloatingSwitchingWidget() +{ + SwitchingWidget* wdg=new SwitchingWidget(); + connect(SignalDispatcher::getDispatcher(), SIGNAL(enableWidget(bool)), wdg, SLOT(setEnableWidget(bool))); + wdg->setEnableWidget(enableWidgetStatus); + wdg->show(); +} + void DebuggerForm::createForm() { updateWindowTitle(); - mainArea = new DockableWidgetArea(); - dockMan.addDockArea(mainArea); - setCentralWidget(mainArea); + createWidgetRegistry(); + + workspaces = new QTabWidget(); + workspaces->setMinimumHeight(500); + workspaces->setTabsClosable(true); + QMenu *workspacemenu=new QMenu(); + QMenu *workspacesubmenu=new QMenu("Predefined layouts"); + workspacesubmenu->addAction(addVDPRegsWorkspaceAction); + workspacesubmenu->addAction(addVDPTilesWorkspaceAction); + workspacesubmenu->addAction(addVDPBitmapWorkspaceAction); + workspacemenu->addMenu(workspacesubmenu); + workspacemenu->addSeparator(); + workspacemenu->addAction(addEmptyWorkspaceAction); + workspacemenu->addSeparator(); + workspacemenu->addAction(addFloatingSwitchingWidgetAction); + + + QIcon icon = QIcon::fromTheme(QLatin1String("window-new")); + QToolButton *btn = new QToolButton(); + btn->setIcon(icon); + btn->setMenu(workspacemenu); + btn->setPopupMode(QToolButton::InstantPopup); + //connect(btn, &QAbstractButton::clicked, this, &App::OpenNewTab); + workspaces->setCornerWidget(btn, Qt::TopRightCorner); + connect(workspaces,&QTabWidget::tabCloseRequested,this,&DebuggerForm::tabCloseRequest); + + mainArea = new DockableWidgetArea(); + dockMan.addDockArea(mainArea); + + QWidget *window = new QWidget; + QVBoxLayout *layout = new QVBoxLayout; + QSplitter *cpusplit=new QSplitter(); + cpusplit->addWidget(workspaces); + cpusplit->addWidget(mainArea); + cpusplit->setChildrenCollapsible(true); + layout->addWidget(cpusplit); + window->setLayout(layout); + +// workspaces->addTab(mainArea,"mainArea"); + workspaces->addTab(createWorkspaceCPU(),"CPU"); + addVDPRegsWorkspace(); + addVDPTilesWorkspace(); + addVDPBitmapWorkspace(); + + + setCentralWidget(window); + + //have the SignalDispatcher refresh it data for the widgets in the blendsplitter + connect(this, SIGNAL(connected()), SignalDispatcher::getDispatcher(), SLOT(refresh())); + connect(this, SIGNAL(breakStateEntered()), SignalDispatcher::getDispatcher(), SLOT(refresh())); + //and have it propagate the signals + connect(this, SIGNAL(connected()), SignalDispatcher::getDispatcher(), SIGNAL(connected())); + connect(this, SIGNAL(breakStateEntered()), SignalDispatcher::getDispatcher(), SIGNAL(breakStateEntered())); + connect(this, SIGNAL(debuggablesChanged(const QMap&)), + SignalDispatcher::getDispatcher(), SIGNAL(debuggablesChanged(const QMap&)) ); + connect(this, &DebuggerForm::breakpointsUpdated, SignalDispatcher::getDispatcher(), &SignalDispatcher::breakpointsUpdated); + // Create main widgets and append them to the list first auto* dw = new DockableWidget(dockMan); @@ -637,9 +916,19 @@ void DebuggerForm::createForm() connectionClosed(); // Disasm viewer - connect(disasmView, &DisasmViewer::breakpointToggled, this, &DebuggerForm::toggleBreakpoint); - connect(this, &DebuggerForm::symbolsChanged, disasmView, &DisasmViewer::refresh); - connect(this, &DebuggerForm::settingsChanged, disasmView, &DisasmViewer::updateLayout); + //split in 2 below: connect(disasmView, &DisasmViewer::breakpointToggled, this, &DebuggerForm::toggleBreakpoint); + connect(disasmView,SIGNAL(breakpointToggled(uint16_t)), SignalDispatcher::getDispatcher(), SIGNAL(breakpointToggled(uint16_t))); + connect(SignalDispatcher::getDispatcher(), SIGNAL(breakpointToggled(uint16_t)), this, SLOT(toggleBreakpoint(uint16_t))); + //in DebuggerForm::processBreakpoints bo direct call to update() anymore + connect(SignalDispatcher::getDispatcher(), SIGNAL(breakpointsUpdated()), disasmView, SLOT(update())); + + //split in 2 below:connect(this, &DebuggerForm::symbolsChanged, disasmView, &DisasmViewer::refresh); + connect(this, SIGNAL(symbolsChanged()), SignalDispatcher::getDispatcher(), SIGNAL(symbolsChanged()) ); + connect(SignalDispatcher::getDispatcher(), SIGNAL(symbolsChanged()), disasmView, SLOT(refresh())); + + //split in 2 below:connect(this, &DebuggerForm::settingsChanged, disasmView, &DisasmViewer::updateLayout); + connect(this, SIGNAL(settingsChanged()), SignalDispatcher::getDispatcher(), SIGNAL(settingsChanged()) ); + connect(SignalDispatcher::getDispatcher(), SIGNAL(settingsChanged()), disasmView, SLOT(updateLayout())); // Main memory viewer connect(this, &DebuggerForm::connected, mainMemoryView, &MainMemoryViewer::refresh); @@ -669,27 +958,124 @@ void DebuggerForm::createForm() connect(&comm, &CommClient::updateParsed, this, &DebuggerForm::handleUpdate); connect(&comm, &CommClient::connectionTerminated, this, &DebuggerForm::connectionClosed); - // init main memory - // added four bytes as runover buffer for dasm - // otherwise dasm would need to check the buffer end continously. - session.breakpoints().setMemoryLayout(&memLayout); - mainMemory = new unsigned char[65536 + 4]; - memset(mainMemory, 0, 65536 + 4); - disasmView->setMemory(mainMemory); - disasmView->setBreakpoints(&session.breakpoints()); - disasmView->setMemoryLayout(&memLayout); - disasmView->setSymbolTable(&session.symbolTable()); - mainMemoryView->setRegsView(regsView); - mainMemoryView->setSymbolTable(&session.symbolTable()); + + + session->breakpoints().setMemoryLayout(SignalDispatcher::getDispatcher()->getMemLayout()); + disasmView->setMemory(SignalDispatcher::getDispatcher()->getMainMemory()); + disasmView->setBreakpoints(&session->breakpoints()); + disasmView->setMemoryLayout(SignalDispatcher::getDispatcher()->getMemLayout()); + disasmView->setSymbolTable(&session->symbolTable()); +// mainMemoryView->setRegsView(regsView); + mainMemoryView->setSymbolTable(&session->symbolTable()); mainMemoryView->setDebuggable("memory", 65536); - stackView->setData(mainMemory, 65536); - slotView->setMemoryLayout(&memLayout); - bpView->setBreakpoints(&session.breakpoints()); + stackView->setData(SignalDispatcher::getDispatcher()->getMainMemory(), 65536); + slotView->setMemoryLayout(SignalDispatcher::getDispatcher()->getMemLayout()); + bpView->setBreakpoints(&session->breakpoints()); +} + +QWidget *DebuggerForm::widgetFactory(factoryclasses fctwidget) +{ + QWidget* wdgt; + switch (fctwidget) { + case disasmViewer: + { + wdgt= new DisasmViewer(); + connect(wdgt, SIGNAL(breakpointToggled(uint16_t)), SignalDispatcher::getDispatcher(), SIGNAL(breakpointToggled(uint16_t))); + connect(SignalDispatcher::getDispatcher(), SIGNAL(connected()), wdgt, SLOT(refresh())); + connect(SignalDispatcher::getDispatcher(), SIGNAL(breakStateEntered()), wdgt, SLOT(refresh())); + connect(SignalDispatcher::getDispatcher(), SIGNAL(symbolsChanged()), wdgt, SLOT(refresh())); + connect(SignalDispatcher::getDispatcher(), SIGNAL(settingsChanged()), wdgt, SLOT(updateLayout())); + connect(SignalDispatcher::getDispatcher(), SIGNAL(setCursorAddress(uint16_t,int,int)), wdgt, SLOT(setCursorAddress(uint16_t,int,int))); + connect(SignalDispatcher::getDispatcher(), SIGNAL(setProgramCounter(uint16_t,bool)), wdgt, SLOT(setProgramCounter(uint16_t,bool))); + connect(SignalDispatcher::getDispatcher(), SIGNAL(breakpointsUpdated()), wdgt, SLOT(update())); + static_cast(wdgt)->setMemory(SignalDispatcher::getDispatcher()->getMainMemory()); + static_cast(wdgt)->setBreakpoints(&DebugSession::getDebugSession()->breakpoints()); + static_cast(wdgt)->setMemoryLayout(SignalDispatcher::getDispatcher()->getMemLayout()); + static_cast(wdgt)->setSymbolTable(&DebugSession::getDebugSession()->symbolTable()); + + }; + break; + case mainMemoryViewer: + wdgt = new MainMemoryViewer(); + // Main memory viewer + connect(SignalDispatcher::getDispatcher(), SIGNAL(connected()), wdgt, SLOT(refresh())); + connect(SignalDispatcher::getDispatcher(), SIGNAL(breakStateEntered()), wdgt, SLOT(refresh())); + connect(SignalDispatcher::getDispatcher(), SIGNAL(registerChanged(int,int)), wdgt, SLOT(registerChanged(int,int))); + //mainMemoryView->setRegsView(regsView); + static_cast(wdgt)->setSymbolTable(&DebugSession::getDebugSession()->symbolTable()); + static_cast(wdgt)->setDebuggable("memory", 65536); + break; + case cpuRegsViewer: + wdgt = new CPURegsViewer(); + //copy current registers to new widget + for(int id=0;id<15;id++){ // CpuRegs::REG_AF up to CpuRegs::REG_IFF + static_cast(wdgt)->setRegister(id, + SignalDispatcher::getDispatcher()->readRegister(id)); + }; + connect(SignalDispatcher::getDispatcher(), SIGNAL(registersUpdate(unsigned char*)), wdgt, SLOT(setData(unsigned char*))); + break; + case flagsViewer: + wdgt = new FlagsViewer(); + static_cast(wdgt)->setFlags(SignalDispatcher::getDispatcher()->readRegister(CpuRegs::REG_AF) & 0xFF); + connect(SignalDispatcher::getDispatcher(), SIGNAL(flagsChanged(quint8)), wdgt, SLOT(setFlags(quint8))); + break; + case stackViewer: + wdgt = new StackViewer(); + static_cast(wdgt)->setData(SignalDispatcher::getDispatcher()->getMainMemory(), 65536); + connect(SignalDispatcher::getDispatcher(), SIGNAL(spChanged(quint16)), wdgt, SLOT(setStackPointer(quint16))); + break; + case slotViewer: + wdgt = new SlotViewer(); + connect(SignalDispatcher::getDispatcher(), SIGNAL(connected()), wdgt, SLOT(refresh())); + connect(SignalDispatcher::getDispatcher(), SIGNAL(breakStateEntered()), wdgt, SLOT(refresh())); + static_cast(wdgt)->setMemoryLayout(SignalDispatcher::getDispatcher()->getMemLayout()); + connect(SignalDispatcher::getDispatcher(), SIGNAL(updateSlots(const QString&)), wdgt, SLOT(updateSlots(const QString&))); + // Received status update back from widget after breakStateEntered/connected + //TODO has to move to SignalDispatcher just as the register stuff!!!! +// connect(slotView, &SlotViewer::slotsUpdated, this, &DebuggerForm::onSlotsUpdated); + + break; + case breakpointViewer: + wdgt = new BreakpointViewer(); + break; + case debuggableViewer: + wdgt = new DebuggableViewer(); + connect(SignalDispatcher::getDispatcher(), SIGNAL(breakStateEntered()), wdgt, SLOT(refresh())); + connect(SignalDispatcher::getDispatcher(), SIGNAL(debuggablesChanged(const QMap&)), + wdgt, SLOT(setDebuggables(const QMap&))); + static_cast(wdgt)->setDebuggables(debuggables); + if (!debuggables.isEmpty()){ + static_cast(wdgt)->debuggableSelected(0); + static_cast(wdgt)->refresh(); + }; + break; + case vdpStatusRegViewer: + wdgt = new VDPStatusRegViewer(); + break; + case vdpCommandRegViewer: + wdgt = new VDPCommandRegViewer(); + break; + case bitMapViewer: + wdgt = new BitMapViewer(); + break; + case tileViewer: + wdgt = new TileViewer(); + break; + case spriteViewer: + wdgt = new SpriteViewer(); + break; + case vdpRegisters: + wdgt = new VDPRegViewer(); + break; + default: + wdgt = new QLabel("Not yet implemented in widgetFactory!"); + break; + }; + return wdgt; } DebuggerForm::~DebuggerForm() { - delete[] mainMemory; delete mainArea; } @@ -698,7 +1084,7 @@ void DebuggerForm::closeEvent(QCloseEvent* e) // handle unsaved session fileNewSession(); // cancel if session is still modified - if (session.isModified()) { + if (session->isModified()) { e->ignore(); return; } @@ -766,12 +1152,12 @@ void DebuggerForm::removeRecentFile(const QString& file) void DebuggerForm::updateWindowTitle() { QString title = "openMSX debugger [%1%2]"; - if (session.existsAsFile()) { - title = title.arg(session.filename()); + if (session->existsAsFile()) { + title = title.arg(session->filename()); } else { title = title.arg("unnamed session"); } - if (session.isModified()) { + if (session->isModified()) { title = title.arg('*'); } else { title = title.arg(""); @@ -880,7 +1266,14 @@ void DebuggerForm::connectionClosed() for (auto* w : dockMan.managedWidgets()) { w->widget()->setEnabled(false); - } + } +// replaced by signal from SignalDispatcher +// QList allSwitchItems= this->findChildren(); +// foreach(SwitchingWidget* wdgt,allSwitchItems){ +// wdgt->setEnableWidget(false); +// } + enableWidgetStatus=false; + emit SignalDispatcher::getDispatcher()->enableWidget(false); } void DebuggerForm::finalizeConnection(bool halted) @@ -903,6 +1296,13 @@ void DebuggerForm::finalizeConnection(bool halted) for (auto* w : dockMan.managedWidgets()) { w->widget()->setEnabled(true); } +// replaced by signal from SignalDispatcher +// QList allSwitchItems= this->findChildren(); +// foreach(SwitchingWidget* wdgt,allSwitchItems){ +// wdgt->setEnableWidget(true); +// } + enableWidgetStatus=true; + emit SignalDispatcher::getDispatcher()->enableWidget(true); } void DebuggerForm::handleUpdate(const QString& type, const QString& name, @@ -951,7 +1351,7 @@ void DebuggerForm::setRunMode() void DebuggerForm::fileNewSession() { - if (session.isModified()) { + if (session->isModified()) { // save current session? int choice = QMessageBox::warning(this, tr("Unsaved session"), tr("The current session has unsaved data.\n" @@ -963,10 +1363,10 @@ void DebuggerForm::fileNewSession() } else if (choice == QMessageBox::Save) { fileSaveSession(); // skip new if session is still modified (save was cancelled) - if (session.isModified()) return; + if (session->isModified()) return; } } - session.clear(); + session->clear(); updateWindowTitle(); } @@ -983,13 +1383,13 @@ void DebuggerForm::fileOpenSession() void DebuggerForm::openSession(const QString& file) { fileNewSession(); - session.open(file); + session->open(file); if (systemDisconnectAction->isEnabled()) { // active connection, merge loaded breakpoints reloadBreakpoints(true); } // update recent - if (session.existsAsFile()) { + if (session->existsAsFile()) { addRecentFile(file); } else { removeRecentFile(file); @@ -1000,8 +1400,8 @@ void DebuggerForm::openSession(const QString& file) void DebuggerForm::fileSaveSession() { - if (session.existsAsFile()) { - session.save(); + if (session->existsAsFile()) { + session->save(); } else { fileSaveSessionAs(); } @@ -1017,10 +1417,10 @@ void DebuggerForm::fileSaveSessionAs() d.setAcceptMode(QFileDialog::AcceptSave); d.setFileMode(QFileDialog::AnyFile); if (d.exec()) { - session.saveAs(d.selectedFiles().at(0)); + session->saveAs(d.selectedFiles().at(0)); // update recent - if (session.existsAsFile()) { - addRecentFile(session.filename()); + if (session->existsAsFile()) { + addRecentFile(session->filename()); } } updateWindowTitle(); @@ -1064,9 +1464,9 @@ void DebuggerForm::systemReboot() void DebuggerForm::systemSymbolManager() { - SymbolManager symManager(session.symbolTable(), this); + SymbolManager symManager(session->symbolTable(), this); connect(&symManager, SIGNAL(symbolTableChanged()), - &session, SLOT(sessionModified())); + session, SLOT(sessionModified())); symManager.exec(); emit symbolsChanged(); updateWindowTitle(); @@ -1081,11 +1481,12 @@ void DebuggerForm::systemPreferences() void DebuggerForm::searchGoto() { - GotoDialog gtd(memLayout, &session, this); + GotoDialog gtd(*SignalDispatcher::getDispatcher()->getMemLayout(), session, this); if (gtd.exec()) { int addr = gtd.address(); if (addr >= 0) { disasmView->setCursorAddress(addr, 0, DisasmViewer::MiddleAlways); + SignalDispatcher::getDispatcher()->setCursorAddress(addr,0,DisasmViewer::MiddleAlways); } } } @@ -1136,14 +1537,11 @@ void DebuggerForm::executeStepBack() setRunMode(); } -void DebuggerForm::toggleBreakpoint(int addr) +void DebuggerForm::toggleBreakpoint(uint16_t addr) { - // toggle address unspecified, use cursor address - if (addr < 0) addr = disasmView->cursorAddress(); - QString cmd; QString id; - if (session.breakpoints().isBreakpoint(addr, &id)) { + if (session->breakpoints().isBreakpoint(addr, &id)) { cmd = Breakpoints::createRemoveCommand(id); } else { // get slot @@ -1156,10 +1554,10 @@ void DebuggerForm::toggleBreakpoint(int addr) reloadBreakpoints(); } -void DebuggerForm::addBreakpoint() +void DebuggerForm::addBreakpoint(uint16_t cursorAddress) { - BreakpointDialog bpd(memLayout, &session, this); - int addr = disasmView->cursorAddress(); + BreakpointDialog bpd(*SignalDispatcher::getDispatcher()->getMemLayout(), session, this); + int addr = cursorAddress; auto [ps, ss, seg] = addressSlot(addr); bpd.setData(Breakpoint::BREAKPOINT, addr, ps, ss, seg); if (bpd.exec()) { @@ -1455,7 +1853,8 @@ void DebuggerForm::setDebuggableSize(const QString& debuggable, int size) debuggables[debuggable] = size; // emit update if size of last debuggable was set if (debuggable == debuggables.keys().last()) { - emit debuggablesChanged(debuggables); + emit debuggablesChanged(debuggables); + emit SignalDispatcher::getDispatcher()->debuggablesChanged(debuggables); } } @@ -1470,20 +1869,20 @@ void DebuggerForm::symbolFileChanged() QMessageBox::Yes | QMessageBox::No); shown = false; if (choice == QMessageBox::Yes) - session.symbolTable().reloadFiles(); + session->symbolTable().reloadFiles(); } DebuggerForm::AddressSlotResult DebuggerForm::addressSlot(int addr) const { int p = (addr & 0xC000) >> 14; - auto ps = qint8(memLayout.primarySlot[p]); - auto ss = qint8(memLayout.secondarySlot[p]); + auto ps = qint8(SignalDispatcher::getDispatcher()->getMemLayout()->primarySlot[p]); + auto ss = qint8(SignalDispatcher::getDispatcher()->getMemLayout()->secondarySlot[p]); int segment = [&] { // figure out (rom) mapper segment - if (memLayout.mapperSize[ps][ss == -1 ? 0 : ss] > 0) { - return memLayout.mapperSegment[p]; + if (SignalDispatcher::getDispatcher()->getMemLayout()->mapperSize[ps][ss == -1 ? 0 : ss] > 0) { + return SignalDispatcher::getDispatcher()->getMemLayout()->mapperSegment[p]; } else { int q = 2 * p + ((addr & 0x2000) >> 13); - int b = memLayout.romBlock[q]; + int b = SignalDispatcher::getDispatcher()->getMemLayout()->romBlock[q]; return (b >= 0) ? b : -1; } }(); @@ -1505,16 +1904,16 @@ void DebuggerForm::reloadBreakpoints(bool merge) void DebuggerForm::processBreakpoints(const QString& message) { - session.breakpoints().setBreakpoints(message); - disasmView->update(); - session.sessionModified(); + session->breakpoints().setBreakpoints(message); +// disasmView->update(); + session->sessionModified(); updateWindowTitle(); emit breakpointsUpdated(); } void DebuggerForm::processMerge(const QString& message) { - QString bps = session.breakpoints().mergeBreakpoints(message); + QString bps = session->breakpoints().mergeBreakpoints(message); if (!bps.isEmpty()) { comm.sendCommand(new SimpleCommand(bps)); reloadBreakpoints(false); @@ -1527,7 +1926,8 @@ void DebuggerForm::onSlotsUpdated(bool slotsChanged) { if (disasmStatus == PC_CHANGED) { disasmView->setProgramCounter(disasmAddress, slotsChanged); - disasmStatus = RESET; + SignalDispatcher::getDispatcher()->setProgramCounter(disasmAddress, slotsChanged); + disasmStatus = RESET; } else { disasmStatus = slotsChanged ? SLOTS_CHANGED : SLOTS_CHECKED; } @@ -1539,6 +1939,7 @@ void DebuggerForm::onPCChanged(uint16_t address) assert(disasmStatus != PC_CHANGED); if (disasmStatus != RESET) { disasmView->setProgramCounter(address, disasmStatus == SLOTS_CHANGED); + SignalDispatcher::getDispatcher()->setProgramCounter(address, disasmStatus == SLOTS_CHANGED); } else { disasmStatus = PC_CHANGED; disasmAddress = address; diff --git a/src/DebuggerForm.h b/src/DebuggerForm.h index a253afd7..6798c92b 100644 --- a/src/DebuggerForm.h +++ b/src/DebuggerForm.h @@ -21,6 +21,8 @@ class VDPStatusRegViewer; class VDPRegViewer; class VDPCommandRegViewer; class BreakpointViewer; +class BlendSplitter; +class QTabWidget; class DebuggerForm : public QMainWindow { @@ -34,15 +36,35 @@ class DebuggerForm : public QMainWindow void onSlotsUpdated(bool slotsChanged); void onPCChanged(uint16_t address); + enum factoryclasses { + disasmViewer, + mainMemoryViewer, + cpuRegsViewer, + flagsViewer, + stackViewer, + slotViewer, + breakpointViewer, + debuggableViewer, + vdpStatusRegViewer, + vdpCommandRegViewer, + bitMapViewer, + tileViewer, + spriteViewer, + vdpRegisters + }; + private: void closeEvent(QCloseEvent* e) override; + void createWidgetRegistry(); void createActions(); void createMenus(); void createToolbars(); void createStatusbar(); void createForm(); + static QWidget* widgetFactory(factoryclasses fctwidget); + void openSession(const QString& file); void updateRecentFiles(); void addRecentFile(const QString& file); @@ -123,6 +145,12 @@ class DebuggerForm : public QMainWindow QAction* helpAboutAction; + QAction* addVDPRegsWorkspaceAction; + QAction* addVDPTilesWorkspaceAction; + QAction* addVDPBitmapWorkspaceAction; + QAction* addEmptyWorkspaceAction; + QAction* addFloatingSwitchingWidgetAction; + DockManager dockMan; DockableWidgetArea* mainArea; QStringList recentFiles; @@ -139,12 +167,12 @@ class DebuggerForm : public QMainWindow BreakpointViewer* bpView; CommClient& comm; - DebugSession session; - MemoryLayout memLayout; - unsigned char* mainMemory; + DebugSession* session; + + QTabWidget *workspaces; bool mergeBreakpoints; - QMap debuggables; + static QMap debuggables; static int counter; enum {RESET = 0, SLOTS_CHECKED, PC_CHANGED, SLOTS_CHANGED} disasmStatus = RESET; @@ -182,9 +210,10 @@ class DebuggerForm : public QMainWindow void executeRunTo(); void executeStepOut(); void executeStepBack(); - void toggleBreakpoint(int addr = -1); - void addBreakpoint(); - +private slots: + void toggleBreakpoint(uint16_t addr); +private: + void addBreakpoint(uint16_t cursorAddress); void toggleView(DockableWidget* widget); void initConnection(); void handleUpdate(const QString& type, const QString& name, @@ -216,7 +245,24 @@ class DebuggerForm : public QMainWindow void runStateEntered(); void breakStateEntered(); void breakpointsUpdated(); - void debuggablesChanged(const QMap& list); + void debuggablesChanged(const QMap& list); + +protected: + BlendSplitter *createWorkspaceCPU(); + BlendSplitter *createWorkspaceVDPRegs(); + BlendSplitter *createWorkspaceVDPTiles(); + BlendSplitter *createWorkspaceVDPBitmap(); + void addVDPRegsWorkspace(); + void addVDPTilesWorkspace(); + void addVDPBitmapWorkspace(); + void addEmptyWorkspace(); + void addFloatingSwitchingWidget(); + + bool enableWidgetStatus; + + +protected slots: + void tabCloseRequest(int index); }; #endif // DEBUGGERFORM_H diff --git a/src/DisasmViewer.cpp b/src/DisasmViewer.cpp index 598376c6..143cfa82 100644 --- a/src/DisasmViewer.cpp +++ b/src/DisasmViewer.cpp @@ -215,7 +215,7 @@ void DisasmViewer::paintEvent(QPaintEvent* e) palette().color(QPalette::Highlight)); if (hasFocus()) { QStyleOptionFocusRect so; - so.backgroundColor = palette().color(QPalette::Highlight); + so.backgroundColor = palette().color(QPalette::Midlight); so.rect = QRect(frameL + 32, y, width() - 32 - frameL - frameR, h); style()->drawPrimitive(QStyle::PE_FrameFocusRect, &so, &p, this); } diff --git a/src/DisasmViewer.h b/src/DisasmViewer.h index 1acd195c..fff9670b 100644 --- a/src/DisasmViewer.h +++ b/src/DisasmViewer.h @@ -84,7 +84,7 @@ public slots: int lineAtPos(const QPoint& pos); signals: - void breakpointToggled(int addr); + void breakpointToggled(uint16_t addr); }; #endif // DISASMVIEWER_H diff --git a/src/MainMemoryViewer.cpp b/src/MainMemoryViewer.cpp index 2ed5e2c8..26ade268 100644 --- a/src/MainMemoryViewer.cpp +++ b/src/MainMemoryViewer.cpp @@ -4,6 +4,7 @@ #include "CPURegsViewer.h" #include "SymbolTable.h" #include "Convert.h" +#include "SignalDispatcher.h" #include #include #include @@ -52,7 +53,7 @@ MainMemoryViewer::MainMemoryViewer(QWidget* parent) isLinked = false; linkedId = 0; - regsViewer = nullptr; +// regsViewer = nullptr; symTable = nullptr; connect(hexView, SIGNAL(locationChanged(int)), @@ -79,10 +80,10 @@ void MainMemoryViewer::setDebuggable(const QString& name, int size) hexView->setDebuggable(name, size); } -void MainMemoryViewer::setRegsView(CPURegsViewer* viewer) -{ - regsViewer = viewer; -} +//void MainMemoryViewer::setRegsView(CPURegsViewer* viewer) +//{ +// regsViewer = viewer; +//} void MainMemoryViewer::setSymbolTable(SymbolTable* symtable) { @@ -136,8 +137,9 @@ void MainMemoryViewer::addressSourceListChanged(int index) linkedId = linkRegisters[index - 1]; addressValue->setReadOnly(true); hexView->setIsInteractive(false); - if (regsViewer) { - setLocation(regsViewer->readRegister(linkedId)); - } +// if (regsViewer) { +// setLocation(regsViewer->readRegister(linkedId)); +// } + setLocation(SignalDispatcher::getDispatcher()->readRegister(linkedId)); } } diff --git a/src/MainMemoryViewer.h b/src/MainMemoryViewer.h index 8c58bb16..d1c00685 100644 --- a/src/MainMemoryViewer.h +++ b/src/MainMemoryViewer.h @@ -16,7 +16,7 @@ class MainMemoryViewer : public QWidget MainMemoryViewer(QWidget* parent = nullptr); void setDebuggable(const QString& name, int size); - void setRegsView(CPURegsViewer* viewer); +// void setRegsView(CPURegsViewer* viewer); void setSymbolTable(SymbolTable* symtable); public slots: @@ -34,7 +34,7 @@ public slots: QComboBox* addressSourceList; QLineEdit* addressValue; - CPURegsViewer* regsViewer; +// CPURegsViewer* regsViewer; SymbolTable* symTable; int linkedId; bool isLinked; diff --git a/src/SignalDispatcher.cpp b/src/SignalDispatcher.cpp new file mode 100644 index 00000000..135843ac --- /dev/null +++ b/src/SignalDispatcher.cpp @@ -0,0 +1,122 @@ +#include "SignalDispatcher.h" +#include "OpenMSXConnection.h" +#include "CommClient.h" + +class DispatchDebugMemMapperHandler : public SimpleCommand +{ +public: + DispatchDebugMemMapperHandler(SignalDispatcher& viewer_) + : SimpleCommand("debug_memmapper"), + viewer(viewer_) + { + } + + void replyOk(const QString& message) override + { + emit viewer.updateSlots(message); + delete this; + } +private: + SignalDispatcher& viewer; +}; + +SignalDispatcher* SignalDispatcher::theDispatcher=nullptr; + +SignalDispatcher* SignalDispatcher::getDispatcher() +{ + if (theDispatcher==nullptr) { + theDispatcher = new SignalDispatcher{}; + }; + return theDispatcher; +} + +SignalDispatcher::~SignalDispatcher() +{ + delete[] mainMemory; +} + + + + +unsigned char *SignalDispatcher::getMainMemory() +{ + return mainMemory; +} + +MemoryLayout* SignalDispatcher::getMemLayout() +{ + return &memLayout; +} + +void SignalDispatcher::setData(unsigned char *datPtr) +{ + setRegister(CpuRegs::REG_AF , datPtr[ 0] * 256 + datPtr[ 1]); + setRegister(CpuRegs::REG_BC , datPtr[ 2] * 256 + datPtr[ 3]); + setRegister(CpuRegs::REG_DE , datPtr[ 4] * 256 + datPtr[ 5]); + setRegister(CpuRegs::REG_HL , datPtr[ 6] * 256 + datPtr[ 7]); + setRegister(CpuRegs::REG_AF2, datPtr[ 8] * 256 + datPtr[ 9]); + setRegister(CpuRegs::REG_BC2, datPtr[10] * 256 + datPtr[11]); + setRegister(CpuRegs::REG_DE2, datPtr[12] * 256 + datPtr[13]); + setRegister(CpuRegs::REG_HL2, datPtr[14] * 256 + datPtr[15]); + setRegister(CpuRegs::REG_IX , datPtr[16] * 256 + datPtr[17]); + setRegister(CpuRegs::REG_IY , datPtr[18] * 256 + datPtr[19]); + setRegister(CpuRegs::REG_PC , datPtr[20] * 256 + datPtr[21]); + setRegister(CpuRegs::REG_SP , datPtr[22] * 256 + datPtr[23]); + setRegister(CpuRegs::REG_I , datPtr[24]); + setRegister(CpuRegs::REG_R , datPtr[25]); + setRegister(CpuRegs::REG_IM , datPtr[26]); + + // IFF separately to only check bit 0 for change + regsChanged[CpuRegs::REG_IFF] = (regs[CpuRegs::REG_IFF] & 1) != (datPtr[27] & 1); + regs[CpuRegs::REG_IFF] = datPtr[27]; + + // reset modifications + memset(®sModified, 0, sizeof(regsModified)); + memcpy(®sCopy, ®s, sizeof(regs)); + + emit pcChanged(regs[CpuRegs::REG_PC]); + emit spChanged(regs[CpuRegs::REG_SP]); + emit flagsChanged(regs[CpuRegs::REG_AF] & 0xFF); + emit registersUpdate(datPtr); // now tell all listeners the new values +} + +void SignalDispatcher::refresh() +{ + CommClient::instance().sendCommand(new DispatchDebugMemMapperHandler(*this)); + +} + +int SignalDispatcher::readRegister(int id) +{ + return regs[id]; +} + +SignalDispatcher::SignalDispatcher() { + // avoid UMR + memset(®s, 0, sizeof(regs)); + memset(®sChanged, 0, sizeof(regsChanged)); + memset(®sModified, 0, sizeof(regsModified)); + + // init main memory + // added four bytes as runover buffer for dasm + // otherwise dasm would need to check the buffer end continously. + mainMemory = new unsigned char[65536 + 4]; + memset(mainMemory, 0, 65536 + 4); + +} + +void SignalDispatcher::setRegister(int id, int value) +{ + regsChanged[id] = regs[id] != value; + regs[id] = value; + if (regsChanged[id]) { + emit registerChanged(id, value); + } +} + +void SignalDispatcher::getRegister(int id, unsigned char *data) +{ + data[0] = regs[id] >> 8; + data[1] = regs[id] & 255; +} + diff --git a/src/SignalDispatcher.h b/src/SignalDispatcher.h new file mode 100644 index 00000000..5e3fddae --- /dev/null +++ b/src/SignalDispatcher.h @@ -0,0 +1,74 @@ +#pragma once + +#include "CPURegs.h" +#include "DebuggerData.h" + +#include + + +/** \brief A singleton signal dispatcher + * + * Several debugger widgets like + * This signal dispatcher also does the CPU registers tracking since multi widgets need those even if there wouldn't be a CPURegsViewer + */ +class SignalDispatcher : public QObject +{ + Q_OBJECT + Q_DISABLE_COPY(SignalDispatcher) +public: + /** \brief Dispatcher getter + * + * This is a singleton class, i. e. you can't construct any object yourself. To get the one-and-only instance of this class, you need to call SignalDispatcher::getDispatcher(). The function will create the object if neccessary (= when called for the first time) and return a pointer to it. + * \return A pointer to the one-and-only instance of SignalDispatcher + */ + static SignalDispatcher* getDispatcher(); + ~SignalDispatcher(); + + unsigned char* getMainMemory(); + MemoryLayout* getMemLayout(); + + int readRegister(int id); + void setData(unsigned char* datPtr); + +public slots: + void refresh(); + +private: + static SignalDispatcher* theDispatcher; + SignalDispatcher(); + + //buffers to handle tracking of the CPU registers + int regs[16], regsCopy[16]; + bool regsModified[16]; + bool regsChanged[16]; + void setRegister(int id, int value); + void getRegister(int id, unsigned char* data); + + //main 64K used by disasmview and stack + unsigned char* mainMemory; + MemoryLayout memLayout; + +signals: + void enableWidget(bool enable); + void connected(); + void settingsChanged(); + void symbolsChanged(); + void runStateEntered(); + void breakStateEntered(); + void breakpointsUpdated(); + void debuggablesChanged(const QMap& list); + // signals concerning CPU registers + void registersUpdate(unsigned char* datPtr); + void registerChanged(int id, int value); + void pcChanged(uint16_t); + void flagsChanged(quint8); + void spChanged(quint16); + // signals concerning slotselection + void updateSlots(const QString& message); + //signals from/for the diasmView + void toggleBreakpoint(uint16_t adr); + void breakpointToggled(uint16_t adr); + void setProgramCounter(uint16_t pc, bool reload = false); + //from the GotoDialog + void setCursorAddress(uint16_t addr, int infoLine, int method); +}; diff --git a/src/SlotViewer.cpp b/src/SlotViewer.cpp index 2ba2e0e4..5abcf843 100644 --- a/src/SlotViewer.cpp +++ b/src/SlotViewer.cpp @@ -2,11 +2,13 @@ #include "DebuggerData.h" #include "OpenMSXConnection.h" #include "CommClient.h" +#include "SignalDispatcher.h" #include #include #include + class DebugMemMapperHandler : public SimpleCommand { public: @@ -19,6 +21,7 @@ class DebugMemMapperHandler : public SimpleCommand void replyOk(const QString& message) override { viewer.updateSlots(message); + SignalDispatcher::getDispatcher()->updateSlots(message); delete this; } diff --git a/src/SlotViewer.h b/src/SlotViewer.h index 9c921f63..80efd20d 100644 --- a/src/SlotViewer.h +++ b/src/SlotViewer.h @@ -13,11 +13,11 @@ class SlotViewer : public QFrame SlotViewer(QWidget* parent = nullptr); void setMemoryLayout(MemoryLayout* ml); - void updateSlots(const QString& message); QSize sizeHint() const override; public slots: + void updateSlots(const QString& message); void refresh(); private: diff --git a/src/blendsplitter/BlendSplitter.cpp b/src/blendsplitter/BlendSplitter.cpp index a4bfb579..8f4a98eb 100644 --- a/src/blendsplitter/BlendSplitter.cpp +++ b/src/blendsplitter/BlendSplitter.cpp @@ -6,8 +6,10 @@ #include "SplitterHandle.h" #include "WidgetDecorator.h" +#include "SignalDispatcher.h" + int BlendSplitter::expanderSize{12}; -int BlendSplitter::switchingBarHeight{36}; +int BlendSplitter::switchingBarHeight{32}; QString BlendSplitter::expanderImage{":/BlendSplitter/Expander"}; BlendSplitter::BlendSplitter(QWidget* (*defaultWidget) (), Qt::Orientation orientation) : QSplitter{orientation, nullptr}, defaultWidget{defaultWidget} @@ -46,7 +48,10 @@ void BlendSplitter::insertWidget(int index, QWidget* widget) void BlendSplitter::insertWidget(int index, RegistryItem* item) { - insertWidget(index, new SwitchingWidget{item}); + SwitchingWidget* wdg=new SwitchingWidget{item}; + insertWidget(index, wdg); + connect(SignalDispatcher::getDispatcher(), SIGNAL(enableWidget(bool)), wdg, SLOT(setEnableWidget(bool))); + } void BlendSplitter::addDecoratedWidget(WidgetDecorator* widget) diff --git a/src/blendsplitter/SwitchingBar.cpp b/src/blendsplitter/SwitchingBar.cpp index 9a57072b..036e8db8 100644 --- a/src/blendsplitter/SwitchingBar.cpp +++ b/src/blendsplitter/SwitchingBar.cpp @@ -21,10 +21,13 @@ void SwitchingBar::addWidget(QWidget* widget) SwitchingBar::SwitchingBar(QWidget* parent) : QWidget(parent), layout{new QHBoxLayout{}}, combo{new SwitchingCombo{}} { - layout->setContentsMargins(BlendSplitter::expanderSize * 3 / 4, 0, 0, 0); + layout->setContentsMargins(BlendSplitter::expanderSize * 3 / 4, 0, BlendSplitter::expanderSize * 3 / 4, 0); setLayout(layout); - setMinimumHeight(BlendSplitter::switchingBarHeight); +// setMinimumHeight(BlendSplitter::switchingBarHeight); setMaximumHeight(BlendSplitter::switchingBarHeight); + setMinimumHeight(combo->minimumHeight()); +// setMaximumHeight(combo->maximumHeight()); +// setMaximumHeight(combo->minimumHeight()); layout->addWidget(combo); layout->addStretch(); } diff --git a/src/blendsplitter/SwitchingWidget.cpp b/src/blendsplitter/SwitchingWidget.cpp index 777d13f9..fceccedf 100644 --- a/src/blendsplitter/SwitchingWidget.cpp +++ b/src/blendsplitter/SwitchingWidget.cpp @@ -5,14 +5,20 @@ #include "SwitchingBar.h" #include "SwitchingCombo.h" -SwitchingWidget::SwitchingWidget(RegistryItem* item, QWidget* parent) : QSplitter(Qt::Vertical, parent), bar{new SwitchingBar{}} +SwitchingWidget::SwitchingWidget(RegistryItem* item, QWidget* parent,bool menuAtTop) : QSplitter(Qt::Vertical, parent), bar{new SwitchingBar{}}, widgetEnabled(true),barAtTop(menuAtTop) { setChildrenCollapsible(true); setHandleWidth(1); setStyleSheet("QSplitter::handle{background: grey;}"); - addWidget((*WidgetRegistry::getRegistry()->getDefault()->widget) ()); - addWidget(bar); - bar->reconstruct(*WidgetRegistry::getRegistry()->getDefault()->populateBar, widget(0)); + if (barAtTop){ + addWidget(bar); + addWidget((*WidgetRegistry::getRegistry()->getDefault()->widget) ()); + } else { + addWidget((*WidgetRegistry::getRegistry()->getDefault()->widget) ()); + addWidget(bar); + + } + bar->reconstruct(*WidgetRegistry::getRegistry()->getDefault()->populateBar, widget(widgetIndex())); connect(bar->combo, static_cast(&QComboBox::activated), this, &SwitchingWidget::changeCurrentWidget); setCurrentWidget(item); } @@ -25,10 +31,21 @@ void SwitchingWidget::setCurrentWidget(RegistryItem *item) } if(WidgetRegistry::getRegistry()->indexOf(item) >= 0) { - delete widget(0); - insertWidget(0, (*item->widget) ()); - bar->reconstruct(*item->populateBar, widget(0)); + delete widget(widgetIndex()); + insertWidget(widgetIndex(), (*item->widget) ()); + bar->reconstruct(*item->populateBar, widget(widgetIndex())); bar->combo->setCurrentIndex(bar->combo->findText(item->name)); + widget(widgetIndex())->setEnabled(widgetEnabled); + } +} + +void SwitchingWidget::setEnableWidget(bool enable) +{ + widgetEnabled=enable; + + QWidget* wdgt=widget(widgetIndex()); + if (wdgt != nullptr){ + wdgt->setEnabled(enable); } } @@ -39,3 +56,13 @@ void SwitchingWidget::changeCurrentWidget(int index) setCurrentWidget(WidgetRegistry::getRegistry()->item(index)); } } + +int SwitchingWidget::barIndex() +{ + return barAtTop?0:1; +} + +int SwitchingWidget::widgetIndex() +{ + return barAtTop?1:0; +} diff --git a/src/blendsplitter/SwitchingWidget.h b/src/blendsplitter/SwitchingWidget.h index 1947b105..a7688369 100644 --- a/src/blendsplitter/SwitchingWidget.h +++ b/src/blendsplitter/SwitchingWidget.h @@ -22,15 +22,21 @@ class SwitchingWidget : public QSplitter * \param item A RegistryItem to display in the widget. If nullptr, then WidgetRegistry::getDefault() is used. * \param parent A parent widget */ - SwitchingWidget(RegistryItem* item = nullptr, QWidget* parent = nullptr); + SwitchingWidget(RegistryItem* item = nullptr, QWidget* parent = nullptr,bool menuAtTop=true); /** \brief Set the current Widget displayed. * * Sets the current widget to be the item * \param item A RegistryItem to display in the widget. If nullptr, then WidgetRegistry::getDefault() is used. */ void setCurrentWidget(RegistryItem* item = nullptr); +public slots: + void setEnableWidget(bool enable = true); private slots: void changeCurrentWidget(int index); private: + int barIndex(); + int widgetIndex(); SwitchingBar* bar; + bool widgetEnabled; + bool barAtTop; }; diff --git a/src/node.mk b/src/node.mk index f6660978..7bb19282 100644 --- a/src/node.mk +++ b/src/node.mk @@ -12,7 +12,16 @@ MOC_SRC_HDR:= \ VDPDataStore VDPStatusRegViewer VDPRegViewer InteractiveLabel \ InteractiveButton VDPCommandRegViewer GotoDialog SymbolTable \ TileViewer VramTiledView PaletteDialog VramSpriteView SpriteViewer \ - BreakpointViewer + BreakpointViewer SignalDispatcher \ + blendsplitter/BlendSplitter blendsplitter/Expander \ + blendsplitter/Overlay blendsplitter/SplitterDecorator \ + blendsplitter/SwitchingBar blendsplitter/SwitchingWidget \ + blendsplitter/WidgetRegistry blendsplitter/ExpanderCorner \ + blendsplitter/RegistryItem \ + blendsplitter/SplitterHandle blendsplitter/SwitchingCombo \ + blendsplitter/WidgetDecorator + + SRC_HDR:= \ DockManager Dasm DasmTables DebuggerData SymbolTable Convert Version \ From 2f41c0f97f6f1956b2255d8d3f369225db190930 Mon Sep 17 00:00:00 2001 From: David Heremans Date: Tue, 19 Apr 2022 16:36:05 +0200 Subject: [PATCH 05/63] Splitting now works as in blender After splitting you end up with two SwitchingWidgets of the same type --- src/DebuggerForm.cpp | 6 +++--- src/blendsplitter/BlendSplitter.cpp | 10 ++++++++-- src/blendsplitter/BlendSplitter.h | 6 ++++++ src/blendsplitter/ExpanderCorner.cpp | 15 +++++++++++++++ src/blendsplitter/SwitchingWidget.cpp | 15 +++++++++++++++ src/blendsplitter/SwitchingWidget.h | 3 +++ 6 files changed, 50 insertions(+), 5 deletions(-) diff --git a/src/DebuggerForm.cpp b/src/DebuggerForm.cpp index b60961bc..89471179 100644 --- a/src/DebuggerForm.cpp +++ b/src/DebuggerForm.cpp @@ -395,7 +395,7 @@ void DebuggerForm::createActions() connect(executeRunAction, &QAction::triggered, this, &DebuggerForm::executeRun); connect(executeStepAction, &QAction::triggered, this, &DebuggerForm::executeStep); connect(executeStepOverAction, &QAction::triggered, this, &DebuggerForm::executeStepOver); - connect(executeRunToAction, &QAction::triggered, this, &DebuggerForm::executeRunTo); + //connect(executeRunToAction, &QAction::triggered, this, &DebuggerForm::executeRunTo); connect(executeStepOutAction, &QAction::triggered, this, &DebuggerForm::executeStepOut); connect(executeStepBackAction, &QAction::triggered, this, &DebuggerForm::executeStepBack); //connect(breakpointToggleAction, &QAction::triggered, this, &DebuggerForm::toggleBreakpoint); @@ -476,7 +476,7 @@ void DebuggerForm::createMenus() executeMenu->addAction(executeStepOverAction); executeMenu->addAction(executeStepOutAction); executeMenu->addAction(executeStepBackAction); - executeMenu->addAction(executeRunToAction); + //executeMenu->addAction(executeRunToAction); // create breakpoint menu breakpointMenu = menuBar()->addMenu(tr("&Breakpoint")); @@ -508,7 +508,7 @@ void DebuggerForm::createToolbars() executeToolbar->addAction(executeStepOverAction); executeToolbar->addAction(executeStepOutAction); executeToolbar->addAction(executeStepBackAction); - executeToolbar->addAction(executeRunToAction); + //executeToolbar->addAction(executeRunToAction); } void DebuggerForm::createStatusbar() diff --git a/src/blendsplitter/BlendSplitter.cpp b/src/blendsplitter/BlendSplitter.cpp index 8f4a98eb..cdc3a23f 100644 --- a/src/blendsplitter/BlendSplitter.cpp +++ b/src/blendsplitter/BlendSplitter.cpp @@ -42,6 +42,9 @@ void BlendSplitter::insertWidget(int index) void BlendSplitter::insertWidget(int index, QWidget* widget) { + if (widget->inherits("SwitchingWidget")){ + connect(SignalDispatcher::getDispatcher(), SIGNAL(enableWidget(bool)), widget, SLOT(setEnableWidget(bool))); + }; WidgetDecorator* decorator{new WidgetDecorator{widget}}; QSplitter::insertWidget(index, decorator); } @@ -50,8 +53,6 @@ void BlendSplitter::insertWidget(int index, RegistryItem* item) { SwitchingWidget* wdg=new SwitchingWidget{item}; insertWidget(index, wdg); - connect(SignalDispatcher::getDispatcher(), SIGNAL(enableWidget(bool)), wdg, SLOT(setEnableWidget(bool))); - } void BlendSplitter::addDecoratedWidget(WidgetDecorator* widget) @@ -75,6 +76,11 @@ void BlendSplitter::insertSplitter(int index, BlendSplitter* splitter) QSplitter::insertWidget(index, decorator); } +QWidget *BlendSplitter::getNestedWidget(int index) +{ + return widget(index)->layout()->itemAt(0)->widget(); +} + QSplitterHandle* BlendSplitter::createHandle() { return new SplitterHandle(orientation(), this); diff --git a/src/blendsplitter/BlendSplitter.h b/src/blendsplitter/BlendSplitter.h index bfb61de9..ec0700a8 100644 --- a/src/blendsplitter/BlendSplitter.h +++ b/src/blendsplitter/BlendSplitter.h @@ -86,6 +86,12 @@ class BlendSplitter : public QSplitter * \param splitter A pointer to the BlendSplitter to be inserted */ void insertSplitter(int index, BlendSplitter* splitter); + /** + * @brief getNestedWidget A helper function to get the widget that is in the splitter at the given position. The actual widget is a WidgetDecorator or SplitterDecorator so we return the widget that is a direct child of this decorator. + * @param index The desired position + * @return A pointer to widget that is decorated + */ + QWidget* getNestedWidget(int index); private: friend Expander; friend ExpanderCorner; diff --git a/src/blendsplitter/ExpanderCorner.cpp b/src/blendsplitter/ExpanderCorner.cpp index bc3afd56..2c9b7702 100644 --- a/src/blendsplitter/ExpanderCorner.cpp +++ b/src/blendsplitter/ExpanderCorner.cpp @@ -5,6 +5,8 @@ #include "WidgetDecorator.h" #include "SplitterDecorator.h" +#include "SignalDispatcher.h" + #include ExpanderCorner::ExpanderCorner(WidgetDecorator* parent,Qt::Corner location) : Expander{parent} , @@ -123,6 +125,9 @@ bool ExpanderCorner::isOnTrailingHandler(BlendSplitter* parentSplitter) */ void ExpanderCorner::performInnerSplit(WidgetDecorator* parentDecorator, BlendSplitter* parentSplitter, Qt::Orientation splitorientation) { + SwitchingWidget* switchwdg=dynamic_cast(parentDecorator->layout()->itemAt(0)->widget()); + SwitchingWidget* addedWidget=nullptr; + if (parentSplitter->orientation() == splitorientation){ QList sizes{parentSplitter->sizes()}; @@ -131,10 +136,12 @@ void ExpanderCorner::performInnerSplit(WidgetDecorator* parentDecorator, BlendSp sizes.insert(index, BlendSplitter::expanderSize); sizes[index + 1] -= BlendSplitter::expanderSize + 1; parentSplitter->insertWidget(index); + addedWidget=dynamic_cast(parentSplitter->getNestedWidget(index)); } else { sizes.insert(index +1, BlendSplitter::expanderSize); sizes[index] -= BlendSplitter::expanderSize + 1; parentSplitter->insertWidget(index+1); + addedWidget=dynamic_cast(parentSplitter->getNestedWidget(index+1)); } parentSplitter->setSizes(sizes); parentSplitter->handle(index + 1)->grabMouse(); @@ -150,13 +157,21 @@ void ExpanderCorner::performInnerSplit(WidgetDecorator* parentDecorator, BlendSp if (after){ newSplitter->addWidget(); newSplitter->addDecoratedWidget(parentDecorator); + addedWidget=dynamic_cast(newSplitter->getNestedWidget(0)); } else { newSplitter->addDecoratedWidget(parentDecorator); newSplitter->addWidget(); + addedWidget=dynamic_cast(newSplitter->getNestedWidget(1)); } parentSplitter->setSizes(sizes); newSplitter->handle(1)->grabMouse(); } + + //now if the original item was a SwitchingWidget we set the same and the enablestate + if (switchwdg && addedWidget){ + addedWidget->setEnableWidget(switchwdg->getEnableWidget()); + addedWidget->setCurrentIndex(switchwdg->getCurrentIndex()); + } } void ExpanderCorner::setupJoiners(WidgetDecorator *parentDecorator, BlendSplitter *parentSplitter, int x, int y, Qt::Orientation /*splitorientation*/) diff --git a/src/blendsplitter/SwitchingWidget.cpp b/src/blendsplitter/SwitchingWidget.cpp index fceccedf..0a50e98d 100644 --- a/src/blendsplitter/SwitchingWidget.cpp +++ b/src/blendsplitter/SwitchingWidget.cpp @@ -39,6 +39,21 @@ void SwitchingWidget::setCurrentWidget(RegistryItem *item) } } +bool SwitchingWidget::getEnableWidget() +{ + return widgetEnabled; +} + +void SwitchingWidget::setCurrentIndex(int index) +{ + setCurrentWidget(WidgetRegistry::getRegistry()->item(index)); +} + +int SwitchingWidget::getCurrentIndex() +{ + return bar->combo->currentIndex(); +} + void SwitchingWidget::setEnableWidget(bool enable) { widgetEnabled=enable; diff --git a/src/blendsplitter/SwitchingWidget.h b/src/blendsplitter/SwitchingWidget.h index a7688369..15e52ae2 100644 --- a/src/blendsplitter/SwitchingWidget.h +++ b/src/blendsplitter/SwitchingWidget.h @@ -29,6 +29,9 @@ class SwitchingWidget : public QSplitter * \param item A RegistryItem to display in the widget. If nullptr, then WidgetRegistry::getDefault() is used. */ void setCurrentWidget(RegistryItem* item = nullptr); + bool getEnableWidget(); + void setCurrentIndex(int index); + int getCurrentIndex(); public slots: void setEnableWidget(bool enable = true); private slots: From 1a58a27f58f8907f39dc07f4970d804a84df7fdf Mon Sep 17 00:00:00 2001 From: David Heremans Date: Wed, 20 Apr 2022 09:31:40 +0200 Subject: [PATCH 06/63] Place all dockingwidgets in comment In effect only BlendSplitter layout in use now --- src/DebuggerForm.cpp | 88 +++++++++++++++++++++++++++++--------------- src/DebuggerForm.h | 38 ++++++++++--------- 2 files changed, 79 insertions(+), 47 deletions(-) diff --git a/src/DebuggerForm.cpp b/src/DebuggerForm.cpp index 89471179..3035e7b6 100644 --- a/src/DebuggerForm.cpp +++ b/src/DebuggerForm.cpp @@ -101,7 +101,7 @@ class CPURegRequest : public ReadDebugBlockCommand void replyOk(const QString& message) override { copyData(message); - form.regsView->setData(buf); +// form.regsView->setData(buf); SignalDispatcher::getDispatcher()->setData(buf); delete this; } @@ -158,10 +158,11 @@ DebuggerForm::DebuggerForm(QWidget* parent) : QMainWindow(parent) , comm(CommClient::instance()),enableWidgetStatus(false) { + /* VDPRegView = nullptr; VDPStatusRegView = nullptr; VDPCommandRegView = nullptr; - + */ session = DebugSession::getDebugSession(); createActions(); @@ -233,7 +234,7 @@ void DebuggerForm::createActions() searchGotoAction = new QAction(tr("&Goto ..."), this); searchGotoAction->setStatusTip(tr("Jump to a specific address or label in the disassembly view")); searchGotoAction->setShortcut(tr("Ctrl+G")); - +/* viewRegistersAction = new QAction(tr("CPU &Registers"), this); viewRegistersAction->setStatusTip(tr("Toggle the cpu registers display")); viewRegistersAction->setCheckable(true); @@ -277,7 +278,7 @@ void DebuggerForm::createActions() viewCharMappedAction->setStatusTip(tr("Decode VRAM as MSX1 screen tiles")); viewSpritesAction = new QAction(tr("Sprites in VRAM"), this); viewSpritesAction->setStatusTip(tr("Decode sprites tiles")); - +*/ executeBreakAction = new QAction(tr("Break"), this); executeBreakAction->setShortcut(tr("CRTL+B")); executeBreakAction->setStatusTip(tr("Halt the execution and enter debug mode")); @@ -325,7 +326,7 @@ void DebuggerForm::createActions() executeStepBackAction->setEnabled(false); connect(this, &DebuggerForm::runStateEntered, [this]{ executeStepBackAction->setEnabled(false); }); connect(this, &DebuggerForm::breakStateEntered, [this]{ executeStepBackAction->setEnabled(true); }); - +/* executeRunToAction = new QAction(tr("Run to"), this); executeRunToAction->setShortcut(tr("F4")); executeRunToAction->setStatusTip(tr("Resume execution until the selected line is reached")); @@ -333,8 +334,9 @@ void DebuggerForm::createActions() executeRunToAction->setEnabled(false); connect(this, &DebuggerForm::runStateEntered, [this]{ executeRunToAction->setEnabled(false); }); connect(this, &DebuggerForm::breakStateEntered, [this]{ executeRunToAction->setEnabled(true); }); +*/ - breakpointToggleAction = new QAction(tr("Toggle"), this); +// breakpointToggleAction = new QAction(tr("Toggle"), this); //now that we have possible multiple disasmviewers the disasmview->getCursorAddr() will not work anymore // breakpointToggleAction->setShortcut(tr("F5")); // breakpointToggleAction->setStatusTip(tr("Toggle breakpoint on/off at cursor")); @@ -348,7 +350,7 @@ void DebuggerForm::createActions() // breakpointAddAction->setEnabled(false); helpAboutAction = new QAction(tr("&About"), this); - executeRunToAction->setStatusTip(tr("Show the application information")); +// executeRunToAction->setStatusTip(tr("Show the application information")); addVDPRegsWorkspaceAction = new QAction(tr("VDP &Regs"), this); addVDPRegsWorkspaceAction->setStatusTip(tr("Show the regular VDP registers")); @@ -378,7 +380,7 @@ void DebuggerForm::createActions() connect(systemSymbolManagerAction, &QAction::triggered, this, &DebuggerForm::systemSymbolManager); connect(systemPreferencesAction, &QAction::triggered, this, &DebuggerForm::systemPreferences); connect(searchGotoAction, &QAction::triggered, this, &DebuggerForm::searchGoto); - connect(viewRegistersAction, &QAction::triggered, this, &DebuggerForm::toggleRegisterDisplay); +/* connect(viewRegistersAction, &QAction::triggered, this, &DebuggerForm::toggleRegisterDisplay); connect(viewBreakpointsAction, &QAction::triggered, this, &DebuggerForm::toggleBreakpointsDisplay); connect(viewFlagsAction, &QAction::triggered, this, &DebuggerForm::toggleFlagsDisplay); connect(viewStackAction, &QAction::triggered, this, &DebuggerForm::toggleStackDisplay); @@ -391,7 +393,7 @@ void DebuggerForm::createActions() connect(viewVDPRegsAction, &QAction::triggered, this, &DebuggerForm::toggleVDPRegsDisplay); connect(viewVDPCommandRegsAction, &QAction::triggered, this, &DebuggerForm::toggleVDPCommandRegsDisplay); connect(viewVDPStatusRegsAction, &QAction::triggered, this, &DebuggerForm::toggleVDPStatusRegsDisplay); - connect(executeBreakAction, &QAction::triggered, this, &DebuggerForm::executeBreak); +*/ connect(executeBreakAction, &QAction::triggered, this, &DebuggerForm::executeBreak); connect(executeRunAction, &QAction::triggered, this, &DebuggerForm::executeRun); connect(executeStepAction, &QAction::triggered, this, &DebuggerForm::executeStep); connect(executeStepOverAction, &QAction::triggered, this, &DebuggerForm::executeStepOver); @@ -441,6 +443,7 @@ void DebuggerForm::createMenus() searchMenu = menuBar()->addMenu(tr("Se&arch")); searchMenu->addAction(searchGotoAction); + /* // create view menu viewMenu = menuBar()->addMenu(tr("&View")); viewMenu->addAction(viewRegistersAction); @@ -466,7 +469,7 @@ void DebuggerForm::createMenus() // create Debuggable Viewers menu (so the user can focus an existing one) connect(viewFloatingWidgetsMenu, &QMenu::aboutToShow, this, &DebuggerForm::updateViewFloatingWidgetsMenu); - +*/ // create execute menu executeMenu = menuBar()->addMenu(tr("&Execute")); executeMenu->addAction(executeBreakAction); @@ -739,16 +742,23 @@ void DebuggerForm::createForm() workspaces->setCornerWidget(btn, Qt::TopRightCorner); connect(workspaces,&QTabWidget::tabCloseRequested,this,&DebuggerForm::tabCloseRequest); + /* mainArea = new DockableWidgetArea(); dockMan.addDockArea(mainArea); + */ QWidget *window = new QWidget; QVBoxLayout *layout = new QVBoxLayout; + /* QSplitter *cpusplit=new QSplitter(); cpusplit->addWidget(workspaces); cpusplit->addWidget(mainArea); cpusplit->setChildrenCollapsible(true); layout->addWidget(cpusplit); + */ + //only splitter now + layout->addWidget(workspaces); + window->setLayout(layout); // workspaces->addTab(mainArea,"mainArea"); @@ -770,10 +780,10 @@ void DebuggerForm::createForm() SignalDispatcher::getDispatcher(), SIGNAL(debuggablesChanged(const QMap&)) ); connect(this, &DebuggerForm::breakpointsUpdated, SignalDispatcher::getDispatcher(), &SignalDispatcher::breakpointsUpdated); + /* // Create main widgets and append them to the list first auto* dw = new DockableWidget(dockMan); - // create the disasm viewer widget disasmView = new DisasmViewer(); dw->setWidget(disasmView); @@ -912,9 +922,12 @@ void DebuggerForm::createForm() } } + */ + + // disable all widgets connectionClosed(); - +/* // Disasm viewer //split in 2 below: connect(disasmView, &DisasmViewer::breakpointToggled, this, &DebuggerForm::toggleBreakpoint); connect(disasmView,SIGNAL(breakpointToggled(uint16_t)), SignalDispatcher::getDispatcher(), SIGNAL(breakpointToggled(uint16_t))); @@ -954,6 +967,8 @@ void DebuggerForm::createForm() // Received status update back from widgets after update connect(regsView, &CPURegsViewer::pcChanged, this, &DebuggerForm::onPCChanged); + */ + connect(&comm, &CommClient::connectionReady, this, &DebuggerForm::initConnection); connect(&comm, &CommClient::updateParsed, this, &DebuggerForm::handleUpdate); connect(&comm, &CommClient::connectionTerminated, this, &DebuggerForm::connectionClosed); @@ -961,6 +976,7 @@ void DebuggerForm::createForm() session->breakpoints().setMemoryLayout(SignalDispatcher::getDispatcher()->getMemLayout()); +/* disasmView->setMemory(SignalDispatcher::getDispatcher()->getMainMemory()); disasmView->setBreakpoints(&session->breakpoints()); disasmView->setMemoryLayout(SignalDispatcher::getDispatcher()->getMemLayout()); @@ -971,6 +987,7 @@ void DebuggerForm::createForm() stackView->setData(SignalDispatcher::getDispatcher()->getMainMemory(), 65536); slotView->setMemoryLayout(SignalDispatcher::getDispatcher()->getMemLayout()); bpView->setBreakpoints(&session->breakpoints()); +*/ } QWidget *DebuggerForm::widgetFactory(factoryclasses fctwidget) @@ -1076,7 +1093,7 @@ QWidget *DebuggerForm::widgetFactory(factoryclasses fctwidget) DebuggerForm::~DebuggerForm() { - delete mainArea; +// delete mainArea; } void DebuggerForm::closeEvent(QCloseEvent* e) @@ -1094,6 +1111,7 @@ void DebuggerForm::closeEvent(QCloseEvent* e) QStringList layoutList; // fill layout list with docked widgets + /* dockMan.getConfig(0, layoutList); // append floating widgets for (auto* widget : dockMan.managedWidgets()) { @@ -1112,7 +1130,7 @@ void DebuggerForm::closeEvent(QCloseEvent* e) widget->hide(); } Settings::get().setValue("Layout/WidgetLayout", layoutList); - + */ QMainWindow::closeEvent(e); } @@ -1258,15 +1276,17 @@ void DebuggerForm::connectionClosed() executeStepOverAction->setEnabled(false); executeStepOutAction->setEnabled(false); executeStepBackAction->setEnabled(false); - executeRunToAction->setEnabled(false); +// executeRunToAction->setEnabled(false); systemDisconnectAction->setEnabled(false); systemConnectAction->setEnabled(true); - breakpointToggleAction->setEnabled(false); +// breakpointToggleAction->setEnabled(false); breakpointAddAction->setEnabled(false); + /* for (auto* w : dockMan.managedWidgets()) { w->widget()->setEnabled(false); } + */ // replaced by signal from SignalDispatcher // QList allSwitchItems= this->findChildren(); // foreach(SwitchingWidget* wdgt,allSwitchItems){ @@ -1280,7 +1300,7 @@ void DebuggerForm::finalizeConnection(bool halted) { systemPauseAction->setEnabled(true); systemRebootAction->setEnabled(true); - breakpointToggleAction->setEnabled(true); +// breakpointToggleAction->setEnabled(true); breakpointAddAction->setEnabled(true); // merge breakpoints on connect mergeBreakpoints = true; @@ -1292,10 +1312,11 @@ void DebuggerForm::finalizeConnection(bool halted) } emit connected(); - + /* for (auto* w : dockMan.managedWidgets()) { w->widget()->setEnabled(true); } + */ // replaced by signal from SignalDispatcher // QList allSwitchItems= this->findChildren(); // foreach(SwitchingWidget* wdgt,allSwitchItems){ @@ -1485,7 +1506,7 @@ void DebuggerForm::searchGoto() if (gtd.exec()) { int addr = gtd.address(); if (addr >= 0) { - disasmView->setCursorAddress(addr, 0, DisasmViewer::MiddleAlways); + //disasmView->setCursorAddress(addr, 0, DisasmViewer::MiddleAlways); SignalDispatcher::getDispatcher()->setCursorAddress(addr,0,DisasmViewer::MiddleAlways); } } @@ -1516,12 +1537,12 @@ void DebuggerForm::executeStepOver() setRunMode(); } -void DebuggerForm::executeRunTo() -{ - comm.sendCommand(new SimpleCommand( - "run_to " + QString::number(disasmView->cursorAddress()))); - setRunMode(); -} +//void DebuggerForm::executeRunTo() +//{ +// comm.sendCommand(new SimpleCommand( +// "run_to " + QString::number(disasmView->cursorAddress()))); +// setRunMode(); +//} void DebuggerForm::executeStepOut() { @@ -1577,7 +1598,7 @@ void DebuggerForm::showAbout() QMessageBox::about( this, "openMSX Debugger", QString(Version::full().c_str())); } - +/* void DebuggerForm::toggleBreakpointsDisplay() { toggleView(qobject_cast(bpView->parentWidget())); @@ -1602,7 +1623,9 @@ void DebuggerForm::toggleSlotsDisplay() { toggleView(qobject_cast(slotView->parentWidget())); } +*/ + /* void DebuggerForm::toggleBitMappedDisplay() { //toggleView(qobject_cast(slotView->parentWidget())); @@ -1618,6 +1641,7 @@ void DebuggerForm::toggleBitMappedDisplay() dw->setDestroyable(true); dw->setMovable(true); dw->setClosable(true); + */ /* connect(dw, SIGNAL(visibilityChanged(DockableWidget*)), this, SLOT(dockWidgetVisibilityChanged(DockableWidget*))); @@ -1625,15 +1649,20 @@ void DebuggerForm::toggleBitMappedDisplay() viewer, SLOT(setDebuggables(const QMap&))); */ - // TODO: refresh should be being hanled by VDPDataStore... + /* + // TODO: refresh should be being hanled by VDPDataStore... connect(this, SIGNAL(breakStateEntered()), viewer, SLOT(refresh())); + */ /* viewer->setDebuggables(debuggables); viewer->setEnabled(disasmView->isEnabled()); */ + /* } + */ +/* void DebuggerForm::toggleCharMappedDisplay() { //toggleView(qobject_cast(slotView->parentWidget())); @@ -1823,6 +1852,7 @@ void DebuggerForm::updateViewFloatingWidgetsMenu() } } } +*/ void DebuggerForm::setDebuggables(const QString& list) { @@ -1925,7 +1955,7 @@ void DebuggerForm::processMerge(const QString& message) void DebuggerForm::onSlotsUpdated(bool slotsChanged) { if (disasmStatus == PC_CHANGED) { - disasmView->setProgramCounter(disasmAddress, slotsChanged); + //disasmView->setProgramCounter(disasmAddress, slotsChanged); SignalDispatcher::getDispatcher()->setProgramCounter(disasmAddress, slotsChanged); disasmStatus = RESET; } else { @@ -1938,7 +1968,7 @@ void DebuggerForm::onPCChanged(uint16_t address) // PC shouldn't update twice. assert(disasmStatus != PC_CHANGED); if (disasmStatus != RESET) { - disasmView->setProgramCounter(address, disasmStatus == SLOTS_CHANGED); + //disasmView->setProgramCounter(address, disasmStatus == SLOTS_CHANGED); SignalDispatcher::getDispatcher()->setProgramCounter(address, disasmStatus == SLOTS_CHANGED); } else { disasmStatus = PC_CHANGED; diff --git a/src/DebuggerForm.h b/src/DebuggerForm.h index 6798c92b..42fbf9aa 100644 --- a/src/DebuggerForm.h +++ b/src/DebuggerForm.h @@ -88,10 +88,12 @@ class DebuggerForm : public QMainWindow QMenu* fileMenu; QMenu* systemMenu; QMenu* searchMenu; + /* QMenu* viewMenu; QMenu* viewVDPDialogsMenu; QMenu* viewFloatingWidgetsMenu; - QMenu* executeMenu; + */ + QMenu* executeMenu; QMenu* breakpointMenu; QMenu* helpMenu; @@ -116,7 +118,7 @@ class DebuggerForm : public QMainWindow QAction* systemPreferencesAction; QAction* searchGotoAction; - +/* QAction* viewRegistersAction; QAction* viewFlagsAction; QAction* viewStackAction; @@ -131,16 +133,16 @@ class DebuggerForm : public QMainWindow QAction* viewVDPStatusRegsAction; QAction* viewVDPRegsAction; QAction* viewVDPCommandRegsAction; - +*/ QAction* executeBreakAction; QAction* executeRunAction; QAction* executeStepAction; QAction* executeStepOverAction; - QAction* executeRunToAction; + //QAction* executeRunToAction; QAction* executeStepOutAction; QAction* executeStepBackAction; - QAction* breakpointToggleAction; + //QAction* breakpointToggleAction; QAction* breakpointAddAction; QAction* helpAboutAction; @@ -151,20 +153,20 @@ class DebuggerForm : public QMainWindow QAction* addEmptyWorkspaceAction; QAction* addFloatingSwitchingWidgetAction; - DockManager dockMan; - DockableWidgetArea* mainArea; +// DockManager dockMan; +// DockableWidgetArea* mainArea; QStringList recentFiles; - DisasmViewer* disasmView; - MainMemoryViewer* mainMemoryView; - CPURegsViewer* regsView; - FlagsViewer* flagsView; - StackViewer* stackView; - SlotViewer* slotView; - VDPStatusRegViewer* VDPStatusRegView; - VDPRegViewer* VDPRegView; - VDPCommandRegViewer* VDPCommandRegView; - BreakpointViewer* bpView; +// DisasmViewer* disasmView; +// MainMemoryViewer* mainMemoryView; +// CPURegsViewer* regsView; +// FlagsViewer* flagsView; +// StackViewer* stackView; +// SlotViewer* slotView; +// VDPStatusRegViewer* VDPStatusRegView; +// VDPRegViewer* VDPRegView; +// VDPCommandRegViewer* VDPCommandRegView; +// BreakpointViewer* bpView; CommClient& comm; DebugSession* session; @@ -207,7 +209,7 @@ class DebuggerForm : public QMainWindow void executeRun(); void executeStep(); void executeStepOver(); - void executeRunTo(); +// void executeRunTo(); void executeStepOut(); void executeStepBack(); private slots: From b3011f0a3e4535d6d12db86b9b94357d2facc6ee Mon Sep 17 00:00:00 2001 From: David Heremans Date: Wed, 20 Apr 2022 11:06:51 +0200 Subject: [PATCH 07/63] Removed DockableWidget related code --- src/DebuggerForm.cpp | 643 +-------------------- src/DebuggerForm.h | 43 +- src/DockManager.cpp | 89 --- src/DockManager.h | 42 -- src/DockableWidget.cpp | 285 --------- src/DockableWidget.h | 66 --- src/DockableWidgetArea.cpp | 50 -- src/DockableWidgetArea.h | 31 - src/DockableWidgetLayout.cpp | 831 --------------------------- src/DockableWidgetLayout.h | 79 --- src/VramBitMappedView.cpp | 4 - src/blendsplitter/ExpanderCorner.cpp | 2 +- src/node.mk | 3 +- 13 files changed, 9 insertions(+), 2159 deletions(-) delete mode 100644 src/DockManager.cpp delete mode 100644 src/DockManager.h delete mode 100644 src/DockableWidget.cpp delete mode 100644 src/DockableWidget.h delete mode 100644 src/DockableWidgetArea.cpp delete mode 100644 src/DockableWidgetArea.h delete mode 100644 src/DockableWidgetLayout.cpp delete mode 100644 src/DockableWidgetLayout.h diff --git a/src/DebuggerForm.cpp b/src/DebuggerForm.cpp index 3035e7b6..0e6c6146 100644 --- a/src/DebuggerForm.cpp +++ b/src/DebuggerForm.cpp @@ -2,8 +2,6 @@ #include "BitMapViewer.h" #include "TileViewer.h" #include "SpriteViewer.h" -#include "DockableWidgetArea.h" -#include "DockableWidget.h" #include "DisasmViewer.h" #include "MainMemoryViewer.h" #include "CPURegsViewer.h" @@ -101,7 +99,6 @@ class CPURegRequest : public ReadDebugBlockCommand void replyOk(const QString& message) override { copyData(message); -// form.regsView->setData(buf); SignalDispatcher::getDispatcher()->setData(buf); delete this; } @@ -158,11 +155,6 @@ DebuggerForm::DebuggerForm(QWidget* parent) : QMainWindow(parent) , comm(CommClient::instance()),enableWidgetStatus(false) { - /* - VDPRegView = nullptr; - VDPStatusRegView = nullptr; - VDPCommandRegView = nullptr; - */ session = DebugSession::getDebugSession(); createActions(); @@ -234,52 +226,8 @@ void DebuggerForm::createActions() searchGotoAction = new QAction(tr("&Goto ..."), this); searchGotoAction->setStatusTip(tr("Jump to a specific address or label in the disassembly view")); searchGotoAction->setShortcut(tr("Ctrl+G")); -/* - viewRegistersAction = new QAction(tr("CPU &Registers"), this); - viewRegistersAction->setStatusTip(tr("Toggle the cpu registers display")); - viewRegistersAction->setCheckable(true); - - viewBreakpointsAction = new QAction(tr("Debug &List"), this); - viewBreakpointsAction->setStatusTip(tr("Toggle the breakpoints/watchpoints display")); - viewBreakpointsAction->setCheckable(true); - - viewFlagsAction = new QAction(tr("CPU &Flags"), this); - viewFlagsAction->setStatusTip(tr("Toggle the cpu flags display")); - viewFlagsAction->setCheckable(true); - - viewStackAction = new QAction(tr("Stack"), this); - viewStackAction->setStatusTip(tr("Toggle the stack display")); - viewStackAction->setCheckable(true); - - viewSlotsAction = new QAction(tr("Slots"), this); - viewSlotsAction->setStatusTip(tr("Toggle the slots display")); - viewSlotsAction->setCheckable(true); - - viewMemoryAction = new QAction(tr("Memory"), this); - viewMemoryAction->setStatusTip(tr("Toggle the main memory display")); - viewMemoryAction->setCheckable(true); - - viewDebuggableViewerAction = new QAction(tr("Add debuggable viewer"), this); - viewDebuggableViewerAction->setStatusTip(tr("Add a hex viewer for debuggables")); - - viewVDPStatusRegsAction = new QAction(tr("Status Registers"), this); - viewVDPStatusRegsAction->setStatusTip(tr("The VDP status registers interpreted")); - viewVDPStatusRegsAction->setCheckable(true); - viewVDPCommandRegsAction = new QAction(tr("Command Registers"), this); - viewVDPCommandRegsAction->setStatusTip(tr("Interact with the VDP command registers")); - viewVDPCommandRegsAction->setCheckable(true); - viewVDPRegsAction = new QAction(tr("Registers"), this); - viewVDPRegsAction->setStatusTip(tr("Interact with the VDP registers")); - viewVDPRegsAction->setCheckable(true); - viewBitMappedAction = new QAction(tr("Bitmapped VRAM"), this); - viewBitMappedAction->setStatusTip(tr("Decode VRAM as screen 5/6/7/8 image")); - //viewBitMappedAction->setCheckable(true); - viewCharMappedAction = new QAction(tr("Tiles in VRAM"), this); - viewCharMappedAction->setStatusTip(tr("Decode VRAM as MSX1 screen tiles")); - viewSpritesAction = new QAction(tr("Sprites in VRAM"), this); - viewSpritesAction->setStatusTip(tr("Decode sprites tiles")); -*/ - executeBreakAction = new QAction(tr("Break"), this); + + executeBreakAction = new QAction(tr("Break"), this); executeBreakAction->setShortcut(tr("CRTL+B")); executeBreakAction->setStatusTip(tr("Halt the execution and enter debug mode")); executeBreakAction->setIcon(QIcon(":/icons/break.png")); @@ -326,22 +274,6 @@ void DebuggerForm::createActions() executeStepBackAction->setEnabled(false); connect(this, &DebuggerForm::runStateEntered, [this]{ executeStepBackAction->setEnabled(false); }); connect(this, &DebuggerForm::breakStateEntered, [this]{ executeStepBackAction->setEnabled(true); }); -/* - executeRunToAction = new QAction(tr("Run to"), this); - executeRunToAction->setShortcut(tr("F4")); - executeRunToAction->setStatusTip(tr("Resume execution until the selected line is reached")); - executeRunToAction->setIcon(QIcon(":/icons/runto.png")); - executeRunToAction->setEnabled(false); - connect(this, &DebuggerForm::runStateEntered, [this]{ executeRunToAction->setEnabled(false); }); - connect(this, &DebuggerForm::breakStateEntered, [this]{ executeRunToAction->setEnabled(true); }); -*/ - -// breakpointToggleAction = new QAction(tr("Toggle"), this); - //now that we have possible multiple disasmviewers the disasmview->getCursorAddr() will not work anymore -// breakpointToggleAction->setShortcut(tr("F5")); -// breakpointToggleAction->setStatusTip(tr("Toggle breakpoint on/off at cursor")); -// breakpointToggleAction->setIcon(QIcon(":/icons/break.png")); -// breakpointToggleAction->setEnabled(false); breakpointAddAction = new QAction(tr("Add ..."), this); //now that we have possible multiple disasmviewers the disasmview->getCursorAddr() will not work anymore @@ -350,7 +282,6 @@ void DebuggerForm::createActions() // breakpointAddAction->setEnabled(false); helpAboutAction = new QAction(tr("&About"), this); -// executeRunToAction->setStatusTip(tr("Show the application information")); addVDPRegsWorkspaceAction = new QAction(tr("VDP &Regs"), this); addVDPRegsWorkspaceAction->setStatusTip(tr("Show the regular VDP registers")); @@ -380,28 +311,13 @@ void DebuggerForm::createActions() connect(systemSymbolManagerAction, &QAction::triggered, this, &DebuggerForm::systemSymbolManager); connect(systemPreferencesAction, &QAction::triggered, this, &DebuggerForm::systemPreferences); connect(searchGotoAction, &QAction::triggered, this, &DebuggerForm::searchGoto); -/* connect(viewRegistersAction, &QAction::triggered, this, &DebuggerForm::toggleRegisterDisplay); - connect(viewBreakpointsAction, &QAction::triggered, this, &DebuggerForm::toggleBreakpointsDisplay); - connect(viewFlagsAction, &QAction::triggered, this, &DebuggerForm::toggleFlagsDisplay); - connect(viewStackAction, &QAction::triggered, this, &DebuggerForm::toggleStackDisplay); - connect(viewSlotsAction, &QAction::triggered, this, &DebuggerForm::toggleSlotsDisplay); - connect(viewMemoryAction, &QAction::triggered, this, &DebuggerForm::toggleMemoryDisplay); - connect(viewDebuggableViewerAction, &QAction::triggered, this, &DebuggerForm::addDebuggableViewer); - connect(viewBitMappedAction, &QAction::triggered, this, &DebuggerForm::toggleBitMappedDisplay); - connect(viewCharMappedAction, &QAction::triggered, this, &DebuggerForm::toggleCharMappedDisplay); - connect(viewSpritesAction, &QAction::triggered, this, &DebuggerForm::toggleSpritesDisplay); - connect(viewVDPRegsAction, &QAction::triggered, this, &DebuggerForm::toggleVDPRegsDisplay); - connect(viewVDPCommandRegsAction, &QAction::triggered, this, &DebuggerForm::toggleVDPCommandRegsDisplay); - connect(viewVDPStatusRegsAction, &QAction::triggered, this, &DebuggerForm::toggleVDPStatusRegsDisplay); -*/ connect(executeBreakAction, &QAction::triggered, this, &DebuggerForm::executeBreak); + + connect(executeBreakAction, &QAction::triggered, this, &DebuggerForm::executeBreak); connect(executeRunAction, &QAction::triggered, this, &DebuggerForm::executeRun); connect(executeStepAction, &QAction::triggered, this, &DebuggerForm::executeStep); connect(executeStepOverAction, &QAction::triggered, this, &DebuggerForm::executeStepOver); - //connect(executeRunToAction, &QAction::triggered, this, &DebuggerForm::executeRunTo); connect(executeStepOutAction, &QAction::triggered, this, &DebuggerForm::executeStepOut); connect(executeStepBackAction, &QAction::triggered, this, &DebuggerForm::executeStepBack); - //connect(breakpointToggleAction, &QAction::triggered, this, &DebuggerForm::toggleBreakpoint); - //connect(breakpointAddAction, &QAction::triggered, this, &DebuggerForm::addBreakpoint); connect(helpAboutAction, &QAction::triggered, this, &DebuggerForm::showAbout); connect(addVDPRegsWorkspaceAction, &QAction::triggered, this, &DebuggerForm::addVDPRegsWorkspace); connect(addVDPTilesWorkspaceAction, &QAction::triggered, this, &DebuggerForm::addVDPTilesWorkspace); @@ -443,33 +359,6 @@ void DebuggerForm::createMenus() searchMenu = menuBar()->addMenu(tr("Se&arch")); searchMenu->addAction(searchGotoAction); - /* - // create view menu - viewMenu = menuBar()->addMenu(tr("&View")); - viewMenu->addAction(viewRegistersAction); - viewMenu->addAction(viewFlagsAction); - viewMenu->addAction(viewStackAction); - viewMenu->addAction(viewSlotsAction); - viewMenu->addAction(viewMemoryAction); - viewMenu->addAction(viewBreakpointsAction); - viewVDPDialogsMenu = viewMenu->addMenu("VDP"); - viewMenu->addSeparator(); - viewFloatingWidgetsMenu = viewMenu->addMenu("Floating widgets:"); - viewMenu->addAction(viewDebuggableViewerAction); - connect(viewMenu, &QMenu::aboutToShow, this, &DebuggerForm::updateViewMenu); - - // create VDP dialogs menu - viewVDPDialogsMenu->addAction(viewVDPRegsAction); - viewVDPDialogsMenu->addAction(viewVDPCommandRegsAction); - viewVDPDialogsMenu->addAction(viewVDPStatusRegsAction); - viewVDPDialogsMenu->addAction(viewBitMappedAction); - viewVDPDialogsMenu->addAction(viewCharMappedAction); - viewVDPDialogsMenu->addAction(viewSpritesAction); - connect(viewVDPDialogsMenu, &QMenu::aboutToShow, this, &DebuggerForm::updateVDPViewMenu); - - // create Debuggable Viewers menu (so the user can focus an existing one) - connect(viewFloatingWidgetsMenu, &QMenu::aboutToShow, this, &DebuggerForm::updateViewFloatingWidgetsMenu); -*/ // create execute menu executeMenu = menuBar()->addMenu(tr("&Execute")); executeMenu->addAction(executeBreakAction); @@ -479,7 +368,6 @@ void DebuggerForm::createMenus() executeMenu->addAction(executeStepOverAction); executeMenu->addAction(executeStepOutAction); executeMenu->addAction(executeStepBackAction); - //executeMenu->addAction(executeRunToAction); // create breakpoint menu breakpointMenu = menuBar()->addMenu(tr("&Breakpoint")); @@ -738,30 +626,14 @@ void DebuggerForm::createForm() btn->setIcon(icon); btn->setMenu(workspacemenu); btn->setPopupMode(QToolButton::InstantPopup); - //connect(btn, &QAbstractButton::clicked, this, &App::OpenNewTab); workspaces->setCornerWidget(btn, Qt::TopRightCorner); connect(workspaces,&QTabWidget::tabCloseRequested,this,&DebuggerForm::tabCloseRequest); - /* - mainArea = new DockableWidgetArea(); - dockMan.addDockArea(mainArea); - */ - QWidget *window = new QWidget; QVBoxLayout *layout = new QVBoxLayout; - /* - QSplitter *cpusplit=new QSplitter(); - cpusplit->addWidget(workspaces); - cpusplit->addWidget(mainArea); - cpusplit->setChildrenCollapsible(true); - layout->addWidget(cpusplit); - */ - //only splitter now layout->addWidget(workspaces); - window->setLayout(layout); -// workspaces->addTab(mainArea,"mainArea"); workspaces->addTab(createWorkspaceCPU(),"CPU"); addVDPRegsWorkspace(); addVDPTilesWorkspace(); @@ -780,214 +652,15 @@ void DebuggerForm::createForm() SignalDispatcher::getDispatcher(), SIGNAL(debuggablesChanged(const QMap&)) ); connect(this, &DebuggerForm::breakpointsUpdated, SignalDispatcher::getDispatcher(), &SignalDispatcher::breakpointsUpdated); - /* - - // Create main widgets and append them to the list first - auto* dw = new DockableWidget(dockMan); - // create the disasm viewer widget - disasmView = new DisasmViewer(); - dw->setWidget(disasmView); - dw->setTitle(tr("Code view")); - dw->setId("CODEVIEW"); - dw->setFloating(false); - dw->setDestroyable(false); - dw->setMovable(false); - dw->setClosable(false); - connect(dw, &DockableWidget::visibilityChanged, this, &DebuggerForm::dockWidgetVisibilityChanged); - - // create the memory view widget - mainMemoryView = new MainMemoryViewer(); - dw = new DockableWidget(dockMan); - dw->setWidget(mainMemoryView); - dw->setTitle(tr("Main memory")); - dw->setId("MEMORY"); - dw->setFloating(false); - dw->setDestroyable(false); - dw->setMovable(true); - dw->setClosable(true); - connect(dw, &DockableWidget::visibilityChanged, this, &DebuggerForm::dockWidgetVisibilityChanged); - - // create register viewer - regsView = new CPURegsViewer(); - dw = new DockableWidget(dockMan); - dw->setWidget(regsView); - dw->setTitle(tr("CPU registers")); - dw->setId("REGISTERS"); - dw->setFloating(false); - dw->setDestroyable(false); - dw->setMovable(true); - dw->setClosable(true); - connect(dw, &DockableWidget::visibilityChanged, this, &DebuggerForm::dockWidgetVisibilityChanged); - - // create flags viewer - flagsView = new FlagsViewer(); - dw = new DockableWidget(dockMan); - dw->setWidget(flagsView); - dw->setTitle(tr("Flags")); - dw->setId("FLAGS"); - dw->setFloating(false); - dw->setDestroyable(false); - dw->setMovable(true); - dw->setClosable(true); - connect(dw, &DockableWidget::visibilityChanged, this, &DebuggerForm::dockWidgetVisibilityChanged); - - // create stack viewer - stackView = new StackViewer(); - dw = new DockableWidget(dockMan); - dw->setWidget(stackView); - dw->setTitle(tr("Stack")); - dw->setId("STACK"); - dw->setFloating(false); - dw->setDestroyable(false); - dw->setMovable(true); - dw->setClosable(true); - connect(dw, &DockableWidget::visibilityChanged, this, &DebuggerForm::dockWidgetVisibilityChanged); - - // create slot viewer - slotView = new SlotViewer(); - dw = new DockableWidget(dockMan); - dw->setWidget(slotView); - dw->setTitle(tr("Memory layout")); - dw->setId("SLOTS"); - dw->setFloating(false); - dw->setDestroyable(false); - dw->setMovable(true); - dw->setClosable(true); - connect(dw, &DockableWidget::visibilityChanged, this, &DebuggerForm::dockWidgetVisibilityChanged); - - // create breakpoints viewer - bpView = new BreakpointViewer(this); - dw = new DockableWidget(dockMan); - dw->setWidget(bpView); - dw->setTitle(tr("Debug list")); - dw->setId("DEBUG"); - dw->setFloating(false); - dw->setDestroyable(false); - dw->setMovable(true); - dw->setClosable(true); - connect(dw, &DockableWidget::visibilityChanged, this, &DebuggerForm::dockWidgetVisibilityChanged); - - // restore layout - restoreGeometry(Settings::get().value("Layout/WindowGeometry", saveGeometry()).toByteArray()); - - QStringList list = Settings::get().value("Layout/WidgetLayout").toStringList(); - // defaults needed? - if (list.empty() || !list.at(0).startsWith("CODEVIEW ")) { - list.clear(); - list.append("CODEVIEW D V R 0 -1 -1"); - list.append("REGISTERS D V R 0 -1 -1"); - list.append("FLAGS D V R 0 -1 -1"); - int regW = dockMan.findDockableWidget("REGISTERS")->sizeHint().width(); - int regH = dockMan.findDockableWidget("REGISTERS")->sizeHint().height(); - list.append(QString("SLOTS D V R 0 -1 %1").arg(regH)); - int codeW = dockMan.findDockableWidget("CODEVIEW")->sizeHint().width(); - int codeH = dockMan.findDockableWidget("CODEVIEW")->sizeHint().height(); - int flagW = dockMan.findDockableWidget("FLAGS")->sizeHint().width(); - int slotW = dockMan.findDockableWidget("SLOTS")->sizeHint().width(); - list.append(QString("STACK D V R 0 -1 %1").arg(codeH)); - list.append(QString("MEMORY D V B %1 %2 %3").arg(codeW) - .arg(regW + flagW + slotW) - .arg(codeH - regH)); - int stackW = dockMan.findDockableWidget("STACK")->sizeHint().width(); - list.append(QString("DEBUG D V B %1 %2 -1").arg(codeW) - .arg(regW + flagW + slotW + stackW)); - } - - // add widgets - for (int i = 0; i < list.size(); ++i) { - QStringList s = list.at(i).split(" ", Qt::SplitBehaviorFlags::SkipEmptyParts); - // get widget - if ((dw = dockMan.findDockableWidget(s.at(0)))) { - if (s.at(1) == "D") { - // dock widget - DockableWidgetLayout::DockSide side; - if (s.at(3) == "T") { - side = DockableWidgetLayout::TOP; - } else if (s.at(3) == "L") { - side = DockableWidgetLayout::LEFT; - } else if (s.at(3) == "R") { - side = DockableWidgetLayout::RIGHT; - } else { - side = DockableWidgetLayout::BOTTOM; - } - dockMan.insertWidget(dw, 0, side, s.at(4).toInt(), - s.at(5).toInt(), s.at(6).toInt()); - if (s.at(2) == "H") dw->hide(); - } else if (s.at(1) == "F") { - // float widget - dw->setFloating(true, s.at(2) == "V"); - dw->resize(s.at(5).toInt(), s.at(6).toInt()); - dw->move (s.at(3).toInt(), s.at(4).toInt()); - } - } - } - - */ - // disable all widgets connectionClosed(); -/* - // Disasm viewer - //split in 2 below: connect(disasmView, &DisasmViewer::breakpointToggled, this, &DebuggerForm::toggleBreakpoint); - connect(disasmView,SIGNAL(breakpointToggled(uint16_t)), SignalDispatcher::getDispatcher(), SIGNAL(breakpointToggled(uint16_t))); - connect(SignalDispatcher::getDispatcher(), SIGNAL(breakpointToggled(uint16_t)), this, SLOT(toggleBreakpoint(uint16_t))); - //in DebuggerForm::processBreakpoints bo direct call to update() anymore - connect(SignalDispatcher::getDispatcher(), SIGNAL(breakpointsUpdated()), disasmView, SLOT(update())); - - //split in 2 below:connect(this, &DebuggerForm::symbolsChanged, disasmView, &DisasmViewer::refresh); - connect(this, SIGNAL(symbolsChanged()), SignalDispatcher::getDispatcher(), SIGNAL(symbolsChanged()) ); - connect(SignalDispatcher::getDispatcher(), SIGNAL(symbolsChanged()), disasmView, SLOT(refresh())); - - //split in 2 below:connect(this, &DebuggerForm::settingsChanged, disasmView, &DisasmViewer::updateLayout); - connect(this, SIGNAL(settingsChanged()), SignalDispatcher::getDispatcher(), SIGNAL(settingsChanged()) ); - connect(SignalDispatcher::getDispatcher(), SIGNAL(settingsChanged()), disasmView, SLOT(updateLayout())); - - // Main memory viewer - connect(this, &DebuggerForm::connected, mainMemoryView, &MainMemoryViewer::refresh); - connect(this, &DebuggerForm::breakStateEntered, mainMemoryView, &MainMemoryViewer::refresh); - - // Slot viewer - connect(this, &DebuggerForm::connected, slotView, &SlotViewer::refresh); - connect(this, &DebuggerForm::breakStateEntered, slotView, &SlotViewer::refresh); - // Received status update back from widget after breakStateEntered/connected - connect(slotView, &SlotViewer::slotsUpdated, this, &DebuggerForm::onSlotsUpdated); - - // Breakpoint viewer - connect(this, &DebuggerForm::breakpointsUpdated, bpView, &BreakpointViewer::sync); - connect(this, &DebuggerForm::runStateEntered, bpView, &BreakpointViewer::setRunState); - connect(this, &DebuggerForm::breakStateEntered, bpView, &BreakpointViewer::setBreakState); - connect(bpView, &BreakpointViewer::contentsUpdated, this, &DebuggerForm::reloadBreakpoints); - - // CPU regs viewer - // Hook up the register viewer with the main memory viewer - connect(regsView, &CPURegsViewer::registerChanged, mainMemoryView, &MainMemoryViewer::registerChanged); - connect(regsView, &CPURegsViewer::flagsChanged, flagsView, &FlagsViewer::setFlags); - connect(regsView, &CPURegsViewer::spChanged, stackView, &StackViewer::setStackPointer); - // Received status update back from widgets after update - connect(regsView, &CPURegsViewer::pcChanged, this, &DebuggerForm::onPCChanged); - - */ connect(&comm, &CommClient::connectionReady, this, &DebuggerForm::initConnection); connect(&comm, &CommClient::updateParsed, this, &DebuggerForm::handleUpdate); connect(&comm, &CommClient::connectionTerminated, this, &DebuggerForm::connectionClosed); - - session->breakpoints().setMemoryLayout(SignalDispatcher::getDispatcher()->getMemLayout()); -/* - disasmView->setMemory(SignalDispatcher::getDispatcher()->getMainMemory()); - disasmView->setBreakpoints(&session->breakpoints()); - disasmView->setMemoryLayout(SignalDispatcher::getDispatcher()->getMemLayout()); - disasmView->setSymbolTable(&session->symbolTable()); -// mainMemoryView->setRegsView(regsView); - mainMemoryView->setSymbolTable(&session->symbolTable()); - mainMemoryView->setDebuggable("memory", 65536); - stackView->setData(SignalDispatcher::getDispatcher()->getMainMemory(), 65536); - slotView->setMemoryLayout(SignalDispatcher::getDispatcher()->getMemLayout()); - bpView->setBreakpoints(&session->breakpoints()); -*/ } QWidget *DebuggerForm::widgetFactory(factoryclasses fctwidget) @@ -1109,28 +782,6 @@ void DebuggerForm::closeEvent(QCloseEvent* e) // store layout Settings::get().setValue("Layout/WindowGeometry", saveGeometry()); - QStringList layoutList; - // fill layout list with docked widgets - /* - dockMan.getConfig(0, layoutList); - // append floating widgets - for (auto* widget : dockMan.managedWidgets()) { - if (widget->isFloating()) { - QString s("%1 F %2 %3 %4 %5 %6"); - s = s.arg(widget->id()); - if (widget->isHidden()) { - s = s.arg("H"); - } else { - s = s.arg("V"); - } - s = s.arg(widget->x()).arg(widget->y()) - .arg(widget->width()).arg(widget->height()); - layoutList.append(s); - } - widget->hide(); - } - Settings::get().setValue("Layout/WidgetLayout", layoutList); - */ QMainWindow::closeEvent(e); } @@ -1276,22 +927,10 @@ void DebuggerForm::connectionClosed() executeStepOverAction->setEnabled(false); executeStepOutAction->setEnabled(false); executeStepBackAction->setEnabled(false); -// executeRunToAction->setEnabled(false); systemDisconnectAction->setEnabled(false); systemConnectAction->setEnabled(true); -// breakpointToggleAction->setEnabled(false); breakpointAddAction->setEnabled(false); - /* - for (auto* w : dockMan.managedWidgets()) { - w->widget()->setEnabled(false); - } - */ -// replaced by signal from SignalDispatcher -// QList allSwitchItems= this->findChildren(); -// foreach(SwitchingWidget* wdgt,allSwitchItems){ -// wdgt->setEnableWidget(false); -// } enableWidgetStatus=false; emit SignalDispatcher::getDispatcher()->enableWidget(false); } @@ -1300,7 +939,6 @@ void DebuggerForm::finalizeConnection(bool halted) { systemPauseAction->setEnabled(true); systemRebootAction->setEnabled(true); -// breakpointToggleAction->setEnabled(true); breakpointAddAction->setEnabled(true); // merge breakpoints on connect mergeBreakpoints = true; @@ -1312,16 +950,7 @@ void DebuggerForm::finalizeConnection(bool halted) } emit connected(); - /* - for (auto* w : dockMan.managedWidgets()) { - w->widget()->setEnabled(true); - } - */ -// replaced by signal from SignalDispatcher -// QList allSwitchItems= this->findChildren(); -// foreach(SwitchingWidget* wdgt,allSwitchItems){ -// wdgt->setEnableWidget(true); -// } + enableWidgetStatus=true; emit SignalDispatcher::getDispatcher()->enableWidget(true); } @@ -1537,13 +1166,6 @@ void DebuggerForm::executeStepOver() setRunMode(); } -//void DebuggerForm::executeRunTo() -//{ -// comm.sendCommand(new SimpleCommand( -// "run_to " + QString::number(disasmView->cursorAddress()))); -// setRunMode(); -//} - void DebuggerForm::executeStepOut() { comm.sendCommand(new SimpleCommand("step_out")); @@ -1598,261 +1220,6 @@ void DebuggerForm::showAbout() QMessageBox::about( this, "openMSX Debugger", QString(Version::full().c_str())); } -/* -void DebuggerForm::toggleBreakpointsDisplay() -{ - toggleView(qobject_cast(bpView->parentWidget())); -} - -void DebuggerForm::toggleRegisterDisplay() -{ - toggleView(qobject_cast(regsView->parentWidget())); -} - -void DebuggerForm::toggleFlagsDisplay() -{ - toggleView(qobject_cast(flagsView->parentWidget())); -} - -void DebuggerForm::toggleStackDisplay() -{ - toggleView(qobject_cast(stackView->parentWidget())); -} - -void DebuggerForm::toggleSlotsDisplay() -{ - toggleView(qobject_cast(slotView->parentWidget())); -} -*/ - - /* -void DebuggerForm::toggleBitMappedDisplay() -{ - //toggleView(qobject_cast(slotView->parentWidget())); - // not sure if this a good idea for a docable widget - - // create new debuggable viewer window - auto* viewer = new BitMapViewer(); - auto* dw = new DockableWidget(dockMan); - dw->setWidget(viewer); - dw->setTitle(tr("Bitmapped VRAM View")); - dw->setId("BITMAPVRAMVIEW"); - dw->setFloating(true); - dw->setDestroyable(true); - dw->setMovable(true); - dw->setClosable(true); - */ - /* - connect(dw, SIGNAL(visibilityChanged(DockableWidget*)), - this, SLOT(dockWidgetVisibilityChanged(DockableWidget*))); - connect(this, SIGNAL(debuggablesChanged(const QMap&)), - viewer, SLOT(setDebuggables(const QMap&))); - */ - - /* - // TODO: refresh should be being hanled by VDPDataStore... - connect(this, SIGNAL(breakStateEntered()), viewer, SLOT(refresh())); - */ - - /* - viewer->setDebuggables(debuggables); - viewer->setEnabled(disasmView->isEnabled()); - */ - /* -} - */ - -/* -void DebuggerForm::toggleCharMappedDisplay() -{ - //toggleView(qobject_cast(slotView->parentWidget())); - // not sure if this a good idea for a docable widget - - // create new debuggable viewer window - auto* viewer = new TileViewer(); - // viewer->adjustSize(); - auto* dw = new DockableWidget(dockMan); - dw->setWidget(viewer); - dw->setTitle(tr("Tile VRAM View")); - dw->setId("CHARMAPVRAMVIEW"); - dw->setFloating(true); - dw->setDestroyable(true); - dw->setMovable(true); - dw->setClosable(true); - // dw->adjustSize(); - - // TODO: refresh should be being hanled by VDPDataStore... - connect(this, SIGNAL(breakStateEntered()), viewer, SLOT(refresh())); -} - -void DebuggerForm::toggleSpritesDisplay() -{ - //toggleView(qobject_cast(slotView->parentWidget())); - // not sure if this a good idea for a docable widget - - // create new debuggable viewer window - auto* viewer = new SpriteViewer(); - auto* dw = new DockableWidget(dockMan); - dw->setWidget(viewer); - dw->setTitle(tr("Sprites View")); - dw->setId("SPRITESVRAMVIEW"); - dw->setFloating(true); - dw->setDestroyable(true); - dw->setMovable(true); - dw->setClosable(true); - - // TODO: refresh should be being hanled by VDPDataStore... - connect(this, SIGNAL(breakStateEntered()), viewer, SLOT(refresh())); -} - -void DebuggerForm::toggleVDPCommandRegsDisplay() -{ - if (VDPCommandRegView == nullptr) { - VDPCommandRegView = new VDPCommandRegViewer(); - auto* dw = new DockableWidget(dockMan); - dw->setWidget(VDPCommandRegView); - dw->setTitle(tr("VDP registers view")); - dw->setId("VDPCommandRegView"); - dw->setFloating(true); - dw->setDestroyable(false); - dw->setMovable(true); - dw->setClosable(true); - connect(this, SIGNAL(breakStateEntered()), - VDPCommandRegView, SLOT(refresh())); - } else { - toggleView(qobject_cast(VDPCommandRegView->parentWidget())); - } -} - -void DebuggerForm::toggleVDPRegsDisplay() -{ - if (VDPRegView == nullptr) { - VDPRegView = new VDPRegViewer(); - auto* dw = new DockableWidget(dockMan); - dw->setWidget(VDPRegView); - dw->setTitle(tr("VDP registers view")); - dw->setId("VDPREGVIEW"); - dw->setFloating(true); - dw->setDestroyable(false); - dw->setMovable(true); - dw->setClosable(true); - connect(this, SIGNAL(breakStateEntered()), - VDPRegView, SLOT(refresh())); - } else { - toggleView(qobject_cast(VDPRegView->parentWidget())); - } -} - -void DebuggerForm::toggleVDPStatusRegsDisplay() -{ - if (VDPStatusRegView == nullptr) { - VDPStatusRegView = new VDPStatusRegViewer(); - auto* dw = new DockableWidget(dockMan); - dw->setWidget(VDPStatusRegView); - dw->setTitle(tr("VDP status registers view")); - dw->setId("VDPSTATUSREGVIEW"); - dw->setFloating(true); - dw->setDestroyable(false); - dw->setMovable(true); - dw->setClosable(true); - connect(this, SIGNAL(breakStateEntered()), - VDPStatusRegView, SLOT(refresh())); - } else { - toggleView(qobject_cast(VDPStatusRegView->parentWidget())); - } -} - -void DebuggerForm::toggleMemoryDisplay() -{ - toggleView(qobject_cast(mainMemoryView->parentWidget())); -} - -void DebuggerForm::toggleView(DockableWidget* widget) -{ - if (widget->isHidden()) { - widget->show(); - } else { - widget->hide(); - } - dockMan.visibilityChanged(widget); -} - -void DebuggerForm::addDebuggableViewer() -{ - // create new debuggable viewer window - auto* viewer = new DebuggableViewer(); - auto* dw = new DockableWidget(dockMan); - dw->setWidget(viewer); - dw->setTitle(tr("Debuggable hex view")); - dw->setId("DEBUGVIEW-" + QString::number(++counter)); - dw->setFloating(true); - dw->setDestroyable(true); - dw->setMovable(true); - dw->setClosable(true); - connect(dw, SIGNAL(visibilityChanged(DockableWidget*)), - this, SLOT(dockWidgetVisibilityChanged(DockableWidget*))); - connect(this, SIGNAL(debuggablesChanged(const QMap&)), - viewer, SLOT(setDebuggables(const QMap&))); - connect(this, SIGNAL(breakStateEntered()), - viewer, SLOT(refresh())); - viewer->setDebuggables(debuggables); - viewer->setEnabled(disasmView->isEnabled()); -} - -void DebuggerForm::showFloatingWidget() -{ - QObject * s = sender(); - QString widget_id = s->property("widget_id").toString(); - DockableWidget* w = dockMan.findDockableWidget(widget_id); - w->show(); - w->activateWindow(); - w->raise(); -} - -void DebuggerForm::dockWidgetVisibilityChanged(DockableWidget* w) -{ - dockMan.visibilityChanged(w); - updateViewMenu(); -} - -void DebuggerForm::updateViewMenu() -{ - viewRegistersAction->setChecked(regsView->parentWidget()->isVisible()); - viewFlagsAction->setChecked(flagsView->isVisible()); - viewStackAction->setChecked(stackView->isVisible()); - viewSlotsAction->setChecked(slotView->isVisible()); - viewMemoryAction->setChecked(mainMemoryView->isVisible()); - viewBreakpointsAction->setChecked(bpView->isVisible()); -} - -void DebuggerForm::updateVDPViewMenu() -{ - if (VDPCommandRegView) { - viewVDPCommandRegsAction->setChecked(VDPCommandRegView->isVisible()); - } - if (VDPRegView) { - viewVDPRegsAction->setChecked(VDPRegView->isVisible()); - } - if (VDPStatusRegView) { - viewVDPStatusRegsAction->setChecked(VDPStatusRegView->isVisible()); - } -} - -void DebuggerForm::updateViewFloatingWidgetsMenu() -{ - viewFloatingWidgetsMenu->clear(); - for (auto* w : dockMan.managedWidgets()) { - if (w->isFloating()) { - // Build up the window title - auto* action = new QAction(w->title()); - // Set the widget_id as a property on the menu item action, so we can read it out later again via sender() on the receiving functor - action->setProperty("widget_id", w->id()); - connect(action, &QAction::triggered, this, &DebuggerForm::showFloatingWidget); - viewFloatingWidgetsMenu->addAction(action); - } - } -} -*/ void DebuggerForm::setDebuggables(const QString& list) { diff --git a/src/DebuggerForm.h b/src/DebuggerForm.h index 42fbf9aa..642314e6 100644 --- a/src/DebuggerForm.h +++ b/src/DebuggerForm.h @@ -1,12 +1,10 @@ #ifndef DEBUGGERFORM_H #define DEBUGGERFORM_H -#include "DockManager.h" #include "DebugSession.h" #include #include -class DockableWidgetArea; class DisasmViewer; class MainMemoryViewer; class CPURegsViewer; @@ -88,12 +86,8 @@ class DebuggerForm : public QMainWindow QMenu* fileMenu; QMenu* systemMenu; QMenu* searchMenu; - /* - QMenu* viewMenu; - QMenu* viewVDPDialogsMenu; - QMenu* viewFloatingWidgetsMenu; - */ - QMenu* executeMenu; + + QMenu* executeMenu; QMenu* breakpointMenu; QMenu* helpMenu; @@ -118,31 +112,13 @@ class DebuggerForm : public QMainWindow QAction* systemPreferencesAction; QAction* searchGotoAction; -/* - QAction* viewRegistersAction; - QAction* viewFlagsAction; - QAction* viewStackAction; - QAction* viewSlotsAction; - QAction* viewMemoryAction; - QAction* viewBreakpointsAction; - QAction* viewDebuggableViewerAction; - - QAction* viewBitMappedAction; - QAction* viewCharMappedAction; - QAction* viewSpritesAction; - QAction* viewVDPStatusRegsAction; - QAction* viewVDPRegsAction; - QAction* viewVDPCommandRegsAction; -*/ QAction* executeBreakAction; QAction* executeRunAction; QAction* executeStepAction; QAction* executeStepOverAction; - //QAction* executeRunToAction; QAction* executeStepOutAction; QAction* executeStepBackAction; - //QAction* breakpointToggleAction; QAction* breakpointAddAction; QAction* helpAboutAction; @@ -153,21 +129,8 @@ class DebuggerForm : public QMainWindow QAction* addEmptyWorkspaceAction; QAction* addFloatingSwitchingWidgetAction; -// DockManager dockMan; -// DockableWidgetArea* mainArea; QStringList recentFiles; -// DisasmViewer* disasmView; -// MainMemoryViewer* mainMemoryView; -// CPURegsViewer* regsView; -// FlagsViewer* flagsView; -// StackViewer* stackView; -// SlotViewer* slotView; -// VDPStatusRegViewer* VDPStatusRegView; -// VDPRegViewer* VDPRegView; -// VDPCommandRegViewer* VDPCommandRegView; -// BreakpointViewer* bpView; - CommClient& comm; DebugSession* session; @@ -216,14 +179,12 @@ private slots: void toggleBreakpoint(uint16_t addr); private: void addBreakpoint(uint16_t cursorAddress); - void toggleView(DockableWidget* widget); void initConnection(); void handleUpdate(const QString& type, const QString& name, const QString& message); void setDebuggables(const QString& list); void setDebuggableSize(const QString& debuggable, int size); void connectionClosed(); - void dockWidgetVisibilityChanged(DockableWidget* w); void updateViewMenu(); void updateVDPViewMenu(); void updateViewFloatingWidgetsMenu(); diff --git a/src/DockManager.cpp b/src/DockManager.cpp deleted file mode 100644 index beb371ba..00000000 --- a/src/DockManager.cpp +++ /dev/null @@ -1,89 +0,0 @@ -#include "DockManager.h" -#include "DockableWidget.h" -#include "DockableWidgetArea.h" - - -void DockManager::addDockArea(DockableWidgetArea* area) -{ - if (areas.indexOf(area) == -1) { - areas.append(area); - } -} - -int DockManager::dockAreaIndex(DockableWidgetArea* area) const -{ - return areas.indexOf(area); -} - -void DockManager::dockWidget(DockableWidget* widget, const QPoint& /*p*/, const QRect& r) -{ - auto it = areaMap.begin(); // TODO - if (it != areaMap.end()) { - areaMap[widget] = it.value(); - return it.value()->addWidget(widget, r); - } -} - -void DockManager::undockWidget(DockableWidget* widget) -{ - auto it = areaMap.find(widget); - if (it != areaMap.end()) { - it.value()->removeWidget(widget); - } -} - -void DockManager::insertWidget( - DockableWidget* widget, int index, - DockableWidgetLayout::DockSide side, int distance, int w, int h) -{ - if (index < 0 || index >= areas.size()) return; - - //Q_ASSERT(areaMap.find(widget) == areaMap.end()); - - areas[index]->addWidget(widget, side, distance, w, h); - areaMap[widget] = areas[index]; -} - -bool DockManager::insertLocation(QRect& r, const QSizePolicy& sizePol) -{ - auto it = areaMap.begin(); // TODO - if (it == areaMap.end()) return false; - - return it.value()->insertLocation(r, sizePol); -} - -void DockManager::visibilityChanged(DockableWidget* widget) -{ - auto it = areaMap.find(widget); - if (it != areaMap.end()) { - it.value()->layout->changed(); - } -} - -void DockManager::getConfig(int index, QStringList& list) const -{ - areas[index]->getConfig(list); -} - -void DockManager::attachWidget(DockableWidget* widget) -{ - dockWidgets.append(widget); -} - -void DockManager::detachWidget(DockableWidget* widget) -{ - dockWidgets.removeAll(widget); -} - -const QList& DockManager::managedWidgets() const -{ - return dockWidgets; -} - -DockableWidget* DockManager::findDockableWidget(const QString& id) const -{ - for (auto* w : dockWidgets) { - if (w->id() == id) return w; - } - return nullptr; -} diff --git a/src/DockManager.h b/src/DockManager.h deleted file mode 100644 index 38f1aa77..00000000 --- a/src/DockManager.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef DOCKMANAGER_H -#define DOCKMANAGER_H - -#include "DockableWidgetLayout.h" -#include -#include - -class QRect; -class QPoint; -class DockableWidget; -class DockableWidgetArea; - -class DockManager -{ -public: - void addDockArea(DockableWidgetArea* area); - int dockAreaIndex(DockableWidgetArea* area) const; - - void insertWidget(DockableWidget* widget, int index, - DockableWidgetLayout::DockSide side, int distance, - int w = -1, int h = -1); - void dockWidget(DockableWidget* widget, const QPoint& p, const QRect& r); - void undockWidget(DockableWidget* widget); - - bool insertLocation(QRect& r, const QSizePolicy& sizePol); - - void visibilityChanged(DockableWidget* widget); - void getConfig(int index, QStringList& list) const; - - void attachWidget(DockableWidget* widget); - void detachWidget(DockableWidget* widget); - const QList& managedWidgets() const; - DockableWidget* findDockableWidget(const QString& id) const; - -private: - using AreaMap = QMap; - AreaMap areaMap; - QList areas; - QList dockWidgets; -}; - -#endif // DOCKMANAGER_H diff --git a/src/DockableWidget.cpp b/src/DockableWidget.cpp deleted file mode 100644 index 959b39c3..00000000 --- a/src/DockableWidget.cpp +++ /dev/null @@ -1,285 +0,0 @@ -#include "DockableWidget.h" -#include "DockManager.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -DockableWidget::DockableWidget(DockManager& manager, QWidget* parent) - : QWidget(parent), dockManager(manager) -{ - mainWidget = nullptr; - floating = false; - movable = true; - closable = true; - destroyable = true; - dragging = false; - setAttribute(Qt::WA_DeleteOnClose, true); -#ifdef Q_OS_MAC - // on Mac the FramelessWindowHint hides the SizeGrip - setWindowFlags(Qt::Tool); -#else - setWindowFlags(Qt::FramelessWindowHint | Qt::Tool); -#endif - - titleLabel = new QLabel(); - closeButton = new QToolButton(); - closeButton->setIcon(style()->standardIcon(QStyle::SP_TitleBarCloseButton)); - closeButton->setToolButtonStyle(Qt::ToolButtonIconOnly); - int sz = style()->pixelMetric(QStyle::PM_SmallIconSize); - closeButton->setIconSize(style()->standardIcon( - QStyle::SP_TitleBarCloseButton).actualSize(QSize(sz, sz))); - closeButton->setAutoRaise(true); - connect(closeButton, SIGNAL(clicked()), this, SLOT(close())); - - headerLayout = new QHBoxLayout(); - headerLayout->setMargin(0); - headerLayout->addWidget(titleLabel, 1); - headerLayout->addWidget(closeButton, 0); - - headerWidget = new QWidget(); - headerWidget->setLayout(headerLayout); - - widgetLayout = new QVBoxLayout(); - widgetLayout->setMargin(3); - widgetLayout->setSpacing(1); - widgetLayout->addWidget(headerWidget); - setLayout(widgetLayout); - - dockManager.attachWidget(this); - - rubberBand = new QRubberBand(QRubberBand::Rectangle); -} - -DockableWidget::~DockableWidget() -{ - delete mainWidget; - delete rubberBand; - dockManager.detachWidget(this); -} - -QWidget* DockableWidget::widget() const -{ - return mainWidget; -} - -void DockableWidget::setWidget(QWidget* widget) -{ - if (mainWidget) { - widgetLayout->removeWidget(mainWidget); - delete statusBar; - } - mainWidget = widget; - - if (widget) { - widgetLayout->addWidget(widget, 1); - int minW = sizeHint().width() - widget->sizeHint().width() - + widget->minimumWidth(); - int minH = sizeHint().height() - widget->sizeHint().height() - + widget->minimumHeight(); - int maxW = sizeHint().width() - widget->sizeHint().width() - + widget->maximumWidth(); - int maxH = sizeHint().height() - widget->sizeHint().height() - + widget->maximumHeight(); - maxW = std::min(maxW, QWIDGETSIZE_MAX); - maxH = std::min(maxH, QWIDGETSIZE_MAX); - setMinimumSize(minW, minH); - setMaximumSize(maxW, maxH); - setSizePolicy(widget->sizePolicy()); - - statusBar = new QStatusBar(nullptr); - statusBar->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed)); - statusBar->setVisible(false); - statusBar->setSizeGripEnabled(false); - widgetLayout->addWidget(statusBar, 2); - } -} - -const QString& DockableWidget::id() const -{ - return widgetId; -} - -void DockableWidget::setId(const QString& str) -{ - widgetId = str; -} - -QString DockableWidget::title() const -{ - return windowTitle(); -} - -void DockableWidget::setTitle(const QString& title) -{ - setWindowTitle(title); - titleLabel->setText(title + ':'); -} - -bool DockableWidget::isFloating() const -{ - return floating; -} - -void DockableWidget::setFloating(bool enable, bool showNow) -{ - if (floating == enable) return; - - floating = enable; - - if (mainWidget->sizePolicy().horizontalPolicy() != QSizePolicy::Fixed && - mainWidget->sizePolicy().verticalPolicy() != QSizePolicy::Fixed) { - statusBar->setVisible(floating); - statusBar->setSizeGripEnabled(floating); - } - - if (floating && showNow) { - // force widget to never get behind main window - -#ifdef Q_OS_MAC - // on Mac the FramelessWindowHint hides the SizeGrip - setWindowFlags(Qt::Tool); -#else - setWindowFlags(Qt::FramelessWindowHint | Qt::Tool); -#endif - show(); - } -} - -bool DockableWidget::isMovable() const -{ - return movable; -} - -void DockableWidget::setMovable(bool enable) -{ - movable = enable; -} - -bool DockableWidget::isClosable() const -{ - return closable; -} - -void DockableWidget::setClosable(bool enable) -{ - if (closable == enable) return; - - closable = enable; - if (enable) { - closeButton->show(); - } else { - closeButton->hide(); - } - dragging = false; - rubberBand->hide(); -} - -bool DockableWidget::isDestroyable() const -{ - return destroyable; -} - -void DockableWidget::setDestroyable(bool enable) -{ - destroyable = enable; - setAttribute(Qt::WA_DeleteOnClose, enable); -} - -void DockableWidget::closeEvent(QCloseEvent* event) -{ - if (closable || destroyable) { - if (destroyable && floating) { - dockManager.undockWidget(this); - event->accept(); - } else { - hide(); - event->ignore(); - emit visibilityChanged(this); - } - } else { - event->ignore(); - } -} - -void DockableWidget::mousePressEvent(QMouseEvent* event) -{ - if (movable && event->button() == Qt::LeftButton) { - dragging = true; - dragStart = event->globalPos(); - dragOffset = event->pos(); - } -} - -void DockableWidget::mouseMoveEvent(QMouseEvent* event) -{ - if (!dragging) return; - - if (event->buttons() & Qt::LeftButton) { - // dragging of widget in progress, update rubberband - if (!rubberBand->isVisible()) { - if (abs(event->globalX() - dragStart.x()) > 20 || - abs(event->globalY() - dragStart.y()) > 20) { - rubberBand->resize(width(), height()); - rubberBand->move(event->globalX()-dragOffset.x(), - event->globalY()-dragOffset.y()); - rubberBand->show(); - } - } else { - QRect r(event->globalX()-dragOffset.x(), - event->globalY()-dragOffset.y(), - width(), height()); - if (floating && dockManager.insertLocation(r, sizePolicy())) { - rubberBand->move(r.x(), r.y()); - rubberBand->resize(r.width(), r.height()); - } else { - rubberBand->move(event->globalX()-dragOffset.x(), - event->globalY()-dragOffset.y()); - rubberBand->resize(width(), height()); - } - } - } else { - dragging = false; - rubberBand->hide(); - } -} - -void DockableWidget::mouseReleaseEvent(QMouseEvent* event) -{ - if (!dragging) return; - - dragging = false; - rubberBand->hide(); - - // only do anything if this was a meaningful drag - if (!movable || - (abs(event->globalX() - dragStart.x()) <= 20 && - abs(event->globalY() - dragStart.y()) <= 20)) { - return; - } - - if (floating) { - QRect mouseRect(event->globalX() - dragOffset.x(), - event->globalY() - dragOffset.y(), - width(), height()); - QRect r(mouseRect); - if (dockManager.insertLocation(r, sizePolicy())) { - setFloating(false); - dockManager.dockWidget(this, QPoint(), mouseRect); - } else { - move(event->globalPos() - dragOffset); - } - } else { - dockManager.undockWidget(this); - setFloating(true); - move(event->globalPos() - dragOffset); - } -} diff --git a/src/DockableWidget.h b/src/DockableWidget.h deleted file mode 100644 index d8f18b80..00000000 --- a/src/DockableWidget.h +++ /dev/null @@ -1,66 +0,0 @@ -#ifndef DOCKABLEWIDGET_H -#define DOCKABLEWIDGET_H - -#include -#include - -class QLabel; -class QToolButton; -class QHBoxLayout; -class QVBoxLayout; -class QRubberBand; -class DockManager; -class QStatusBar; - -class DockableWidget : public QWidget -{ - Q_OBJECT -public: - DockableWidget(DockManager& manager, QWidget* parent = nullptr); - ~DockableWidget() override; - - QWidget* widget() const; - void setWidget(QWidget* widget); - const QString& id() const; - void setId(const QString& str); - - QString title() const; - void setTitle(const QString& title); - - bool isFloating() const; - void setFloating(bool enable, bool showNow = true); - bool isMovable() const; - void setMovable(bool enable); - bool isClosable() const; - void setClosable(bool enable); - bool isDestroyable() const; - void setDestroyable(bool enable); - -private: - void mousePressEvent(QMouseEvent* event) override; - void mouseMoveEvent(QMouseEvent* event) override; - void mouseReleaseEvent(QMouseEvent* event) override; - void closeEvent(QCloseEvent* event) override; - - DockManager& dockManager; - QString widgetId; - - bool floating; - bool closable, movable, destroyable; - bool dragging; - QPoint dragStart, dragOffset; - QRubberBand* rubberBand; - - QWidget* mainWidget; - QHBoxLayout* headerLayout; - QVBoxLayout* widgetLayout; - QWidget* headerWidget; - QLabel* titleLabel; - QToolButton* closeButton; - QStatusBar* statusBar; - -signals: - void visibilityChanged(DockableWidget* w); -}; - -#endif // DOCKABLEWIDGET_H diff --git a/src/DockableWidgetArea.cpp b/src/DockableWidgetArea.cpp deleted file mode 100644 index 47a1c478..00000000 --- a/src/DockableWidgetArea.cpp +++ /dev/null @@ -1,50 +0,0 @@ -#include "DockableWidgetArea.h" -#include "DockableWidgetLayout.h" -#include "DockableWidget.h" - -DockableWidgetArea::DockableWidgetArea(QWidget* parent) - : QWidget(parent) -{ - layout = new DockableWidgetLayout(); - setLayout(layout); -} - -void DockableWidgetArea::removeWidget(DockableWidget* widget) -{ - layout->removeWidget(widget); - widget->setParent(nullptr); -} - -void DockableWidgetArea::addWidget(DockableWidget* widget, const QRect& rect) -{ - widget->setParent(this); - QRect r(rect); - r.moveTopLeft(mapFromGlobal(r.topLeft())); - layout->addWidget(widget, r); -} - -void DockableWidgetArea::addWidget( - DockableWidget* widget, DockableWidgetLayout::DockSide side, - int distance, int w, int h) -{ - widget->setParent(this); - layout->addWidget(widget, side, distance, w, h); -} - -void DockableWidgetArea::paintEvent(QPaintEvent* e) -{ - QWidget::paintEvent(e); -} - -bool DockableWidgetArea::insertLocation(QRect& r, const QSizePolicy& sizePol) -{ - r.moveTopLeft(mapFromGlobal(r.topLeft())); - bool ok = layout->insertLocation(r, sizePol); - r.moveTopLeft(mapToGlobal(r.topLeft())); - return ok; -} - -void DockableWidgetArea::getConfig(QStringList& list) -{ - layout->getConfig(list); -} diff --git a/src/DockableWidgetArea.h b/src/DockableWidgetArea.h deleted file mode 100644 index d71aa0c0..00000000 --- a/src/DockableWidgetArea.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef DOCKABLETWIDGETAREA_H -#define DOCKABLETWIDGETAREA_H - -#include "DockableWidgetLayout.h" -#include - -class DockableWidget; -class QPaintEvent; - -class DockableWidgetArea : public QWidget -{ - Q_OBJECT -public: - DockableWidgetArea(QWidget* parent = nullptr); - -private: - void paintEvent(QPaintEvent* e) override; - - void removeWidget(DockableWidget* widget); - void addWidget(DockableWidget* widget, const QRect& rect); - void addWidget(DockableWidget* widget, DockableWidgetLayout::DockSide side, - int distance, int width = -1, int height = -1); - bool insertLocation(QRect& r, const QSizePolicy& sizePol); - void getConfig(QStringList& list); - - DockableWidgetLayout* layout; - - friend class DockManager; -}; - -#endif // DOCKABLETWIDGETAREA_H diff --git a/src/DockableWidgetLayout.cpp b/src/DockableWidgetLayout.cpp deleted file mode 100644 index b499a94b..00000000 --- a/src/DockableWidgetLayout.cpp +++ /dev/null @@ -1,831 +0,0 @@ -#include "DockableWidgetLayout.h" -#include "DockableWidget.h" -#include -#include -#include -#include - -static const int SNAP_DISTANCE = 16; - -DockableWidgetLayout::DockableWidgetLayout(QWidget* parent, int margin, int spacing) - : QLayout(parent) -{ - setMargin(margin); - setSpacing(spacing); - minWidth = minHeight = 0; - maxWidth = maxHeight = 0; -} - -DockableWidgetLayout::DockableWidgetLayout(int spacing) -{ - setSpacing(spacing); - minWidth = minHeight = 0; - maxWidth = maxHeight = 0; -} - -DockableWidgetLayout::~DockableWidgetLayout() -{ - while (!dockedWidgets.empty()) { - DockInfo* info = dockedWidgets.takeFirst(); - delete info->item; - delete info->widget; - delete info; - } -} - -void DockableWidgetLayout::addItem(QLayoutItem* item) -{ - addItem(item, -1); -} - -void DockableWidgetLayout::addItem( - QLayoutItem* item, int index, DockSide side, int dist, int w, int h) -{ - auto* info = new DockInfo(); - info->item = item; - info->widget = qobject_cast(item->widget()); - info->dockSide = side; - info->dockDistance = dist; - info->left = 0; - info->top = 0; - info->width = -1; - info->height = -1; - info->useHintWidth = true; - info->useHintHeight = true; - - if (info->widget->sizePolicy().horizontalPolicy() != QSizePolicy::Fixed && - w > 0) { - info->width = w; - info->useHintWidth = false; - } - if (info->widget->sizePolicy().verticalPolicy() != QSizePolicy::Fixed && - h > 0) { - info->height = h; - info->useHintHeight = false; - } - - // first widget is the resize widget, set initial size - if (dockedWidgets.empty()) { - if (info->width == -1) { - info->width = item->sizeHint().width(); - } - if (info->height == -1) { - info->height = item->sizeHint().height(); - } - info->useHintWidth = false; - info->useHintHeight = false; - } - - for (const auto* w : dockedWidgets) { - Q_ASSERT(w->widget != item->widget()); - } - - if (index > -1 && index < dockedWidgets.size()) { - dockedWidgets.insert(index, info); - } else { - dockedWidgets.append(info); - } - - // recalculate size limits - calcSizeLimits(); -} - -void DockableWidgetLayout::addWidget(DockableWidget* widget, const QRect& rect) -{ - int index; - DockSide side; - QRect r(rect); - if (insertLocation(r, index, side, widget->sizePolicy())) { - DockInfo* d = dockedWidgets.first(); - int dist; - switch (side) { - case TOP: - case BOTTOM: - dist = r.left() - d->left; - break; - case LEFT: - case RIGHT: - dist = r.top() - d->top; - break; - } - widget->show(); - addItem(new QWidgetItem(widget), index, side, dist, - r.width(), r.height()); - update(); - } -} - -void DockableWidgetLayout::addWidget( - DockableWidget* widget, DockSide side, int dist, int w, int h) -{ - // append item at the back - addItem(new QWidgetItem(widget), -1, side, dist, w, h); -} - -void DockableWidgetLayout::changed() -{ - calcSizeLimits(); - update(); -} - -Qt::Orientations DockableWidgetLayout::expandingDirections() const -{ - return Qt::Horizontal | Qt::Vertical; -} - -bool DockableWidgetLayout::hasHeightForWidth() const -{ - return false; -} - -int DockableWidgetLayout::count() const -{ - return dockedWidgets.size(); -} - -QLayoutItem* DockableWidgetLayout::takeAt(int index) -{ - if (index < 0 || index >= dockedWidgets.size()) return nullptr; - - DockInfo* info = dockedWidgets.takeAt(index); - QLayoutItem* item = info->item; - delete info; - - calcSizeLimits(); - return item; -} - -QLayoutItem* DockableWidgetLayout::itemAt(int index) const -{ - if (index < 0 || index >= dockedWidgets.size()) return nullptr; - - return dockedWidgets.at(index)->item; -} - -QSize DockableWidgetLayout::minimumSize() const -{ - return {minWidth, minHeight}; -} - -QSize DockableWidgetLayout::maximumSize() const -{ - return {maxWidth, maxHeight}; -} - -QSize DockableWidgetLayout::sizeHint() const -{ - return {layoutWidth, layoutHeight}; -} - -void DockableWidgetLayout::setGeometry(const QRect& rect) -{ - QLayout::setGeometry(rect); - - // Qt sometimes sets the geometry outside the minimumSize/maximumSize range. :/ - int W = std::clamp(rect.width(), minWidth, maxWidth ); - int H = std::clamp(rect.height(), minHeight, maxHeight); - - // set main widget size - int dx = W - layoutWidth; - int dy = H - layoutHeight; - - if (dx != 0 || dy != 0) { - sizeMove(dx, dy); - calcSizeLimits(); - } - - // resize the widgets - for (auto* d : dockedWidgets) { - if (!d->widget->isHidden()) { - d->item->setGeometry(d->bounds()); - } - } -} - -void DockableWidgetLayout::calcSizeLimits() -{ - if (dockedWidgets.empty()) return; - - // layout with current sizes - doLayout(); - DockInfo* d = dockedWidgets.first(); - - // store current size - int curWidth = d->width; - int curHeight = d->height; - QVector distStore; - for (auto* d : dockedWidgets) { - distStore.push_back(d->dockDistance); - } - - // first check minimum width (blunt method) - for (int i = d->widget->minimumWidth(); i <= curWidth; ++i) { - // trial layout - sizeMove(i - d->width, 0); - doLayout(true); - // restore - d->width = curWidth; - for (int j = 1; j < dockedWidgets.size(); ++j) { - dockedWidgets.at(j)->dockDistance = distStore.at(j); - } - // check result - if (layoutHeight == checkHeight && - layoutWidth - checkWidth == d->width - i) { - break; - } - } - minWidth = checkWidth; - - // first check maximum width (blunt method) - for (int i = d->widget->maximumWidth(); i >= curWidth; --i) { - // trial layout - sizeMove(i - d->width, 0); - doLayout(true); - // restore - d->width = curWidth; - for (int j = 1; j < dockedWidgets.size(); ++j) { - dockedWidgets.at(j)->dockDistance = distStore.at(j); - } - // check result - if (layoutHeight == checkHeight && - layoutWidth - checkWidth == d->width - i) { - break; - } - } - maxWidth = checkWidth; - - // first check minimum height (blunt method) - for (int i = d->widget->minimumHeight(); i <= curHeight; ++i) { - // trial layout - sizeMove(0, i - d->height); - doLayout(true); - // restore - d->height = curHeight; - for (int j = 1; j < dockedWidgets.size(); ++j) { - dockedWidgets.at(j)->dockDistance = distStore.at(j); - } - // check result - if (layoutWidth == checkWidth && - layoutHeight - checkHeight == d->height - i) { - break; - } - } - minHeight = checkHeight; - - // first check maximum width (blunt method) - for (int i = d->widget->maximumHeight(); i >= curHeight; --i) { - // trial layout - sizeMove(0, i - d->height); - doLayout(true); - // restore - d->height = curHeight; - for (int j = 1; j < dockedWidgets.size(); ++j) { - dockedWidgets.at(j)->dockDistance = distStore.at(j); - } - // check result - if (layoutWidth == checkWidth && - layoutHeight - checkHeight == d->height - i) { - break; - } - } - maxHeight = checkHeight; - - // restore layout - doLayout(); -} - -void DockableWidgetLayout::sizeMove(int dx, int dy) -{ - DockInfo* d0 = dockedWidgets.first(); - for (int i = 1; i < dockedWidgets.size(); ++i) { - DockInfo* d = dockedWidgets.at(i); - if (d->dockSide == TOP || d->dockSide == BOTTOM) { - if (d->dockDistance >= d0->width) { - d->dockDistance += dx; - } - } - if (d->dockSide == LEFT || d->dockSide == RIGHT) { - if (d->dockDistance >= d0->height) { - d->dockDistance += dy; - } - } - } - d0->width += dx; - d0->height += dy; -} - -void DockableWidgetLayout::doLayout(bool check) -{ - if (dockedWidgets.empty()) return; - - DockInfo* d = dockedWidgets.first(); - d->left = 0; - d->top = 0; - int W = d->width; - int H = d->height; - - int dx = 0, dy = 0; - for (int i = 1; i < dockedWidgets.size(); ++i) { - d = dockedWidgets[i]; - // only process visible widgets - if (d->widget->isHidden()) { - d->left = -10000; - d->top = -10000; - continue; - } - // determine size - if (d->useHintWidth) { - d->width = d->item->sizeHint().width(); - } - if (d->useHintHeight) { - d->height = d->item->sizeHint().height(); - } - // determine location - switch (d->dockSide) { - case TOP: - d->left = d->dockDistance; - if (d->dockDistance >= W || d->dockDistance+d->width <= 0) { - d->top = H - d->height; - } else { - d->top = -d->height; - } - // adjust position until it doesn't overlap other widgets - for (int j = 1; j < i; ++j) { - DockInfo* d2 = dockedWidgets[j]; - QRect r(d->left, d->top - QWIDGETSIZE_MAX, - d->width, d->height + QWIDGETSIZE_MAX); - if (r.intersects(d2->bounds())) { - d->top = d2->top - d->height; - } - } - break; - case LEFT: - d->top = d->dockDistance; - if (d->dockDistance >= H || d->dockDistance+d->height <= 0) { - d->left = W - d->width; - } else { - d->left = -d->width; - } - // adjust position until it doesn't overlap other widgets - for (int j = 1; j < i; ++j) { - DockInfo* d2 = dockedWidgets[j]; - QRect r(d->left - QWIDGETSIZE_MAX, d->top, - d->width + QWIDGETSIZE_MAX, d->height); - if (r.intersects(d2->bounds())) { - d->left = d2->left - d->width; - } - } - break; - case RIGHT: - d->top = d->dockDistance; - if (d->dockDistance >= H || d->dockDistance+d->height <= 0) { - d->left = 0; - } else { - d->left = W; - } - // adjust position until it doesn't overlap other widgets - for (int j = 1; j < i; ++j) { - DockInfo* d2 = dockedWidgets[j]; - QRect r(d->left, d->top, - d->width + QWIDGETSIZE_MAX, d->height); - if (r.intersects(d2->bounds())) { - d->left = d2->left + d2->width; - } - } - break; - case BOTTOM: - d->left = d->dockDistance; - if (d->dockDistance >= W || d->dockDistance+d->width <= 0) { - d->top = 0; - } else { - d->top = H; - } - // adjust position until it doesn't overlap other widgets - for (int j = 1; j < i; ++j) { - DockInfo* d2 = dockedWidgets[j]; - QRect r(d->left, d->top, - d->width, d->height + QWIDGETSIZE_MAX); - if (r.intersects(d2->bounds())) { - d->top = d2->top + d2->height; - } - } - break; - } - // check negative coordinates - if (d->left < dx) dx = d->left; - if (d->top < dy) dy = d->top; - } - - // translate widgets and calculate size - int& w = check ? checkWidth : layoutWidth; - int& h = check ? checkHeight : layoutHeight; - w = h = 0; - for (auto* d : dockedWidgets) { - if (!d->widget->isHidden()) { - d->left -= dx; - d->top -= dy; - w = std::max(w, d->right()); - h = std::max(h, d->bottom()); - } - } -} - -bool DockableWidgetLayout::overlaysWithFirstNWidgets(const QRect& r, int n) const -{ - for (int i = 0; i < n; ++i) { - if (r.intersects(dockedWidgets[i]->bounds())) { - return true; - } - } - return false; -} - -static bool isClose(int a, int b) -{ - return abs(a - b) < SNAP_DISTANCE; -} - -bool DockableWidgetLayout::insertLocation( - QRect& rect, int& index, DockSide& side, const QSizePolicy& sizePol) -{ - // best insertion data - // Distance is a number that represents the how far - // the insertion rectangle is from the final location. - unsigned bestDistance = 0xFFFFFFFF; - int bestIndex = 0; - DockSide bestSide; - QRect bestRect; - - // loop over all widgets and find appropriate matching sides - for (int i = 0; i < dockedWidgets.size(); ++i) { - DockInfo* d = dockedWidgets[i]; - /***************************************************** - * Check for placement against the top of the widget * - *****************************************************/ - if (i == 0 || d->dockSide != BOTTOM) { - if (!(rect.left() > d->right() - SNAP_DISTANCE || - rect.right() < d->left + SNAP_DISTANCE) && - isClose(rect.bottom(), d->top)) { - // rectangle is close to the edge - unsigned dist = 8 * abs(rect.bottom() - d->top); - // now find all points on this side - // (use set as a sorted unique list) - QSet sidePoints; - for (int j = 0; j <= i; ++j) { - DockInfo* d2 = dockedWidgets[j]; - if (d->top == d2->top) { - sidePoints.insert(d2->left); - sidePoints.insert(d2->right()); - // check if any other widget rest against this side - for (int k = i + 1; k < dockedWidgets.size(); ++k) { - DockInfo* d3 = dockedWidgets[k]; - if (d3->bottom() == d2->top) { - sidePoints.insert(d3->left); - sidePoints.insert(d3->right()); - } - } - } - } - // widget placement can occur at all points, find the closest - auto it = sidePoints.begin(); - for (int j = 0; j < sidePoints.size() - 1; ++j) { - // check after point - unsigned newDist1 = dist + abs(*it - rect.left()); - if (newDist1 < bestDistance && isClose(*it, rect.left())) { - QRect r(QPoint(*it, d->top - rect.height()), rect.size()); - if (!overlaysWithFirstNWidgets(r, i)) { - bestDistance = newDist1; - bestIndex = i + 1; - bestSide = TOP; - bestRect = r; - } - } - ++it; - // check before point - unsigned newDist2 = dist + abs(*it - rect.right()); - if (newDist2 < bestDistance && isClose(*it, rect.right())) { - QRect r(QPoint(*it - rect.width(), d->top - rect.height()), - rect.size()); - if (!overlaysWithFirstNWidgets(r, i)) { - bestDistance = newDist2; - bestIndex = i + 1; - bestSide = TOP; - bestRect = r; - } - } - } - // check for resized placement options - if (sizePol.horizontalPolicy() != QSizePolicy::Fixed) { - int mid = rect.left() + rect.width() / 2; - for (auto ita = std::next(sidePoints.begin()); ita != sidePoints.end(); ++ita) { - for (auto itb = sidePoints.begin(); ita != itb; ++itb) { - int sp_mid = (*ita + *itb) / 2; - int sp_diff = *ita - *itb; - if (isClose(sp_mid, mid)) { - QRect r(*itb, d->top - rect.height(), - sp_diff, rect.height()); - if (!overlaysWithFirstNWidgets(r, i)) { - bestDistance = dist + abs(sp_mid - mid); - bestIndex = i + 1; - bestSide = TOP; - bestRect = r; - } - } - } - } - } - } - } - - /******************************************************** - * Check for placement against the bottom of the widget * - ********************************************************/ - if (i == 0 || d->dockSide != TOP) { - if (!(rect.left() > d->right() - SNAP_DISTANCE || - rect.right() < d->left + SNAP_DISTANCE) && - isClose(rect.top(), d->bottom())) { - // rectangle is close to the edge - unsigned dist = 8 * abs(rect.top() - d->bottom()); - // now find all points on this side - // (use set as a sorted unique list) - QSet sidePoints; - for (int j = 0; j <= i; ++j) { - DockInfo* d2 = dockedWidgets[j]; - if (d->bottom() == d2->bottom()) { - sidePoints.insert(d2->left); - sidePoints.insert(d2->right()); - // check if any other widget rest against this side - for (int k = i + 1; k < dockedWidgets.size(); ++k) { - DockInfo* d3 = dockedWidgets[k]; - if (d3->top == d2->bottom()) { - sidePoints.insert(d3->left); - sidePoints.insert(d3->right()); - } - } - } - } - // widget placement can occur at all points, find the closest - auto it = sidePoints.begin(); - for (int j = 0; j < sidePoints.size() - 1; ++j) { - // check after point - unsigned newDist1 = dist + abs(*it - rect.left()); - if (newDist1 < bestDistance && isClose(*it, rect.left())) { - QRect r(QPoint(*it, d->bottom()), rect.size()); - if (!overlaysWithFirstNWidgets(r, i)) { - bestDistance = newDist1; - bestIndex = i + 1; - bestSide = BOTTOM; - bestRect = r; - } - } - ++it; - // check before point - unsigned newDist2 = dist + abs(*it - rect.right()); - if (newDist2 < bestDistance && isClose(*it, rect.right())) { - QRect r(QPoint(*it - rect.width(), d->bottom()), rect.size()); - if (!overlaysWithFirstNWidgets(r, i)) { - bestDistance = newDist2; - bestIndex = i + 1; - bestSide = BOTTOM; - bestRect = r; - } - } - } - // check for resized placement options - if (sizePol.horizontalPolicy() != QSizePolicy::Fixed) { - int mid = rect.left() + rect.width() / 2; - for (auto ita = std::next(sidePoints.begin()); ita != sidePoints.end(); ++ita) { - for (auto itb = sidePoints.begin(); ita != itb; ++itb) { - int sp_mid = (*ita + *itb) / 2; - int sp_diff = *ita - *itb; - if (isClose(sp_mid, mid)) { - QRect r(*itb, d->bottom(), - sp_diff, rect.height()); - if (!overlaysWithFirstNWidgets(r, i)) { - bestDistance = dist + abs(sp_mid - mid); - bestIndex = i + 1; - bestSide = BOTTOM; - bestRect = r; - } - } - } - } - } - } - } - - /****************************************************** - * Check for placement against the left of the widget * - ******************************************************/ - if (i == 0 || d->dockSide != RIGHT) { - if (!(rect.top() > d->bottom() - SNAP_DISTANCE || - rect.bottom() < d->top + SNAP_DISTANCE) && - isClose(rect.right(), d->left)) { - // rectangle is close to the edge - unsigned dist = 8 * abs(rect.right() - d->left); - // now find all points on this side - // (use set as a sorted unique list) - QSet sidePoints; - for (int j = 0; j <= i; ++j) { - DockInfo* d2 = dockedWidgets[j]; - if (d->left == d2->left) { - sidePoints.insert(d2->top); - sidePoints.insert(d2->bottom()); - // check if any other widget rest against this side - for (int k = i + 1; k < dockedWidgets.size(); ++k) { - DockInfo* d3 = dockedWidgets[k]; - if (d3->right() == d2->left) { - sidePoints.insert(d3->top); - sidePoints.insert(d3->bottom()); - } - } - } - } - // widget placement can occur at all points, find the closest - auto it = sidePoints.begin(); - for (int j = 0; j < sidePoints.size() - 1; ++j) { - // check after point - unsigned newDist1 = dist + abs(*it - rect.top()); - if (newDist1 < bestDistance && isClose(*it, rect.top())) { - QRect r(QPoint(d->left - rect.width(), *it), rect.size()); - if (!overlaysWithFirstNWidgets(r, i)) { - bestDistance = newDist1; - bestIndex = i + 1; - bestSide = LEFT; - bestRect = r; - } - } - ++it; - // check before point - unsigned newDist2 = dist + abs(*it - rect.bottom()); - if (newDist2 < bestDistance && isClose(*it, rect.bottom())) { - QRect r(QPoint(d->left - rect.width(), *it - rect.height()), - rect.size()); - if (!overlaysWithFirstNWidgets(r, i)) { - bestDistance = newDist2; - bestIndex = i + 1; - bestSide = LEFT; - bestRect = r; - } - } - } - // check for resized placement options - if (sizePol.verticalPolicy() != QSizePolicy::Fixed) { - int mid = rect.top() + rect.height() / 2; - for (auto ita = std::next(sidePoints.begin()); ita != sidePoints.end(); ++ita) { - for (auto itb = sidePoints.begin(); ita != itb; ++itb) { - int sp_mid = (*ita + *itb) / 2; - int sp_diff = *ita - *itb; - if (isClose(sp_mid, mid)) { - QRect r(d->left - rect.width(), *itb, - rect.width(), sp_diff); - if (!overlaysWithFirstNWidgets(r, i)) { - bestDistance = dist + abs(sp_mid - mid); - bestIndex = i + 1; - bestSide = LEFT; - bestRect = r; - } - } - } - } - } - } - } - /******************************************************* - * Check for placement against the right of the widget * - *******************************************************/ - if (i == 0 || d->dockSide != LEFT) { - if (!(rect.top() > d->bottom() - SNAP_DISTANCE || - rect.bottom() < d->top + SNAP_DISTANCE) && - isClose(rect.left(), d->right())) { - // rectangle is close to the edge - unsigned dist = 8 * abs(rect.left() - d->right()); - // now find all points on this side - // (use set as a sorted unique list) - QSet sidePoints; - for (int j = 0; j <= i; ++j) { - DockInfo* d2 = dockedWidgets[j]; - if (d->right() == d2->right()) { - sidePoints.insert(d2->top); - sidePoints.insert(d2->bottom()); - // check if any other widget rest against this side - for (int k = i + 1; k < dockedWidgets.size(); ++k) { - DockInfo* d3 = dockedWidgets[k]; - if (d3->left == d2->right()) { - sidePoints.insert(d3->top); - sidePoints.insert(d3->bottom()); - } - } - } - } - // widget placement can occur at all points, find the closest - auto it = sidePoints.begin(); - for (int j = 0; j < sidePoints.size() - 1; ++j) { - // check after point - unsigned newDist1 = dist + abs(*it - rect.top()); - if (newDist1 < bestDistance && isClose(*it, rect.top())) { - QRect r(QPoint(d->left + d->width, *it), rect.size()); - if (!overlaysWithFirstNWidgets(r, i)) { - bestDistance = newDist1; - bestIndex = i + 1; - bestSide = RIGHT; - bestRect = r; - } - } - ++it; - // check before point - unsigned newDist2 = dist + abs(*it - rect.bottom()); - if (newDist2 < bestDistance && isClose(*it, rect.bottom())) { - QRect r(QPoint(d->right(), *it - rect.height()), rect.size()); - if (!overlaysWithFirstNWidgets(r, i)) { - bestDistance = newDist2; - bestIndex = i + 1; - bestSide = RIGHT; - bestRect = r; - } - } - } - // check for resized placement options - if (sizePol.verticalPolicy() != QSizePolicy::Fixed) { - int mid = rect.top() + rect.height() / 2; - for (auto ita = std::next(sidePoints.begin()); ita != sidePoints.end(); ++ita) { - for (auto itb = sidePoints.begin(); ita != itb; ++itb) { - int sp_mid = (*ita + *itb) / 2; - int sp_diff = *ita - *itb; - if (isClose(sp_mid, mid)) { - QRect r(d->right(), *itb, rect.width(), sp_diff); - if (!overlaysWithFirstNWidgets(r, i)) { - bestDistance = dist + abs(sp_mid - mid); - bestIndex = i + 1; - bestSide = RIGHT; - bestRect = r; - } - } - } - } - } - } - } - } - - if (bestIndex) { - rect = bestRect; - index = bestIndex; - side = bestSide; - return true; - } else { - return false; - } -} - -bool DockableWidgetLayout::insertLocation(QRect& rect, const QSizePolicy& sizePol) -{ - int index; - DockSide side; - return insertLocation(rect, index, side, sizePol); -} - -void DockableWidgetLayout::getConfig(QStringList& list) -{ - for (auto* d : dockedWidgets) { - // string format D [Hidden/Visible] [Side] [Distance] [Width] [Height] - QString s("%1 D %2 %3 %4 %5 %6"); - s = s.arg(d->widget->id()); - - if (d->widget->isHidden()) { - s = s.arg("H"); - } else { - s = s.arg("V"); - } - - switch (d->dockSide) { - case TOP: - s = s.arg("T"); - break; - case LEFT: - s = s.arg("L"); - break; - case RIGHT: - s = s.arg("R"); - break; - case BOTTOM: - s = s.arg("B"); - break; - } - - s = s.arg(d->dockDistance); - - if (d->useHintWidth) { - s = s.arg(-1); - } else { - s = s.arg(d->width); - } - - if (d->useHintHeight) { - s = s.arg(-1); - } else { - s = s.arg(d->height); - } - list.append(s); - } -} diff --git a/src/DockableWidgetLayout.h b/src/DockableWidgetLayout.h deleted file mode 100644 index 67445f3b..00000000 --- a/src/DockableWidgetLayout.h +++ /dev/null @@ -1,79 +0,0 @@ -#ifndef DOCKABLEWIDGETLAYOUT_H -#define DOCKABLEWIDGETLAYOUT_H - -#include -#include - -class QLayoutItem; -class DockableWidget; -class QStringList; - -class DockableWidgetLayout : public QLayout -{ - Q_OBJECT -public: - enum DockSide { TOP, LEFT, RIGHT, BOTTOM }; - - DockableWidgetLayout(QWidget* parent = nullptr, int margin = 0, int spacing = -1); - DockableWidgetLayout(int spacing); - ~DockableWidgetLayout() override; - - void addItem(QLayoutItem* item) override; - void addItem(QLayoutItem* item, int index, DockSide side = RIGHT, - int dist = 0, int w = -1, int h = -1); - void addWidget(DockableWidget* widget, const QRect& rect); - void addWidget(DockableWidget* widget, DockSide side, int distance, - int width = -1, int height = -1); - bool insertLocation(QRect& rect, const QSizePolicy& sizePol); - - QLayoutItem* itemAt(int index) const override; - QLayoutItem* takeAt(int index) override; - int count() const override; - - Qt::Orientations expandingDirections() const override; - bool hasHeightForWidth() const override; - - QSize minimumSize() const override; - QSize maximumSize() const override; - void setGeometry(const QRect &rect) override; - - QSize sizeHint() const override; - void changed(); - - void getConfig(QStringList& list); - -private: - class DockInfo - { - public: - QRect bounds() const { return {left, top, width, height}; } - int right() const { return left + width; } - int bottom() const { return top + height; } - - DockableWidget* widget; - QLayoutItem* item; - DockSide dockSide; - int dockDistance; - int left; - int top; - int width; - int height; - bool useHintHeight; - bool useHintWidth; - }; - - QList dockedWidgets; - int layoutWidth, layoutHeight; - int minWidth, minHeight; - int maxWidth, maxHeight; - int checkWidth, checkHeight; - - void calcSizeLimits(); - void sizeMove(int dx, int dy); - void doLayout(bool check = false); - bool insertLocation(QRect& rect, int& index, DockSide& side, - const QSizePolicy& sizePol); - bool overlaysWithFirstNWidgets(const QRect& r, int n) const; -}; - -#endif // DOCKABLEWIDGETLAYOUT_H diff --git a/src/VramBitMappedView.cpp b/src/VramBitMappedView.cpp index 932ee08b..22ea5a79 100644 --- a/src/VramBitMappedView.cpp +++ b/src/VramBitMappedView.cpp @@ -27,10 +27,6 @@ void VramBitMappedView::decode() { if (!vramBase) return; - printf("\n" - "screenMode: %i\n" - "vram to start decoding: %i\n", - screenMode, vramAddress); switch (screenMode) { case 5: decodeSCR5(); break; case 6: decodeSCR6(); break; diff --git a/src/blendsplitter/ExpanderCorner.cpp b/src/blendsplitter/ExpanderCorner.cpp index 2c9b7702..d57da811 100644 --- a/src/blendsplitter/ExpanderCorner.cpp +++ b/src/blendsplitter/ExpanderCorner.cpp @@ -230,7 +230,7 @@ void ExpanderCorner::followDragJoiners(WidgetDecorator *parentDecorator, BlendSp // already an overlay and we are still dragging 'inside' of the splitter, so externalOverlay->show(); // maybe we need to change direction of the join ? - qDebug() << "overlay->parentWidget()!=externalJoinWidget" << externalOverlay->parentWidget() << " " <parentWidget()!=externalJoinWidget" << externalOverlay->parentWidget() << " " <orientation(); if ((isOnTrailingHandler(parentSplitter) and pickCoordinate(x,y,o)>pickSize(parentDecorator->size(),o)) diff --git a/src/node.mk b/src/node.mk index 7bb19282..d97c5c0d 100644 --- a/src/node.mk +++ b/src/node.mk @@ -4,7 +4,6 @@ SUBDIRS:= \ openmsx MOC_SRC_HDR:= \ - DockableWidget DockableWidgetArea DockableWidgetLayout \ CPURegsViewer CommClient DebuggerForm DisasmViewer FlagsViewer HexViewer \ SlotViewer StackViewer ConnectDialog OpenMSXConnection SymbolManager \ Settings PreferencesDialog BreakpointDialog DebuggableViewer \ @@ -24,7 +23,7 @@ MOC_SRC_HDR:= \ SRC_HDR:= \ - DockManager Dasm DasmTables DebuggerData SymbolTable Convert Version \ + Dasm DasmTables DebuggerData SymbolTable Convert Version \ CPURegs SimpleHexRequest SRC_ONLY:= \ From b76f243395093454dfc3df61a727bf0c547ab12f Mon Sep 17 00:00:00 2001 From: david Date: Thu, 21 Apr 2022 22:16:34 +0200 Subject: [PATCH 08/63] Fixed some crashes and added cursor shapes --- src/blendsplitter/ExpanderCorner.cpp | 61 +++++++++++++++++----------- src/blendsplitter/ExpanderCorner.h | 1 - src/blendsplitter/SplitterHandle.cpp | 52 +++++++++++++++++++++++- 3 files changed, 89 insertions(+), 25 deletions(-) diff --git a/src/blendsplitter/ExpanderCorner.cpp b/src/blendsplitter/ExpanderCorner.cpp index d57da811..6e9a01a5 100644 --- a/src/blendsplitter/ExpanderCorner.cpp +++ b/src/blendsplitter/ExpanderCorner.cpp @@ -12,7 +12,7 @@ ExpanderCorner::ExpanderCorner(WidgetDecorator* parent,Qt::Corner location) : Expander{parent} , corner{location},unitX{1},unitY{1},hotspotX{0},hotspotY{0},dragaction{undecidedDrag}, dragorientation{Qt::Horizontal},internalOverlay{nullptr},externalOverlay{nullptr}, - externalJoinWidget{nullptr},joinarrow{Qt::NoArrow} + joinarrow{Qt::NoArrow} { //now do some masking and pixmap rotating depending on location //also set out unit steps @@ -204,10 +204,10 @@ void ExpanderCorner::setupJoiners(WidgetDecorator *parentDecorator, BlendSplitte //now show overlay if we started a valid joindrag if (externalOverlay){ externalOverlay->show(); - externalJoinWidget=wdgt; internalOverlay=new Overlay{parentDecorator,Overlay::invertArrow(joinarrow)}; internalOverlay->hide(); dragaction=joinDrag; + //qDebug() << "starting joindrag " << wdgt << " ( <-wdgt parentDecorator->) " << parentDecorator; } } } @@ -227,27 +227,26 @@ void ExpanderCorner::followDragJoiners(WidgetDecorator *parentDecorator, BlendSp y=pos().y()+y; if (isInContinuationOfSplitter(parentSplitter,x,y)){ - // already an overlay and we are still dragging 'inside' of the splitter, so - externalOverlay->show(); // maybe we need to change direction of the join ? - //qDebug() << "overlay->parentWidget()!=externalJoinWidget" << externalOverlay->parentWidget() << " " <orientation(); if ((isOnTrailingHandler(parentSplitter) and pickCoordinate(x,y,o)>pickSize(parentDecorator->size(),o)) or (!isOnTrailingHandler(parentSplitter) and pickCoordinate(x,y,o)<0) ) { externalOverlay->show(); internalOverlay->hide(); + setCursor(parentSplitter->orientation()==Qt::Horizontal?Qt::SizeHorCursor:Qt::SizeVerCursor); } else if ((isOnTrailingHandler(parentSplitter) and pickCoordinate(x,y,o)<=pickSize(parentDecorator->size(),o)) or (!isOnTrailingHandler(parentSplitter) and pickCoordinate(x,y,o)>=0) ) { externalOverlay->hide(); internalOverlay->show(); + setCursor(parentSplitter->orientation()==Qt::Horizontal?Qt::SizeHorCursor:Qt::SizeVerCursor); } } else { // hide all overlay since we dragged 'to the side' of the splitter externalOverlay->hide(); internalOverlay->hide(); + setCursor(Qt::ForbiddenCursor); } } @@ -361,6 +360,9 @@ void ExpanderCorner::mouseReleaseEvent(QMouseEvent *event) if(event->button() != Qt::LeftButton or dragaction != joinDrag){ return; }; + //back to default cursor for handler + setCursor(Qt::SizeAllCursor); + //correct button and we have an overlay, so continue... if(externalOverlay->isVisible() && internalOverlay->isVisible()) { @@ -370,23 +372,36 @@ void ExpanderCorner::mouseReleaseEvent(QMouseEvent *event) QWidget* widgetToRemove=nullptr; //improved readability later on - if (externalOverlay->isHidden()){ - externalOverlay->deleteLater(); - } else { + QWidget* widgetToKeep=nullptr; //improved readability later on + + if (externalOverlay->isVisible() && !internalOverlay->isVisible()){ + widgetToKeep=internalOverlay->parentWidget(); widgetToRemove=externalOverlay->parentWidget(); + } else if (!externalOverlay->isVisible() && internalOverlay->isVisible()){ + widgetToKeep=externalOverlay->parentWidget(); + widgetToRemove=internalOverlay->parentWidget(); }; - if (internalOverlay->isHidden()){ + + // The visible overlays will be deleted when we remove the widget, + // so we need to clean up the invisble overlays + if (!internalOverlay->isVisible()){ internalOverlay->deleteLater(); - } else { - widgetToRemove=internalOverlay->parentWidget(); + }; + if (!externalOverlay->isVisible()){ + externalOverlay->deleteLater(); }; - + //do nothing if both overlays were hidden + if (widgetToRemove==nullptr){ + externalOverlay = nullptr; + internalOverlay = nullptr; + return; + } //first get our decorator and the parent blendSplitter - WidgetDecorator* parentDecorator{qobject_cast(parentWidget())}; - if(parentDecorator == 0) + WidgetDecorator* toKeepDecorator{qobject_cast(widgetToKeep)}; + if(toKeepDecorator == 0) { qCritical("A BlendSplitter library error occurred. Error code: 1"); return; @@ -399,16 +414,16 @@ void ExpanderCorner::mouseReleaseEvent(QMouseEvent *event) } - //now delete the item with the overlay from the splitter + //now delete the item with the visible overlay from the splitter QList sizes{parentSplitter->sizes()}; - int parentIndex{parentSplitter->indexOf(parentDecorator)}; - int overlayIndex{parentSplitter->indexOf(widgetToRemove)}; - sizes[parentIndex] += sizes[overlayIndex] + 1; - sizes.removeAt(overlayIndex); - delete parentSplitter->widget(overlayIndex); + int toKeepIndex{parentSplitter->indexOf(toKeepDecorator)}; + int toRemoveIndex{parentSplitter->indexOf(widgetToRemove)}; + sizes[toKeepIndex] += sizes[toRemoveIndex] + 1; + sizes.removeAt(toRemoveIndex); + delete parentSplitter->widget(toRemoveIndex); externalOverlay = nullptr; - externalJoinWidget = nullptr; + internalOverlay = nullptr; // if we now have a blendSplitter with a single item, which is inside // another blendSplitter then we remove this singular-item splitter @@ -422,7 +437,7 @@ void ExpanderCorner::mouseReleaseEvent(QMouseEvent *event) return; } QList sizes2{newParent->sizes()}; - newParent->insertDecoratedWidget(newParent->indexOf(parentSplitter->parentWidget()), parentDecorator); + newParent->insertDecoratedWidget(newParent->indexOf(parentSplitter->parentWidget()), toKeepDecorator); delete parentSplitter->parentWidget(); newParent->setSizes(sizes2); } diff --git a/src/blendsplitter/ExpanderCorner.h b/src/blendsplitter/ExpanderCorner.h index 3dd31c6d..63a89222 100644 --- a/src/blendsplitter/ExpanderCorner.h +++ b/src/blendsplitter/ExpanderCorner.h @@ -42,7 +42,6 @@ protected slots: Overlay* internalOverlay; Overlay* externalOverlay; - QWidget* externalJoinWidget; Qt::ArrowType joinarrow; int pickCoordinate(int x,int y,Qt::Orientation orient); int pickSize(const QSize &size, Qt::Orientation orient); diff --git a/src/blendsplitter/SplitterHandle.cpp b/src/blendsplitter/SplitterHandle.cpp index 2c3bc815..e433e094 100644 --- a/src/blendsplitter/SplitterHandle.cpp +++ b/src/blendsplitter/SplitterHandle.cpp @@ -12,7 +12,57 @@ SplitterHandle::SplitterHandle(Qt::Orientation orientation, QSplitter* parent) : SplitterHandle::~SplitterHandle() { - delete popupmenu; //Qmenu has ownership of the actions + if (popupmenu){ + delete popupmenu; //Qmenu has ownership of the actions + popupmenu=nullptr; + }; + /* + delete popupmenu; + This sometimes causes a crash???? + Default CPU workspace and grep handler to close "CPU registers"/"Flags" + wiggled a bit left/right when joining and sometimes this happened???? + 1 SplitterHandle::~SplitterHandle SplitterHandle.cpp 15 0x5555556b6d3e + 2 SplitterHandle::~SplitterHandle SplitterHandle.cpp 16 0x5555556b6d90 + 3 QSplitterLayoutStruct::~QSplitterLayoutStruct qsplitter_p.h 74 0x7ffff7a65bfd + 4 QSplitter::childEvent qsplitter.cpp 1312 0x7ffff7a65bfd + 5 QObject::event qobject.cpp 1361 0x7ffff658abcb + 6 QWidget::event qwidget.cpp 9094 0x7ffff79099d3 + 7 QFrame::event qframe.cpp 550 0x7ffff79b179e + 8 QApplicationPrivate::notify_helper qapplication.cpp 3685 0x7ffff78cab0c + 9 QApplication::notify qapplication.cpp 3431 0x7ffff78d1a90 + 10 QCoreApplication::notifyInternal2 qcoreapplication.cpp 1075 0x7ffff655bc48 + 11 QCoreApplication::sendEvent qcoreapplication.cpp 1470 0x7ffff655bdfe + 12 QObjectPrivate::setParent_helper qobject.cpp 2166 0x7ffff6590082 + 13 QObject::~QObject qobject.cpp 1118 0x7ffff6590592 + 14 QWidget::~QWidget qwidget.cpp 1408 0x7ffff790526c + 15 WidgetDecorator::~WidgetDecorator WidgetDecorator.cpp 26 0x5555556b8852 + 16 WidgetDecorator::~WidgetDecorator WidgetDecorator.cpp 29 0x5555556b887c + 17 ExpanderCorner::mouseReleaseEvent ExpanderCorner.cpp 409 0x5555556b5239 + 18 QWidget::event qwidget.cpp 9033 0x7ffff7909670 + 19 QFrame::event qframe.cpp 550 0x7ffff79b179e + 20 QApplicationPrivate::notify_helper qapplication.cpp 3685 0x7ffff78cab0c + 21 QApplication::notify qapplication.cpp 3129 0x7ffff78d26f8 + 22 QCoreApplication::notifyInternal2 qcoreapplication.cpp 1075 0x7ffff655bc48 + 23 QCoreApplication::sendSpontaneousEvent qcoreapplication.cpp 1482 0x7ffff655be0e + 24 QApplicationPrivate::sendMouseEvent qapplication.cpp 2615 0x7ffff78d0fda + 25 QWidgetWindow::handleMouseEvent qwidgetwindow.cpp 674 0x7ffff7922dd1 + 26 QWidgetWindow::event qwidgetwindow.cpp 295 0x7ffff7925a1b + 27 QApplicationPrivate::notify_helper qapplication.cpp 3685 0x7ffff78cab0c + 28 QApplication::notify qapplication.cpp 3431 0x7ffff78d1a90 + 29 QCoreApplication::notifyInternal2 qcoreapplication.cpp 1075 0x7ffff655bc48 + 30 QCoreApplication::sendSpontaneousEvent qcoreapplication.cpp 1482 0x7ffff655be0e + 31 QGuiApplicationPrivate::processMouseEvent qguiapplication.cpp 2203 0x7ffff6fb9738 + 32 QGuiApplicationPrivate::processWindowSystemEvent qguiapplication.cpp 1935 0x7ffff6fbac15 + 33 QWindowSystemInterface::sendWindowSystemEvents qwindowsysteminterface.cpp 1170 0x7ffff6f96f4b + 34 xcbSourceDispatch qxcbeventdispatcher.cpp 105 0x7ffff2a0a33a + 35 g_main_context_dispatch 0x7ffff392817d + 36 ?? 0x7ffff3928400 + 37 g_main_context_iteration 0x7ffff39284a3 + 38 QEventDispatcherGlib::processEvents qeventdispatcher_glib.cpp 423 0x7ffff65b473c + 39 QEventLoop::exec qeventloop.cpp 225 0x7ffff655a662 + 40 QCoreApplication::exec qcoreapplication.cpp 1383 0x7ffff6563590 + 41 main main.cpp 20 0x5555556b9e54 + */ } void SplitterHandle::mousePressEvent(QMouseEvent *event) From 699fa02611452c82cf25a82de50b688e360b672e Mon Sep 17 00:00:00 2001 From: david Date: Fri, 22 Apr 2022 19:19:42 +0200 Subject: [PATCH 09/63] Added QScrollArea to SwitchingWidget Also tried some fancier popup menu on the SplitterHandle, but this causes a lot of crashes. I assume that the handler is already free'ed while the mouseReleaseEvent is still being processed causing these SegFaults. Also I got divide by zero errors when creating new StackViewer with an open openMSX connection, it seems to handle the command reply before the widget is fully initialized??? Also the changing of background (when connecting/disconnecting the emulator) in the scrollarea isn't eassily triggered. If you resize by hand it will correctly change the color not covered by the single widget, but simply setting an new background doesn't cause an update, neither doesn explicitely calling update() or repaint(). --- src/HexViewer.cpp | 12 ++- src/StackViewer.cpp | 2 +- src/blendsplitter/BlendSplitter.h | 2 + src/blendsplitter/Expander.cpp | 110 +++++++++---------- src/blendsplitter/Expander.h | 6 +- src/blendsplitter/ExpanderCorner.cpp | 18 +++- src/blendsplitter/ExpanderCorner.h | 3 + src/blendsplitter/SplitterHandle.cpp | 150 ++++++++++++++++++++++++-- src/blendsplitter/SplitterHandle.h | 17 ++- src/blendsplitter/SwitchingWidget.cpp | 36 ++++++- src/blendsplitter/SwitchingWidget.h | 2 + 11 files changed, 277 insertions(+), 81 deletions(-) diff --git a/src/HexViewer.cpp b/src/HexViewer.cpp index ab61af68..4fba6ff4 100644 --- a/src/HexViewer.cpp +++ b/src/HexViewer.cpp @@ -43,14 +43,13 @@ class HexRequest : public ReadDebugBlockCommand HexViewer::HexViewer(QWidget* parent) : QFrame(parent) - , wheelRemainder(0) + , wheelRemainder(0),horBytes{16} { setFrameStyle(WinPanel | Sunken); setFocusPolicy(Qt::StrongFocus); setBackgroundRole(QPalette::Base); setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding)); - horBytes = 16; hexTopAddress = 0; hexMarkAddress = 0; hexData = nullptr; @@ -166,7 +165,7 @@ void HexViewer::setDisplayMode(Mode mode) void HexViewer::setDisplayWidth(short width) { displayMode = FIXED; - horBytes = width; + horBytes = std::max(short{1},width); setSizes(); } @@ -492,7 +491,12 @@ void HexViewer::transferCancelled(HexRequest* r) delete r; waitingForData = false; // check whether a new value is available - if (int(hexTopAddress / horBytes) != vertScrollBar->value()) { + if (horBytes==0) { + // for some reasson we could get a floating point exception here when cerating a new Hexviewer in disconnected mode?? + qDebug()<< "Avoided divide by zero??"; + return; + }; + if (int(hexTopAddress / horBytes) != vertScrollBar->value()) { vertScrollBar->setValue(hexTopAddress / horBytes); } } diff --git a/src/StackViewer.cpp b/src/StackViewer.cpp index 970cdb46..43de2eb7 100644 --- a/src/StackViewer.cpp +++ b/src/StackViewer.cpp @@ -66,7 +66,7 @@ StackViewer::StackViewer(QWidget* parent) QSize StackViewer::sizeHint() const { - return {frameL + 4 + fontMetrics().horizontalAdvance("FFFFWFFFF ") + 4 + frameR, + return {frameL + 4 + fontMetrics().horizontalAdvance("FFFFWFFFF ") + 4 + frameR, frameT + 8 * fontMetrics().height() + frameB}; } diff --git a/src/blendsplitter/BlendSplitter.h b/src/blendsplitter/BlendSplitter.h index ec0700a8..4a6a5955 100644 --- a/src/blendsplitter/BlendSplitter.h +++ b/src/blendsplitter/BlendSplitter.h @@ -98,5 +98,7 @@ class BlendSplitter : public QSplitter QWidget* (*defaultWidget) (); virtual QSplitterHandle* createHandle() override; void addDecoratedWidget(WidgetDecorator* widget); +public: void insertDecoratedWidget(int index, WidgetDecorator* widget); + }; diff --git a/src/blendsplitter/Expander.cpp b/src/blendsplitter/Expander.cpp index a1488330..28f9f566 100644 --- a/src/blendsplitter/Expander.cpp +++ b/src/blendsplitter/Expander.cpp @@ -9,7 +9,7 @@ Expander::Expander(WidgetDecorator* parent) : QLabel(parent), pixmap{new QPixmap *pixmap = pixmap->scaledToHeight(BlendSplitter::expanderSize, Qt::FastTransformation); setPixmap(*pixmap); resize(BlendSplitter::expanderSize, BlendSplitter::expanderSize); - setCursor(Qt::SizeAllCursor); + setCursor(Qt::WhatsThisCursor); } void Expander::reposition() @@ -17,61 +17,61 @@ void Expander::reposition() raise(); } -void Expander::mousePressEvent(QMouseEvent* event) -{ - if(event->button() == Qt::LeftButton) - { - event->accept(); // No-op - } - else - { - releaseMouse(); - event->ignore(); // Propagate event - } -} +//void Expander::mousePressEvent(QMouseEvent* event) +//{ +// if(event->button() == Qt::LeftButton) +// { +// event->accept(); // No-op +// } +// else +// { +// releaseMouse(); +// event->ignore(); // Propagate event +// } +//} -void Expander::mouseReleaseEvent(QMouseEvent* event) -{ - if(event->button() == Qt::LeftButton and overlay != nullptr) - { - WidgetDecorator* parentDecorator{qobject_cast(parentWidget())}; - if(parentDecorator == 0) - { - qCritical("A BlendSplitter library error occurred. Error code: 1"); - return; - } - BlendSplitter* parentSplitter{qobject_cast(overlay->parentWidget()->parentWidget())}; - if(parentSplitter == 0) - { - qCritical("A BlendSplitter library error occurred. Error code: 2"); - return; - } - QList sizes{parentSplitter->sizes()}; - int parentIndex{parentSplitter->indexOf(parentDecorator)}; - int overlayIndex{parentSplitter->indexOf(overlay->parentWidget())}; - sizes[parentIndex] += sizes[overlayIndex] + 1; - sizes.removeAt(overlayIndex); - delete parentSplitter->widget(overlayIndex); - if(parentSplitter->count() == 1 and parentSplitter->parentWidget()->inherits("SplitterDecorator")) - { - BlendSplitter* newParent{qobject_cast(parentSplitter->parentWidget()->parentWidget())}; - if(newParent == 0) - { - qCritical("A BlendSplitter library error occurred. Error code: 3"); - return; - } - QList sizes2{newParent->sizes()}; - newParent->insertDecoratedWidget(newParent->indexOf(parentSplitter->parentWidget()), parentDecorator); - delete parentSplitter->parentWidget(); - newParent->setSizes(sizes2); - } - else - { - parentSplitter->setSizes(sizes); - } - overlay = nullptr; - } -} +//void Expander::mouseReleaseEvent(QMouseEvent* event) +//{ +// if(event->button() == Qt::LeftButton and overlay != nullptr) +// { +// WidgetDecorator* parentDecorator{qobject_cast(parentWidget())}; +// if(parentDecorator == 0) +// { +// qCritical("A BlendSplitter library error occurred. Error code: 1"); +// return; +// } +// BlendSplitter* parentSplitter{qobject_cast(overlay->parentWidget()->parentWidget())}; +// if(parentSplitter == 0) +// { +// qCritical("A BlendSplitter library error occurred. Error code: 2"); +// return; +// } +// QList sizes{parentSplitter->sizes()}; +// int parentIndex{parentSplitter->indexOf(parentDecorator)}; +// int overlayIndex{parentSplitter->indexOf(overlay->parentWidget())}; +// sizes[parentIndex] += sizes[overlayIndex] + 1; +// sizes.removeAt(overlayIndex); +// delete parentSplitter->widget(overlayIndex); +// if(parentSplitter->count() == 1 and parentSplitter->parentWidget()->inherits("SplitterDecorator")) +// { +// BlendSplitter* newParent{qobject_cast(parentSplitter->parentWidget()->parentWidget())}; +// if(newParent == 0) +// { +// qCritical("A BlendSplitter library error occurred. Error code: 3"); +// return; +// } +// QList sizes2{newParent->sizes()}; +// newParent->insertDecoratedWidget(newParent->indexOf(parentSplitter->parentWidget()), parentDecorator); +// delete parentSplitter->parentWidget(); +// newParent->setSizes(sizes2); +// } +// else +// { +// parentSplitter->setSizes(sizes); +// } +// overlay = nullptr; +// } +//} Expander::~Expander() { diff --git a/src/blendsplitter/Expander.h b/src/blendsplitter/Expander.h index 15cfa07a..a7d6c106 100644 --- a/src/blendsplitter/Expander.h +++ b/src/blendsplitter/Expander.h @@ -19,7 +19,7 @@ class Expander : public QLabel protected slots: // virtual void enterEvent(QEvent* event) override final; // virtual void leaveEvent(QEvent* event) override final; - virtual void mousePressEvent(QMouseEvent* event) override; - virtual void mouseMoveEvent(QMouseEvent* event) override = 0; - virtual void mouseReleaseEvent(QMouseEvent* event) override; +// virtual void mousePressEvent(QMouseEvent* event) override; +// virtual void mouseMoveEvent(QMouseEvent* event) override = 0; +// virtual void mouseReleaseEvent(QMouseEvent* event) override; }; diff --git a/src/blendsplitter/ExpanderCorner.cpp b/src/blendsplitter/ExpanderCorner.cpp index 6e9a01a5..344fa8ab 100644 --- a/src/blendsplitter/ExpanderCorner.cpp +++ b/src/blendsplitter/ExpanderCorner.cpp @@ -172,6 +172,10 @@ void ExpanderCorner::performInnerSplit(WidgetDecorator* parentDecorator, BlendSp addedWidget->setEnableWidget(switchwdg->getEnableWidget()); addedWidget->setCurrentIndex(switchwdg->getCurrentIndex()); } + + //have the cursor take the correct shape + setCursor(splitorientation == Qt::Horizontal ? Qt::SplitHCursor : Qt::SplitVCursor); + } void ExpanderCorner::setupJoiners(WidgetDecorator *parentDecorator, BlendSplitter *parentSplitter, int x, int y, Qt::Orientation /*splitorientation*/) @@ -221,6 +225,12 @@ int ExpanderCorner::pickSize(const QSize &size, Qt::Orientation orient) return (orient == Qt::Horizontal) ? size.width() : size.height(); } +void ExpanderCorner::enterEvent(QEvent *event) +{ + setCursor(Qt::CrossCursor); //after innersplit the cursor is still wrong when entering... + Expander::enterEvent(event); +} + void ExpanderCorner::followDragJoiners(WidgetDecorator *parentDecorator, BlendSplitter *parentSplitter, int x, int y, Qt::Orientation /*splitorientation*/) { x=pos().x()+x; @@ -357,11 +367,15 @@ void ExpanderCorner::mousePressEvent(QMouseEvent *event) void ExpanderCorner::mouseReleaseEvent(QMouseEvent *event) { + if(event->button() == Qt::LeftButton){ + //releasing leftbutton set us back to default cursor for handler + // since we might have changed due to split or join + setCursor(Qt::CrossCursor); + }; + if(event->button() != Qt::LeftButton or dragaction != joinDrag){ return; }; - //back to default cursor for handler - setCursor(Qt::SizeAllCursor); //correct button and we have an overlay, so continue... if(externalOverlay->isVisible() && internalOverlay->isVisible()) diff --git a/src/blendsplitter/ExpanderCorner.h b/src/blendsplitter/ExpanderCorner.h index 63a89222..b5da9de1 100644 --- a/src/blendsplitter/ExpanderCorner.h +++ b/src/blendsplitter/ExpanderCorner.h @@ -45,4 +45,7 @@ protected slots: Qt::ArrowType joinarrow; int pickCoordinate(int x,int y,Qt::Orientation orient); int pickSize(const QSize &size, Qt::Orientation orient); + +protected slots: + virtual void enterEvent(QEvent* event) override final; }; diff --git a/src/blendsplitter/SplitterHandle.cpp b/src/blendsplitter/SplitterHandle.cpp index e433e094..ffe780f8 100644 --- a/src/blendsplitter/SplitterHandle.cpp +++ b/src/blendsplitter/SplitterHandle.cpp @@ -1,13 +1,16 @@ #include "SplitterHandle.h" +#include "BlendSplitter.h" +#include "WidgetDecorator.h" #include #include #include +#include -SplitterHandle::SplitterHandle(Qt::Orientation orientation, QSplitter* parent) : QSplitterHandle(orientation, parent) +SplitterHandle::SplitterHandle(Qt::Orientation orientation, QSplitter* parent) : QSplitterHandle(orientation, parent), + popupmenu{nullptr},joinBeforeAction{nullptr},joinAfterAction{nullptr}, + splitHoriBeforeAction{nullptr},splitHoriAfterAction{nullptr}, + splitVertBeforeAction{nullptr},splitVertAfterAction{nullptr} { - popupmenu= new QMenu(this); - splitAction= popupmenu->addAction(tr("Split")); - joinAction= popupmenu->addAction(tr("Join")); } SplitterHandle::~SplitterHandle() @@ -68,7 +71,18 @@ SplitterHandle::~SplitterHandle() void SplitterHandle::mousePressEvent(QMouseEvent *event) { - if (event->button() == Qt::RightButton){ + if (false && event->button() == Qt::RightButton){ //this causes too much crashes so disabled for now + // Probably the QT internal code deletes the handler when we remove widgets from + // the QSplitters and the rest of the Qt internals event handlers are then calling invalidated memory. + // It is never a good idea to delete objects while they are still needed :-) + // + // So either I remove this entirely or I use the old trick of decoupling the event from the deletion + // like setting it up with a QTimer so that the main Qt loop will trigger the deletion while there is no handler code active... + + + + + createPopupMenu(); QPoint pos=event->globalPos(); // When positioning a menu with exec() or popup(), bear in mind that you // cannot rely on the menu's current size(). For performance reasons, @@ -78,15 +92,29 @@ void SplitterHandle::mousePressEvent(QMouseEvent *event) // contents. pos.setX(pos.x() - popupmenu->sizeHint().width() / 2); // QAction* act=popupmenu->exec(pos); - if (act==joinAction){ - //not yet implemented - } else if (act==splitAction){ - //not yet implemented - } + if (act==nullptr){ + //if nothing select and some action are nullpointers.... + } else if (act==joinBeforeAction){ + releaseMouse(); + event->accept(); + int index = splitter()->indexOf(this); + removeFromSplitter(index,index-1); + } else if (act==joinAfterAction){ + releaseMouse(); + event->accept(); + //calling this will cause a segfault, so disabled... + QMessageBox::information(this,"function disabled","The current code would crash the program, so this function is disabled for now.If you are a developper please help us out..."); + //int index = splitter()->indexOf(this); + //removeFromSplitter(index-1,index); + } else { + QSplitterHandle::mousePressEvent(event); + }; + destroyPopupMenu(); // setFocus(); // grabMouse(); + } else { + QSplitterHandle::mousePressEvent(event); } - QSplitterHandle::mousePressEvent(event); } void SplitterHandle::mouseReleaseEvent(QMouseEvent* event) { @@ -99,3 +127,103 @@ bool SplitterHandle::event(QEvent *event) // qDebug() << " SplitterHandle::event " << event ; return QSplitterHandle::event(event); } + +void SplitterHandle::createPopupMenu() +{ + int index=splitter()->indexOf(this); + bool joinBeforePossible=splitter()->widget(index-1)->inherits("WidgetDecorator"); //do not join over splitters! + bool joinAfterPossible=splitter()->widget(index)->inherits("WidgetDecorator"); //do not join over splitters! + + // given all the crashes with joining and the simplicity of dragsplitting + // maybe we should simply drop the idea of reimplementing this blender functionality? + bool splitHoriBeforePossible=false; + bool splitVertBeforePossible=false; + bool splitHoriAfterPossible=false; + bool splitVertAfterPossible=false; + + popupmenu= new QMenu(this); + bool hori = orientation()==Qt::Horizontal; + if (joinBeforePossible){ + joinBeforeAction = popupmenu->addAction(hori ? tr("remove left") : tr("remove above")); + }; + if (joinAfterPossible){ + joinAfterAction = popupmenu->addAction(hori ? tr("remove right") : tr("remove below")); + } + + if (joinAfterPossible || joinBeforePossible){ + popupmenu->addSeparator(); + }; + + if (splitHoriBeforePossible){ + splitHoriBeforeAction = popupmenu->addAction(hori ? tr("split left horizontal") : tr("split above horizontal")); + }; + if (splitVertBeforePossible){ + splitVertBeforeAction = popupmenu->addAction(hori ? tr("split left vertical") : tr("split above vertical")); + }; + if (splitHoriAfterPossible){ + splitHoriAfterAction = popupmenu->addAction(hori ? tr("split right horizontal") : tr("split below horizontal")); + }; + if (splitVertAfterPossible){ + splitVertAfterAction = popupmenu->addAction(hori ? tr("split right horizontal") : tr("split below horizontal")); + } +} + +void SplitterHandle::destroyPopupMenu() +{ + if (popupmenu){ + delete popupmenu; + popupmenu=nullptr; + joinBeforeAction=nullptr; + joinAfterAction=nullptr; + splitHoriAfterAction=nullptr; + splitVertAfterAction=nullptr; + splitHoriBeforeAction=nullptr; + splitHoriAfterAction=nullptr; + } +} + +void SplitterHandle::removeFromSplitter(int toKeepIndex, int toRemoveIndex) +{ + QSplitter* parentSplitter=splitter(); + if(parentSplitter == nullptr) + { + qCritical("A BlendSplitter library error occurred. Error code: 20"); + return; + } + WidgetDecorator* toKeepDecorator{qobject_cast(parentSplitter->widget(toKeepIndex))}; + if(!(toKeepDecorator || parentSplitter->widget(toKeepIndex)->inherits("SplitterDecorator") )) + { + qCritical("A BlendSplitter library error occurred. Error code: 21"); + return; + } + //TODO: exact same code as in ExpanderCorner => isolate in sepereate method later + + QList sizes{parentSplitter->sizes()}; + sizes[toKeepIndex] += sizes[toRemoveIndex] + 1; + sizes.removeAt(toRemoveIndex); + QWidget* oldcontent = parentSplitter->widget(toRemoveIndex); + // we now avoid delete parentSplitter->widget(toRemoveIndex); + // we hope this also impacts the handler... + oldcontent->hide(); + oldcontent->setParent(nullptr); //removes it from splitter and makes it standalone (already hidden) window. + oldcontent->deleteLater(); + if(parentSplitter->count() == 1 and + parentSplitter->parentWidget()->inherits("SplitterDecorator")) + { + BlendSplitter* newParent{qobject_cast(parentSplitter->parentWidget()->parentWidget())}; + if(newParent == nullptr) + { + qCritical("A BlendSplitter library error occurred. Error code: 3"); + return; + } + QList sizes2{newParent->sizes()}; + newParent->insertDecoratedWidget(newParent->indexOf(parentSplitter->parentWidget()), toKeepDecorator); + delete parentSplitter->parentWidget(); + newParent->setSizes(sizes2); + } + else + { + parentSplitter->setSizes(sizes); + } + +} diff --git a/src/blendsplitter/SplitterHandle.h b/src/blendsplitter/SplitterHandle.h index fb07b50b..84966b11 100644 --- a/src/blendsplitter/SplitterHandle.h +++ b/src/blendsplitter/SplitterHandle.h @@ -15,13 +15,26 @@ class SplitterHandle final : public QSplitterHandle SplitterHandle(Qt::Orientation orientation, QSplitter* parent); ~SplitterHandle(); +protected: + void createPopupMenu(); + void destroyPopupMenu(); + + void removeFromSplitter(int toKeepIndex,int toRemoveIndex); + protected slots: virtual void mousePressEvent(QMouseEvent* event) override; virtual void mouseReleaseEvent(QMouseEvent* event) override; virtual bool event(QEvent *event) override; + + + private: QMenu* popupmenu; - QAction* joinAction; - QAction* splitAction; + QAction* joinBeforeAction; + QAction* joinAfterAction; + QAction* splitHoriBeforeAction; + QAction* splitHoriAfterAction; + QAction* splitVertBeforeAction; + QAction* splitVertAfterAction; }; diff --git a/src/blendsplitter/SwitchingWidget.cpp b/src/blendsplitter/SwitchingWidget.cpp index 0a50e98d..dd48907b 100644 --- a/src/blendsplitter/SwitchingWidget.cpp +++ b/src/blendsplitter/SwitchingWidget.cpp @@ -4,6 +4,7 @@ #include "RegistryItem.h" #include "SwitchingBar.h" #include "SwitchingCombo.h" +#include SwitchingWidget::SwitchingWidget(RegistryItem* item, QWidget* parent,bool menuAtTop) : QSplitter(Qt::Vertical, parent), bar{new SwitchingBar{}}, widgetEnabled(true),barAtTop(menuAtTop) { @@ -12,9 +13,9 @@ SwitchingWidget::SwitchingWidget(RegistryItem* item, QWidget* parent,bool menuAt setStyleSheet("QSplitter::handle{background: grey;}"); if (barAtTop){ addWidget(bar); - addWidget((*WidgetRegistry::getRegistry()->getDefault()->widget) ()); + addWidget(wrapInScrollArea( (*WidgetRegistry::getRegistry()->getDefault()->widget) () ) ); } else { - addWidget((*WidgetRegistry::getRegistry()->getDefault()->widget) ()); + addWidget(wrapInScrollArea( (*WidgetRegistry::getRegistry()->getDefault()->widget) () ) ); addWidget(bar); } @@ -32,7 +33,7 @@ void SwitchingWidget::setCurrentWidget(RegistryItem *item) if(WidgetRegistry::getRegistry()->indexOf(item) >= 0) { delete widget(widgetIndex()); - insertWidget(widgetIndex(), (*item->widget) ()); + insertWidget(widgetIndex(),wrapInScrollArea( (*item->widget) ())); bar->reconstruct(*item->populateBar, widget(widgetIndex())); bar->combo->setCurrentIndex(bar->combo->findText(item->name)); widget(widgetIndex())->setEnabled(widgetEnabled); @@ -59,9 +60,22 @@ void SwitchingWidget::setEnableWidget(bool enable) widgetEnabled=enable; QWidget* wdgt=widget(widgetIndex()); + + if (isWrappedInScrollArea){ + static_cast(wdgt)->setAutoFillBackground(true); +// static_cast(wdgt)->setBackgroundRole(QPalette::Text); //trying to force repaint of background +// static_cast(wdgt)->update(); + static_cast(wdgt)->setBackgroundRole(enable ? QPalette::Window : QPalette::Dark); + if (static_cast(wdgt)->viewport()){ + static_cast(wdgt)->viewport()->update(); + }; + wdgt=static_cast(wdgt)->widget(); + }; + if (wdgt != nullptr){ wdgt->setEnabled(enable); } + } void SwitchingWidget::changeCurrentWidget(int index) @@ -72,6 +86,22 @@ void SwitchingWidget::changeCurrentWidget(int index) } } +QWidget *SwitchingWidget::wrapInScrollArea(QWidget *wdgt, bool dowrap) +{ + isWrappedInScrollArea=dowrap; + if (!dowrap){ + return wdgt; + }; + + QScrollArea* scrollArea = new QScrollArea; + //scrollArea->setBackgroundRole(QPalette::Dark); + scrollArea->setSizePolicy(QSizePolicy::Expanding , QSizePolicy::Expanding); + scrollArea->setContentsMargins(0,0,0,0); + scrollArea->setWidget(wdgt); + scrollArea->setWidgetResizable(true); + return scrollArea; +} + int SwitchingWidget::barIndex() { return barAtTop?0:1; diff --git a/src/blendsplitter/SwitchingWidget.h b/src/blendsplitter/SwitchingWidget.h index 15e52ae2..52284348 100644 --- a/src/blendsplitter/SwitchingWidget.h +++ b/src/blendsplitter/SwitchingWidget.h @@ -37,9 +37,11 @@ public slots: private slots: void changeCurrentWidget(int index); private: + QWidget* wrapInScrollArea(QWidget* wdgt, bool dowrap=true); int barIndex(); int widgetIndex(); SwitchingBar* bar; bool widgetEnabled; bool barAtTop; + bool isWrappedInScrollArea; }; From 928a1c7a0d8788846910ed3060e147f1717cbe0e Mon Sep 17 00:00:00 2001 From: David Heremans Date: Tue, 26 Apr 2022 11:45:28 +0200 Subject: [PATCH 10/63] Introduced a QuickGuide explaining the splitter This widget simply contains a richtext label to explain the new workings of the debugger. The idea is that this is the default widget for a new SwitchingWidget until the user is familiar with the workings and we have a setting to switch this behaviour to a more regular blender like splitting of the current area. --- resources/quickguide/areas_borders.png | Bin 0 -> 8693 bytes resources/quickguide/areas_join.png | Bin 0 -> 7284 bytes resources/quickguide/areas_resize.png | Bin 0 -> 2481 bytes resources/quickguide/areas_split.png | Bin 0 -> 7883 bytes resources/resources.qrc | 6 ++++ src/DebuggerForm.cpp | 19 +++++++--- src/DebuggerForm.h | 3 +- src/QuickGuide.cpp | 15 ++++++++ src/QuickGuide.h | 22 ++++++++++++ src/QuickGuide.ui | 46 +++++++++++++++++++++++++ src/blendsplitter/ExpanderCorner.cpp | 3 +- src/blendsplitter/SwitchingWidget.cpp | 2 +- src/node.mk | 5 +-- 13 files changed, 112 insertions(+), 9 deletions(-) create mode 100644 resources/quickguide/areas_borders.png create mode 100644 resources/quickguide/areas_join.png create mode 100644 resources/quickguide/areas_resize.png create mode 100644 resources/quickguide/areas_split.png create mode 100644 src/QuickGuide.cpp create mode 100644 src/QuickGuide.h create mode 100644 src/QuickGuide.ui diff --git a/resources/quickguide/areas_borders.png b/resources/quickguide/areas_borders.png new file mode 100644 index 0000000000000000000000000000000000000000..b47960eeca82cbb895b711a931271c9f557f4320 GIT binary patch literal 8693 zcmYj$1yoyI&@EORiWGN;VuezqXek!7hC2i+!QI`8TX85*pb#{H0L4pjhay3XL-F9+ zcl-VSTkox`o4eLsCzCm6_ROByH|C9|G7&y4J{lSt5lBVh9dJJdu6A4u;M?h4^*kCH z<{P`$uit=Pzh-uJb+WdDSfQbb$5(wAQ~U7t$-|aLxmi|3c+xltC40iKppAQmU6#3M zW>z}0(=wgM$7S(WvEq@@i2AtbZ&k6ZCy#5RDG`K53a=D-#Tr~mpE#>McE8>Rz1?$7l=p}-x-a@@lmdlOLoTL2 zRjP3p*0f|58ca%ZlJ-L=r0hvMbFHNCqMDTEqPTX%d+oVwPlh!<7wEyE+PKVP?k-OAvIZqkvI|AyTI?usRo8uPadQG4;+7_dM4_Ra zg~C9-`d@dUJM6`FyRpq^j%>;zeO_pkZy7m+g)@sZLxj36q7{aVMv_u3zhaVjHJ>K5 z4%jMK>HMXi`}@u4K?eU)Xw4AE?jz#}cyX#Rq z*--T9P}Rtl8lC8=qf@hs06*ZpEnne|!qxRTG+a&uFFM>Ot=dhV~C92~41-O*mVTA90BftkJR+-;eaK^kv#Lx`z> zMc5W<$_i+I|9!r+m8GJgF`|PMUVZSMKgc6+|1jO$_dcY$M2%1|j5)O5uznnhg6;6X z%g`ByC$&$VGmD-5c~(}d zb^k4B9C7h5!nx3$r97IOH7sGXbz4(eDeZTG-1fh{J!tDVowH#Th%Cy^$r;O)m{P*G zR3t&Nv*z@3k|NPlrgqt3AX?6r@856QE|ovE%+CIvRI_9LXLuK>1WaV05SvT^9rzSnG*>%qSJ@ z9uRQ%Hw`d&qd%FAj+Ry_j=Ik0 zbjxMEcXgf4skP2(=yQ%!JI$`g-b`H;35QmWC{fSWXkJcU-iUDB^~J%0;<;aPkA=@p zVbs=GK_aS?R-59c12W}m4xZn5aWZ=ZfXCKYyb?t34ONB;0|+3^_H z3IgFvz>1*aHwb@|Q+<;RPRaZHx!2Zvw%yzQ1fXjTp!}9WS^e@zz5ny;Uecjd0M6vXeTbFGc1Sy;lMKvxo=H`?Z?bWM;D75)z4WTyKlDK1LTT=XiR_UHXOJo zYrG>sCcODzX~~w%a0s4_ETW~Qjox?WTA=(?0fn-`y7TtC+23(LT{8u~Ri7f;&NIFf z<~i6HN=~uT1Bym&%Q~?E2p- z*!t9Wj58dMMkEe3>{yk97g+fw|I$0n#6px3v|jitzLPK9*nGvZaFeMIe(vgDvAV*} z@kG_+v#MwJkjKUKG=h$QtwV@%?+x6+-Sqq4Xej3gu$7fd&d}gs(rG-%AG*g^O<^H8 zM->tCslPa*W-31e(-|8%H+Ka!y{~9#X>n}G(~tOxa9C&>!NbG*QRD4{_4+Tn-K*oY ztycO>d$wn02lEXLvJFDr6+wC&*=0%H?ebaM`F_OKY^nV-B*^Sj*Usvju6>vt$8ar5 zQuY1&_st`Z9zE(eH_a+d`@+5uj=bXlEvHd7~(*_4|`Kp>ERzP!`c zrup-P-vsC7jg4Mip^r2)G)$A)uP|iRz>iZhq6lf;nVK@qbrZ8At0PZ*DmZ(4b6(p5 zKR`{(H;Fnew*saTXkUChS?kd(BhLb$(y_ zpp;$U84c+rJ-dLGmDwydx%|EAll3(YM~Da9h^Td(O{zh4Ym_j+bcEO@TVao7(2zw$ zeQ`8lES{*1fkc@bZW&4n3Um4BxHzml4i1h=bse19; zdJiB=l$HDbm8Q{1i4CB>|0GpXR)%N%Fh4pjS-_8w^r$M-WeD|fISluI3%cs(N1|H! zP@LrU4(y%>^DiuW3G1hgy_T#*Xr(1oRH4N9$i-(eTFrqyfcHj!bj{6K`1berTQ^wi zd$tRLh*L%jWMw`6e3*+=uPvF~^Px%lm)jGO-H}9=HAk<$L!tJAX*`l%hYG%@TO-V5 zc>BbpqlZf^$ucf$KgSDS%RXFLesy7QXlTHB%y_qa*&gKyadH|P9tL|PFv;d0%sNCA z<$bSu#qlGp>CZ=&z6NUljn5Dtlda_^TeUMv7#d*FoMi8Z>uud?quqg5?+mofVJ=wG z_wuqzg8MFIc2lK9OfvpwI}ZQ=d@_#%zLD!WTH={VG>9GJp? z1_U}59(1?PbUH)%S;BLF4q(?ITIBRUXB5HP+uOy;-=%fxANe+Olc%;vLloGm!9dyh zybKWUAExP=y_ycjRpG@LxzG&d6_S+rpGde(2A_UtorH{xi2`B)Us2M-Fbse7BK({= znIFYz?=U=2(|+@`UC|QbK7xP>*6p_U1>NvP5?FHiJ4%j_Y|X~XsNF(z9rycf#K0p? zbNPKw(n@KMKWW@DuqjQ~`tmcA+k1{2YT&QB@^Nhd4MGcLYk${m?(H)Q6k-m&J~Q zb)e}%eB9hkNA0(77)MTil55qf58DU75EdqDG5qe%L!00fEfe_`Ym@X3OS{cxU9n3* zDCVLL_u_vZks=@bkkdJpJ@mvl^Gww^Xnq&_=*WC}_7ZJvWdzKi)mvx{p*d-m!a$G1 zqb_P4Ph1jl(hYEWNHQ8Gb}525MeaDc0DQY^ zIQZy;U_{ujfd-5?v{!K&e>o)aH_ynwrz~wIi8303H*czbGaTtbXNJNwFA7u&1w4Fx z#s?m9pZs}OmJ#;K^C{^4%~;Tb+tzRvfW}V}$u(nEyb8#vvAZrdO~ia9E*Y{9L^}Z# zMB@Q#duu_{_Td8MgFk;P#Fit#(7~kN$r`gXA}q24Iup0>7zkOi1~^I(8TFVcAvSi3 z3>g+6-QO~zudlzkx%nd(C^=_mXKn$5!^3H|N&x`@nwrF-;g+;?beJi-iP-hf!opXd zJh~c(_>rA2U%t%dN56=HgsAortbUz()0BREX2&fAiI0j%uXa0;)EZOTT$`!Ewo5_g61hNZ?Y0b7HOE*rmY+- zUWtvELr_p_$CUdWWvMQ02ed4p||Z1LmTvBSE`(8g}ffr>*&Q>4?glOW6;~pKsDvuWI^$Mm; zB`2zchIWGy*)@^+uV2BPStJ5)A|aXhed|H*3&u5?g@kcCB|dQrzs?J^9_)UJwNLwX z4=Em|Ae-UPkRi0tpq)++SL}=8p>xB}sREO9BGzoCuCK4r2hs{jYJu3370{9TAdy@% z#1s@1WPOmMCDDHkp~U9rPn{Y+pHCW;Y@vp&m9>R3?6)gJJ;i% zk(n8t+7TC+x2NmdF?qAuGh~bJDMUv{NlB^dq$d~^e?li|MFp2`c#7eOC5sxso+&9Q z!SyA<9*Bm6KDOiFRo*kfaX{i78?*4XI6>ioUcUG9WhpY#)6=9#7Ij2LK3x}gLV57x zg=#9In#HiRSE3c7S?cotu<@G{76Un_E}GMp{g()-(Gb=g1u!seu}U6~#V18W8j|?$ z|Fk`UMQGv12&^wa5Q~dO7yK0|sQnUO9mXs0Z1CRWGy@+J5*R<_kVMEExwT?znJOs~ z8Ssz8UbykC9O4XmNj6~Zm1tmS7#kalj^4o-qa#Po%!Ko?!2kz>t6e2^JRoqi_xOpC z56Q960z?#3hv!J{)MFFffPy}@|H5JTvtyMOxba-todBMtok?_c>Oxjhk&YvS+zhx6 z3FUo^q4p1sSE)^N|!amG#jm_p?Dit_^A~-jJ8YF!Kp+GLZ+Ys>;PjQ zG?*po-o^UGo(B@9UJPj%bB!%x1Y4X8NqJ{EDvSOen>GJIsAQx^1t zyx$(gjGr$NM~1ip21IG&{i#pW(Wa}V#*2(Ur801PachYt(3N#k&s~KfgiVU7f28Bk zHmDKl-UFU$8;vO$aTxiqtotJ7fuPO`yhvgo@#4PVWB?B2!;o~pWnTgZ7gxb~1;EQ+ zzkVe_DgfdRb^~Q>Nf-3bpFaSb|H}&CsDdHd_ZZ~K8YxCt1t}+Y_h3cx%Cac0{IC#LEA+-PvNiJWJ1Q3+#}$7A4mJhWc!V zaJ977NW2*r=o!#4+YI?QpmREiIf4Xsj9)2*D~`N7Va7FnFN*%>ZUi_83TK#fL!_2Y z)NW?gRys~LT2-aJ=oH3_uiHr9ty6&2P}_u<3|YEEX6?3A&>r~x(Rr;hxB{T0r%%H#v(9{_ zUHxCY1^^oF+4XI3P_@vQGZl32Nu=UA!mG2Tdg}{~h9qZLsj2ZkuK4`HXm@8q2VvRN z30P?%;na*uN=!hTkoa^F&(M0S=rda?tk$aU*AlQ~F@&M4A*zxi4_2ln8Pa1_g*=X+9 z5(|rhvj3K)G?U@|qH%`3K%hD$k#AgFglc<(Xhi>=)VP2+9=F*`407Sc;{8EPEvL!y z`|@~T{X~vChCHHIhmlZ46d^A}nR@jUh&>5XTTk!X)GjzzqMoM>)j72=CXRd|6!zar zZ!S7g3PQPrIOY}&E8fQn;Nn+uqOph<=0N1^?KZmvgRX}Ldp1q_+nrZ2_DZQ&!Gul~ z20qNJ3%l+p)6?;A_wJm97I?jhG!hmo`8&8QAO)z; zSV{Y$in@%?VB}AIuS zf%}`ri&N5ZGEHmcCDm6b9k9R4H6d@w00r#WT}6_x1F! z$Oq$O@eVl(D#}$F2;%V23Td@Dmxw9rRlXiZyro>Az6`o(f!dqalbe6S<#%dZg2ck+ zA`ROgg4U;liuq;=tq=SDv_KUmqAObI31Oz*s}W9HJa$1?S*)l5|$KfS$Y>iB^qV4vhm3G zA3m^uQu?sD`MXN0e{5`}(TT}3D?gu+iD|5Qz-h55+56o!4HyEcoZ7uZ4GFF`Y;0_( zWeD7#*91jqEj?hQ`u^JqsF44^mX|X*ZNe<|UXTog_b6t+Iz@9Gu{J!tJ^#+&%d>PP)w`*BsMZZY%kzDwR`3hc~v#F=d|&KAjG*4Tnike zh|doQkx!_oqL`7NC3!p0FO^~)+*dT_g#sF#YubbC3rv@eU6(pQEL?GmEGnK$A8*rp zZlDKCOG{(YmqvgJg%Z+!D^AUc-(CZB;^&W{SJ~qY_Olp{jt8=!)xvT1mXEvX%AJFy z>CTlv(U5d6BE40G+D5MNK7d#%lQ?o}@E)zP!jOi1cW<4XjzS+1WM^l$GnZ>0yV|B0 zpO|uLf#DPrMu2+4B<<@Cbjf2b;`A#I7mY#3VN6Dxb~+G{X0$0CP13$T+?qkcHGCVg zfFP0pXsb#HX6{)d$9%h)VH$XM(&t0W8n0{O^9T%2Z1FtE7P9OGwA`cbdjiE1{lb8n z6MD}Ya+fFRrI{;E8dLE1ZaYK3m`o>O7ywJq-PK94QoQf&L8I)|?=VBh=105#)MX0p zr%$uRoJ;^+`0n~tO;wfM(drrXVaMOV4fVX2=ba&#d~U;;LV%o<%B2-}Hle&dnny=P z)rUGoq29pYaJcTRd`@38`Dw(PW7oN4BDf$P7VNpOFxpg4EY-;bSa`{$j{y)hcL5z% zKV*1V9gd9qc{(QB;kv2%84qS}Z?DhF$ywUg*4EzsfLL%;Q&)eYli*YkaG@Xm5{X0t z(uZNgM{Q+g98Z@ekJ&DP4XrHUM+}%8VouA1KT9Bwl+Z;Ge|C2P?FhYLhj9*{gUNS? z#kxoGsP%NtGO=#{;W$bb7(ln)ecJ&P5@@C+3K+w!_EFRDL$|R5M(dvDk?su0@%F&1Fc~tf4zRZ+6`#^JF18g zYs;)?B@0VS#s35kCHD}9x-+kiTVwh^5BIlG#0)PhOlM7l0$f~9f(=>jN`AnhuKXpM#l#CTdQ)Bdn67FMf&%5^F%LVY# zfGH~u!k!e?-%wxw#IBxA-WfsBt&$l`jr=hfu@d?g5%(CQxJ)xo6$I*9ZZX~n;H}3~ z@-?BJI_Zt4Q#5?FgNCa)Q)BvfEmqJos>mDOMA1s04fgZ-jAreHhlRi=AV|JKjs^B= z;v@r_gIK?kMPC8~HFHjOc5SgTqYoAsUN!fIUtJE+@d5!QB|M#=<54k0nS@%}2gS~s z1WM&x#j1mA0n-Xuqr8pZQQKuL-YChlx%F0^dW!J&PZP8N?KL+WuX1@y&<`9w!3DE@ zQ^e?AZJ0ILa~4l}*htl4^!|;`eoPw8Mw}(##)<8kG=jiT(t&FKf16~(?F8gOmXO@r z!xpEX(WIF|`QB@IyN3J*_1wb3t}~VTwf!EvoC-XEn0ZL3Mv5%tQ&6T8g)qaqBOvP9 z4CY^QbLk2Hh|?Y7s{IGKm+pSw>;a)nY{{K`lybgX`&c+xgBA8V6j*&`P?|*5N^b%# zD=qy2Ios8Fw}bx>k+Hh>jCH~686Z0kTnP!KL}LB@F?8%folLZQ?t5nK%cG1-@IWLp zGnlHuN{VC$#vN7|PR_n;vWjZ-GNBg!#N{;3_NzA%U}y!RD(iSHW=i?xYj zyFo&C{P!(q^xX#iPBR=TW(#LkipaeWBLOI zxwYX-?F?3tG+tz;9^U)&6pb248tcDC5(cVZ$uR-F{7s-1135_MU(bUAsnq})Ak3or ztjaDaD45u(O@J&CdoR4XvGGA$+sAi=B}`A%y1#YCMGgjqLfzclJYF*V77!G)$vQtj zw;cfTNW{<5(o#-1267DsTJvrYP!SXm3b2r+X18rKnOddyz$AWg_8ft6qLP-L4$P_7 z1t2gmpY7y9N#;q3vI`1=PSzCj@wU4hsAc1n*qE!Us?O8!m?ZNw-3i0Gf)n}q`R8~B zzsT!Fk1#b{LJlibu$(s<=giN)Y?+xtKOjD;un*~ zH34!8U%Zlvnp$_#stsrI0VcA@s~UrcWCn?}gCphW#uPw=iYk)y#KX;d2EuzAKU`uwXbYNbA%F4oJfU=1OD0G zOpRZqOvXGVp^MDAB~`;6VqS6JWTU%61%@VW-$Y~!5yGoOUlDgp^s4AgzToP2_WNP* z61hK*Yk^Ifs9&Ws@r7XOe|@|f)!wHtStanBX!=5Q&F8q)^9B!turW&oZS&&7^E1y= zHZlw9@Wj^Ih1}n`;=Vz^c5RY&y1!w8i%G{LRk|tPeu*m|7#kjEzWs~dbS%H3ml$pY QydFjaDQYTI%bSJ%AMKv&vj6}9 literal 0 HcmV?d00001 diff --git a/resources/quickguide/areas_join.png b/resources/quickguide/areas_join.png new file mode 100644 index 0000000000000000000000000000000000000000..2adcf93734d70b96a9f9981e783a3a6097915b1b GIT binary patch literal 7284 zcmXw81z1zx`yZl|BA|e@5_7b4h;)pQZb1+kJ<>6hMp`7s=vG?N0RyC@OFCr007-$- zCH)`Y=l8$&xpmHa&pq#XKkw%~=e?0ST3~WA1~LEuK(3~$q=&yA;E!OETln*D^p9cy zfKbOlQBg-tQSphJhpVjv)CK^Mh%Pf2(lF4azFO5Rev=v+5;sgq%MtVInH?l~w}ME=Xs(Qs$?!N3tV$~DIFiuUkmr%CII0atBD&`{4RgFI0S^tnlDq7uN4YL1jzw{#E%WAak^m8n7T;!i< zke$%J`jCl^odApd)dRlYbS2!DOPQnMG7eW^lc)K;<&9~tm?p^ zx7DnJ;3*pEi!<+{Kkl_`zhCWZROPQq4pO+i6i`f8N1IEjO^AG;bq*Qfr`M$Fq`ylQ zzTWwdqlX6PGN{yBHkppF>)Gz9Zrg>>2))pU58+CVJZ6jKToY=(brjak{jrY64pL3~ zb2Axdd3~h0hj?hmqMN$qk`ccgajIp@WMeepQyfq{i%#m1kna?jZ#Yo*9*P*(xaic_ zTUP$iqOO_oVsNDMJEMj}DCCM%w|Jg2oXk`nTWyGUF;X{G({}*CeNX(6K_E6ypNuag zhN)>P6R+N8AO-M!UgEgI7tzC%O<;OjMaZ}GF&#mIM?lRhW@Cv)=+I}JNnAL|2dE^;u&fQFL`m6$+{QCI&2 z1?KM}o4AP%FU998^z_I|pu}Il`8l6Y@6Rw8O+J*!$)lE0E*pxmWNA4XGV>^uFc$-5 z4@8O6-=Avs^Ko%;k)52mg4=ADVP`UMD`WAKv)EZa#QpGKm;tfa=atxpGp!Mua@|2O zZO1=CU98domJ}=kk{)M=>-6;WCiO1ZAEl+dx11(Rxp;X+;+iTvE#H0p{XyFuQ=DJ^ zeGnDEiM_P<2dgz;T|lA1>g}&9zdQZrXUE8bU!DhSyKJ~TvoA3l?moOFZh2C>bK<1} z26wkp$j(krfBI5oH$+=!H;|U!$_ELq*?e2LNmA%!pp7bL_qmmL{U=R&&oH+8plXza zQo0s_Q1?l(P`N}RaFvvPkB`)!o#t~bl{oAGR{2`b%^p|OJ}o+# z`VZ_gL_>4%$$W)EpI$;z=@?^|jh&bPCeF}sd3sAV6>BP3wLjN3E8{b~!n8%bXdvGl@vHo&(SzCd=iXcEl~4V4$F zhGZDUU1rrlnXsb?rESS<(a-~T(>OaCh z;*2f*jz++bC*GE~T%BR6>=eToz{&Ac2-Yn}dcWb@FV^kW~qpvNU$bZmyFzEC5OL%$XzB(D_ z-un7F6J~n)8-_AxUsL;VU~p+qhh{cvS(PjTfdpyGEJm<%-UaK)`h=$)X8fh$0HFsh zbn6on6K}^Oks2Brq>cX;qqJY_-6r@JA7=go#`UMh={Jk#xUQw|UT0q-59nnIV18g= zAY)Wg&hLDy_S(NLVo&;Bu4b>8UxUlpXC(C@sRCS2@4?^kiHW_MoScPGjc1o)p@gqs;e}eUrH!sOp%kqh_^ukTKAC7>n`R=UEF2zUv;AJar+VA7hFVvbaqsiI#(-s+s(a8L^0Fu<}dHQoA1&JJ! zgwT+I&}zu1x?lqrWo6}Xt-ZZHaV+d%kn;@sPn6T%Z}WHLkgBo>{z<>)EF3V-Nv}`K@>ic`rqa7s-2nT#A*w3S)GM%c~c4DxM9vzKqj+ z)1SmwJMS-*IlD1Yq9{0>T|bE!@QhvAugS|(Vn0uJZT=Gj^T<|-W(Y-cC+b^R@N@k& zt>5@oBIYt1A)8Z?ZCYh3eeg>-tZJB$;>9lB40aHR8)06SU$0o1@BBl}D&e?+d?{!T ziwFpPY@sGRT>UTf^z^hNj#7q`;Ca@&A?eyCZSlGH>@;P5E5;-Xw$n14?jZ7A9+hxa zF|NN4Ll`}vj*e}l1(mf}I3q$qENCEI{9RxLy`JQQFq#3|p1DdZLQy&G3g%zT?*=m@ z!>U45Gmv=nJFosqEm%)CYTk(~z=(>7=+Imwst($`kz4pBJao^zT~RrBA0`;RuwWd!#-$y|8 zhCw8C7!2li!OPT-wb8ZeDPQHq2wud!8Xz`b}lVARL z=dQ#ZP!>yaYxW=BjuoZC{s;j+z5$(IfW#f2uPrzMTuDVU+t13x+pOukz+`haM7vo* z##A0naTE$AR6C=|_>Sksjn;dM%ui{$gP*@mh~{Y{h|{!GzKmg!X2_1!)hZDsyNfxy z&B_>?3OK$YnuO%tc%a61-O_!@Kug#9723Yem9u|Kv70>LHUJ0L6MI5-$tW}WBVqrG z_d-X~8X+@sqGzRm8B{puFX6UP0Ig^!9#JdLvVX=u`v zj-w-Y6EERpM5crXq%X2elBBb<)7`5}kQvXID4YH?b|8QEjp!=fFpaUf``LQo5~C8X zg9@mx1yvke{Gy81qwa}W;bX5G3BhBeC{sMF>80d%(avvmw1VDvdJle@{!T3jmX;7! zapC@;!B0%3FfUJnDMlVSP@gCF{F^aj*M4^-pX~`^f&1QP&lX5-Mh4TUZo0=k>(ix< z<4GM_NK1Ymq_3;%3vbU{(aqgt%E+^p3lwa9G$bS>%P-HnCgA!?u_U;mp(b^5`UPDy zu1sBB26aiv*w@n|06ZT?EtK;+%Q%{ur8nwKATNXCNB?|Ev}6B*Wd2^pw|{V8?R!8T z#ryg4<7R%35rhYot91O$PFMbB4eLT& zcXsC8UV(pz>@?GGM4L?V%Q$;i^u(vESMs&{LHZV2*8JS`{XXMTbz!&M=Q zpp;vjL2YdcmME34d(2DOfr z3}cr}R&7&LQ=?*$XXxwlBYaFMT)Ba#$oR|<-jy&Wd;qaVLh&A;5jj>wPoDzy)w--` z1u@c`zH(9!d%EFc&QSXGtHL=M5Fdv}k$nE>)laJ06wZqg;Lp(Z7?Y{sV5Pv|dg}hZ zzP6f?q;>zdvmK+OqebKaAhM2Dr7&z;QWEWS#2mPdB^JCG3Jq9?*xHWr2dj#4@7GL* zK%WR4V*Y`qe`6cGmR#x2pz}(*CcfcWx~z=uy??lB;*Wrs%3Z7Dd^<3 z3Ph^LKwVt6lc8F9a}p-~)FV^zLZSuoP=;P(`ecp8=6d}L{FY}SIEWBOh0z7j#DHoIr&0McNdPn&dx-X31c6{CB2Dfl3jD$A9I5q6Kp60BY_@Olopz z6XUNQqUt;8E}(ssIYY-lDQ-WsRfRZ7Qf7CNzF@p++adq$j0Tkd57R zkk=-!Q4g*O`805bvlm(j1hq|Z1rY$992*^gQ3N6()l^pTZ1?WXlBtea^0;v%@^ZKV z>e600U5&>+thQqxZF2a!=X(jAcVaj9hsPbLyzEViq5}n?==?hsD&v}1ieY>#!kjUO zDhxRaasX7&OE$^RAN#K|VRL5*#UgrQ(Fv1_ph%H{Of<+wDBc;j%q`k+yOL7pZ|vW^ z9PkXUzMj}PV0hSuND=LTD(Ff#Lec%K;XouPmk@jlt!y!RlJmOPM8i%NfTF+UI8?QM zdMJx{3>-PL)<@N!Qye1DD#!Q;8Ih>wr;bB5Y0sQPp3GE6u^x{})3FJ@WY6MBqU(tZ zjEF&Mee}tPdm&4UMV;R%%}YPwD!nI035x&d+Q+2W=)gfRIC`9Zm@Gx!x@RC!#tuH~ z`d6jXLC*YKl#oLoHI~kil@85Tp!Q(V%PD_Z{^1+V+eyzjOUP+~R z#hDaH4~ZpO4NE>j3A(%CjY>i0PJbj=2Rmdk-wqLsWg`7~Thg(67%-a zS#8Et+dM3js9(NIZV)D*TU21fF)j_Yomr^$-9zRryed!{O^avNVo>XCg=xQC3yc>P zovV%~&tC=9#aG5{RnQ#T=^miYqbq6z#a%m|qk2Ovh;eze)kKr#&)n7k#W2UzFzUy_ zX3l{`tLAhQ-NRcWqobeVg}fxEa^j+*`*E>sYV`eP?ta(b#z5ddpNEVXC6c^!537EUPz&v_iZP;+nxe#No1mR zqQMLtN~1my61a0vW305{a*3rqGM{nscF_k#0&iQ zmSF2ZB}i&NQNXt+W-3MrKgSkqwu`5s?ecFWpA55F3G$DRY>Wmiz@9(!yd^_~C14@p zM$urBkkZ46#DRCaiBRN7;(9H}BcXt(2h^BP(EeVQzkP(9$=&A#5Mi=aV|oT+lLX4= zn5>A1TY3=fd;M&8ty>m|oZ2h*bI|A{3-k9!z?na8JqnD@DxcON#lyXDu#)-Dsht=r zQ-~Gr(d-*%IwKZ2F;ar+{uQCP=p}j2zYV?t56u-pW?R^zJmZ^MG$loc&_kVI6EoS# zov$HZ_Q$myia77_P=r8d;oe?M6w%Ofg7#S#jdSQklKN%bP3INF;(PJTjes{~Msf5g zlOj0GTwC%#nW(6@#!KfU5;I`-9~k!Vb8-%AGlCbB{+T6E(xbk!^6`kVNReCYh_)8o)mZ9N`VGS-Kp&4gfdW5ZF+^&5LI{ z7XY>Ha<lr&$Ru;~9%Mf3!4PT}yJH-f< z|6Ct!A)?T|652m*ZXi$(Z)b&+oZ{hEvTC>KwBgPVKWW*_aFnL-=uTmT znVz{h@9)H$Z{JUZN_P|>jNY>s?4^k>;uWF6SaFyQ46)Qh!0s#Zw|k86D|fKhN)Ve_ zFE=W;VP6hW2BE=>y#A2WV}$yI`&<4(2f|~j42K!BC~X#J)94*kSx4OzS0+H`9mc5R zhm{(X*f=NlQB5JSb;J}3AR)L;h=JMO`~gO#&bQYG%yq+fOlJUJ)fJ@Lg`X7^|Wjn8vjKciUydQb_ z`R^N>z7)Qt*;GP^Nl+LVGV(*?NAC-VurM-<{j-hW07<&LGDJcv#qy5kP3z9R=?qMS zTEDO7)gMsgihsTCb0z?#^S&{d`6iEl`vxQGiW#`Ht2{h*$>aZjU=`rw#w<4=W|jKE zL$SEDR9_x{mPd}m`AyG(l+mL(Swo@=(OkdY&`>JNah^3ztVp` zpirP`>{8-}$?)y_og`YH&iP7L7a^wt5LV!gXc?$#&3wP@|GD3$E5aCWGXcEQRlKlQ zbA)Hsc6(OqQ@%Jnm9oQ(!+_$_iyaR&^x}7+*xWh& zwcf!&Jlm2q@irr?>Nni97Nk;If8f!;ia{i+94EE76u{Ekh-+0s4 zs6w|D~+-H8Qy+2yYTwtQ!=Wn_K$lXn&*O#FwPZvDuKhpoFLlSQL zZ2MEVcf*$M^HOcN(FGdX`k6uuIyF2!{o`#Xne%N)zcUyS;xn1;KpL=4pyP0h5KmuR z^M$IYnoaDsW9|EP)Oe`7MT8%^<@Jwx);Nh_jiIvog&WsmJ6~uGcK%RisNd(46_>HW zEA?&MGp0&tum;-qyV}LfZ01+0F!TLzmE*6 z+h9-Z@v9$>KMc+ozICyWqlwBzlEPc<tlgFbf+VLZey)o;7RJnDXf&$@hz26JK< z!%-nnAW&Z{At5aHJ|{lckI(b}FU=2BM#smqnW=F}T*~el%NrT?I9}raP5{)DwUo*g H-hBK&_hMsH literal 0 HcmV?d00001 diff --git a/resources/quickguide/areas_resize.png b/resources/quickguide/areas_resize.png new file mode 100644 index 0000000000000000000000000000000000000000..1dc29f41f00563c21eab899df525c77b25bf0126 GIT binary patch literal 2481 zcmXYx2{_bi7r_70Hx<)WDjNHBl@^5=p-437j$MV+kjl&$M3%-@LJ?OaghAZMKDLZ4 zOLpOJW@H!Uv5gdl(b#5;@89=)zvrCyJ@0wXyFKSQZ@5bkm#GM+GeN0w;3#i#Wz138h$2 zmEfC9B;V6aA-`4doRog-I;mZ+mEB7Vr@o5JFOF7R6)TIBsDfh+4UEoeReB#j>S2=0 z7JMNaYW3+Z>o6~F)G;q_jIY7+?R##=R;%vSt_{-}f2OHM+A;ojUGxXz1x%(xy`RIm z+%>DP&VLvjVmY#5@Se+Mw0ExcawnoaWA6$iesS3i76Pe7DnY1`G_84-EfLun$)+9S z>?u8>W#6A`&VODrfeQ;cd}uYXMLjg{Xrn@z4szU7*J51TCj5rYNGeHoTE(kqX=Ffa zIa z_>f=iT5Nrniy_W-S7u~4A1lxk8OVTD=_U1CvFn~I&eLTRoE}$v)T8Sx>+Ae{mxC3rYSL{Sq*>F zAbx^&cr5sgj9rFb*fIE5H~OyBf1@%_NW> zIbh0fH(i}I3ixbdo~}#lYcH2JC5Af-4pKqYqI(ckty0Px3SNYjNh znTTY_xz874ZnTfJSLy&DTX^Z{@1jKb8r||mdp>-K^Y8`G-ne_dIA;YvqOXg>HH^8H zUFaW@03h_*%Iu~Q6by0a&K)ck>)_zv=;-L|?2O0b2?TlQZvebxy6_u#(iHNzM88MnOvV6PO$(BP*3*wQ%9 zPTb(=zDJlI5P6q;*-Yb{C|X}m$~G0ZMG;|vXp zUlzkYtMTWjPsm2F?W>m)TjzG3GlnZG2cMj;jvv%LKkGj@xT;Re z_qmHkKYeQ1wdhq}lfv7O1bKlbc&4L-=BB8>1ATW`?KOLRaynX{`bw0b*_gqsS601}DWy3^4hsl&b@fKVTKU_51&sQ8 zjJOaYF9tL?HA)EI3%1e4s=}q0Ud6eMoM#cjdpPXNt;RaSz3E%VNlev~G2XEBt*(t; z%hzU7b8u~+;^pd%5p3<;n^u|l744Tw^%-yN$#3ls`8-ik%RmwnQ4BEpJ-L110CYj& zUKue0lDHdoFZ*36J|ikV`B6(*A59;{thwsgfj=m{1lL$Ao}T(gT5}BH!m6Fd1$=|% zLwJ;b;^sC!VzSeP2o`a#M?XN8HBSvE(ez4vsCSlt0FT#IksV$!uBIKRZ2|Y6`&g@g z(yRgd+u@)iS~R25$;Gabn`w{lgn>?-^Qa0Cu*#(?qK?bR_4Nc{V!@^$)O$O3+gK1t zB^%*^UQiJQ5b$w`5L87CT_1YS|7A24;S6JdDo9}$yaZWD0~HOeu*bp9psdJ3ZD7;v zvwdzCplwIxI=ain)=pOKT6bfMSO#mm(Zv%p^*vIy{rIj%({2w7+2oFTu33`v%pMQ~ z9=LC5CucMqaWiWH;Ua#2JN3+yrVyqJ=!#LHNV36JgnZ9%MV;TOeqhc8xEiV{=UYAH z-yXMHS*PFWNWDlwxKE7YN9zY<=#Q~r1}p_}l#Op4;dnW^2B&z&P^j2&GQugD`&eg` zN*$Bysx$+7;f3mc^wN!k^Ol?bI2b8Y;~Gesq~YXQAMM-Rf9~jlq)ZtMtaapkRU^~b z2HSsnU;&Lq3a53}@*4`f`*|wU@dyQ;3wA=8YRrf<#fP|OdsU{1$51ArsBb?tOM>N- zei%b`TXl^yY!6ws2fi1nlZ1$LCY?bY>Vo4w7lYlD|A|Th!Vupy1Xn^ixkkhz$~2yL z!H=if;QvJm=aLO1nb1l8n-a-jQ*S9O;>nX`RLaz?H-GA};B=`t#-c4A2T6%+#SL<( jKE4wv912?CV7owEq*-fDmh+e2A3Da!!m#A3Q`mn2JD?$n literal 0 HcmV?d00001 diff --git a/resources/quickguide/areas_split.png b/resources/quickguide/areas_split.png new file mode 100644 index 0000000000000000000000000000000000000000..6d96f79bebed2d573e10c275d123ca29e7f4fe80 GIT binary patch literal 7883 zcmZvB1yoesyZ#W;jesL5Aq|6c!$(PjGzbhev;z#?A)%BA!q8nxNP{#;4?kFe(V1K_pWu1QjNGCC^~M$raF3t7I5KlwaA9WBg=AICGe zadQ6R{Yl1Y33?+Axc`#MZ!YENxrDQ~GRw;vmPE@g6h~mYtIAnZm);J8svi@Sr9{L6 z&>lij>Vak@d!KgMi=Fr4+W@cF)I^5-0JQo{9M7J?i*zD{de7pN5k=$gQte7`DE!(^ zlR8G6lpT!k85Zs3W!9ET3a+A_~Wkt2sRIVK5g%A8g z8mNTx0fNS+Yo#4~S<5YM%EceoZY~E77J=c*woWvr>~fOi3@>lVMdeuALaNl$bpbe4 z(Ht%|j#ZIJ@sAtSXIw|zo~TCkDe1=MGt^!{9-(OCSR<#?ywj#kS|KtKvLv;dIwNu+ z8sYd1tubk;=LlkQx})NsfAopRdNcRCxSaD{%-m&ZaQDPK^S4l~>ky40`I_6RGrGom zy`vrLxjW6H?hm1Y0vj?64&t<1L4j&IU_WiP_c_w4vJ9+r&kJn120yM4ZJBq`L6O!}EeuX5gR#a-$^7#xgegDS%+SDMp@B@_oh>+Po+fs=7Fnl}TQ zCtE53-5T0CG80n+b@ZCf(e`(Q`jzWku|#HytBppODMsk=+zbW)kojO*4wl$DFasmR z_g2?d!AIggCIk>$9T(zYL_lv9Q*R}xySu|HZ-A1QgN?U?J&T{Sw-bw+y0)H41Q{Ks z6P~T6nlj-2?^e)Ro(cdwo>x~^H1uCO%Ek9!Fv=PtjaiD6diJ3GC6?yu`(p&-%UP;) ze$yAdS=&hid^7J~jclZ|2|N`9gN5+2IWm9Xha(Jmrz@ z2$hB1hN0b?-A9QRc!_h9i4FU5ZhdPd%Idy zdC}2wi*WovA9e)5)y>VGhK9yjTUhf7o$^nc+hYB|%&EQW^VC2P!VwS($bQtkB_M9t5Bfix;jFCkES&Es8@-|*ZMMZhe_G^9EYz+?>OaT6@jKfw|EP4;=Cueu) zw(YIrdJ8b<>+nCZMV?Tu*yCM0s4WyVQKL80#5hD7v7KGv`Q0ML^ zDZG*piUxLm z1yy7H?h3hHIGvOiR8T!2d3W-FJu6dI|DdoE)Zfu7-V#kr7eh>yPghcTI!F)I+vXS` zJw;>+4{%D|6f#v?wCFTWFbDsNsDJ__A0z&CP54ckPPKKD6_>HpY=0d3IW2^Wdv!Fs zQ7gKF@26osNV6eMStH|$_gX^Pfihn!0?2$Kf3?e2mvElZ(IHcpP&e<7UljS25+MnI zZDy$&d#Z55tdL-LgDkTHptc+8YD0%8*h)c7SzkZp(UcM^M-jhpyhNIdTtyfL$hZxZ z2teCW`8dL}^@ADtGQYh%qK`q%+-!Tmp{lAX!N}P7?V1J^w?3)iAJ}k0haS1Bt1BV0 z0)#?VZOHIQDVGBQ#xDVeb@&0NevjFR(<^fF+bN~TWO1kI6sPD*vd zUcsS&Y42lsl6sXMS!dBWB>#gFE~)Z&j2Y1esr3Y}mB1Fkq09|huclju6}6vqRt+7I zU8VaQhIN@7E$;4gE(cwJPs8hnN-5>Oe*Gp(#hre|6DVnK9E#h3g*Z}c-XA|y0w);` z@rxB6pTAT@wY;J!zz_Wu{e-!moclWPOb9zy8RU483zS`uf*Ucmer(Qdv7AL0j4@%LQ&o}nYkLLHJ}&llxe^QYFoULNqGHr@dPC=tcKA>;yc z<~t+()xv8jKGnj0cZ0oXM}9kiM{O86eIpsyZDNSVWX`yYoqXNw`8tLo^D$PD-CL1TSuJxNM{u zxy-je-s+xLkSkD9kpIkh9niIBEW7SnP&ff_UCplQ_3{oQi zb^q!kKAf|FGS=OG*A#RR?EFpDe*ER2Z@KFRt?7H*wo^~7BN4HBfif@)*%O#sU#tB+ zd(HzRzke-FyC^c;KHHaHW$0RF^dLK_f?Sl*iur-pCyMVMp*2J`GGe-xp)*u}hGOT@ zK4E5KjyYFf(7T?=T+r^{#uqDa>7bJVx`xdp=_E_95sp658m<06;1@T}<++18GAGJn zu5)~67%r%v)|I!c>b~0lv=Jhdc{j>i`*1nzB;J}p7x?UGD^(Zr$)pzInCnB^eu>Op zjHa{V3br2cCh6$){PmgAENRnHw)8O~>-VxAv%Xy2>)%cRg-lck!kz@^X!xUFfPK-^ zIWDf}2(?*aP=5w>c#pleThzfSw?WzG2gJ0WU28kVI#6@f7K_KL?E~n|Wci8X*3Bf3 zrLB=vGc~nX(=Kl`hua|YnqIJUr-oW#l%Rx<-1?HcMnh0pjQNsLXNH`ngCyeom^ z-SlIZuo`|-|F0UeSL*HiW{czU_lqyPTn33sp?>-3MGM%XcK6L{9IW4ty~7%ezDZGI z;_gtleIXkjja_%}|$ zUUD4{%IO=*df?c6rIh83I)g78v&74G+tGo~L7Wn}MWW<)tT(yKrv0Kvqza+(3zXq zg7EN_TZo3Pr2=8vwWRs!U^0DckbcH~V7agQmX&Dl&d(4nM0+P)NQ{efMVRJZ4t<2e|&9^o2hkNU^Ewr}1e!QvID01;V1{Ta+MgJey2pZOA1VRF&nfDpr5(?*) zm{^DS_|r4=9oP)oCz@CVsFW0nN+aQR3l15UwA7I7aax`B`@3rue9Nu2y8P8wbnnPp z@fRA(WvXXtmr4P8(1`3>DZ6O%^Wa2tKQ(QNYJbDjTO8!LoFV8A)Y9nh6Ou^0p32#sXQ3>(1{I({RJ|CW^g6x3HCjw^H)`D}M)4#0vPYI)d zbtLL=wn@e|=Cy!QYwq2mcmZ2^+MD6G8MM66yu!>QmB(AIvMZe>7CvFpD_I9NNqAC? ze`ff5m-c2|R;^uUR5;P>L=SGe~)>3=eA{9F0Qeutw4>rQc$jBCWmw0lV;HOd5pFs&8L_6k( zJT({n`mwKR#eXvq8#TdGDlb43GRY^E_z@;i7%ihf_*jJurYLZ|^}djie=&bKyZan~+n>SeG0 z*~hoRUodtNYT>#)OdYTZV`TDjN|^#0o0|s?L*ZO#_di~k>Ie|&&A~+k8Z0-Aj$a3d z*s!qlByc;M#t3c|CrN2YSoU9G&@oWchJ0L?;0~Zi{t4L0GWtQ9gM3Ku&X&H0;+Gw^Uw}kE=Q6!4De4=_oW+BG&?S z3?6yOJoHGga2-!chQ|7>MCpJWu@Dq^i9Lvzkv;D3<~v<-s!|nJP(k9uGu|$j+Mlb1 zid`e)tGr+Q=fwq@{)A;ka;QCg;6C4?7X9)bKvCd2^uu&3qT?MWdQj4FOXaiVky(5pIXzmxdu%x~Y=LuCZ z1BwsBot4=J?6JSOevpBzv(I#_w)JI}MPMOOcma9w?X)CHHTbf$TQ=XC>^%6;3RZt1 z!!Tl%-!fQCKj!?Y_opwhBP6H1Ehk%XNZa|&>mD72ts33-* zhi{!ywn0jrDzY1yhDt|DxTg}hjKz0=O9gFt{M|<)4++~gpIUf3COew_gVS`I1D?Qw zV}0%@1Y{G1+A6MDPjNCxW4m2Dq(@QQZ+`x!L5;8@IK`A^+7`LsJJe{5d<}J(*qxnh z%BFhTrw6(S6XSamtf6m)lFCg#ztsO2T%P~riZbsvS;?QIlj~Brbh?V&kfMBhqPFc^ zmGHnq@cMIF%l$`DT=#oh`tlzO)JhgR8F5fVD{8jZq_P5EWgSWj>$GFU@o18wjWHE4 z2q@!Tkh&|*pfLCiY9}}jNiek1D{H)IQ%966iMFRFH_LO&6&`w$dk7{N>gn~MPfvx{ zq`U4meMZyGvLy{c-3o7Z;HIGIc|5yPTwxx{j;OEH(YmWcW(D8mS3Y$j%Ig6JT;B^N z`((qRLTv9g$`Q78Td!?!asZ4qqMd?*EaKeZ+LtL2S@ZLCJd;aXLiZvuJxf6Vhm^yn> zpdBNbBCiZn{=_HM*Jzx@DxF2W0h$M=vpnXeTADiJfE&C9hP_eVRQjr_9PzO1jKRdC z0;U&1?w-TBbf@ZE5=BXt8Ua+qsc?7-?+2+7lW;~)a$LAkwJ~C?*oTYrX@ZNlZPHYw z9zEozgr5L$@@d4OYkc9aTwI9CC3AH=*D2oMoUd%2lyD@jWx@y``IDSHBwbL|vL{4# z^KRv!Cd$IPvW^(=1O)<6+1hHF#;q_Y8$%r`iK4p%`0|O1i4k$0?r9XS9r8s=i#9uM|zh``62&fNH~`14`tFRHbAl*>CmG1l0?z7C1~So z3=?fhs7YwMa(@=g`O*JS`SDyG$%S4e2OMB=oE(c^Lp|2|io_>P=o1A^zmqgt*`C<2 zxh^3%ZZ!E@T}q#CF+uDb_~Jz_fTXWq9~xTh_WRnFc_zxcgc4zf2W#X?c2b}6vIQ#O zxb;N(7&5IOLQT3O!(E+n=^f`kCHZ1B=hK;!0~yFbcFdVEw9NA?^PXgfY{3Gq?|yc) z(uVwKGF@&^=YpAXyf9_v=Q1y11Yg{K)?&%QS*DPpOMe$C-*HfMGo7Le+5sS(WNpqy zM_DaQ%=B%@h(8mp^v%2q`oghW(ad`#5@Hny$NG3z7~zhVp_quDGm?||MpXDmb?j+! ze3LAF1QY3&y-j-OBFJz1fVl5S*;Pefb?-SFynzJbT%+;Cz>usXbtLsi3^r5An4c9N z{>K{zN%HhPi@z3~|?xt{Ij40LdUu4_A9Ktk3<(zqPU;g%iD-9mbv4t} zj5k&7LbuyZnJ(Vlbxg;oh8h5RR1s2^>rGM_INq$iQri1!3=!N`Uml70z5@j||A^ z(JB*r17_j`DQ#P4L~9>?Z1WZ-gz&^C^mKS_YfLx!PMJIG{MHcaXh3g!HF*Tsm`^B; zzH-mD?0do!e_>CA*n2b{sSgeZQiDKJe3r$KAAN&vQ%>xUvC>o7dcHqsC_nts`24)= z_o`lGCMLeqB*GA#kxavj{F+QdjD=dDav;RUrB+fRb<|>q15OBeA=ZTe(lV zm0>N%;gv^**`rx${z;n3R4;Du;{u%$zbB*}qO{e35Gh^ZNlN0sLtaaMD6kVf{YdWn z`e+wfiOU{8`%De{qqVq3JVyggW$BBU%!z3P>}zD^s2_=q4#%$P_?P{tyIwRVtKs&l z{0&U1#p$MHz>z}*m&!DovQv>$hB|N=no$XEKqwWnFdldhra2g;!Oe7C@35#8Tq(VH zOzxYINc)bD7LgLJF}=h!P5}8oG>Ps$>Jrv82-;~e>S$;-s2i^%=sA&nw={WYm{mJB<4SbXEIW0=Mp-V;V|L`b5UYmp36k)Nc z|1sT&doGc-^q}Y0#GGSxR86h4%BK~yzrnW`Hu^tFpF?nARdW)VYi@r{Ws|UwIu$u! zP|Yu^2p*z9+GEFKK@{2#rlqXJ8&qiut;@~-saLA9%d_O?7toeqF>6F2>ef=!G~*w@ zq_8WuHU2we4D?ud@OBfwH?(aB7UfGqs{$;(HzTyit71g>8f-mIxQ`M6V^naqh~pfg z71rguMXGvhC}FptT4WXZj5dfGfeTCTVIXWg$`>j02^|)*btz%8uk;Vc%wkBSWE4oV zAeY%EE=dsURKykZZI5}1=Rk1|=RX5!d-)*xg+5(9&qz+0Md3bA+n(jVG&0adh+B}|fXEy)ZTm~flcx(4*f%e(P zWP+>a5K5F+*GorXg7Cd-=B+Hk;z0j~*4og_*F0@sdzP*F!>wMK1buFd^Od{N0WXbO zt|ebKRzv1|deVBfOWsyacn-Dw2N?EkbA5e%BYcrMph#MhlVt}N2-5-MHkdJj|EGk4 z7*Z@leJdiG!ucf?hV7;EPG|>L6*MFzkcmS4|BjwIAj~UQk|rMVjm%VT4)r@&WEDM@ zDmDMVsiao}aSA_puZ)SC+0rx4{haWBPbH>Ufh~&cf8+Yo%mDWpCa}pk@W1S(1xm%x zWG2yjW!4?s80SYn=VoTUVix#KJw59lJt@BbEH{_B!>!9>?WIGp!|tA7P+eO~em@)& zgJ*1H^g;CBd+VM%IV`!=`&@$WV+tPPA)FqygU#$4~`8Uc<#I*9tWh#S5 zBo(Pr8&7Hy&LLWi^!$@r+W#$%#E6gi%Hs!89m}3h8sr&vZRM~;s4tlg{T`Z|n`=Eq z%xndWrjBOhP=A$FrD{tDshB`;_1aa;pcimmv2IWRxH0O~3_$~FIhBmWC` C&@3hZ literal 0 HcmV?d00001 diff --git a/resources/resources.qrc b/resources/resources.qrc index f1d57763..f4545386 100644 --- a/resources/resources.qrc +++ b/resources/resources.qrc @@ -22,4 +22,10 @@ expander.png + + quickguide/areas_borders.png + quickguide/areas_join.png + quickguide/areas_resize.png + quickguide/areas_split.png + diff --git a/src/DebuggerForm.cpp b/src/DebuggerForm.cpp index 0e6c6146..a0739fda 100644 --- a/src/DebuggerForm.cpp +++ b/src/DebuggerForm.cpp @@ -24,6 +24,7 @@ #include "SignalDispatcher.h" #include "blendsplitter/BlendSplitter.h" #include "blendsplitter/WidgetRegistry.h" +#include "QuickGuide.h" #include #include #include @@ -464,8 +465,8 @@ void DebuggerForm::createWidgetRegistry() tr("Debuggable hex view"), []()->QWidget* {return widgetFactory(debuggableViewer);} }; - //WidgetRegistry::getRegistry()->addItem(item); - WidgetRegistry::getRegistry()->setDefault(item); + WidgetRegistry::getRegistry()->addItem(item); + //WidgetRegistry::getRegistry()->setDefault(item); //8: register the VDP Status Registers item = new RegistryItem{ @@ -506,10 +507,17 @@ void DebuggerForm::createWidgetRegistry() item = new RegistryItem{ tr("VDP registers"), []()->QWidget* {return widgetFactory(vdpRegisters);} -}; + }; WidgetRegistry::getRegistry()->addItem(item); - + //14: register the quick guide manuel + item = new RegistryItem{ + tr("Quick Guide"), + []()->QWidget* {return widgetFactory(quickguide);} + }; + //WidgetRegistry::getRegistry()->addItem(item); + WidgetRegistry::getRegistry()->setDefault(item); } + BlendSplitter* DebuggerForm::createWorkspaceCPU() { BlendSplitter* split = new BlendSplitter([]()->QWidget* {return new SwitchingWidget{};},Qt::Horizontal); @@ -757,6 +765,9 @@ QWidget *DebuggerForm::widgetFactory(factoryclasses fctwidget) case vdpRegisters: wdgt = new VDPRegViewer(); break; + case quickguide: + wdgt = new QuickGuide(); + break; default: wdgt = new QLabel("Not yet implemented in widgetFactory!"); break; diff --git a/src/DebuggerForm.h b/src/DebuggerForm.h index 642314e6..3f1079d3 100644 --- a/src/DebuggerForm.h +++ b/src/DebuggerForm.h @@ -48,7 +48,8 @@ class DebuggerForm : public QMainWindow bitMapViewer, tileViewer, spriteViewer, - vdpRegisters + vdpRegisters, + quickguide }; private: diff --git a/src/QuickGuide.cpp b/src/QuickGuide.cpp new file mode 100644 index 00000000..dfc06ae7 --- /dev/null +++ b/src/QuickGuide.cpp @@ -0,0 +1,15 @@ +#include "QuickGuide.h" +#include "ui_QuickGuide.h" + + +QuickGuide::QuickGuide(QWidget *parent) : + QWidget(parent), + ui(new Ui::QuickGuide) +{ + ui->setupUi(this); +} + +QuickGuide::~QuickGuide() +{ + delete ui; +} diff --git a/src/QuickGuide.h b/src/QuickGuide.h new file mode 100644 index 00000000..51c5f361 --- /dev/null +++ b/src/QuickGuide.h @@ -0,0 +1,22 @@ +#ifndef QUICKGUIDE_H +#define QUICKGUIDE_H + +#include + +namespace Ui { +class QuickGuide; +} + +class QuickGuide : public QWidget +{ + Q_OBJECT + +public: + explicit QuickGuide(QWidget *parent = nullptr); + ~QuickGuide(); + +private: + Ui::QuickGuide *ui; +}; + +#endif // QUICKGUIDE_H diff --git a/src/QuickGuide.ui b/src/QuickGuide.ui new file mode 100644 index 00000000..ed89dbbe --- /dev/null +++ b/src/QuickGuide.ui @@ -0,0 +1,46 @@ + + + QuickGuide + + + + 0 + 0 + 1800 + 781 + + + + Form + + + + + + true + + + <html><head/><body><h1 style=" margin-top:18px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:xx-large; font-weight:700; color:#000001;">Quickguide to the new blendsplitter way of working</span></h1><p><span style=" color:#000001;">Hi you may have accidentally stumbled upon the new way of working in the openMSX debugger. </span></p><p><span style=" color:#000001;">The old dockingwidgets has been abandoned in favor of a new layouting scheme that is inspired by the open source 3D package Blender. Here is a quick summary of how to work with the new layouts.</span></p><h2 style=" margin-top:16px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:x-large; font-weight:700; color:#000001;">Workspaces</span></h2><p><span style=" color:#000001;">Workspaces are essentially predefined window layouts.</span></p><p><span style=" color:#000001;">You can access the workspaces with the tabar at the top. Use the button at the rigth of the tabs to create a new workspace, you can create empty workspaces or pick an existent predefined workspace.</span></p><h2 style=" margin-top:16px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:x-large; font-weight:700; color:#000001;">Areas</span></h2><p><span style=" color:#000001;">The debugger window is divided into a number of rectangles called Areas. An area has 4 corner handlers.</span></p><p><span style=" color:#000001;">Each area contains a switcher that contains a seperate debuggerview. You can change the debuggerview by selecting an alternative debuggerview in the dropdown list.</span></p><p><img src=":/quickguide/borders.png"/></p><h3 style=" margin-top:14px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:large; font-weight:700; color:#000001;">Resizing areas</span></h3><p><span style=" color:#000001;">You can resize areas by dragging their borders with </span><span style=" font-family:'monospace'; color:#000001;">LMB</span><span style=" color:#000001;">. Move your mouse cursor over the border between two areas, so that the cursor changes to a double-headed arrow, and then click and drag.</span></p><p><img src=":/quickguide/resize.png"/></p><h3 style=" margin-top:14px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:large; font-weight:700; color:#000001;">Splitting areas</span></h3><p><span style=" color:#000001;">Splitting an area will create a new area. Placing the mouse cursor in an area corner will change the cursor to a cross (+) to indicate that pressing down </span><span style=" font-family:'monospace'; color:#000001;">LMB</span><span style=" color:#000001;"> will activate splitting or joining operator. Dragging from area corner </span><span style=" font-weight:700; color:#000001;">inward</span><span style=" color:#000001;"> will </span><span style=" font-style:italic; color:#000001;">split</span><span style=" color:#000001;"> the area. You define the split direction by dragging either horizontally or vertically.</span></p><p><img src=":/quickguide/split.png"/></p><h3 style=" margin-top:14px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:large; font-weight:700; color:#000001;">Joining areas</span></h3><p><span style=" color:#000001;">Dragging from an area corner </span><span style=" font-weight:700; color:#000001;">outward</span><span style=" color:#000001;"> will </span><span style=" font-style:italic; color:#000001;">join</span><span style=" color:#000001;"> two areas. The area that will be closed shows a dark overlay. You can select which area will be closed by moving the mouse over areas. Release the </span><span style=" font-family:'monospace'; color:#000001;">LMB</span><span style=" color:#000001;"> to complete the join. If you press </span><span style=" font-family:'monospace'; color:#000001;">Esc</span><span style=" color:#000001;"> or </span><span style=" font-family:'monospace'; color:#000001;">RMB</span><span style=" color:#000001;"> before releasing the mouse, the operation will be canceled.</span></p><p><span style=" color:#000001;">You can only join areas if they share a common border.</span></p><p><img src=":/quickguide/join.png"/></p><h3 style=" margin-top:14px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:large; font-weight:700; color:#000001;">Switching the viewer in an area</span></h3><p><span style=" color:#000001;">Each area contains one viewer you can switch between viewers by selecting the desired viewer from the dropdown box at the top of each area.</span></p><p><span style=" color:#000001;">There is no limitation one the amount of viewers per type that can be used.<br/></span></p><p><span style=" color:#000001;"><br/></span></p><p><span style=" color:#000001;"><br/></span></p></body></html> + + + Qt::RichText + + + false + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + true + + + Qt::TextBrowserInteraction + + + + + + + + diff --git a/src/blendsplitter/ExpanderCorner.cpp b/src/blendsplitter/ExpanderCorner.cpp index 344fa8ab..9e4e1032 100644 --- a/src/blendsplitter/ExpanderCorner.cpp +++ b/src/blendsplitter/ExpanderCorner.cpp @@ -170,7 +170,8 @@ void ExpanderCorner::performInnerSplit(WidgetDecorator* parentDecorator, BlendSp //now if the original item was a SwitchingWidget we set the same and the enablestate if (switchwdg && addedWidget){ addedWidget->setEnableWidget(switchwdg->getEnableWidget()); - addedWidget->setCurrentIndex(switchwdg->getCurrentIndex()); + //if new user we need show the quickguide (is the default widget) otherwise +// addedWidget->setCurrentIndex(switchwdg->getCurrentIndex()); } //have the cursor take the correct shape diff --git a/src/blendsplitter/SwitchingWidget.cpp b/src/blendsplitter/SwitchingWidget.cpp index dd48907b..fe6508a0 100644 --- a/src/blendsplitter/SwitchingWidget.cpp +++ b/src/blendsplitter/SwitchingWidget.cpp @@ -65,7 +65,7 @@ void SwitchingWidget::setEnableWidget(bool enable) static_cast(wdgt)->setAutoFillBackground(true); // static_cast(wdgt)->setBackgroundRole(QPalette::Text); //trying to force repaint of background // static_cast(wdgt)->update(); - static_cast(wdgt)->setBackgroundRole(enable ? QPalette::Window : QPalette::Dark); + /*static_cast(wdgt)->setBackgroundRole(enable ? QPalette::Window : QPalette::Dark);*/ if (static_cast(wdgt)->viewport()){ static_cast(wdgt)->viewport()->update(); }; diff --git a/src/node.mk b/src/node.mk index d97c5c0d..aecde82c 100644 --- a/src/node.mk +++ b/src/node.mk @@ -18,7 +18,7 @@ MOC_SRC_HDR:= \ blendsplitter/WidgetRegistry blendsplitter/ExpanderCorner \ blendsplitter/RegistryItem \ blendsplitter/SplitterHandle blendsplitter/SwitchingCombo \ - blendsplitter/WidgetDecorator + blendsplitter/WidgetDecorator QuickGuide @@ -32,6 +32,7 @@ SRC_ONLY:= \ UI:= \ ConnectDialog SymbolManager PreferencesDialog BreakpointDialog \ BitMapViewer VDPStatusRegisters VDPRegistersExplained VDPCommandRegisters \ - GotoDialog TileViewer PaletteDialog SpriteViewer BreakpointViewer + GotoDialog TileViewer PaletteDialog SpriteViewer BreakpointViewer \ + QuickGuide include build/node-end.mk From 565050a1f27e8100c0d6c6969f430d3bd27e9213 Mon Sep 17 00:00:00 2001 From: David Heremans Date: Wed, 27 Apr 2022 17:10:02 +0200 Subject: [PATCH 11/63] Save and load workspaces layout Use JSon format to save and load the current workspaces TODO: set the enabledWidget status to current connection status. Maybe save setting from the widgets in the SwitchingWidgets also? --- src/DebuggerForm.cpp | 124 +++++++++++++++++++++++++- src/DebuggerForm.h | 11 +++ src/blendsplitter/BlendSplitter.cpp | 70 +++++++++++++++ src/blendsplitter/BlendSplitter.h | 4 + src/blendsplitter/SwitchingWidget.cpp | 20 +++++ src/blendsplitter/SwitchingWidget.h | 6 ++ 6 files changed, 232 insertions(+), 3 deletions(-) diff --git a/src/DebuggerForm.cpp b/src/DebuggerForm.cpp index a0739fda..405c850e 100644 --- a/src/DebuggerForm.cpp +++ b/src/DebuggerForm.cpp @@ -43,6 +43,9 @@ #include #include #include +#include +#include +#include QMap DebuggerForm::debuggables; @@ -181,11 +184,23 @@ void DebuggerForm::createActions() fileSaveSessionAction = new QAction(tr("&Save Session"), this); fileSaveSessionAction->setShortcut(tr("Ctrl+S")); - fileSaveSessionAction->setStatusTip(tr("Save the the current debug session")); + fileSaveSessionAction->setStatusTip(tr("Save the current debug session")); fileSaveSessionAsAction = new QAction(tr("Save Session &As"), this); fileSaveSessionAsAction->setStatusTip(tr("Save the debug session in a selected file")); + fileOpenWorkspaceLayoutAction = new QAction(tr("&Open workspaces"), this); + fileOpenWorkspaceLayoutAction->setStatusTip(tr("Load a workspace layout.")); + + fileSaveWorkspaceLayoutAction = new QAction(tr("&Save workspaces"), this); + fileSaveWorkspaceLayoutAction->setStatusTip(tr("Save the current workspaces and splitters layout")); + + fileSaveWorkspaceLayoutAsAction = new QAction(tr("Save workspaces &As"), this); + fileSaveWorkspaceLayoutAsAction->setStatusTip(tr("Save the current workspaces and splitters in a selected file")); + + + + fileQuitAction = new QAction(tr("&Quit"), this); fileQuitAction->setShortcut(tr("Ctrl+Q")); fileQuitAction->setStatusTip(tr("Quit the openMSX debugger")); @@ -304,6 +319,11 @@ void DebuggerForm::createActions() connect(fileOpenSessionAction, &QAction::triggered, this, &DebuggerForm::fileOpenSession); connect(fileSaveSessionAction, &QAction::triggered, this, &DebuggerForm::fileSaveSession); connect(fileSaveSessionAsAction, &QAction::triggered, this, &DebuggerForm::fileSaveSessionAs); + + connect(fileOpenWorkspaceLayoutAction, &QAction::triggered, this, &DebuggerForm::fileOpenWorkspace); + connect(fileSaveWorkspaceLayoutAction, &QAction::triggered, this, &DebuggerForm::fileSaveWorkspace); + connect(fileSaveWorkspaceLayoutAsAction, &QAction::triggered, this, &DebuggerForm::fileSaveWorkspaceAs); + connect(fileQuitAction, &QAction::triggered, this, &DebuggerForm::close); connect(systemConnectAction, &QAction::triggered, this, &DebuggerForm::systemConnect); connect(systemDisconnectAction, &QAction::triggered, this, &DebuggerForm::systemDisconnect); @@ -335,6 +355,11 @@ void DebuggerForm::createMenus() fileMenu->addAction(fileOpenSessionAction); fileMenu->addAction(fileSaveSessionAction); fileMenu->addAction(fileSaveSessionAsAction); + fileMenu->addSeparator(); + fileMenu->addAction(fileOpenWorkspaceLayoutAction); +// fileMenu->addAction(fileSaveWorkspaceLayoutAction); + fileMenu->addAction(fileSaveWorkspaceLayoutAsAction); + fileMenu->addSeparator(); recentFileSeparator = fileMenu->addSeparator(); for (auto* rfa : recentFileActions) @@ -1091,7 +1116,41 @@ void DebuggerForm::fileRecentOpen() { if (auto* action = qobject_cast(sender())) { openSession(action->data().toString()); - } + } +} + +void DebuggerForm::fileOpenWorkspace() +{ + QString fileName = QFileDialog::getOpenFileName( + this, tr("Open workspace layout"), + QDir::currentPath(), tr("Debug Workspace Layout Files (*.omdl)")); + + if (!fileName.isEmpty()) + loadWorkspaces(fileName); +} + +void DebuggerForm::fileSaveWorkspace() +{ + +} + +void DebuggerForm::fileSaveWorkspaceAs() +{ + QFileDialog d(this, tr("Save workspace layout")); + d.setNameFilter(tr("Debug Workspace Layout Files (*.omdl)")); + d.setDefaultSuffix("omdl"); + d.setDirectory(QDir::currentPath()); + d.setAcceptMode(QFileDialog::AcceptSave); + d.setFileMode(QFileDialog::AnyFile); + if (d.exec()) { +// session->saveAs(d.selectedFiles().at(0)); + saveWorkspacesAs(d.selectedFiles().at(0)); + // update recent +// if (session->existsAsFile()) { +// addRecentFile(session->filename()); +// } + } + updateWindowTitle(); } void DebuggerForm::systemConnect() @@ -1294,7 +1353,66 @@ DebuggerForm::AddressSlotResult DebuggerForm::addressSlot(int addr) const return (b >= 0) ? b : -1; } }(); - return {ps, ss, segment}; + return {ps, ss, segment}; +} + +bool DebuggerForm::saveWorkspacesAs(const QString &newFileName) +{ + // open file for save + QFile file(newFileName); + if (!file.open(QFile::WriteOnly | QFile::Text)) { + QMessageBox::warning(nullptr, tr("Save session ..."), + tr("Cannot write file %1:\n%2.") + .arg(newFileName, file.errorString())); + return false; + }; + QJsonObject jsonObj; + QJsonArray spacesArray; + //iterate over workspaces + for (int i=0;icount();i++){ + QJsonObject jsonTab; + jsonTab["name"]=workspaces->tabText(i); + jsonTab["workspace"]=static_cast(workspaces->widget(i))->save2json(); + spacesArray.append(jsonTab); + }; + jsonObj["workspaces"]=spacesArray; + QJsonDocument jsonDoc(jsonObj); + file.write(jsonDoc.toJson()); + // file.close(); done automatically when going out of scope + return true; + +} + +void DebuggerForm::loadWorkspaces(const QString &filename) +{ + QFile file(filename); + if (!file.open(QFile::ReadOnly | QFile::Text)) { + QMessageBox::warning(nullptr, tr("Loading workspaces ..."), + tr("Cannot read file %1:\n%2.") + .arg(filename,file.errorString())); + return; + }; + //Now try to parse the json file + QJsonParseError parseError; + QJsonDocument jsonDoc=QJsonDocument::fromJson(file.readAll(), &parseError); + if (parseError.error != QJsonParseError::NoError) { + QMessageBox::warning(nullptr, tr("Open workspaces ..."), + tr("Parse error at %1:%2.").arg(QString::number(parseError.offset), parseError.errorString()) + ); + return; + }; + + // delete all the current tabs before reading the new ones + while(workspaces->count()) { + delete workspaces->widget(0); + }; + //now recreate workspaces + QJsonObject obj = jsonDoc.object(); + foreach (const QJsonValue & value, obj["workspaces"].toArray()) { + QJsonObject obj = value.toObject(); + BlendSplitter* splitter=BlendSplitter::createFromJson(obj["workspace"].toObject()); + workspaces->addTab(splitter,obj["name"].toString()); + } } void DebuggerForm::reloadBreakpoints(bool merge) diff --git a/src/DebuggerForm.h b/src/DebuggerForm.h index 3f1079d3..908bc46c 100644 --- a/src/DebuggerForm.h +++ b/src/DebuggerForm.h @@ -99,6 +99,11 @@ class DebuggerForm : public QMainWindow QAction* fileOpenSessionAction; QAction* fileSaveSessionAction; QAction* fileSaveSessionAsAction; + + QAction* fileOpenWorkspaceLayoutAction; + QAction* fileSaveWorkspaceLayoutAction; + QAction* fileSaveWorkspaceLayoutAsAction; + QAction* fileQuitAction; enum { MaxRecentFiles = 5 }; @@ -144,11 +149,17 @@ class DebuggerForm : public QMainWindow enum {RESET = 0, SLOTS_CHECKED, PC_CHANGED, SLOTS_CHANGED} disasmStatus = RESET; uint16_t disasmAddress; + bool saveWorkspacesAs(const QString& newFileName); + void loadWorkspaces(const QString& filename); + void fileNewSession(); void fileOpenSession(); void fileSaveSession(); void fileSaveSessionAs(); void fileRecentOpen(); + void fileOpenWorkspace(); + void fileSaveWorkspace(); + void fileSaveWorkspaceAs(); void systemConnect(); void systemDisconnect(); void systemPause(); diff --git a/src/blendsplitter/BlendSplitter.cpp b/src/blendsplitter/BlendSplitter.cpp index cdc3a23f..9f480fcc 100644 --- a/src/blendsplitter/BlendSplitter.cpp +++ b/src/blendsplitter/BlendSplitter.cpp @@ -8,6 +8,11 @@ #include "SignalDispatcher.h" +#include +#include +#include +#include + int BlendSplitter::expanderSize{12}; int BlendSplitter::switchingBarHeight{32}; QString BlendSplitter::expanderImage{":/BlendSplitter/Expander"}; @@ -81,6 +86,71 @@ QWidget *BlendSplitter::getNestedWidget(int index) return widget(index)->layout()->itemAt(0)->widget(); } +QJsonObject BlendSplitter::save2json() const +{ + QJsonObject obj; + QJsonArray ar_sizes,ar_subwidgets; + + obj["type"]="BlendSplitter"; + obj["orientation"]=orientation(); + obj["size_width"]=size().width(); + obj["size_height"]=size().height(); + foreach(int i,sizes()){ + ar_sizes.append(i); + }; + obj["sizes"]=ar_sizes; + for(int i=0 ; iinherits("WidgetDecorator")){ + QWidget* wdg = widget(i)->layout()->itemAt(0)->widget(); + if (wdg->inherits("SwitchingWidget")){ + ar_subwidgets.append(static_cast(wdg)->save2json()); + } + } else if (widget(i)->inherits("SplitterDecorator")){ + QWidget* wdg = widget(i)->layout()->itemAt(0)->widget(); + ar_subwidgets.append(static_cast(wdg)->save2json()); + } else { + QJsonObject o; + ar_subwidgets.append(o); + }; + }; + obj["subs"]=ar_subwidgets; + + + return obj; +} + +BlendSplitter *BlendSplitter::createFromJson(const QJsonObject &obj) +{ + + BlendSplitter *split= new BlendSplitter([]()->QWidget* {return new SwitchingWidget{};}, + obj["orientation"].toInt(1)==1?Qt::Horizontal:Qt::Vertical); + + foreach (const QJsonValue & value, obj["subs"].toArray()) { + QJsonObject obj = value.toObject(); + if (obj["type"].toString()=="SwitchingWidget"){ + split->addWidget(SwitchingWidget::createFromJson(obj)); + } else if (obj["type"].toString()=="BlendSplitter"){ + split->addSplitter(BlendSplitter::createFromJson(obj)); + } else { + QMessageBox::warning(nullptr, tr("Open workspaces ..."), + tr("Unknown subs type:%1").arg(obj["type"].toString()) + ); + } + + } + + QList sizes; + split->resize(obj["size_width"].toInt(),obj["size_height"].toInt()); + foreach (const QJsonValue & value, obj["sizes"].toArray()) { + sizes.append(value.toInt()); + } + split->setSizes(sizes); +// qDebug() << "split->size" << split->size(); + + return split; +} + QSplitterHandle* BlendSplitter::createHandle() { return new SplitterHandle(orientation(), this); diff --git a/src/blendsplitter/BlendSplitter.h b/src/blendsplitter/BlendSplitter.h index 4a6a5955..ba7c0843 100644 --- a/src/blendsplitter/BlendSplitter.h +++ b/src/blendsplitter/BlendSplitter.h @@ -12,6 +12,7 @@ class ExpanderCorner; class ExpanderBottom; class ExpanderTop; class WidgetDecorator; +class QJsonObject; /** \brief A user-defined Splitter * @@ -92,6 +93,9 @@ class BlendSplitter : public QSplitter * @return A pointer to widget that is decorated */ QWidget* getNestedWidget(int index); + + QJsonObject save2json() const; + static BlendSplitter* createFromJson(const QJsonObject& obj); private: friend Expander; friend ExpanderCorner; diff --git a/src/blendsplitter/SwitchingWidget.cpp b/src/blendsplitter/SwitchingWidget.cpp index fe6508a0..30d0f463 100644 --- a/src/blendsplitter/SwitchingWidget.cpp +++ b/src/blendsplitter/SwitchingWidget.cpp @@ -5,6 +5,7 @@ #include "SwitchingBar.h" #include "SwitchingCombo.h" #include +#include SwitchingWidget::SwitchingWidget(RegistryItem* item, QWidget* parent,bool menuAtTop) : QSplitter(Qt::Vertical, parent), bar{new SwitchingBar{}}, widgetEnabled(true),barAtTop(menuAtTop) { @@ -55,6 +56,25 @@ int SwitchingWidget::getCurrentIndex() return bar->combo->currentIndex(); } +QJsonObject SwitchingWidget::save2json() +{ + QJsonObject obj; + obj["type"]="SwitchingWidget"; + obj["item"]=bar->combo->currentIndex(); + obj["size_width"]=size().width(); + obj["size_height"]=size().height(); + return obj; +} + +SwitchingWidget *SwitchingWidget::createFromJson(const QJsonObject &obj) +{ + int i=obj["item"].toInt(); + SwitchingWidget* wdgt= new SwitchingWidget{WidgetRegistry::getRegistry()->item(i)}; + wdgt->resize(obj["size_width"].toInt(),obj["size_height"].toInt()); + + return wdgt; +} + void SwitchingWidget::setEnableWidget(bool enable) { widgetEnabled=enable; diff --git a/src/blendsplitter/SwitchingWidget.h b/src/blendsplitter/SwitchingWidget.h index 52284348..5a9cecb9 100644 --- a/src/blendsplitter/SwitchingWidget.h +++ b/src/blendsplitter/SwitchingWidget.h @@ -4,6 +4,7 @@ class SwitchingBar; class RegistryItem; +class QJsonObject; /** \brief A widget whose actual content can be selected from a combo box * @@ -32,6 +33,11 @@ class SwitchingWidget : public QSplitter bool getEnableWidget(); void setCurrentIndex(int index); int getCurrentIndex(); + + QJsonObject save2json(); + static SwitchingWidget* createFromJson(const QJsonObject& obj); + + public slots: void setEnableWidget(bool enable = true); private slots: From 53a5def99137ec55285d9516d291fb3f88d6b787 Mon Sep 17 00:00:00 2001 From: David Heremans Date: Thu, 28 Apr 2022 13:08:02 +0200 Subject: [PATCH 12/63] Moved getEnabledWidget to SignalDispatcher And prevent direct emitting of the signal so that the SignalDispatcher is the single source of truth. --- src/DebuggerForm.cpp | 10 ++++------ src/DebuggerForm.h | 2 -- src/SignalDispatcher.cpp | 15 ++++++++++++++- src/SignalDispatcher.h | 6 ++++++ src/blendsplitter/BlendSplitter.cpp | 4 +++- 5 files changed, 27 insertions(+), 10 deletions(-) diff --git a/src/DebuggerForm.cpp b/src/DebuggerForm.cpp index 405c850e..3b205488 100644 --- a/src/DebuggerForm.cpp +++ b/src/DebuggerForm.cpp @@ -157,7 +157,7 @@ int DebuggerForm::counter = 0; DebuggerForm::DebuggerForm(QWidget* parent) : QMainWindow(parent) - , comm(CommClient::instance()),enableWidgetStatus(false) + , comm(CommClient::instance()) { session = DebugSession::getDebugSession(); @@ -629,7 +629,7 @@ void DebuggerForm::addFloatingSwitchingWidget() { SwitchingWidget* wdg=new SwitchingWidget(); connect(SignalDispatcher::getDispatcher(), SIGNAL(enableWidget(bool)), wdg, SLOT(setEnableWidget(bool))); - wdg->setEnableWidget(enableWidgetStatus); + wdg->setEnableWidget(SignalDispatcher::getDispatcher()->getEnableWidget()); wdg->show(); } @@ -967,8 +967,7 @@ void DebuggerForm::connectionClosed() systemConnectAction->setEnabled(true); breakpointAddAction->setEnabled(false); - enableWidgetStatus=false; - emit SignalDispatcher::getDispatcher()->enableWidget(false); + SignalDispatcher::getDispatcher()->setEnableWidget(false); } void DebuggerForm::finalizeConnection(bool halted) @@ -987,8 +986,7 @@ void DebuggerForm::finalizeConnection(bool halted) emit connected(); - enableWidgetStatus=true; - emit SignalDispatcher::getDispatcher()->enableWidget(true); + SignalDispatcher::getDispatcher()->setEnableWidget(true); } void DebuggerForm::handleUpdate(const QString& type, const QString& name, diff --git a/src/DebuggerForm.h b/src/DebuggerForm.h index 908bc46c..14cf60d7 100644 --- a/src/DebuggerForm.h +++ b/src/DebuggerForm.h @@ -233,8 +233,6 @@ private slots: void addEmptyWorkspace(); void addFloatingSwitchingWidget(); - bool enableWidgetStatus; - protected slots: void tabCloseRequest(int index); diff --git a/src/SignalDispatcher.cpp b/src/SignalDispatcher.cpp index 135843ac..a1c35ce6 100644 --- a/src/SignalDispatcher.cpp +++ b/src/SignalDispatcher.cpp @@ -80,18 +80,31 @@ void SignalDispatcher::setData(unsigned char *datPtr) emit registersUpdate(datPtr); // now tell all listeners the new values } +bool SignalDispatcher::getEnableWidget() +{ + return isEnableWidget; +} + void SignalDispatcher::refresh() { CommClient::instance().sendCommand(new DispatchDebugMemMapperHandler(*this)); } +void SignalDispatcher::setEnableWidget(bool value) +{ + if (isEnableWidget != value){ + isEnableWidget=value; + emit enableWidget(value); + } +} + int SignalDispatcher::readRegister(int id) { return regs[id]; } -SignalDispatcher::SignalDispatcher() { +SignalDispatcher::SignalDispatcher(): isEnableWidget(false) { // avoid UMR memset(®s, 0, sizeof(regs)); memset(®sChanged, 0, sizeof(regsChanged)); diff --git a/src/SignalDispatcher.h b/src/SignalDispatcher.h index 5e3fddae..873d3e76 100644 --- a/src/SignalDispatcher.h +++ b/src/SignalDispatcher.h @@ -30,8 +30,11 @@ class SignalDispatcher : public QObject int readRegister(int id); void setData(unsigned char* datPtr); + bool getEnableWidget(); + public slots: void refresh(); + void setEnableWidget(bool value); private: static SignalDispatcher* theDispatcher; @@ -71,4 +74,7 @@ public slots: void setProgramCounter(uint16_t pc, bool reload = false); //from the GotoDialog void setCursorAddress(uint16_t addr, int infoLine, int method); + +private: + bool isEnableWidget; }; diff --git a/src/blendsplitter/BlendSplitter.cpp b/src/blendsplitter/BlendSplitter.cpp index 9f480fcc..2a1168af 100644 --- a/src/blendsplitter/BlendSplitter.cpp +++ b/src/blendsplitter/BlendSplitter.cpp @@ -48,7 +48,9 @@ void BlendSplitter::insertWidget(int index) void BlendSplitter::insertWidget(int index, QWidget* widget) { if (widget->inherits("SwitchingWidget")){ - connect(SignalDispatcher::getDispatcher(), SIGNAL(enableWidget(bool)), widget, SLOT(setEnableWidget(bool))); + connect(SignalDispatcher::getDispatcher(), &SignalDispatcher::enableWidget, + static_cast(widget), &SwitchingWidget::setEnableWidget); + static_cast(widget)->setEnableWidget(SignalDispatcher::getDispatcher()->getEnableWidget()); }; WidgetDecorator* decorator{new WidgetDecorator{widget}}; QSplitter::insertWidget(index, decorator); From d27bcf874f74fca648d8a4d45367fde1182b80a4 Mon Sep 17 00:00:00 2001 From: David Heremans Date: Sat, 30 Apr 2022 21:12:03 +0200 Subject: [PATCH 13/63] improved QuickGuide text --- resources/quickguide/switching_widget.png | Bin 0 -> 744 bytes resources/quickguide/workspaces_tab.png | Bin 0 -> 1504 bytes resources/resources.qrc | 2 ++ src/QuickGuide.ui | 18 +++++++++++++++--- 4 files changed, 17 insertions(+), 3 deletions(-) create mode 100644 resources/quickguide/switching_widget.png create mode 100644 resources/quickguide/workspaces_tab.png diff --git a/resources/quickguide/switching_widget.png b/resources/quickguide/switching_widget.png new file mode 100644 index 0000000000000000000000000000000000000000..9f19fc4d6f8a739aed680dcb116fcd413fd0de64 GIT binary patch literal 744 zcmVP)M00087Nkll=2~gEjl$-bWy6+{afQOOFdFj9O=!k^8zVG$mByHi@K4zZPn+K< z;mZ`Z#AxV;{De%m!S9SFNU8rn=xe{}HXiXd;X5tMkNGwz$bL;M8{7tL0ohZyyd*mU zY;;1SCzsNHr*7cSgdAQ>uLVm2Iwf~QrBj>{*Cw^k#7aJPepYCMSLGQC7gtWYQwti<%pyCix=8b6l0BY{u{Jp0hnZ>Z% z?H)GPSg?($e3039sFDq>O~ZVu_1?`_RdvHOFB}?u=|s$i5yjVkDVeK%;PxOBb>w6S zwSgdnN!15A6Gd!jxHjQrldJ#9UYO&0<0wl08Jv>I#x00002^kX000H2Nklr(g$ArVNDlB6UlMUs>xB}qwAO2m@wMt$Tlc1V)#9XI)i**xndjW_v; z@nV}nsI+xopV@Y<0!C8Llce6_92pfRBTh@(jJ9(Y@GI#Y0iiPDY?;}1t^!ul%TM&e zL86%&Mg%S3S8`N9$x*|opaqhoBzeb3Qj%nZl4D1hmzKObAtfC%E$R3Vj>)%=qJ?7x zu}uics|T2ux~IOGA<5|%Od(mDsfb^D&8wBgtG9c+%3d^7kssJ>d%WK3E+mLjUL}Wh zS8nTlo6FFmCzaS7i6mVX)5mi`uw<30-ZNJ1^=ggYq4Y0>i+jUMYEPoY z`Mdj5=E@bhO=umhByO<*v!+PcWDWI+e&`GLdArtp2eyp_u`B#U!?ff5hmxFj0V_!b zGLi5-yP|ERsP{Kf${w^{@$4<{_%mf&PzWs0*!JNZZ3m z)oo+qX^B}@DmNwj`tr*a@qw!l3g)wpX9{(B`2nkq{~|pNk@-Zrnd62Kx}DiSVnlyz3tt66l1(bSqLtm3et?=n(wUp6$vElZkc6}o zV7cciTU9Hg=Q7;1_z;#nr#)s*-Vb|Lfi3YX(8tn}m04D61Hb|k;7xGXlLLT911VjU zw7Q4$AtiJ>+CMOoxP`BRAj!^HPvGoEna4=x2i`E6PdxarM)SIjL$Y`Sl&ohD252Sh z=t>oz_6e}p$+)O;s80Z}M)%bxp^=reWYfGOc6O$C6U6)ofJgoL^@&7{?y#L}qM_UU zlDLJhf*?tc^7KC>S2mzU@tgkb*EU2wV5mybXtFHfCEH~~y03B7DLGyNd`xD10Y_sM z3dOyx$8=~Uhn9r8waHb?Oz|d&>7^e?m{DIYKSQKEq|p?1aZEIHyI<1R!c#$zB(*Qe z=pp<4l6$j?H;E>$Cuz+Rj-7Ysxl7vTh+SL0Tjux;kI1Fc)>ttI8bSpby zSq0!tj3ge#2TWe{@*3OlHuODy#4*v3?P&k3ByQoWU<%1FA*&8rY=5}il>3Ic>=cKj zCF(eHQAFR%S(q$Y7k9~&Emyt(P`@lLcO5NxdXaqLX8;u{)d1c^OX5)`zpr1KS8Hl) zG;YZQQVT%q;VJNM382$*kkS#_t|ZJk8~9|$!1FYX%@94eT{s> zg&wZ|2UjG$s3m`*Pi^{BPKZC^mL$j6yS5}5sidoDj6HKEJYtW?B}-lS8su?Lo!rXF zBR4Wf+(N`7^0V7_HFuBGsm@TuuW^julHAI1k;E-d$-e<+fftk~ngBWg0000quickguide/areas_join.png quickguide/areas_resize.png quickguide/areas_split.png + quickguide/workspaces_tab.png + quickguide/switching_widget.png diff --git a/src/QuickGuide.ui b/src/QuickGuide.ui index ed89dbbe..df195d01 100644 --- a/src/QuickGuide.ui +++ b/src/QuickGuide.ui @@ -6,10 +6,16 @@ 0 0 - 1800 - 781 + 1099 + 1555 + + + 0 + 0 + + Form @@ -19,8 +25,14 @@ true + + + 0 + 0 + + - <html><head/><body><h1 style=" margin-top:18px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:xx-large; font-weight:700; color:#000001;">Quickguide to the new blendsplitter way of working</span></h1><p><span style=" color:#000001;">Hi you may have accidentally stumbled upon the new way of working in the openMSX debugger. </span></p><p><span style=" color:#000001;">The old dockingwidgets has been abandoned in favor of a new layouting scheme that is inspired by the open source 3D package Blender. Here is a quick summary of how to work with the new layouts.</span></p><h2 style=" margin-top:16px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:x-large; font-weight:700; color:#000001;">Workspaces</span></h2><p><span style=" color:#000001;">Workspaces are essentially predefined window layouts.</span></p><p><span style=" color:#000001;">You can access the workspaces with the tabar at the top. Use the button at the rigth of the tabs to create a new workspace, you can create empty workspaces or pick an existent predefined workspace.</span></p><h2 style=" margin-top:16px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:x-large; font-weight:700; color:#000001;">Areas</span></h2><p><span style=" color:#000001;">The debugger window is divided into a number of rectangles called Areas. An area has 4 corner handlers.</span></p><p><span style=" color:#000001;">Each area contains a switcher that contains a seperate debuggerview. You can change the debuggerview by selecting an alternative debuggerview in the dropdown list.</span></p><p><img src=":/quickguide/borders.png"/></p><h3 style=" margin-top:14px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:large; font-weight:700; color:#000001;">Resizing areas</span></h3><p><span style=" color:#000001;">You can resize areas by dragging their borders with </span><span style=" font-family:'monospace'; color:#000001;">LMB</span><span style=" color:#000001;">. Move your mouse cursor over the border between two areas, so that the cursor changes to a double-headed arrow, and then click and drag.</span></p><p><img src=":/quickguide/resize.png"/></p><h3 style=" margin-top:14px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:large; font-weight:700; color:#000001;">Splitting areas</span></h3><p><span style=" color:#000001;">Splitting an area will create a new area. Placing the mouse cursor in an area corner will change the cursor to a cross (+) to indicate that pressing down </span><span style=" font-family:'monospace'; color:#000001;">LMB</span><span style=" color:#000001;"> will activate splitting or joining operator. Dragging from area corner </span><span style=" font-weight:700; color:#000001;">inward</span><span style=" color:#000001;"> will </span><span style=" font-style:italic; color:#000001;">split</span><span style=" color:#000001;"> the area. You define the split direction by dragging either horizontally or vertically.</span></p><p><img src=":/quickguide/split.png"/></p><h3 style=" margin-top:14px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:large; font-weight:700; color:#000001;">Joining areas</span></h3><p><span style=" color:#000001;">Dragging from an area corner </span><span style=" font-weight:700; color:#000001;">outward</span><span style=" color:#000001;"> will </span><span style=" font-style:italic; color:#000001;">join</span><span style=" color:#000001;"> two areas. The area that will be closed shows a dark overlay. You can select which area will be closed by moving the mouse over areas. Release the </span><span style=" font-family:'monospace'; color:#000001;">LMB</span><span style=" color:#000001;"> to complete the join. If you press </span><span style=" font-family:'monospace'; color:#000001;">Esc</span><span style=" color:#000001;"> or </span><span style=" font-family:'monospace'; color:#000001;">RMB</span><span style=" color:#000001;"> before releasing the mouse, the operation will be canceled.</span></p><p><span style=" color:#000001;">You can only join areas if they share a common border.</span></p><p><img src=":/quickguide/join.png"/></p><h3 style=" margin-top:14px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:large; font-weight:700; color:#000001;">Switching the viewer in an area</span></h3><p><span style=" color:#000001;">Each area contains one viewer you can switch between viewers by selecting the desired viewer from the dropdown box at the top of each area.</span></p><p><span style=" color:#000001;">There is no limitation one the amount of viewers per type that can be used.<br/></span></p><p><span style=" color:#000001;"><br/></span></p><p><span style=" color:#000001;"><br/></span></p></body></html> + <html><head/><body><h1 style=" margin-top:18px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:xx-large; font-weight:700; color:#000001;">Quickguide to the new blendsplitter way of working</span></h1><p><span style=" color:#000001;">Hi you may have accidentally stumbled upon the new way of working in the openMSX debugger. </span></p><p><span style=" color:#000001;">The old dockingwidgets has been abandoned in favor of a new layouting scheme that is inspired by the open source 3D package Blender. Here is a quick summary of how to work with the new layouts.</span></p><h2 style=" margin-top:16px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:x-large; font-weight:700; color:#000001;">Workspaces</span></h2><p><span style=" color:#000001;">Workspaces are essentially predefined window layouts.</span></p><p><span style=" color:#000001;">You can access the workspaces with the tabar at the top. Use the button at the rigth of the tabs to create a new workspace, you can create empty workspaces or pick an existent predefined workspace.</span></p><p><img src=":/quickguide/workspaces.png"/></p><h2 style=" margin-top:16px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:x-large; font-weight:700; color:#000001;">Areas</span></h2><p><span style=" color:#000001;">The debugger window is divided into a number of rectangles called Areas. An area has 4 corner handlers.</span></p><p><span style=" color:#000001;">Each area contains a switcher that contains a seperate debuggerview. You can change the debuggerview by selecting an alternative debuggerview in the dropdown list.</span></p><p><img src=":/quickguide/borders.png"/></p><h3 style=" margin-top:14px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:large; font-weight:700; color:#000001;">Resizing areas</span></h3><p><span style=" color:#000001;">You can resize areas by dragging their borders with </span><span style=" font-family:'monospace'; color:#000001;">LMB</span><span style=" color:#000001;">. Move your mouse cursor over the border between two areas, so that the cursor changes to a double-headed arrow, and then click and drag.</span></p><p><img src=":/quickguide/resize.png"/></p><h3 style=" margin-top:14px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:large; font-weight:700; color:#000001;">Splitting areas</span></h3><p><span style=" color:#000001;">Splitting an area will create a new area. Placing the mouse cursor in an area corner will change the cursor to a cross (+) to indicate that pressing down </span><span style=" font-family:'monospace'; color:#000001;">LMB</span><span style=" color:#000001;"> will activate splitting or joining operator. Dragging from area corner </span><span style=" font-weight:700; color:#000001;">inward</span><span style=" color:#000001;"> will </span><span style=" font-style:italic; color:#000001;">split</span><span style=" color:#000001;"> the area. You define the split direction by dragging either horizontally or vertically.</span></p><p><img src=":/quickguide/split.png"/></p><h3 style=" margin-top:14px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:large; font-weight:700; color:#000001;">Joining areas</span></h3><p><span style=" color:#000001;">Dragging from an area corner </span><span style=" font-weight:700; color:#000001;">outward</span><span style=" color:#000001;"> will </span><span style=" font-style:italic; color:#000001;">join</span><span style=" color:#000001;"> two areas. The area that will be closed shows a dark overlay. You can select which area will be closed by moving the mouse over areas. Release the </span><span style=" font-family:'monospace'; color:#000001;">LMB</span><span style=" color:#000001;"> to complete the join. If you press </span><span style=" font-family:'monospace'; color:#000001;">Esc</span><span style=" color:#000001;"> or </span><span style=" font-family:'monospace'; color:#000001;">RMB</span><span style=" color:#000001;"> before releasing the mouse, the operation will be canceled.</span></p><p><span style=" color:#000001;">You can only join areas if they share a common border.</span></p><p><img src=":/quickguide/join.png"/></p><h3 style=" margin-top:14px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:large; font-weight:700; color:#000001;">Switching the viewer in an area</span></h3><p><span style=" color:#000001;">Each area contains one viewer you can switch between viewers by selecting the desired viewer from the dropdown box at the top of each area.</span></p><p><img src=":/quickguide/switching.png"/></p><p><span style=" color:#000001;">There is no limitation to the amount of viewers per type that can be used.<br/></span></p><h2 style=" margin-top:16px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:x-large; font-weight:700; color:#000001;">Saving your current workspaces and area layout</span></h2><p><span style=" color:#000001;">You can save your current workspaces and layouts using the File menu.</span></p><p><span style=" color:#000001;">In the </span><span style=" font-weight:700; color:#000001;">&quot;System&quot; -&gt; &quot;Preferences...&quot;</span><span style=" color:#000001;"> menu you can select the </span><span style=" font-weight:700; color:#000001;">&quot;Workspace Layout&quot;</span><span style=" color:#000001;"> tab to select the layout that the debugger needs to use when starting.<br/>By default the selection is </span><span style=" font-style:italic; color:#000001;">&quot;First Time User&quot;</span><span style=" color:#000001;"> so that you will see this manual as first workspace when starting.<br/>Also for first time users each area split will by default show this manual, in regular usage an area split will create a duplicate of the area you started to split.</span></p><p><span style=" color:#000001;">Floating widgets aren't saved and need to be create manually each time.</span></p><p><span style=" color:#000001;"><br/></span></p><p><span style=" color:#000001;"><br/></span></p></body></html> Qt::RichText From bd6b0f495e411ca19cdb0c8daaf7afdbb4f9fc6b Mon Sep 17 00:00:00 2001 From: David Heremans Date: Sat, 30 Apr 2022 21:27:32 +0200 Subject: [PATCH 14/63] Now select your workspace when starting In preferences you can now can select a default workspace to load when starting. Also added a 'new user' setting so that the QuickGuide is clearly visible for new users. The CPU view/code debugger is now a workspace that can be added/removed. --- src/DebuggerForm.cpp | 57 +++++-- src/DebuggerForm.h | 8 +- src/PreferencesDialog.cpp | 82 +++++++-- src/PreferencesDialog.h | 5 + src/PreferencesDialog.ui | 237 ++++++++++++++++++-------- src/blendsplitter/ExpanderCorner.cpp | 8 +- src/blendsplitter/SwitchingWidget.cpp | 20 ++- src/blendsplitter/SwitchingWidget.h | 3 + 8 files changed, 315 insertions(+), 105 deletions(-) diff --git a/src/DebuggerForm.cpp b/src/DebuggerForm.cpp index 3b205488..601c0dfe 100644 --- a/src/DebuggerForm.cpp +++ b/src/DebuggerForm.cpp @@ -299,6 +299,9 @@ void DebuggerForm::createActions() helpAboutAction = new QAction(tr("&About"), this); + addCPUWorkspaceAction = new QAction(tr("&Code debugger"), this); + addCPUWorkspaceAction->setStatusTip(tr("The default way of debugging CPU code")); + addVDPRegsWorkspaceAction = new QAction(tr("VDP &Regs"), this); addVDPRegsWorkspaceAction->setStatusTip(tr("Show the regular VDP registers")); @@ -340,6 +343,7 @@ void DebuggerForm::createActions() connect(executeStepOutAction, &QAction::triggered, this, &DebuggerForm::executeStepOut); connect(executeStepBackAction, &QAction::triggered, this, &DebuggerForm::executeStepBack); connect(helpAboutAction, &QAction::triggered, this, &DebuggerForm::showAbout); + connect(addCPUWorkspaceAction, &QAction::triggered, this, &DebuggerForm::addCPUWorkspace); connect(addVDPRegsWorkspaceAction, &QAction::triggered, this, &DebuggerForm::addVDPRegsWorkspace); connect(addVDPTilesWorkspaceAction, &QAction::triggered, this, &DebuggerForm::addVDPTilesWorkspace); connect(addVDPBitmapWorkspaceAction, &QAction::triggered, this, &DebuggerForm::addVDPBitmapWorkspace); @@ -599,15 +603,22 @@ void DebuggerForm::tabCloseRequest(int index) if((index < 0) || (index >= workspaces->count())){ return; }; - //index 0 is the CPU workspace, refuse to delete this one for now - //Also this way at least one workspace remains, altough we could do this diferently in the future - if (index > 0){ + + if (workspaces->count() > 1){ QWidget *splitter=workspaces->widget(index); workspaces->removeTab(index); delete splitter; } } +void DebuggerForm::addInfoWorkspace(){ + BlendSplitter* split = new BlendSplitter([]()->QWidget* {return new SwitchingWidget{};},Qt::Horizontal); + split->addWidget(WidgetRegistry::getRegistry()->item(14)); //14: the quick guide manuel + workspaces->addTab(split,"Welcome new user"); +} +void DebuggerForm::addCPUWorkspace(){ + workspaces->addTab(createWorkspaceCPU(),"CPU"); +} void DebuggerForm::addVDPRegsWorkspace(){ workspaces->addTab(createWorkspaceVDPRegs(),"VDP Registers"); } @@ -644,6 +655,7 @@ void DebuggerForm::createForm() workspaces->setTabsClosable(true); QMenu *workspacemenu=new QMenu(); QMenu *workspacesubmenu=new QMenu("Predefined layouts"); + workspacesubmenu->addAction(addCPUWorkspaceAction); workspacesubmenu->addAction(addVDPRegsWorkspaceAction); workspacesubmenu->addAction(addVDPTilesWorkspaceAction); workspacesubmenu->addAction(addVDPBitmapWorkspaceAction); @@ -667,11 +679,22 @@ void DebuggerForm::createForm() layout->addWidget(workspaces); window->setLayout(layout); - workspaces->addTab(createWorkspaceCPU(),"CPU"); - addVDPRegsWorkspace(); - addVDPTilesWorkspace(); - addVDPBitmapWorkspace(); + Settings& s = Settings::get(); + int workspacetype =s.value("creatingWorkspaceType",0).toInt(); + switch (workspacetype) { + case 0: + addInfoWorkspace(); + [[fallthrough]]; + case 1: + addDefaultWorkspaces(); + break; + default: + if (!loadWorkspaces(s.value("creatingWorkspaceFile",0).toString())){ + addDefaultWorkspaces(); + } + break; + }; setCentralWidget(window); @@ -696,6 +719,14 @@ void DebuggerForm::createForm() session->breakpoints().setMemoryLayout(SignalDispatcher::getDispatcher()->getMemLayout()); } +void DebuggerForm::addDefaultWorkspaces() +{ + addCPUWorkspace(); + addVDPRegsWorkspace(); + addVDPTilesWorkspace(); + addVDPBitmapWorkspace(); +} + QWidget *DebuggerForm::widgetFactory(factoryclasses fctwidget) { QWidget* wdgt; @@ -1123,8 +1154,9 @@ void DebuggerForm::fileOpenWorkspace() this, tr("Open workspace layout"), QDir::currentPath(), tr("Debug Workspace Layout Files (*.omdl)")); - if (!fileName.isEmpty()) + if (!fileName.isEmpty()){ loadWorkspaces(fileName); + } } void DebuggerForm::fileSaveWorkspace() @@ -1381,14 +1413,14 @@ bool DebuggerForm::saveWorkspacesAs(const QString &newFileName) } -void DebuggerForm::loadWorkspaces(const QString &filename) +bool DebuggerForm::loadWorkspaces(const QString &filename) { QFile file(filename); if (!file.open(QFile::ReadOnly | QFile::Text)) { QMessageBox::warning(nullptr, tr("Loading workspaces ..."), tr("Cannot read file %1:\n%2.") .arg(filename,file.errorString())); - return; + return false; }; //Now try to parse the json file QJsonParseError parseError; @@ -1397,7 +1429,7 @@ void DebuggerForm::loadWorkspaces(const QString &filename) QMessageBox::warning(nullptr, tr("Open workspaces ..."), tr("Parse error at %1:%2.").arg(QString::number(parseError.offset), parseError.errorString()) ); - return; + return false; }; // delete all the current tabs before reading the new ones @@ -1410,7 +1442,8 @@ void DebuggerForm::loadWorkspaces(const QString &filename) QJsonObject obj = value.toObject(); BlendSplitter* splitter=BlendSplitter::createFromJson(obj["workspace"].toObject()); workspaces->addTab(splitter,obj["name"].toString()); - } + }; + return true; } void DebuggerForm::reloadBreakpoints(bool merge) diff --git a/src/DebuggerForm.h b/src/DebuggerForm.h index 14cf60d7..4d434d51 100644 --- a/src/DebuggerForm.h +++ b/src/DebuggerForm.h @@ -106,7 +106,7 @@ class DebuggerForm : public QMainWindow QAction* fileQuitAction; - enum { MaxRecentFiles = 5 }; + static const int MaxRecentFiles = 5; QAction* recentFileActions[MaxRecentFiles]; QAction* recentFileSeparator; @@ -129,6 +129,7 @@ class DebuggerForm : public QMainWindow QAction* helpAboutAction; + QAction* addCPUWorkspaceAction; QAction* addVDPRegsWorkspaceAction; QAction* addVDPTilesWorkspaceAction; QAction* addVDPBitmapWorkspaceAction; @@ -150,7 +151,7 @@ class DebuggerForm : public QMainWindow uint16_t disasmAddress; bool saveWorkspacesAs(const QString& newFileName); - void loadWorkspaces(const QString& filename); + bool loadWorkspaces(const QString& filename); void fileNewSession(); void fileOpenSession(); @@ -227,11 +228,14 @@ private slots: BlendSplitter *createWorkspaceVDPRegs(); BlendSplitter *createWorkspaceVDPTiles(); BlendSplitter *createWorkspaceVDPBitmap(); + void addInfoWorkspace(); + void addCPUWorkspace(); void addVDPRegsWorkspace(); void addVDPTilesWorkspace(); void addVDPBitmapWorkspace(); void addEmptyWorkspace(); void addFloatingSwitchingWidget(); + void addDefaultWorkspaces(); protected slots: diff --git a/src/PreferencesDialog.cpp b/src/PreferencesDialog.cpp index 40bc8206..143342ec 100644 --- a/src/PreferencesDialog.cpp +++ b/src/PreferencesDialog.cpp @@ -3,27 +3,47 @@ #include #include #include +#include + PreferencesDialog::PreferencesDialog(QWidget* parent) : QDialog(parent) { setupUi(this); - connect(listFonts, SIGNAL(currentRowChanged(int)), - this, SLOT(fontSelectionChange(int))); - connect(rbUseAppFont, SIGNAL(toggled(bool)), - this, SLOT(fontTypeChanged(bool))); - connect(rbUseFixedFont, SIGNAL(toggled(bool)), - this, SLOT(fontTypeChanged(bool))); - connect(rbUseCustomFont, SIGNAL(toggled(bool)), - this, SLOT(fontTypeChanged(bool))); - connect(btnSelectFont, SIGNAL(clicked()), - this, SLOT(fontSelectCustom())); - connect(btnFontColor, SIGNAL(clicked()), - this, SLOT(fontSelectColor())); + //font stuff + connect(listFonts, &QListWidget::currentRowChanged, + this, &PreferencesDialog::fontSelectionChange); + connect(rbUseAppFont,&QRadioButton::toggled, + this, &PreferencesDialog::fontTypeChanged); + connect(rbUseFixedFont, &QRadioButton::toggled, + this, &PreferencesDialog::fontTypeChanged); + connect(rbUseCustomFont, &QRadioButton::toggled, + this, &PreferencesDialog::fontTypeChanged); + connect(btnSelectFont, &QPushButton::clicked, + this, &PreferencesDialog::fontSelectCustom); + connect(btnFontColor, &QPushButton::clicked, + this, &PreferencesDialog::fontSelectColor); initFontList(); listFonts->setCurrentRow(0); + + //layout stuff + QList rblayouttypes; + rblayouttypes << rbFirstTimeUser << rbDefaultWorkspaces << rbLayoutFromFile; + foreach(auto rb, rblayouttypes){ + connect(rb, &QRadioButton::toggled, + this, &PreferencesDialog::layoutTypeChanged); + }; +// connect(rbDefaultWorkspaces, &QRadioButton::toggled, +// this, &PreferencesDialog::layoutTypeChanged); +// connect(rbLayoutFromFile, &QRadioButton::toggled, +// this, &PreferencesDialog::layoutTypeChanged); + updating=true; + Settings& s = Settings::get(); + rblayouttypes.at(s.value("creatingWorkspaceType",0).toInt())->setChecked(true); + leFileName->setText(s.value("creatingWorkspaceFile","").toString()); + updating=false; } /* @@ -106,7 +126,24 @@ void PreferencesDialog::fontSelectColor() if (newColor.isValid()) { Settings::get().setFontColor(f, newColor); setFontPreviewColor(newColor); - } + } +} + +void PreferencesDialog::layoutTypeChanged(bool state) +{ + if (!state || updating) return; + + Settings& s = Settings::get(); + + int wst=2; + if (rbFirstTimeUser->isChecked()){ + wst=0; + } else if (rbDefaultWorkspaces->isChecked()){ + wst=1; + } else { + s.setValue("creatingWorkspaceFile",leFileName->text()); + } + s.setValue("creatingWorkspaceType",wst); } void PreferencesDialog::setFontPreviewColor(const QColor& c) @@ -119,3 +156,22 @@ void PreferencesDialog::setFontPreviewColor(const QColor& c) lblPreview->setPalette(QPalette()); } } + +void PreferencesDialog::on_btnBrowseLayout_clicked() +{ + QString fileName = QFileDialog::getOpenFileName( + this, tr("Select workspace layout"), + QDir::currentPath(), tr("Debug Workspace Layout Files (*.omdl)")); + + if (!fileName.isEmpty()){ + leFileName->setText(fileName); + rbLayoutFromFile->setChecked(true); //not sure if setText with already string in lineEdit will trigger the on_leFileName_textChanged + } +} + +void PreferencesDialog::on_leFileName_textChanged(const QString &arg1) +{ + if (updating) return; + rbLayoutFromFile->setChecked(true); +} + diff --git a/src/PreferencesDialog.h b/src/PreferencesDialog.h index 2c4e589d..fb1a4d05 100644 --- a/src/PreferencesDialog.h +++ b/src/PreferencesDialog.h @@ -21,6 +21,11 @@ private slots: void fontTypeChanged(bool state); void fontSelectCustom(); void fontSelectColor(); + + void layoutTypeChanged(bool state); + void on_btnBrowseLayout_clicked(); + + void on_leFileName_textChanged(const QString &arg1); }; #endif // PREFERENCESDIALOG_OPENMSX_H diff --git a/src/PreferencesDialog.ui b/src/PreferencesDialog.ui index 159cfcc3..4df17ffa 100644 --- a/src/PreferencesDialog.ui +++ b/src/PreferencesDialog.ui @@ -1,10 +1,8 @@ - - - - + + PreferencesDialog - - + + 0 0 @@ -12,78 +10,81 @@ 512 - + Preferences - - - 9 - - + + 6 + + 9 + - - - + + + 0 + + + Fonts - - - 9 - - + + 6 + + 9 + - - + + QAbstractItemView::SelectRows - - - 0 - - + + 6 + + 0 + - - - 0 - - + + 6 + + 0 + - - + + false - + - - + + false - + Use default fixed font - - + + false - + Use custom font @@ -91,63 +92,61 @@ - - - 0 - - + + 6 + + 0 + - - - - 7 - 0 + + + 0 0 - + 0 80 - + QFrame::WinPanel - + QFrame::Sunken - + openMSX debugger! - - + + false - + Select custom font - - + + Select font color - + Qt::Vertical - + 20 40 @@ -161,22 +160,113 @@ + + + Workspace Layout + + + + + + Behavior at startup + + + + + + First Time User + + + + + + + Create the default workspaces + + + true + + + + + + + + + Load from file + + + + + + + + + + Br&owse... + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Save current layout... + + + + + + + + + + + + Qt::Vertical + + + + 20 + 237 + + + + + + - - - 0 - - + + 6 + + 0 + - + Qt::Horizontal - + 131 31 @@ -185,8 +275,8 @@ - - + + Close @@ -195,7 +285,6 @@ - @@ -204,11 +293,11 @@ PreferencesDialog accept() - + 278 253 - + 96 254 diff --git a/src/blendsplitter/ExpanderCorner.cpp b/src/blendsplitter/ExpanderCorner.cpp index 9e4e1032..b5463682 100644 --- a/src/blendsplitter/ExpanderCorner.cpp +++ b/src/blendsplitter/ExpanderCorner.cpp @@ -6,6 +6,7 @@ #include "SplitterDecorator.h" #include "SignalDispatcher.h" +#include "Settings.h" #include @@ -170,8 +171,11 @@ void ExpanderCorner::performInnerSplit(WidgetDecorator* parentDecorator, BlendSp //now if the original item was a SwitchingWidget we set the same and the enablestate if (switchwdg && addedWidget){ addedWidget->setEnableWidget(switchwdg->getEnableWidget()); - //if new user we need show the quickguide (is the default widget) otherwise -// addedWidget->setCurrentIndex(switchwdg->getCurrentIndex()); + //if new user we need show the quickguide (is the default widget) otherwise we split current one + Settings& s = Settings::get(); + if (s.value("creatingWorkspaceType",0).toInt() ){ + addedWidget->setCurrentIndex(switchwdg->getCurrentIndex()); + } } //have the cursor take the correct shape diff --git a/src/blendsplitter/SwitchingWidget.cpp b/src/blendsplitter/SwitchingWidget.cpp index 30d0f463..5e5fa846 100644 --- a/src/blendsplitter/SwitchingWidget.cpp +++ b/src/blendsplitter/SwitchingWidget.cpp @@ -6,8 +6,10 @@ #include "SwitchingCombo.h" #include #include +#include -SwitchingWidget::SwitchingWidget(RegistryItem* item, QWidget* parent,bool menuAtTop) : QSplitter(Qt::Vertical, parent), bar{new SwitchingBar{}}, widgetEnabled(true),barAtTop(menuAtTop) +SwitchingWidget::SwitchingWidget(RegistryItem* item, QWidget* parent,bool menuAtTop) : QSplitter(Qt::Vertical, parent), + bar{new SwitchingBar{}}, widgetEnabled(true),isWidgetAlwaysEnabled(false),barAtTop(menuAtTop) { setChildrenCollapsible(true); setHandleWidth(1); @@ -39,6 +41,9 @@ void SwitchingWidget::setCurrentWidget(RegistryItem *item) bar->combo->setCurrentIndex(bar->combo->findText(item->name)); widget(widgetIndex())->setEnabled(widgetEnabled); } + //hack to have manual always enabled + qDebug() << "WidgetRegistry::getRegistry()->indexOf(item) " << WidgetRegistry::getRegistry()->indexOf(item); + setWidgetAlwaysEnabled(WidgetRegistry::getRegistry()->indexOf(item)==14); } bool SwitchingWidget::getEnableWidget() @@ -93,11 +98,22 @@ void SwitchingWidget::setEnableWidget(bool enable) }; if (wdgt != nullptr){ - wdgt->setEnabled(enable); + bool finalstatus=enable||isWidgetAlwaysEnabled; +// qDebug() << "wdgt->setEnabled(" << enable << "||" << isWidgetAlwaysEnabled << "= "<< finalstatus<< " ) "; + + wdgt->setEnabled(finalstatus); + wdgt->update(); } } +void SwitchingWidget::setWidgetAlwaysEnabled(bool enable) +{ + isWidgetAlwaysEnabled=enable; +// qDebug() << "SwitchingWidget::setWidgetAlwaysEnabled(bool "<= 0) diff --git a/src/blendsplitter/SwitchingWidget.h b/src/blendsplitter/SwitchingWidget.h index 5a9cecb9..dc7f2c60 100644 --- a/src/blendsplitter/SwitchingWidget.h +++ b/src/blendsplitter/SwitchingWidget.h @@ -40,6 +40,8 @@ class SwitchingWidget : public QSplitter public slots: void setEnableWidget(bool enable = true); + void setWidgetAlwaysEnabled(bool enable = true); + private slots: void changeCurrentWidget(int index); private: @@ -48,6 +50,7 @@ private slots: int widgetIndex(); SwitchingBar* bar; bool widgetEnabled; + bool isWidgetAlwaysEnabled; //some widgets need to be always enabled even if disconnect from openMSX bool barAtTop; bool isWrappedInScrollArea; }; From e17b826101711d03af1554dffa6c7fd4fc11d0a6 Mon Sep 17 00:00:00 2001 From: David Heremans Date: Sun, 1 May 2022 22:01:15 +0200 Subject: [PATCH 15/63] Rename the tabs by double clicking them --- src/DebuggerForm.cpp | 36 +++++++++++++++++++++++++-- src/DebuggerForm.h | 5 ++++ src/blendsplitter/SwitchingWidget.cpp | 2 +- 3 files changed, 40 insertions(+), 3 deletions(-) diff --git a/src/DebuggerForm.cpp b/src/DebuggerForm.cpp index 601c0dfe..15e63ae3 100644 --- a/src/DebuggerForm.cpp +++ b/src/DebuggerForm.cpp @@ -46,6 +46,7 @@ #include #include #include +#include QMap DebuggerForm::debuggables; @@ -157,7 +158,7 @@ int DebuggerForm::counter = 0; DebuggerForm::DebuggerForm(QWidget* parent) : QMainWindow(parent) - , comm(CommClient::instance()) + , comm(CommClient::instance()), tabLineEdit{nullptr},editedTab{-1} { session = DebugSession::getDebugSession(); @@ -611,6 +612,36 @@ void DebuggerForm::tabCloseRequest(int index) } } +void DebuggerForm::tabBarDoubleClicked(int index) +{ + editedTab=index; + if (index==-1){ + return; + }; + QRect r=workspaces->tabBar()->tabRect(index); + QString t=workspaces->tabBar()->tabText(index); + tabLineEdit=new QLineEdit{workspaces->tabBar()}; + tabLineEdit->show(); + tabLineEdit->move(r.topLeft()); + tabLineEdit->resize(r.size()); + tabLineEdit->setText(t); + tabLineEdit->selectAll(); + tabLineEdit->setFocus(); + connect(tabLineEdit,SIGNAL(editingFinished()), + this,SLOT(tabNameEditingFinished())); + +} + +void DebuggerForm::tabNameEditingFinished() +{ + QString newname=tabLineEdit->text(); + if (!newname.isEmpty()){ + workspaces->tabBar()->setTabText(editedTab,newname); + }; + tabLineEdit->deleteLater(); + tabLineEdit=nullptr; +} + void DebuggerForm::addInfoWorkspace(){ BlendSplitter* split = new BlendSplitter([]()->QWidget* {return new SwitchingWidget{};},Qt::Horizontal); split->addWidget(WidgetRegistry::getRegistry()->item(14)); //14: the quick guide manuel @@ -673,7 +704,8 @@ void DebuggerForm::createForm() btn->setPopupMode(QToolButton::InstantPopup); workspaces->setCornerWidget(btn, Qt::TopRightCorner); connect(workspaces,&QTabWidget::tabCloseRequested,this,&DebuggerForm::tabCloseRequest); - + connect(workspaces->tabBar(),&QTabBar::tabBarDoubleClicked, + this,&DebuggerForm::tabBarDoubleClicked); QWidget *window = new QWidget; QVBoxLayout *layout = new QVBoxLayout; layout->addWidget(workspaces); diff --git a/src/DebuggerForm.h b/src/DebuggerForm.h index 4d434d51..8dc569cb 100644 --- a/src/DebuggerForm.h +++ b/src/DebuggerForm.h @@ -21,6 +21,7 @@ class VDPCommandRegViewer; class BreakpointViewer; class BlendSplitter; class QTabWidget; +class QLineEdit; class DebuggerForm : public QMainWindow { @@ -238,8 +239,12 @@ private slots: void addDefaultWorkspaces(); + QLineEdit* tabLineEdit; + int editedTab; protected slots: void tabCloseRequest(int index); + void tabBarDoubleClicked(int index); + void tabNameEditingFinished(); }; #endif // DEBUGGERFORM_H diff --git a/src/blendsplitter/SwitchingWidget.cpp b/src/blendsplitter/SwitchingWidget.cpp index 5e5fa846..8362af23 100644 --- a/src/blendsplitter/SwitchingWidget.cpp +++ b/src/blendsplitter/SwitchingWidget.cpp @@ -42,7 +42,7 @@ void SwitchingWidget::setCurrentWidget(RegistryItem *item) widget(widgetIndex())->setEnabled(widgetEnabled); } //hack to have manual always enabled - qDebug() << "WidgetRegistry::getRegistry()->indexOf(item) " << WidgetRegistry::getRegistry()->indexOf(item); + //qDebug() << "WidgetRegistry::getRegistry()->indexOf(item) " << WidgetRegistry::getRegistry()->indexOf(item); setWidgetAlwaysEnabled(WidgetRegistry::getRegistry()->indexOf(item)==14); } From 363555df9b80027f65e2e5d8079cd51381f444c6 Mon Sep 17 00:00:00 2001 From: David Heremans Date: Mon, 2 May 2022 23:02:58 +0200 Subject: [PATCH 16/63] Improved tab renamer Moved code in single class, and improved usage. ESC will now cancel any ongoing edits. Clicking on other tabs will now close the lineEdit. And the tabs are now movable. --- src/DebuggerForm.cpp | 45 ++++---------------- src/DebuggerForm.h | 11 ++--- src/TabRenamerHelper.cpp | 91 ++++++++++++++++++++++++++++++++++++++++ src/TabRenamerHelper.h | 28 +++++++++++++ src/node.mk | 2 +- 5 files changed, 135 insertions(+), 42 deletions(-) create mode 100644 src/TabRenamerHelper.cpp create mode 100644 src/TabRenamerHelper.h diff --git a/src/DebuggerForm.cpp b/src/DebuggerForm.cpp index 15e63ae3..03da272d 100644 --- a/src/DebuggerForm.cpp +++ b/src/DebuggerForm.cpp @@ -25,6 +25,7 @@ #include "blendsplitter/BlendSplitter.h" #include "blendsplitter/WidgetRegistry.h" #include "QuickGuide.h" +#include "TabRenamerHelper.h" #include #include #include @@ -46,7 +47,7 @@ #include #include #include -#include + QMap DebuggerForm::debuggables; @@ -95,9 +96,9 @@ class QueryBreakedHandler : public SimpleCommand class CPURegRequest : public ReadDebugBlockCommand { public: - CPURegRequest(DebuggerForm& form_) + CPURegRequest(DebuggerForm& /*form_*/) : ReadDebugBlockCommand("{CPU regs}", 0, 28, buf) - , form(form_) +// , form(form_) { } @@ -109,7 +110,7 @@ class CPURegRequest : public ReadDebugBlockCommand } private: - DebuggerForm& form; +// DebuggerForm& form; unsigned char buf[28]; }; @@ -158,7 +159,7 @@ int DebuggerForm::counter = 0; DebuggerForm::DebuggerForm(QWidget* parent) : QMainWindow(parent) - , comm(CommClient::instance()), tabLineEdit{nullptr},editedTab{-1} + , comm(CommClient::instance()) { session = DebugSession::getDebugSession(); @@ -612,35 +613,6 @@ void DebuggerForm::tabCloseRequest(int index) } } -void DebuggerForm::tabBarDoubleClicked(int index) -{ - editedTab=index; - if (index==-1){ - return; - }; - QRect r=workspaces->tabBar()->tabRect(index); - QString t=workspaces->tabBar()->tabText(index); - tabLineEdit=new QLineEdit{workspaces->tabBar()}; - tabLineEdit->show(); - tabLineEdit->move(r.topLeft()); - tabLineEdit->resize(r.size()); - tabLineEdit->setText(t); - tabLineEdit->selectAll(); - tabLineEdit->setFocus(); - connect(tabLineEdit,SIGNAL(editingFinished()), - this,SLOT(tabNameEditingFinished())); - -} - -void DebuggerForm::tabNameEditingFinished() -{ - QString newname=tabLineEdit->text(); - if (!newname.isEmpty()){ - workspaces->tabBar()->setTabText(editedTab,newname); - }; - tabLineEdit->deleteLater(); - tabLineEdit=nullptr; -} void DebuggerForm::addInfoWorkspace(){ BlendSplitter* split = new BlendSplitter([]()->QWidget* {return new SwitchingWidget{};},Qt::Horizontal); @@ -682,8 +654,11 @@ void DebuggerForm::createForm() createWidgetRegistry(); workspaces = new QTabWidget(); + tabRenamer = new TabRenamerHelper{workspaces}; + workspaces->setMinimumHeight(500); workspaces->setTabsClosable(true); + workspaces->setMovable(true); QMenu *workspacemenu=new QMenu(); QMenu *workspacesubmenu=new QMenu("Predefined layouts"); workspacesubmenu->addAction(addCPUWorkspaceAction); @@ -704,8 +679,6 @@ void DebuggerForm::createForm() btn->setPopupMode(QToolButton::InstantPopup); workspaces->setCornerWidget(btn, Qt::TopRightCorner); connect(workspaces,&QTabWidget::tabCloseRequested,this,&DebuggerForm::tabCloseRequest); - connect(workspaces->tabBar(),&QTabBar::tabBarDoubleClicked, - this,&DebuggerForm::tabBarDoubleClicked); QWidget *window = new QWidget; QVBoxLayout *layout = new QVBoxLayout; layout->addWidget(workspaces); diff --git a/src/DebuggerForm.h b/src/DebuggerForm.h index 8dc569cb..75eed5ee 100644 --- a/src/DebuggerForm.h +++ b/src/DebuggerForm.h @@ -21,7 +21,7 @@ class VDPCommandRegViewer; class BreakpointViewer; class BlendSplitter; class QTabWidget; -class QLineEdit; +class TabRenamerHelper; class DebuggerForm : public QMainWindow { @@ -143,6 +143,7 @@ class DebuggerForm : public QMainWindow DebugSession* session; QTabWidget *workspaces; + TabRenamerHelper *tabRenamer; bool mergeBreakpoints; static QMap debuggables; @@ -215,6 +216,8 @@ private slots: friend class ListDebuggablesHandler; friend class DebuggableSizeHandler; + friend class TabRenamerHelper; + signals: void connected(); void settingsChanged(); @@ -239,12 +242,10 @@ private slots: void addDefaultWorkspaces(); - QLineEdit* tabLineEdit; - int editedTab; + protected slots: void tabCloseRequest(int index); - void tabBarDoubleClicked(int index); - void tabNameEditingFinished(); + }; #endif // DEBUGGERFORM_H diff --git a/src/TabRenamerHelper.cpp b/src/TabRenamerHelper.cpp new file mode 100644 index 00000000..7972f523 --- /dev/null +++ b/src/TabRenamerHelper.cpp @@ -0,0 +1,91 @@ +#include "TabRenamerHelper.h" +#include +#include +#include +#include +#include + +TabRenamerHelper::TabRenamerHelper(QTabWidget *parent) + : QObject{parent},workspaces{parent}, + tabLineEdit{nullptr},editedTab{-1} +{ + connect(workspaces->tabBar(),&QTabBar::tabBarDoubleClicked, + this,&TabRenamerHelper::tabBarDoubleClicked); + workspaces->tabBar()->installEventFilter(this); +// workspaces->installEventFilter(this); + +} + +void TabRenamerHelper::tabBarDoubleClicked(int index) +{ + editedTab=index; + if (index==-1){ + return; + }; + QRect r=workspaces->tabBar()->tabRect(index); + QString t=workspaces->tabBar()->tabText(index); + tabLineEdit=new QLineEdit{workspaces->tabBar()}; + tabLineEdit->show(); + tabLineEdit->move(r.topLeft()); + tabLineEdit->resize(r.size()); + tabLineEdit->setText(t); + tabLineEdit->selectAll(); + tabLineEdit->setFocus(); + tabLineEdit->installEventFilter(this); + connect(tabLineEdit,SIGNAL(editingFinished()), + this,SLOT(tabNameEditingFinished())); + +} + + +void TabRenamerHelper::tabNameEditingFinished() +{ + QString newname=tabLineEdit->text(); + if (!newname.isEmpty()){ + workspaces->tabBar()->setTabText(editedTab,newname); + }; + tabLineEdit->deleteLater(); + tabLineEdit=nullptr; +} + +bool TabRenamerHelper::eventFilter(QObject *obj, QEvent *event) +{ + bool result=QObject::eventFilter(obj,event); + QTabBar* bar=workspaces->tabBar(); + if (obj == bar){ + if (event->type() == QEvent::MouseButtonPress){ + // the user is trying to move away from editing by clicking another tab + QMouseEvent* me = static_cast(event); + int clickedTabId = bar->tabAt(me->pos()); + if (editedTab!=-1 && editedTab!= clickedTabId && tabLineEdit){ + emit tabLineEdit->editingFinished(); + return false; + } + }; + if (event->type() == QEvent::MouseButtonDblClick){ + //perhaps we need to start a new name editing action? + QMouseEvent* me = static_cast(event); + int clickedTabId = bar->tabAt(me->pos()); + if (clickedTabId == -1){ + return result; + } + if (editedTab!=-1 && editedTab!= clickedTabId && tabLineEdit){ + emit tabLineEdit->editingFinished(); + return false; + } + } + } + //handle some events on the line edit to make it behave itself nicely as a rename editor + if (obj == tabLineEdit && event->type() == QEvent::KeyPress) { + QKeyEvent* ke = static_cast(event); + if (ke->key() == Qt::Key_Escape) { + disconnect(tabLineEdit,SIGNAL(editingFinished()), + this,SLOT(tabNameEditingFinished())); + tabLineEdit->deleteLater(); + tabLineEdit=nullptr; + return true; //no further handling of this event is required + } + } + + return result; +} diff --git a/src/TabRenamerHelper.h b/src/TabRenamerHelper.h new file mode 100644 index 00000000..811173d1 --- /dev/null +++ b/src/TabRenamerHelper.h @@ -0,0 +1,28 @@ +#ifndef TABRENAMERHELPER_H +#define TABRENAMERHELPER_H + +#include + +class QLineEdit; +class QTabWidget; + +class TabRenamerHelper : public QObject +{ + Q_OBJECT +public: + explicit TabRenamerHelper(QTabWidget *parent = nullptr); + +public slots: + void tabBarDoubleClicked(int index); + void tabNameEditingFinished(); + +protected: + bool eventFilter(QObject *obj, QEvent *event) override; + + QTabWidget* workspaces; + QLineEdit* tabLineEdit; + int editedTab; + +}; + +#endif // TABRENAMERHELPER_H diff --git a/src/node.mk b/src/node.mk index aecde82c..24351ba0 100644 --- a/src/node.mk +++ b/src/node.mk @@ -18,7 +18,7 @@ MOC_SRC_HDR:= \ blendsplitter/WidgetRegistry blendsplitter/ExpanderCorner \ blendsplitter/RegistryItem \ blendsplitter/SplitterHandle blendsplitter/SwitchingCombo \ - blendsplitter/WidgetDecorator QuickGuide + blendsplitter/WidgetDecorator QuickGuide TabRenamerHelper From be9e648c4ff0db14e9d5883c7e20e2308a0c4956 Mon Sep 17 00:00:00 2001 From: David Heremans Date: Tue, 3 May 2022 12:13:22 +0200 Subject: [PATCH 17/63] Code cleanup Thanks to a quick review of Wouter --- src/DebugSession.cpp | 2 +- src/DebugSession.h | 14 +- src/DebuggerForm.cpp | 249 +++++++++---------- src/SignalDispatcher.h | 32 ++- src/blendsplitter/BlendSplitter.cpp | 95 ++++---- src/blendsplitter/BlendSplitter.h | 43 +++- src/blendsplitter/Expander.cpp | 42 ++-- src/blendsplitter/Expander.h | 31 ++- src/blendsplitter/ExpanderCorner.cpp | 310 +++++++++++------------- src/blendsplitter/ExpanderCorner.h | 44 ++-- src/blendsplitter/Global.h | 5 +- src/blendsplitter/Overlay.cpp | 105 ++++---- src/blendsplitter/Overlay.h | 20 +- src/blendsplitter/RegistryItem.cpp | 9 +- src/blendsplitter/RegistryItem.h | 20 +- src/blendsplitter/SplitterDecorator.cpp | 5 +- src/blendsplitter/SplitterDecorator.h | 11 +- src/blendsplitter/SplitterHandle.cpp | 140 +++++------ src/blendsplitter/SplitterHandle.h | 21 +- src/blendsplitter/SwitchingBar.cpp | 24 +- src/blendsplitter/SwitchingBar.h | 25 +- src/blendsplitter/SwitchingCombo.cpp | 19 +- src/blendsplitter/SwitchingCombo.h | 12 +- src/blendsplitter/SwitchingWidget.cpp | 117 ++++----- src/blendsplitter/SwitchingWidget.h | 21 +- src/blendsplitter/WidgetDecorator.cpp | 84 +++---- src/blendsplitter/WidgetDecorator.h | 34 +-- src/blendsplitter/WidgetRegistry.cpp | 41 +--- src/blendsplitter/WidgetRegistry.h | 48 ++-- 29 files changed, 827 insertions(+), 796 deletions(-) diff --git a/src/DebugSession.cpp b/src/DebugSession.cpp index b1e2f940..9db140b2 100644 --- a/src/DebugSession.cpp +++ b/src/DebugSession.cpp @@ -43,7 +43,7 @@ SymbolTable& DebugSession::symbolTable() DebugSession *DebugSession::getDebugSession() { - if(theDebugSession == nullptr){ + if (theDebugSession == nullptr) { theDebugSession = new DebugSession{}; } return theDebugSession; diff --git a/src/DebugSession.h b/src/DebugSession.h index 7d3e1822..741d9768 100644 --- a/src/DebugSession.h +++ b/src/DebugSession.h @@ -10,9 +10,12 @@ class QXmlStreamReader; class DebugSession : public QObject { Q_OBJECT - Q_DISABLE_COPY(DebugSession) + public: - static DebugSession* getDebugSession(); + DebugSession(const DebugSession&) = delete; + DebugSession& operator=(const DebugSession&) = delete; + + static DebugSession* getDebugSession(); // session void clear(); @@ -27,18 +30,19 @@ class DebugSession : public QObject SymbolTable& symbolTable(); public slots: - void sessionModified(); + void sessionModified(); private: + DebugSession(); void skipUnknownElement(QXmlStreamReader& ses); +private: Breakpoints breaks; SymbolTable symTable; QString fileName; bool modified; - static DebugSession* theDebugSession; - DebugSession(); + static DebugSession* theDebugSession; }; #endif // DEBUGSESSION_H diff --git a/src/DebuggerForm.cpp b/src/DebuggerForm.cpp index 03da272d..bfcf73f0 100644 --- a/src/DebuggerForm.cpp +++ b/src/DebuggerForm.cpp @@ -442,141 +442,119 @@ void DebuggerForm::createStatusbar() void DebuggerForm::createWidgetRegistry() { + auto& registry = WidgetRegistry::instance(); + //0: register the disasm viewer widget - RegistryItem *item = new RegistryItem{ - tr("Code view"), - []()->QWidget* {return widgetFactory(disasmViewer);} - }; - WidgetRegistry::getRegistry()->addItem(item); + registry.addItem(new RegistryItem{ + tr("Code view"), + [] { return widgetFactory( disasmViewer); }}); //1: register the memory view widget - item = new RegistryItem{ - tr("Main memory"), - []()->QWidget* {return widgetFactory(mainMemoryViewer);} - }; - WidgetRegistry::getRegistry()->addItem(item); + registry.addItem(new RegistryItem{ + tr("Main memory"), + [] { return widgetFactory( mainMemoryViewer); }}); //2: register the register viewer - item = new RegistryItem{ - tr("CPU registers"), - []()->QWidget* {return widgetFactory(cpuRegsViewer);} - }; - WidgetRegistry::getRegistry()->addItem(item); + registry.addItem(new RegistryItem{ + tr("CPU registers"), + [] { return widgetFactory(cpuRegsViewer); }}); //3: register the flags viewer - item = new RegistryItem{ - tr("Flags"), - []()->QWidget* {return widgetFactory(flagsViewer);} - }; - WidgetRegistry::getRegistry()->addItem(item); + registry.addItem(new RegistryItem{ + tr("Flags"), + [] { return widgetFactory(flagsViewer); }}); //4: register the stack viewer - item = new RegistryItem{ - tr("Stack"), - []()->QWidget* {return widgetFactory(stackViewer);} - }; - WidgetRegistry::getRegistry()->addItem(item); + registry.addItem(new RegistryItem{ + tr("Stack"), + [] { return widgetFactory(stackViewer); }}); //5: register the slot viewer - item = new RegistryItem{ - tr("Memory layout"), - []()->QWidget* {return widgetFactory(slotViewer);} - }; - WidgetRegistry::getRegistry()->addItem(item); + registry.addItem(new RegistryItem{ + tr("Memory layout"), + [] { return widgetFactory(slotViewer); }}); //6: register the breakpoints viewer - item = new RegistryItem{ - tr("Debug list"), - []()->QWidget* {return widgetFactory(breakpointViewer);} - }; - WidgetRegistry::getRegistry()->addItem(item); + registry.addItem(new RegistryItem{ + tr("Debug list"), + [] { return widgetFactory(breakpointViewer); }}); //7: register the debuggable viewer - item = new RegistryItem{ - tr("Debuggable hex view"), - []()->QWidget* {return widgetFactory(debuggableViewer);} - }; - WidgetRegistry::getRegistry()->addItem(item); - //WidgetRegistry::getRegistry()->setDefault(item); + registry.addItem(new RegistryItem{ + tr("Debuggable hex view"), + [] { return widgetFactory(debuggableViewer); }}); + //registry.setDefault(item); //8: register the VDP Status Registers - item = new RegistryItem{ - tr("VDP status registers"), - []()->QWidget* {return widgetFactory(vdpStatusRegViewer);} - }; - WidgetRegistry::getRegistry()->addItem(item); + registry.addItem(new RegistryItem{ + tr("VDP status registers"), + [] { return widgetFactory(vdpStatusRegViewer); }}); //9: register the VDP command registers view - item = new RegistryItem{ - tr("VDP command registers "), - []()->QWidget* {return widgetFactory(vdpCommandRegViewer);} - }; - WidgetRegistry::getRegistry()->addItem(item); + registry.addItem(new RegistryItem{ + tr("VDP command registers "), + [] { return widgetFactory(vdpCommandRegViewer); }}); //10: register the Bitmapped VRAM View - item = new RegistryItem{ - tr("VRAM as bitmap"), - []()->QWidget* {return widgetFactory(bitMapViewer);} - }; - WidgetRegistry::getRegistry()->addItem(item); + registry.addItem(new RegistryItem{ + tr("VRAM as bitmap"), + [] { return widgetFactory(bitMapViewer); }}); //11: register the Tile VRAM View - item = new RegistryItem{ - tr("VRAM as tiles"), - []()->QWidget* {return widgetFactory(tileViewer);} - }; - WidgetRegistry::getRegistry()->addItem(item); + registry.addItem(new RegistryItem{ + tr("VRAM as tiles"), + [] { return widgetFactory(tileViewer); }}); //12: register the Sprites View - item = new RegistryItem{ - tr("Sprites View"), - []()->QWidget* {return widgetFactory(spriteViewer);} - }; - WidgetRegistry::getRegistry()->addItem(item); + registry.addItem(new RegistryItem{ + tr("Sprites View"), + [] { return widgetFactory(spriteViewer); }}); //13: register the general VDP registers - item = new RegistryItem{ - tr("VDP registers"), - []()->QWidget* {return widgetFactory(vdpRegisters);} - }; - WidgetRegistry::getRegistry()->addItem(item); + registry.addItem(new RegistryItem{ + tr("VDP registers"), + [] { return widgetFactory(vdpRegisters); }}); + //14: register the quick guide manuel - item = new RegistryItem{ - tr("Quick Guide"), - []()->QWidget* {return widgetFactory(quickguide);} - }; - //WidgetRegistry::getRegistry()->addItem(item); - WidgetRegistry::getRegistry()->setDefault(item); + auto* item = new RegistryItem{ + tr("Quick Guide"), + [] { return widgetFactory(quickguide); }}; + registry.addItem(item); + registry.setDefault(item); } BlendSplitter* DebuggerForm::createWorkspaceCPU() { - BlendSplitter* split = new BlendSplitter([]()->QWidget* {return new SwitchingWidget{};},Qt::Horizontal); - split->addWidget(WidgetRegistry::getRegistry()->item(2)); //2: the register viewer - split->addWidget(WidgetRegistry::getRegistry()->item(3)); //3: the flags viewer - split->addWidget(WidgetRegistry::getRegistry()->item(5)); //5: the slot viewer + auto& registry = WidgetRegistry::instance(); + + auto* split = new BlendSplitter({}, Qt::Horizontal); + split->addWidget(registry.item(2)); //2: the register viewer + split->addWidget(registry.item(3)); //3: the flags viewer + split->addWidget(registry.item(5)); //5: the slot viewer - BlendSplitter* split2 = new BlendSplitter([]()->QWidget* {return new SwitchingWidget{};},Qt::Vertical); + auto* split2 = new BlendSplitter({}, Qt::Vertical); split2->addSplitter(split); - split2->addWidget(WidgetRegistry::getRegistry()->item(1)); //1: the memory view widget - split2->addWidget(WidgetRegistry::getRegistry()->item(6)); //6: the breakpoints viewer + split2->addWidget(registry.item(1)); //1: the memory view widget + split2->addWidget(registry.item(6)); //6: the breakpoints viewer - BlendSplitter* split3 = new BlendSplitter([]()->QWidget* {return new SwitchingWidget{};},Qt::Horizontal); - split3->addWidget(WidgetRegistry::getRegistry()->item(0)); //0: the disasm viewer + auto* split3 = new BlendSplitter({}, Qt::Horizontal); + split3->addWidget(registry.item(0)); //0: the disasm viewer split3->addSplitter(split2); - split3->addWidget(WidgetRegistry::getRegistry()->item(4)); //4: the stack viewer + split3->addWidget(registry.item(4)); //4: the stack viewer return split3; } BlendSplitter* DebuggerForm::createWorkspaceVDPRegs() { - BlendSplitter* split2 = new BlendSplitter([]()->QWidget* {return new SwitchingWidget{};},Qt::Vertical); - split2->addWidget(WidgetRegistry::getRegistry()->item(8)); //8: the VDP Status Registers - split2->addWidget(WidgetRegistry::getRegistry()->item(9)); //9: the VDP command registers view + auto& registry = WidgetRegistry::instance(); - BlendSplitter* split3 = new BlendSplitter([]()->QWidget* {return new SwitchingWidget{};},Qt::Horizontal); - split3->addWidget(WidgetRegistry::getRegistry()->item(13)); //13: the general VDP registers + auto* split2 = new BlendSplitter({}, Qt::Vertical); + split2->addWidget(registry.item(8)); //8: the VDP Status Registers + split2->addWidget(registry.item(9)); //9: the VDP command registers view + + auto* split3 = new BlendSplitter({}, Qt::Horizontal); + split3->addWidget(registry.item(13)); //13: the general VDP registers split3->addSplitter(split2); return split3; @@ -584,29 +562,28 @@ BlendSplitter* DebuggerForm::createWorkspaceVDPRegs() BlendSplitter *DebuggerForm::createWorkspaceVDPTiles() { - BlendSplitter* split3 = new BlendSplitter([]()->QWidget* {return new SwitchingWidget{};},Qt::Horizontal); - split3->addWidget(WidgetRegistry::getRegistry()->item(11)); //11: the Tile VRAM View - split3->addWidget(WidgetRegistry::getRegistry()->item(12)); //12: the Sprites View - + auto& registry = WidgetRegistry::instance(); + auto* split3 = new BlendSplitter({}, Qt::Horizontal); + split3->addWidget(registry.item(11)); //11: the Tile VRAM View + split3->addWidget(registry.item(12)); //12: the Sprites View return split3; } BlendSplitter *DebuggerForm::createWorkspaceVDPBitmap() { - BlendSplitter* split3 = new BlendSplitter([]()->QWidget* {return new SwitchingWidget{};},Qt::Horizontal); - split3->addWidget(WidgetRegistry::getRegistry()->item(10)); //10: the Bitmapped VRAM View - split3->addWidget(WidgetRegistry::getRegistry()->item(12)); //12: the Sprites View - + auto& registry = WidgetRegistry::instance(); + auto* split3 = new BlendSplitter({}, Qt::Horizontal); + split3->addWidget(registry.item(10)); //10: the Bitmapped VRAM View + split3->addWidget(registry.item(12)); //12: the Sprites View return split3; } void DebuggerForm::tabCloseRequest(int index) { - if((index < 0) || (index >= workspaces->count())){ + if ((index < 0) || (index >= workspaces->count())) { return; - }; - - if (workspaces->count() > 1){ + } + if (workspaces->count() > 1) { QWidget *splitter=workspaces->widget(index); workspaces->removeTab(index); delete splitter; @@ -614,29 +591,37 @@ void DebuggerForm::tabCloseRequest(int index) } -void DebuggerForm::addInfoWorkspace(){ - BlendSplitter* split = new BlendSplitter([]()->QWidget* {return new SwitchingWidget{};},Qt::Horizontal); - split->addWidget(WidgetRegistry::getRegistry()->item(14)); //14: the quick guide manuel - workspaces->addTab(split,"Welcome new user"); +void DebuggerForm::addInfoWorkspace() +{ + auto* split = new BlendSplitter([]()->QWidget* {return new SwitchingWidget{};},Qt::Horizontal); + split->addWidget(WidgetRegistry::instance().item(14)); //14: the quick guide manuel + workspaces->addTab(split, "Welcome new user"); } -void DebuggerForm::addCPUWorkspace(){ - workspaces->addTab(createWorkspaceCPU(),"CPU"); + +void DebuggerForm::addCPUWorkspace() +{ + workspaces->addTab(createWorkspaceCPU(), "CPU"); } -void DebuggerForm::addVDPRegsWorkspace(){ - workspaces->addTab(createWorkspaceVDPRegs(),"VDP Registers"); + +void DebuggerForm::addVDPRegsWorkspace() +{ + workspaces->addTab(createWorkspaceVDPRegs(), "VDP Registers"); } -void DebuggerForm::addVDPTilesWorkspace(){ - workspaces->addTab(createWorkspaceVDPTiles(),"VDP tiles"); + +void DebuggerForm::addVDPTilesWorkspace() +{ + workspaces->addTab(createWorkspaceVDPTiles(), "VDP tiles"); } + void DebuggerForm::addVDPBitmapWorkspace(){ - workspaces->addTab(createWorkspaceVDPBitmap(),"VDP bitmap"); + workspaces->addTab(createWorkspaceVDPBitmap(), "VDP bitmap"); } void DebuggerForm::addEmptyWorkspace() { - BlendSplitter* split = new BlendSplitter([]()->QWidget* {return new SwitchingWidget{};},Qt::Horizontal); + auto* split = new BlendSplitter({}, Qt::Horizontal); split->addWidget(); - workspaces->addTab(split,"custom"); + workspaces->addTab(split, "custom"); } void DebuggerForm::addFloatingSwitchingWidget() @@ -677,8 +662,8 @@ void DebuggerForm::createForm() btn->setIcon(icon); btn->setMenu(workspacemenu); btn->setPopupMode(QToolButton::InstantPopup); - workspaces->setCornerWidget(btn, Qt::TopRightCorner); - connect(workspaces,&QTabWidget::tabCloseRequested,this,&DebuggerForm::tabCloseRequest); + workspaces->setCornerWidget(btn, Qt::TopRightCorner); + connect(workspaces, &QTabWidget::tabCloseRequested, this, &DebuggerForm::tabCloseRequest); QWidget *window = new QWidget; QVBoxLayout *layout = new QVBoxLayout; layout->addWidget(workspaces); @@ -686,7 +671,7 @@ void DebuggerForm::createForm() Settings& s = Settings::get(); - int workspacetype =s.value("creatingWorkspaceType",0).toInt(); + int workspacetype =s.value("creatingWorkspaceType", 0).toInt(); switch (workspacetype) { case 0: addInfoWorkspace(); @@ -695,7 +680,7 @@ void DebuggerForm::createForm() addDefaultWorkspaces(); break; default: - if (!loadWorkspaces(s.value("creatingWorkspaceFile",0).toString())){ + if (!loadWorkspaces(s.value("creatingWorkspaceFile", 0).toString())){ addDefaultWorkspaces(); } break; @@ -709,8 +694,8 @@ void DebuggerForm::createForm() //and have it propagate the signals connect(this, SIGNAL(connected()), SignalDispatcher::getDispatcher(), SIGNAL(connected())); connect(this, SIGNAL(breakStateEntered()), SignalDispatcher::getDispatcher(), SIGNAL(breakStateEntered())); - connect(this, SIGNAL(debuggablesChanged(const QMap&)), - SignalDispatcher::getDispatcher(), SIGNAL(debuggablesChanged(const QMap&)) ); + connect(this, SIGNAL(debuggablesChanged(const QMap&)), + SignalDispatcher::getDispatcher(), SIGNAL(debuggablesChanged(const QMap&)) ); connect(this, &DebuggerForm::breakpointsUpdated, SignalDispatcher::getDispatcher(), &SignalDispatcher::breakpointsUpdated); @@ -732,7 +717,7 @@ void DebuggerForm::addDefaultWorkspaces() addVDPBitmapWorkspace(); } -QWidget *DebuggerForm::widgetFactory(factoryclasses fctwidget) +QWidget* DebuggerForm::widgetFactory(factoryclasses fctwidget) { QWidget* wdgt; switch (fctwidget) { @@ -744,8 +729,8 @@ QWidget *DebuggerForm::widgetFactory(factoryclasses fctwidget) connect(SignalDispatcher::getDispatcher(), SIGNAL(breakStateEntered()), wdgt, SLOT(refresh())); connect(SignalDispatcher::getDispatcher(), SIGNAL(symbolsChanged()), wdgt, SLOT(refresh())); connect(SignalDispatcher::getDispatcher(), SIGNAL(settingsChanged()), wdgt, SLOT(updateLayout())); - connect(SignalDispatcher::getDispatcher(), SIGNAL(setCursorAddress(uint16_t,int,int)), wdgt, SLOT(setCursorAddress(uint16_t,int,int))); - connect(SignalDispatcher::getDispatcher(), SIGNAL(setProgramCounter(uint16_t,bool)), wdgt, SLOT(setProgramCounter(uint16_t,bool))); + connect(SignalDispatcher::getDispatcher(), SIGNAL(setCursorAddress(uint16_t, int, int)), wdgt, SLOT(setCursorAddress(uint16_t, int, int))); + connect(SignalDispatcher::getDispatcher(), SIGNAL(setProgramCounter(uint16_t, bool)), wdgt, SLOT(setProgramCounter(uint16_t, bool))); connect(SignalDispatcher::getDispatcher(), SIGNAL(breakpointsUpdated()), wdgt, SLOT(update())); static_cast(wdgt)->setMemory(SignalDispatcher::getDispatcher()->getMainMemory()); static_cast(wdgt)->setBreakpoints(&DebugSession::getDebugSession()->breakpoints()); @@ -759,7 +744,7 @@ QWidget *DebuggerForm::widgetFactory(factoryclasses fctwidget) // Main memory viewer connect(SignalDispatcher::getDispatcher(), SIGNAL(connected()), wdgt, SLOT(refresh())); connect(SignalDispatcher::getDispatcher(), SIGNAL(breakStateEntered()), wdgt, SLOT(refresh())); - connect(SignalDispatcher::getDispatcher(), SIGNAL(registerChanged(int,int)), wdgt, SLOT(registerChanged(int,int))); + connect(SignalDispatcher::getDispatcher(), SIGNAL(registerChanged(int, int)), wdgt, SLOT(registerChanged(int, int))); //mainMemoryView->setRegsView(regsView); static_cast(wdgt)->setSymbolTable(&DebugSession::getDebugSession()->symbolTable()); static_cast(wdgt)->setDebuggable("memory", 65536); @@ -800,8 +785,8 @@ QWidget *DebuggerForm::widgetFactory(factoryclasses fctwidget) case debuggableViewer: wdgt = new DebuggableViewer(); connect(SignalDispatcher::getDispatcher(), SIGNAL(breakStateEntered()), wdgt, SLOT(refresh())); - connect(SignalDispatcher::getDispatcher(), SIGNAL(debuggablesChanged(const QMap&)), - wdgt, SLOT(setDebuggables(const QMap&))); + connect(SignalDispatcher::getDispatcher(), SIGNAL(debuggablesChanged(const QMap&)), + wdgt, SLOT(setDebuggables(const QMap&))); static_cast(wdgt)->setDebuggables(debuggables); if (!debuggables.isEmpty()){ static_cast(wdgt)->debuggableSelected(0); @@ -1241,7 +1226,7 @@ void DebuggerForm::searchGoto() int addr = gtd.address(); if (addr >= 0) { //disasmView->setCursorAddress(addr, 0, DisasmViewer::MiddleAlways); - SignalDispatcher::getDispatcher()->setCursorAddress(addr,0,DisasmViewer::MiddleAlways); + SignalDispatcher::getDispatcher()->setCursorAddress(addr, 0, DisasmViewer::MiddleAlways); } } } @@ -1424,7 +1409,7 @@ bool DebuggerForm::loadWorkspaces(const QString &filename) if (!file.open(QFile::ReadOnly | QFile::Text)) { QMessageBox::warning(nullptr, tr("Loading workspaces ..."), tr("Cannot read file %1:\n%2.") - .arg(filename,file.errorString())); + .arg(filename, file.errorString())); return false; }; //Now try to parse the json file @@ -1446,7 +1431,7 @@ bool DebuggerForm::loadWorkspaces(const QString &filename) foreach (const QJsonValue & value, obj["workspaces"].toArray()) { QJsonObject obj = value.toObject(); BlendSplitter* splitter=BlendSplitter::createFromJson(obj["workspace"].toObject()); - workspaces->addTab(splitter,obj["name"].toString()); + workspaces->addTab(splitter, obj["name"].toString()); }; return true; } diff --git a/src/SignalDispatcher.h b/src/SignalDispatcher.h index 873d3e76..4b05edb0 100644 --- a/src/SignalDispatcher.h +++ b/src/SignalDispatcher.h @@ -1,4 +1,5 @@ -#pragma once +#ifndef SIGNALDISPATCHER_H +#define SIGNALDISPATCHER_H #include "CPURegs.h" #include "DebuggerData.h" @@ -8,14 +9,17 @@ /** \brief A singleton signal dispatcher * - * Several debugger widgets like + * Several debugger widgets like * This signal dispatcher also does the CPU registers tracking since multi widgets need those even if there wouldn't be a CPURegsViewer */ class SignalDispatcher : public QObject { Q_OBJECT - Q_DISABLE_COPY(SignalDispatcher) + public: + SignalDispatcher(const SignalDispatcher&) = delete; + SignalDispatcher& operator=(const SignalDispatcher&) = delete; + /** \brief Dispatcher getter * * This is a singleton class, i. e. you can't construct any object yourself. To get the one-and-only instance of this class, you need to call SignalDispatcher::getDispatcher(). The function will create the object if neccessary (= when called for the first time) and return a pointer to it. @@ -37,20 +41,11 @@ public slots: void setEnableWidget(bool value); private: - static SignalDispatcher* theDispatcher; SignalDispatcher(); - //buffers to handle tracking of the CPU registers - int regs[16], regsCopy[16]; - bool regsModified[16]; - bool regsChanged[16]; void setRegister(int id, int value); void getRegister(int id, unsigned char* data); - //main 64K used by disasmview and stack - unsigned char* mainMemory; - MemoryLayout memLayout; - signals: void enableWidget(bool enable); void connected(); @@ -76,5 +71,18 @@ public slots: void setCursorAddress(uint16_t addr, int infoLine, int method); private: + static SignalDispatcher* theDispatcher; + + //main 64K used by disasmview and stack + unsigned char* mainMemory; + MemoryLayout memLayout; + + //buffers to handle tracking of the CPU registers + int regs[16], regsCopy[16]; + bool regsModified[16]; + bool regsChanged[16]; + bool isEnableWidget; }; + +#endif diff --git a/src/blendsplitter/BlendSplitter.cpp b/src/blendsplitter/BlendSplitter.cpp index 2a1168af..1470b00b 100644 --- a/src/blendsplitter/BlendSplitter.cpp +++ b/src/blendsplitter/BlendSplitter.cpp @@ -13,13 +13,11 @@ #include #include -int BlendSplitter::expanderSize{12}; -int BlendSplitter::switchingBarHeight{32}; -QString BlendSplitter::expanderImage{":/BlendSplitter/Expander"}; - -BlendSplitter::BlendSplitter(QWidget* (*defaultWidget) (), Qt::Orientation orientation) : QSplitter{orientation, nullptr}, defaultWidget{defaultWidget} +BlendSplitter::BlendSplitter(std::function defaultWidget, Qt::Orientation orientation) + : QSplitter{orientation, nullptr} + , defaultWidget{defaultWidget} { -// Q_INIT_RESOURCE(BlendSplitterResources); + //Q_INIT_RESOURCE(BlendSplitterResources); setChildrenCollapsible(false); setHandleWidth(1); setStyleSheet("QSplitter::handle{background: black;}"); @@ -27,7 +25,7 @@ BlendSplitter::BlendSplitter(QWidget* (*defaultWidget) (), Qt::Orientation orien void BlendSplitter::addWidget() { - addWidget((*defaultWidget) ()); + addWidget(defaultWidget()); } void BlendSplitter::addWidget(QWidget* widget) @@ -42,23 +40,24 @@ void BlendSplitter::addWidget(RegistryItem* item) void BlendSplitter::insertWidget(int index) { - insertWidget(index, (*defaultWidget) ()); + insertWidget(index, defaultWidget()); } void BlendSplitter::insertWidget(int index, QWidget* widget) { - if (widget->inherits("SwitchingWidget")){ + if (widget->inherits("SwitchingWidget")) { + auto* sw = static_cast(widget); connect(SignalDispatcher::getDispatcher(), &SignalDispatcher::enableWidget, - static_cast(widget), &SwitchingWidget::setEnableWidget); - static_cast(widget)->setEnableWidget(SignalDispatcher::getDispatcher()->getEnableWidget()); - }; - WidgetDecorator* decorator{new WidgetDecorator{widget}}; + sw, &SwitchingWidget::setEnableWidget); + sw->setEnableWidget(SignalDispatcher::getDispatcher()->getEnableWidget()); + } + auto* decorator = new WidgetDecorator{widget}; QSplitter::insertWidget(index, decorator); } void BlendSplitter::insertWidget(int index, RegistryItem* item) { - SwitchingWidget* wdg=new SwitchingWidget{item}; + auto* wdg = new SwitchingWidget{item}; insertWidget(index, wdg); } @@ -72,18 +71,18 @@ void BlendSplitter::insertDecoratedWidget(int index, WidgetDecorator* widget) QSplitter::insertWidget(index, widget); } -void BlendSplitter::addSplitter(BlendSplitter *splitter) +void BlendSplitter::addSplitter(BlendSplitter* splitter) { insertSplitter(-1, splitter); } void BlendSplitter::insertSplitter(int index, BlendSplitter* splitter) { - SplitterDecorator* decorator{new SplitterDecorator{splitter}}; + auto* decorator = new SplitterDecorator{splitter}; QSplitter::insertWidget(index, decorator); } -QWidget *BlendSplitter::getNestedWidget(int index) +QWidget* BlendSplitter::getNestedWidget(int index) { return widget(index)->layout()->itemAt(0)->widget(); } @@ -91,65 +90,61 @@ QWidget *BlendSplitter::getNestedWidget(int index) QJsonObject BlendSplitter::save2json() const { QJsonObject obj; - QJsonArray ar_sizes,ar_subwidgets; + obj["type"] = "BlendSplitter"; + obj["orientation"] = orientation(); + obj["size_width"] = size().width(); + obj["size_height"] = size().height(); - obj["type"]="BlendSplitter"; - obj["orientation"]=orientation(); - obj["size_width"]=size().width(); - obj["size_height"]=size().height(); - foreach(int i,sizes()){ + QJsonArray ar_sizes; + for (auto i : sizes()) { ar_sizes.append(i); - }; - obj["sizes"]=ar_sizes; - for(int i=0 ; iinherits("WidgetDecorator")){ - QWidget* wdg = widget(i)->layout()->itemAt(0)->widget(); - if (wdg->inherits("SwitchingWidget")){ + } + obj["sizes"] = ar_sizes; + + QJsonArray ar_subwidgets; + for (int i = 0; i < count(); ++i) { + //qDebug() << " i " << i << " : " << widget(i); + if (widget(i)->inherits("WidgetDecorator")) { + auto* wdg = widget(i)->layout()->itemAt(0)->widget(); + if (wdg->inherits("SwitchingWidget")) { ar_subwidgets.append(static_cast(wdg)->save2json()); } - } else if (widget(i)->inherits("SplitterDecorator")){ - QWidget* wdg = widget(i)->layout()->itemAt(0)->widget(); + } else if (widget(i)->inherits("SplitterDecorator")) { + auto* wdg = widget(i)->layout()->itemAt(0)->widget(); ar_subwidgets.append(static_cast(wdg)->save2json()); } else { QJsonObject o; ar_subwidgets.append(o); - }; - }; - obj["subs"]=ar_subwidgets; - + } + } + obj["subs"] = ar_subwidgets; return obj; } -BlendSplitter *BlendSplitter::createFromJson(const QJsonObject &obj) +BlendSplitter* BlendSplitter::createFromJson(const QJsonObject &obj) { + auto* split = new BlendSplitter({}, obj["orientation"].toInt(1) == 1 ? Qt::Horizontal : Qt::Vertical); - BlendSplitter *split= new BlendSplitter([]()->QWidget* {return new SwitchingWidget{};}, - obj["orientation"].toInt(1)==1?Qt::Horizontal:Qt::Vertical); - - foreach (const QJsonValue & value, obj["subs"].toArray()) { + for (const QJsonValue& value : obj["subs"].toArray()) { QJsonObject obj = value.toObject(); - if (obj["type"].toString()=="SwitchingWidget"){ + if (obj["type"].toString() == "SwitchingWidget") { split->addWidget(SwitchingWidget::createFromJson(obj)); - } else if (obj["type"].toString()=="BlendSplitter"){ + } else if (obj["type"].toString() == "BlendSplitter") { split->addSplitter(BlendSplitter::createFromJson(obj)); } else { QMessageBox::warning(nullptr, tr("Open workspaces ..."), - tr("Unknown subs type:%1").arg(obj["type"].toString()) - ); + tr("Unknown subs type:%1").arg(obj["type"].toString())); } - } QList sizes; - split->resize(obj["size_width"].toInt(),obj["size_height"].toInt()); - foreach (const QJsonValue & value, obj["sizes"].toArray()) { + split->resize(obj["size_width"].toInt(), obj["size_height"].toInt()); + for (const QJsonValue& value : obj["sizes"].toArray()) { sizes.append(value.toInt()); } split->setSizes(sizes); -// qDebug() << "split->size" << split->size(); - + //qDebug() << "split->size" << split->size(); return split; } diff --git a/src/blendsplitter/BlendSplitter.h b/src/blendsplitter/BlendSplitter.h index ba7c0843..cda49e38 100644 --- a/src/blendsplitter/BlendSplitter.h +++ b/src/blendsplitter/BlendSplitter.h @@ -1,12 +1,15 @@ -#pragma once - -#include +#ifndef BLENDSPLITTER_H +#define BLENDSPLITTER_H #include "RegistryItem.h" #include "SwitchingBar.h" #include "SwitchingWidget.h" #include "WidgetRegistry.h" +#include + +#include + class Expander; class ExpanderCorner; class ExpanderBottom; @@ -27,39 +30,50 @@ class QJsonObject; class BlendSplitter : public QSplitter { Q_OBJECT - Q_DISABLE_COPY(BlendSplitter) + public: - static int expanderSize; /**< Size of the expanders in the corners. Default value: 12 */ - static int switchingBarHeight; /**< Height of the SwitchingBar. Default value: 36 */ - static QString expanderImage; /**< The image to be used for the top left expander. The bottom right one will rotate this by pi (180 degrees). Default value: \":/BlendSplitter/Expander\" */ + static constexpr int expanderSize = 12; /**< Size of the expanders in the corners. Default value: 12 */ + static constexpr int switchingBarHeight = 32; /**< Height of the SwitchingBar. Default value: 36 */ + static constexpr const char* const expanderImage = ":/BlendSplitter/Expander"; /**< The image to be used for the top left expander. The bottom right one will rotate this by pi (180 degrees). Default value: \":/BlendSplitter/Expander\" */ + +public: + BlendSplitter(const BlendSplitter&) = delete; + BlendSplitter& operator=(const BlendSplitter&) = delete; + /** \brief BlendSplitter class constructor * \param defaultWidget A pointer to function constructing the default widget. This function is called when a new widget is added to BlendSplitter. * \param orientation Orientation of the main BlendSplitter */ - BlendSplitter(QWidget* (*defaultWidget) () = []()->QWidget* {return new SwitchingWidget{};}, Qt::Orientation orientation = Qt::Horizontal); + BlendSplitter(std::function defaultWidget = [] { return new SwitchingWidget{}; }, + Qt::Orientation orientation = Qt::Horizontal); + /** \brief Add a widget to the BlendSplitter * * Adds the default widget to the very bottom/right of the BlendSplitter. */ void addWidget(); + /** \brief Add a widget to the BlendSplitter * * Adds the specified widget to the very bottom/right of the BlendSplitter * \param widget A pointer to the widget to be added */ void addWidget(QWidget* widget); + /** \brief Add a widget to the BlendSplitter * * Adds the specified widget from the WidgetRegistry to the very bottom/right of the BlendSplitter * \param item A RegistryItem to be added (inside a SwitchingWidget). */ void addWidget(RegistryItem* item); + /** \brief Insert a widget into the BlendSplitter * * Inserts the default widget into the BlendSplitter at the given position counting from top/left (counting starts at 0). This function should NOT be called with a BlendSplitter as a parameter. * \param index The desired position */ void insertWidget(int index); + /** \brief Insert a widget into the BlendSplitter * * Inserts the specified widget into the BlendSplitter at the given position counting from top/left (counting starts at 0). This function should NOT be called with a BlendSplitter as a parameter. @@ -67,6 +81,7 @@ class BlendSplitter : public QSplitter * \param widget A pointer to the widget to be inserted */ void insertWidget(int index, QWidget* widget); + /** \brief Insert a widget into the BlendSplitter * * Inserts the specified widget from WidgetRegistry into the BlendSplitter at the given position counting from top/left (counting starts at 0). This function should NOT be called with a BlendSplitter as a parameter. @@ -74,12 +89,14 @@ class BlendSplitter : public QSplitter * \param item A RegistryItem to be added (inside a SwitchingWidget). */ void insertWidget(int index, RegistryItem* item); + /** \brief Add another BlendSplitter to this BlendSplitter * * Adds a BlendSplitter (usually with parallel orientation) to the BlendSplitter * \param splitter A pointer to the BlendSplitter to be added */ void addSplitter(BlendSplitter* splitter); + /** \brief Insert another BlendSplitter into this BlendSplitter * * Inserts a BlendSplitter (usually with parallel orientation) into the BlendSplitter at the given position counting from top/left (counting starts at 0). @@ -87,6 +104,7 @@ class BlendSplitter : public QSplitter * \param splitter A pointer to the BlendSplitter to be inserted */ void insertSplitter(int index, BlendSplitter* splitter); + /** * @brief getNestedWidget A helper function to get the widget that is in the splitter at the given position. The actual widget is a WidgetDecorator or SplitterDecorator so we return the widget that is a direct child of this decorator. * @param index The desired position @@ -96,13 +114,16 @@ class BlendSplitter : public QSplitter QJsonObject save2json() const; static BlendSplitter* createFromJson(const QJsonObject& obj); + private: friend Expander; friend ExpanderCorner; - QWidget* (*defaultWidget) (); - virtual QSplitterHandle* createHandle() override; + std::function defaultWidget; + QSplitterHandle* createHandle() override; void addDecoratedWidget(WidgetDecorator* widget); + public: void insertDecoratedWidget(int index, WidgetDecorator* widget); - }; + +#endif diff --git a/src/blendsplitter/Expander.cpp b/src/blendsplitter/Expander.cpp index 28f9f566..b3ce36eb 100644 --- a/src/blendsplitter/Expander.cpp +++ b/src/blendsplitter/Expander.cpp @@ -4,7 +4,10 @@ #include "Overlay.h" #include "WidgetDecorator.h" -Expander::Expander(WidgetDecorator* parent) : QLabel(parent), pixmap{new QPixmap{BlendSplitter::expanderImage}}, overlay{nullptr} +Expander::Expander(WidgetDecorator* parent) + : QLabel(parent) + , pixmap{new QPixmap{BlendSplitter::expanderImage}} + , overlay{nullptr} { *pixmap = pixmap->scaledToHeight(BlendSplitter::expanderSize, Qt::FastTransformation); setPixmap(*pixmap); @@ -19,12 +22,9 @@ void Expander::reposition() //void Expander::mousePressEvent(QMouseEvent* event) //{ -// if(event->button() == Qt::LeftButton) -// { +// if (event->button() == Qt::LeftButton) { // event->accept(); // No-op -// } -// else -// { +// } else { // releaseMouse(); // event->ignore(); // Propagate event // } @@ -32,17 +32,14 @@ void Expander::reposition() //void Expander::mouseReleaseEvent(QMouseEvent* event) //{ -// if(event->button() == Qt::LeftButton and overlay != nullptr) -// { -// WidgetDecorator* parentDecorator{qobject_cast(parentWidget())}; -// if(parentDecorator == 0) -// { +// if (event->button() == Qt::LeftButton && overlay != nullptr) { +// auto* parentDecorator = qobject_cast(parentWidget()); +// if (!parentDecorator) { // qCritical("A BlendSplitter library error occurred. Error code: 1"); // return; // } -// BlendSplitter* parentSplitter{qobject_cast(overlay->parentWidget()->parentWidget())}; -// if(parentSplitter == 0) -// { +// auto* parentSplitter = qobject_cast(overlay->parentWidget()->parentWidget()); +// if (!parentSplitter) { // qCritical("A BlendSplitter library error occurred. Error code: 2"); // return; // } @@ -52,11 +49,9 @@ void Expander::reposition() // sizes[parentIndex] += sizes[overlayIndex] + 1; // sizes.removeAt(overlayIndex); // delete parentSplitter->widget(overlayIndex); -// if(parentSplitter->count() == 1 and parentSplitter->parentWidget()->inherits("SplitterDecorator")) -// { -// BlendSplitter* newParent{qobject_cast(parentSplitter->parentWidget()->parentWidget())}; -// if(newParent == 0) -// { +// if (parentSplitter->count() == 1 && parentSplitter->parentWidget()->inherits("SplitterDecorator")) { +// auto* newParent = qobject_cast(parentSplitter->parentWidget()->parentWidget()); +// if (!newParent) { // qCritical("A BlendSplitter library error occurred. Error code: 3"); // return; // } @@ -64,9 +59,7 @@ void Expander::reposition() // newParent->insertDecoratedWidget(newParent->indexOf(parentSplitter->parentWidget()), parentDecorator); // delete parentSplitter->parentWidget(); // newParent->setSizes(sizes2); -// } -// else -// { +// } else { // parentSplitter->setSizes(sizes); // } // overlay = nullptr; @@ -78,13 +71,12 @@ Expander::~Expander() delete pixmap; } - -//void Expander::enterEvent(QEvent *event) +//void Expander::enterEvent(QEvent* event) //{ // setCursor(Qt::SizeAllCursor); //} -//void Expander::leaveEvent(QEvent *event) +//void Expander::leaveEvent(QEvent* event) //{ // setCursor(Qt::ArrowCursor); //} diff --git a/src/blendsplitter/Expander.h b/src/blendsplitter/Expander.h index a7d6c106..b908172e 100644 --- a/src/blendsplitter/Expander.h +++ b/src/blendsplitter/Expander.h @@ -1,4 +1,5 @@ -#pragma once +#ifndef EXPANDER_H +#define EXPANDER_H #include "Global.h" @@ -8,18 +9,26 @@ class WidgetDecorator; class Expander : public QLabel { Q_OBJECT - Q_DISABLE_COPY(Expander) + +public: + Expander(const Expander&) = delete; + Expander& operator=(const Expander&) = delete; + protected: - QPixmap* pixmap; - Overlay* overlay; - Expander() = delete; explicit Expander(WidgetDecorator* parent); - virtual void reposition() ; //= 0 ; + virtual void reposition(); //= 0; ~Expander(); + protected slots: -// virtual void enterEvent(QEvent* event) override final; -// virtual void leaveEvent(QEvent* event) override final; -// virtual void mousePressEvent(QMouseEvent* event) override; -// virtual void mouseMoveEvent(QMouseEvent* event) override = 0; -// virtual void mouseReleaseEvent(QMouseEvent* event) override; + //void enterEvent(QEvent* event) override final; + //void leaveEvent(QEvent* event) override final; + //void mousePressEvent(QMouseEvent* event) override; + //void mouseMoveEvent(QMouseEvent* event) override = 0; + //void mouseReleaseEvent(QMouseEvent* event) override; + +protected: + QPixmap* pixmap; + Overlay* overlay; }; + +#endif diff --git a/src/blendsplitter/ExpanderCorner.cpp b/src/blendsplitter/ExpanderCorner.cpp index b5463682..44e5df80 100644 --- a/src/blendsplitter/ExpanderCorner.cpp +++ b/src/blendsplitter/ExpanderCorner.cpp @@ -10,10 +10,14 @@ #include -ExpanderCorner::ExpanderCorner(WidgetDecorator* parent,Qt::Corner location) : Expander{parent} , - corner{location},unitX{1},unitY{1},hotspotX{0},hotspotY{0},dragaction{undecidedDrag}, - dragorientation{Qt::Horizontal},internalOverlay{nullptr},externalOverlay{nullptr}, - joinarrow{Qt::NoArrow} +ExpanderCorner::ExpanderCorner(WidgetDecorator* parent, Qt::Corner location) + : Expander{parent} + , corner{location} + , unitX{1}, unitY{1} + , hotspotX{0}, hotspotY{0} + , dragaction{undecidedDrag}, dragorientation{Qt::Horizontal} + , internalOverlay{nullptr}, externalOverlay{nullptr} + , joinarrow{Qt::NoArrow} { //now do some masking and pixmap rotating depending on location //also set out unit steps @@ -24,14 +28,14 @@ ExpanderCorner::ExpanderCorner(WidgetDecorator* parent,Qt::Corner location) : Ex *pixmap = pixmap->transformed(rot.rotate(-90), Qt::FastTransformation); setPixmap(*pixmap); mask << QPoint{BlendSplitter::expanderSize, 0} - << QPoint{BlendSplitter::expanderSize, BlendSplitter::expanderSize/10} + << QPoint{BlendSplitter::expanderSize, BlendSplitter::expanderSize / 10} << QPoint{BlendSplitter::expanderSize / 10, BlendSplitter::expanderSize} << QPoint{0, BlendSplitter::expanderSize} << QPoint{0, 0}; -// done by constructor unitX=1; -// done by constructor unitY=1; - }; + unitX = 1; + unitY = 1; break; + } case Qt::TopRightCorner: { QTransform rot; *pixmap = pixmap->transformed(rot.rotate(0), Qt::FastTransformation); @@ -41,39 +45,40 @@ ExpanderCorner::ExpanderCorner(WidgetDecorator* parent,Qt::Corner location) : Ex << QPoint{BlendSplitter::expanderSize * 9 / 10, BlendSplitter::expanderSize} << QPoint{BlendSplitter::expanderSize, BlendSplitter::expanderSize} << QPoint{BlendSplitter::expanderSize, 0}; - unitX=-1; -// done by constructor unitY=1; - hotspotX=BlendSplitter::expanderSize-1; - }; + unitX = -1; + unitY = 1; + hotspotX = BlendSplitter::expanderSize - 1; break; + } case Qt::BottomLeftCorner: { QTransform rot; *pixmap = pixmap->transformed(rot.rotate(180), Qt::FastTransformation); setPixmap(*pixmap); mask << QPoint{0, 0} - << QPoint{BlendSplitter::expanderSize/10, 0} + << QPoint{BlendSplitter::expanderSize / 10, 0} << QPoint{BlendSplitter::expanderSize, BlendSplitter::expanderSize * 9 / 10} << QPoint{BlendSplitter::expanderSize, BlendSplitter::expanderSize} << QPoint{0, BlendSplitter::expanderSize}; -// done by constructor unitX=1; - unitY=-1; - hotspotY=BlendSplitter::expanderSize-1; - }; + unitX = 1; + unitY = -1; + hotspotY = BlendSplitter::expanderSize - 1; break; + } case Qt::BottomRightCorner: { QTransform rot; *pixmap = pixmap->transformed(rot.rotate(90), Qt::FastTransformation); setPixmap(*pixmap); mask << QPoint{BlendSplitter::expanderSize, 0} - << QPoint{BlendSplitter::expanderSize * 9 /10, 0} + << QPoint{BlendSplitter::expanderSize * 9 / 10, 0} << QPoint{0, BlendSplitter::expanderSize * 9 / 10} << QPoint{0, BlendSplitter::expanderSize} << QPoint{BlendSplitter::expanderSize, BlendSplitter::expanderSize}; - }; - unitX=-1; - unitY=-1; - hotspotX=BlendSplitter::expanderSize-1; - hotspotY=BlendSplitter::expanderSize-1; + unitX = -1; + unitY = -1; + hotspotX = BlendSplitter::expanderSize - 1; + hotspotY = BlendSplitter::expanderSize - 1; + break; + } default: break; @@ -101,7 +106,7 @@ void ExpanderCorner::reposition() move(0, parentWidget()->height()-height()); break; case Qt::BottomRightCorner: - move(parentWidget()->width() - width(), parentWidget()->height()-height()); + move(parentWidget()->width() - width(), parentWidget()->height() - height()); break; default: break; @@ -111,7 +116,7 @@ void ExpanderCorner::reposition() bool ExpanderCorner::isOnTrailingHandler(BlendSplitter* parentSplitter) { - return (parentSplitter->orientation()==Qt::Horizontal)? unitX<0 : unitY<0; + return (parentSplitter->orientation() == Qt::Horizontal) ? unitX < 0 : unitY < 0; } /** @@ -122,107 +127,104 @@ bool ExpanderCorner::isOnTrailingHandler(BlendSplitter* parentSplitter) * * This will split the widget. * If the orientation of the split corresponds to the splitter we simply add an item - * If the orietation is orthogonal we replace the widget with a new splitter and have the widget added to the new splitter + * If the orientation is orthogonal we replace the widget with a new splitter and have the widget added to the new splitter */ void ExpanderCorner::performInnerSplit(WidgetDecorator* parentDecorator, BlendSplitter* parentSplitter, Qt::Orientation splitorientation) { - SwitchingWidget* switchwdg=dynamic_cast(parentDecorator->layout()->itemAt(0)->widget()); - SwitchingWidget* addedWidget=nullptr; - - if (parentSplitter->orientation() == splitorientation){ + auto* switchwdg = dynamic_cast(parentDecorator->layout()->itemAt(0)->widget()); + SwitchingWidget* addedWidget = nullptr; + if (parentSplitter->orientation() == splitorientation) { QList sizes{parentSplitter->sizes()}; int index{parentSplitter->indexOf(parentDecorator)}; - if (!isOnTrailingHandler(parentSplitter)){ + if (!isOnTrailingHandler(parentSplitter)) { sizes.insert(index, BlendSplitter::expanderSize); sizes[index + 1] -= BlendSplitter::expanderSize + 1; parentSplitter->insertWidget(index); - addedWidget=dynamic_cast(parentSplitter->getNestedWidget(index)); + addedWidget = dynamic_cast(parentSplitter->getNestedWidget(index)); } else { sizes.insert(index +1, BlendSplitter::expanderSize); sizes[index] -= BlendSplitter::expanderSize + 1; parentSplitter->insertWidget(index+1); - addedWidget=dynamic_cast(parentSplitter->getNestedWidget(index+1)); + addedWidget = dynamic_cast(parentSplitter->getNestedWidget(index + 1)); } parentSplitter->setSizes(sizes); parentSplitter->handle(index + 1)->grabMouse(); } else { //add a new splitter orthogonal to the current one - Qt::Orientation newOrientation{parentSplitter->orientation()==Qt::Horizontal?Qt::Vertical:Qt::Horizontal}; - BlendSplitter* newSplitter{new BlendSplitter{parentSplitter->defaultWidget, newOrientation}}; + Qt::Orientation newOrientation{parentSplitter->orientation() == Qt::Horizontal ? Qt::Vertical : Qt::Horizontal}; + auto* newSplitter = new BlendSplitter{parentSplitter->defaultWidget, newOrientation}; QList sizes{parentSplitter->sizes()}; parentSplitter->insertSplitter(parentSplitter->indexOf(parentDecorator), newSplitter); // add a widget in current splitter but on the correct side - bool after = (newOrientation==Qt::Horizontal)? unitX>0 : unitY>0; + bool after = (newOrientation == Qt::Horizontal) ? unitX > 0 : unitY > 0; - if (after){ + if (after) { newSplitter->addWidget(); newSplitter->addDecoratedWidget(parentDecorator); - addedWidget=dynamic_cast(newSplitter->getNestedWidget(0)); + addedWidget = dynamic_cast(newSplitter->getNestedWidget(0)); } else { newSplitter->addDecoratedWidget(parentDecorator); newSplitter->addWidget(); - addedWidget=dynamic_cast(newSplitter->getNestedWidget(1)); + addedWidget = dynamic_cast(newSplitter->getNestedWidget(1)); } parentSplitter->setSizes(sizes); newSplitter->handle(1)->grabMouse(); } //now if the original item was a SwitchingWidget we set the same and the enablestate - if (switchwdg && addedWidget){ + if (switchwdg && addedWidget) { addedWidget->setEnableWidget(switchwdg->getEnableWidget()); //if new user we need show the quickguide (is the default widget) otherwise we split current one - Settings& s = Settings::get(); - if (s.value("creatingWorkspaceType",0).toInt() ){ + auto& s = Settings::get(); + if (s.value("creatingWorkspaceType", 0).toInt()) { addedWidget->setCurrentIndex(switchwdg->getCurrentIndex()); } } //have the cursor take the correct shape setCursor(splitorientation == Qt::Horizontal ? Qt::SplitHCursor : Qt::SplitVCursor); - } -void ExpanderCorner::setupJoiners(WidgetDecorator *parentDecorator, BlendSplitter *parentSplitter, int x, int y, Qt::Orientation /*splitorientation*/) +void ExpanderCorner::setupJoiners(WidgetDecorator* parentDecorator, BlendSplitter* parentSplitter, int x, int y, Qt::Orientation /*splitorientation*/) { - Q_ASSERT(dragaction ==undecidedDrag); + Q_ASSERT(dragaction == undecidedDrag); Q_ASSERT(externalOverlay == nullptr); Q_ASSERT(internalOverlay == nullptr); - if(isInContinuationOfSplitter(parentSplitter,pos().x()+x,pos().y()+y) ){ + if (isInContinuationOfSplitter(parentSplitter, pos().x() + x, pos().y() + y)) { QWidget* wdgt = nullptr; - if( isOnTrailingHandler(parentSplitter) and + if (isOnTrailingHandler(parentSplitter) && parentSplitter->indexOf(parentDecorator) + 1 < parentSplitter->count()) { - wdgt = parentSplitter->widget(parentSplitter->indexOf(parentDecorator) + 1); //do not join if the target widget is also splitted - if (!wdgt->inherits("SplitterDecorator")){ - joinarrow=parentSplitter->orientation()==Qt::Horizontal?Qt::RightArrow:Qt::DownArrow; - externalOverlay = new Overlay{wdgt,joinarrow}; + if (!wdgt->inherits("SplitterDecorator")) { + joinarrow = parentSplitter->orientation() == Qt::Horizontal ? Qt::RightArrow : Qt::DownArrow; + externalOverlay = new Overlay{wdgt, joinarrow}; } - } else if (!isOnTrailingHandler(parentSplitter) and + } else if (!isOnTrailingHandler(parentSplitter) && parentSplitter->indexOf(parentDecorator) > 0) { - wdgt = parentSplitter->widget(parentSplitter->indexOf(parentDecorator) - 1); //do not join if the target widget is also splitted - if (!wdgt->inherits("SplitterDecorator")){ - joinarrow=parentSplitter->orientation()==Qt::Horizontal?Qt::LeftArrow:Qt::UpArrow; - externalOverlay = new Overlay{wdgt,joinarrow}; + if (!wdgt->inherits("SplitterDecorator")) { + joinarrow = parentSplitter->orientation() == Qt::Horizontal ? Qt::LeftArrow : Qt::UpArrow; + externalOverlay = new Overlay{wdgt, joinarrow}; } - }; + } //now show overlay if we started a valid joindrag - if (externalOverlay){ + if (externalOverlay) { externalOverlay->show(); - internalOverlay=new Overlay{parentDecorator,Overlay::invertArrow(joinarrow)}; + internalOverlay = new Overlay{parentDecorator, Overlay::invertArrow(joinarrow)}; internalOverlay->hide(); - dragaction=joinDrag; + dragaction = joinDrag; //qDebug() << "starting joindrag " << wdgt << " ( <-wdgt parentDecorator->) " << parentDecorator; } } } -int ExpanderCorner::pickCoordinate(int x,int y,Qt::Orientation orient) + +int ExpanderCorner::pickCoordinate(int x, int y, Qt::Orientation orient) { - return orient==Qt::Horizontal?x:y; + return orient == Qt::Horizontal ? x : y; } int ExpanderCorner::pickSize(const QSize &size, Qt::Orientation orient) @@ -230,32 +232,30 @@ int ExpanderCorner::pickSize(const QSize &size, Qt::Orientation orient) return (orient == Qt::Horizontal) ? size.width() : size.height(); } -void ExpanderCorner::enterEvent(QEvent *event) +void ExpanderCorner::enterEvent(QEvent* event) { setCursor(Qt::CrossCursor); //after innersplit the cursor is still wrong when entering... Expander::enterEvent(event); } -void ExpanderCorner::followDragJoiners(WidgetDecorator *parentDecorator, BlendSplitter *parentSplitter, int x, int y, Qt::Orientation /*splitorientation*/) +void ExpanderCorner::followDragJoiners(WidgetDecorator* parentDecorator, BlendSplitter* parentSplitter, int x, int y, Qt::Orientation /*splitorientation*/) { - x=pos().x()+x; - y=pos().y()+y; + x = pos().x() + x; + y = pos().y() + y; - if (isInContinuationOfSplitter(parentSplitter,x,y)){ + if (isInContinuationOfSplitter(parentSplitter, x, y)) { // maybe we need to change direction of the join ? - Qt::Orientation o=parentSplitter->orientation(); - if ((isOnTrailingHandler(parentSplitter) and pickCoordinate(x,y,o)>pickSize(parentDecorator->size(),o)) - or (!isOnTrailingHandler(parentSplitter) and pickCoordinate(x,y,o)<0) - ) { + Qt::Orientation o = parentSplitter->orientation(); + if ((isOnTrailingHandler(parentSplitter) && pickCoordinate(x, y, o) > pickSize(parentDecorator->size(), o)) + || (!isOnTrailingHandler(parentSplitter) && pickCoordinate(x, y, o) < 0)) { externalOverlay->show(); internalOverlay->hide(); - setCursor(parentSplitter->orientation()==Qt::Horizontal?Qt::SizeHorCursor:Qt::SizeVerCursor); - } else if ((isOnTrailingHandler(parentSplitter) and pickCoordinate(x,y,o)<=pickSize(parentDecorator->size(),o)) - or (!isOnTrailingHandler(parentSplitter) and pickCoordinate(x,y,o)>=0) - ) { + setCursor(parentSplitter->orientation() == Qt::Horizontal ? Qt::SizeHorCursor : Qt::SizeVerCursor); + } else if ((isOnTrailingHandler(parentSplitter) && pickCoordinate(x, y, o) <= pickSize(parentDecorator->size(), o)) + || (!isOnTrailingHandler(parentSplitter) && pickCoordinate(x, y, o) >= 0)) { externalOverlay->hide(); internalOverlay->show(); - setCursor(parentSplitter->orientation()==Qt::Horizontal?Qt::SizeHorCursor:Qt::SizeVerCursor); + setCursor(parentSplitter->orientation() == Qt::Horizontal ? Qt::SizeHorCursor : Qt::SizeVerCursor); } } else { // hide all overlay since we dragged 'to the side' of the splitter @@ -265,20 +265,16 @@ void ExpanderCorner::followDragJoiners(WidgetDecorator *parentDecorator, BlendSp } } - - -bool ExpanderCorner::isInContinuationOfSplitter(BlendSplitter *parentSplitter, int x, int y) +bool ExpanderCorner::isInContinuationOfSplitter(BlendSplitter* parentSplitter, int x, int y) { if (parentSplitter->orientation() == Qt::Horizontal - and y > 0 and y < parentSplitter->height() - ) { - return true; - }; + && y > 0 && y < parentSplitter->height()) { + return true; + } if (parentSplitter->orientation() == Qt::Vertical - and x > 0 and x < parentSplitter->width() - ) { - return true; - }; + && x > 0 && x < parentSplitter->width()) { + return true; + } return false; } @@ -289,150 +285,135 @@ bool ExpanderCorner::isInContinuationOfSplitter(BlendSplitter *parentSplitter, i *If a drag is just started this function helps determine if we drag inwards *our outward and if it is a horizontal or vertical drag. */ -void ExpanderCorner::decideDragAction(QMouseEvent *event, WidgetDecorator* parentDecorator, BlendSplitter* parentSplitter) +void ExpanderCorner::decideDragAction(QMouseEvent* event, WidgetDecorator* parentDecorator, BlendSplitter* parentSplitter) { - int x=event->x()-hotspotX; - int y=event->y()-hotspotY; + int x = event->x()-hotspotX; + int y = event->y()-hotspotY; - if (abs(x) < BlendSplitter::expanderSize and abs(y) < BlendSplitter::expanderSize ){ + if (abs(x) < BlendSplitter::expanderSize && abs(y) < BlendSplitter::expanderSize) { return; - }; + } // we dragged far enough - dragorientation= (abs(x) > abs(y)) ? Qt::Horizontal : Qt::Vertical ; + dragorientation = (abs(x) > abs(y)) ? Qt::Horizontal : Qt::Vertical; // but did we drag inwards? // (and als prefent splitting if widget already too small!) - if ( x*unitX >0 and y*unitY>0 and ( - (dragorientation==Qt::Horizontal and parentDecorator->width()>2*BlendSplitter::expanderSize) or - (dragorientation==Qt::Vertical and parentDecorator->height()>2*BlendSplitter::expanderSize)) - ) - { - dragaction=splitDrag; // we dragged inwards - performInnerSplit(parentDecorator,parentSplitter,dragorientation); - } - // do we join widgets together? - else if (dragorientation == parentSplitter->orientation()){ - setupJoiners(parentDecorator,parentSplitter,x,y,dragorientation); + if (x * unitX > 0 && y * unitY > 0 && + ((dragorientation == Qt::Horizontal && parentDecorator->width() > 2 * BlendSplitter::expanderSize) || + (dragorientation == Qt::Vertical && parentDecorator->height() > 2 * BlendSplitter::expanderSize))) { + dragaction = splitDrag; // we dragged inwards + performInnerSplit(parentDecorator, parentSplitter, dragorientation); + } else if (dragorientation == parentSplitter->orientation()) { + // do we join widgets together? + setupJoiners(parentDecorator, parentSplitter, x, y, dragorientation); } else { - //here we could start a relocationdrag.... + // here we could start a relocationdrag.... } } -void ExpanderCorner::mouseMoveEvent(QMouseEvent *event) +void ExpanderCorner::mouseMoveEvent(QMouseEvent* event) { - if( !(event->buttons() & Qt::LeftButton)){ + if (!(event->buttons() & Qt::LeftButton)) { return; } //get our parentdecorator and our immediate blendSplitter - WidgetDecorator* parentDecorator{qobject_cast(parentWidget())}; - if(parentDecorator == 0) - { + auto* parentDecorator = qobject_cast(parentWidget()); + if (!parentDecorator) { qCritical("A BlendSplitter library error occurred. Error code: 4"); return; } - BlendSplitter* parentSplitter{qobject_cast(parentDecorator->parentWidget())}; - if(parentSplitter == 0) - { + auto* parentSplitter = qobject_cast(parentDecorator->parentWidget()); + if (!parentSplitter) { qCritical("A BlendSplitter library error occurred. Error code: 5"); return; } switch (dragaction) { case undecidedDrag: - decideDragAction(event,parentDecorator,parentSplitter); + decideDragAction(event, parentDecorator, parentSplitter); break; - case joinDrag: - { - int x=event->x()-hotspotX; - int y=event->y()-hotspotY; - followDragJoiners(parentDecorator,parentSplitter,x,y,(abs(x) > abs(y)) ? Qt::Horizontal : Qt::Vertical); - }; + case joinDrag: { + int x = event->x()-hotspotX; + int y = event->y()-hotspotY; + followDragJoiners(parentDecorator, parentSplitter, x, y, (abs(x) > abs(y)) ? Qt::Horizontal : Qt::Vertical); break; + } case splitDrag: default: break; } } -void ExpanderCorner::mousePressEvent(QMouseEvent *event) +void ExpanderCorner::mousePressEvent(QMouseEvent* event) { - if(event->button() == Qt::LeftButton) - { - dragaction=undecidedDrag; //start of drag + if (event->button() == Qt::LeftButton) { + dragaction = undecidedDrag; //start of drag event->accept(); // No-op - } - else - { + } else { releaseMouse(); event->ignore(); // Propagate event } } -void ExpanderCorner::mouseReleaseEvent(QMouseEvent *event) +void ExpanderCorner::mouseReleaseEvent(QMouseEvent* event) { - if(event->button() == Qt::LeftButton){ + if (event->button() == Qt::LeftButton) { //releasing leftbutton set us back to default cursor for handler // since we might have changed due to split or join setCursor(Qt::CrossCursor); - }; + } - if(event->button() != Qt::LeftButton or dragaction != joinDrag){ + if (event->button() != Qt::LeftButton || dragaction != joinDrag) { return; - }; + } //correct button and we have an overlay, so continue... - if(externalOverlay->isVisible() && internalOverlay->isVisible()) - { + if (externalOverlay->isVisible() && internalOverlay->isVisible()) { qCritical("A BlendSplitter library error occurred. Error code: 8"); return; } + QWidget* widgetToRemove = nullptr; //improved readability later on + QWidget* widgetToKeep = nullptr; //improved readability later on - QWidget* widgetToRemove=nullptr; //improved readability later on - QWidget* widgetToKeep=nullptr; //improved readability later on - - if (externalOverlay->isVisible() && !internalOverlay->isVisible()){ - widgetToKeep=internalOverlay->parentWidget(); - widgetToRemove=externalOverlay->parentWidget(); - } else if (!externalOverlay->isVisible() && internalOverlay->isVisible()){ - widgetToKeep=externalOverlay->parentWidget(); - widgetToRemove=internalOverlay->parentWidget(); - }; - + if (externalOverlay->isVisible() && !internalOverlay->isVisible()) { + widgetToKeep = internalOverlay->parentWidget(); + widgetToRemove = externalOverlay->parentWidget(); + } else if (!externalOverlay->isVisible() && internalOverlay->isVisible()) { + widgetToKeep = externalOverlay->parentWidget(); + widgetToRemove = internalOverlay->parentWidget(); + } // The visible overlays will be deleted when we remove the widget, // so we need to clean up the invisble overlays - if (!internalOverlay->isVisible()){ + if (!internalOverlay->isVisible()) { internalOverlay->deleteLater(); - }; - if (!externalOverlay->isVisible()){ + } + if (!externalOverlay->isVisible()) { externalOverlay->deleteLater(); - }; + } //do nothing if both overlays were hidden - if (widgetToRemove==nullptr){ + if (widgetToRemove == nullptr) { externalOverlay = nullptr; internalOverlay = nullptr; return; } //first get our decorator and the parent blendSplitter - WidgetDecorator* toKeepDecorator{qobject_cast(widgetToKeep)}; - if(toKeepDecorator == 0) - { + auto* toKeepDecorator = qobject_cast(widgetToKeep); + if (!toKeepDecorator) { qCritical("A BlendSplitter library error occurred. Error code: 1"); return; } - BlendSplitter* parentSplitter{qobject_cast(externalOverlay->parentWidget()->parentWidget())}; - if(parentSplitter == 0) - { + auto* parentSplitter = qobject_cast(externalOverlay->parentWidget()->parentWidget()); + if (!parentSplitter) { qCritical("A BlendSplitter library error occurred. Error code: 2"); return; } - //now delete the item with the visible overlay from the splitter QList sizes{parentSplitter->sizes()}; @@ -446,12 +427,10 @@ void ExpanderCorner::mouseReleaseEvent(QMouseEvent *event) // if we now have a blendSplitter with a single item, which is inside // another blendSplitter then we remove this singular-item splitter - if(parentSplitter->count() == 1 and - parentSplitter->parentWidget()->inherits("SplitterDecorator")) - { - BlendSplitter* newParent{qobject_cast(parentSplitter->parentWidget()->parentWidget())}; - if(newParent == nullptr) - { + if (parentSplitter->count() == 1 && + parentSplitter->parentWidget()->inherits("SplitterDecorator")) { + auto* newParent = qobject_cast(parentSplitter->parentWidget()->parentWidget()); + if (!newParent) { qCritical("A BlendSplitter library error occurred. Error code: 3"); return; } @@ -459,10 +438,7 @@ void ExpanderCorner::mouseReleaseEvent(QMouseEvent *event) newParent->insertDecoratedWidget(newParent->indexOf(parentSplitter->parentWidget()), toKeepDecorator); delete parentSplitter->parentWidget(); newParent->setSizes(sizes2); - } - else - { + } else { parentSplitter->setSizes(sizes); } - } diff --git a/src/blendsplitter/ExpanderCorner.h b/src/blendsplitter/ExpanderCorner.h index b5da9de1..d60c2aef 100644 --- a/src/blendsplitter/ExpanderCorner.h +++ b/src/blendsplitter/ExpanderCorner.h @@ -1,23 +1,38 @@ -#pragma once +#ifndef EXPANDERCORNER_H +#define EXPANDERCORNER_H #include "Global.h" #include "Expander.h" + class WidgetDecorator; class BlendSplitter; class ExpanderCorner final : public Expander { Q_OBJECT - Q_DISABLE_COPY(ExpanderCorner) + public: - ExpanderCorner() = delete; - explicit ExpanderCorner(WidgetDecorator* parent,Qt::Corner location); - virtual void reposition() override; + ExpanderCorner(const ExpanderCorner&) = delete; + ExpanderCorner& operator=(const ExpanderCorner&) = delete; + explicit ExpanderCorner(WidgetDecorator* parent, Qt::Corner location); + void reposition() override; + protected slots: - virtual void mouseMoveEvent(QMouseEvent* event) override; - virtual void mousePressEvent(QMouseEvent* event) override final; - virtual void mouseReleaseEvent(QMouseEvent* event) override final; + void mouseMoveEvent(QMouseEvent* event) override; + void mousePressEvent(QMouseEvent* event) override final; + void mouseReleaseEvent(QMouseEvent* event) override final; + +private: + void decideDragAction(QMouseEvent* event, WidgetDecorator* parentDecorator, BlendSplitter* parentSplitter); + void performInnerSplit(WidgetDecorator* parentDecorator, BlendSplitter* parentSplitter, Qt::Orientation splitorientation); + void setupJoiners(WidgetDecorator* parentDecorator, BlendSplitter* parentSplitter, int x, int y, Qt::Orientation splitorientation); + void followDragJoiners(WidgetDecorator* parentDecorator, BlendSplitter* parentSplitter, int x, int y, Qt::Orientation splitorientation); + bool isInContinuationOfSplitter(BlendSplitter* parentSplitter, int x, int y); + bool isOnTrailingHandler(BlendSplitter* parentSplitter); + + int pickCoordinate(int x, int y, Qt::Orientation orient); + int pickSize(const QSize &size, Qt::Orientation orient); private: Qt::Corner corner; @@ -33,19 +48,12 @@ protected slots: } dragaction; Qt::Orientation dragorientation; - void decideDragAction(QMouseEvent *event, WidgetDecorator *parentDecorator, BlendSplitter *parentSplitter); - void performInnerSplit(WidgetDecorator *parentDecorator, BlendSplitter *parentSplitter, Qt::Orientation splitorientation); - void setupJoiners(WidgetDecorator *parentDecorator, BlendSplitter *parentSplitter, int x, int y, Qt::Orientation splitorientation); - void followDragJoiners(WidgetDecorator *parentDecorator, BlendSplitter *parentSplitter, int x, int y, Qt::Orientation splitorientation); - bool isInContinuationOfSplitter(BlendSplitter *parentSplitter, int x, int y); - bool isOnTrailingHandler(BlendSplitter *parentSplitter); - Overlay* internalOverlay; Overlay* externalOverlay; Qt::ArrowType joinarrow; - int pickCoordinate(int x,int y,Qt::Orientation orient); - int pickSize(const QSize &size, Qt::Orientation orient); protected slots: - virtual void enterEvent(QEvent* event) override final; + void enterEvent(QEvent* event) override final; }; + +#endif diff --git a/src/blendsplitter/Global.h b/src/blendsplitter/Global.h index 176ac66b..fd17fe92 100644 --- a/src/blendsplitter/Global.h +++ b/src/blendsplitter/Global.h @@ -1,4 +1,5 @@ -#pragma once +#ifndef GLOBAL_H +#define GLOBAL_H #include #include @@ -6,3 +7,5 @@ #include #include #include + +#endif diff --git a/src/blendsplitter/Overlay.cpp b/src/blendsplitter/Overlay.cpp index 49b24536..10f931b7 100644 --- a/src/blendsplitter/Overlay.cpp +++ b/src/blendsplitter/Overlay.cpp @@ -3,16 +3,18 @@ #include #include -Overlay::Overlay(QWidget* parent, Qt::ArrowType direction) : QLabel(parent),arrow(),arrowtype(direction) +Overlay::Overlay(QWidget* parent, Qt::ArrowType direction) + : QLabel(parent) + , arrowtype(direction) { move(0, 0); reposition(); - // setStyleSheet("background-color: rgba(0, 0, 0, 128);"); + //setStyleSheet("background-color: rgba(0, 0, 0, 128);"); } void Overlay::setArrowshape(Qt::ArrowType arrow) { - arrowtype=arrow; + arrowtype = arrow; //makeArrowshape(); //update(); } @@ -27,20 +29,15 @@ Qt::ArrowType Overlay::invertArrow(Qt::ArrowType arrow) switch (arrow) { case Qt::UpArrow: return Qt::DownArrow; - break; case Qt::DownArrow: return Qt::UpArrow; - break; case Qt::LeftArrow: return Qt::RightArrow; - break; case Qt::RightArrow: return Qt::LeftArrow; - break; case Qt::NoArrow: default: return Qt::NoArrow; - break; } } @@ -54,90 +51,84 @@ void Overlay::reposition() void Overlay::makeArrowshape() { - if (arrowtype == Qt::NoArrow){ + if (arrowtype == Qt::NoArrow) { arrow.clear(); return; } - int unit,midpoint; - int height=parentWidget()->height(); - int width=parentWidget()->width(); + int unit, midpoint; + int height = parentWidget()->height(); + int width = parentWidget()->width(); - switch(arrowtype){ + switch (arrowtype) { case Qt::DownArrow: case Qt::UpArrow: //create vertical pointing arrow - midpoint=width/2; - unit=std::min(midpoint , height/2) /4; + midpoint = width / 2; + unit = std::min(midpoint, height / 2) / 4; break; case Qt::LeftArrow: case Qt::RightArrow: //create horizontal pointing arrow - midpoint=height/2; - unit=std::min(midpoint , width/2) /4; + midpoint = height / 2; + unit = std::min(midpoint, width / 2) / 4; case Qt::NoArrow: default: break; } - switch(arrowtype){ + switch(arrowtype) { case Qt::DownArrow: arrow.setPoints(7, - midpoint+unit,0, - midpoint+unit,2*unit, - midpoint+2*unit,2*unit, - midpoint, 4*unit, - midpoint-2*unit,2*unit, - midpoint-unit,2*unit, - midpoint-unit,0 - ); + midpoint + unit, 0, + midpoint + unit, 2 * unit, + midpoint + 2 * unit, 2 * unit, + midpoint , 4 * unit, + midpoint - 2 * unit, 2 * unit, + midpoint - unit, 2 * unit, + midpoint - unit, 0); break; case Qt::UpArrow: arrow.setPoints(7, - midpoint+unit,height, - midpoint+unit,height-2*unit, - midpoint+2*unit,height-2*unit, - midpoint, height-4*unit, - midpoint-2*unit,height-2*unit, - midpoint-unit,height-2*unit, - midpoint-unit,height - ); + midpoint + unit, height, + midpoint + unit, height - 2 * unit, + midpoint + 2 * unit, height - 2 * unit, + midpoint , height - 4 * unit, + midpoint - 2 * unit, height - 2 * unit, + midpoint - unit, height - 2 * unit, + midpoint - unit, height); break; case Qt::RightArrow: arrow.setPoints(7, - 0,midpoint+unit, - 2*unit,midpoint+unit, - 2*unit,midpoint+2*unit, - 4*unit,midpoint, - 2*unit,midpoint-2*unit, - 2*unit,midpoint-unit, - 0,midpoint-unit - ); + 0 , midpoint + unit, + 2 * unit, midpoint + unit, + 2 * unit, midpoint + 2 * unit, + 4 * unit, midpoint, + 2 * unit, midpoint - 2 * unit, + 2 * unit, midpoint - unit, + 0 , midpoint - unit); break; case Qt::LeftArrow: arrow.setPoints(7, - width,midpoint+unit, - width-2*unit,midpoint+unit, - width-2*unit,midpoint+2*unit, - width-4*unit,midpoint, - width-2*unit,midpoint-2*unit, - width-2*unit,midpoint-unit, - width,midpoint-unit - ); + width , midpoint + unit, + width - 2 * unit, midpoint + unit, + width - 2 * unit, midpoint + 2 * unit, + width - 4 * unit, midpoint, + width - 2 * unit, midpoint - 2 * unit, + width - 2 * unit, midpoint - unit, + width , midpoint - unit); case Qt::NoArrow: default: break; - }; - - + } } -void Overlay::paintEvent(QPaintEvent *) +void Overlay::paintEvent(QPaintEvent*) { QPainter qp(this); - qp.setBrush(QColor(0,0,0,128)); + qp.setBrush(QColor(0, 0, 0, 128)); qp.setPen(Qt::NoPen); - qp.drawRect(0,0,size().width(),size().height() ); - qp.setBrush(QColor(255,255,255,128)); + qp.drawRect(0, 0, size().width(), size().height()); + qp.setBrush(QColor(255, 255, 255, 128)); qp.drawPolygon(arrow); } diff --git a/src/blendsplitter/Overlay.h b/src/blendsplitter/Overlay.h index f22b6c3e..a970a7e5 100644 --- a/src/blendsplitter/Overlay.h +++ b/src/blendsplitter/Overlay.h @@ -1,14 +1,16 @@ -#pragma once +#ifndef OVERLAY_H +#define OVERLAY_H #include "Global.h" class Overlay final : public QLabel { Q_OBJECT - Q_DISABLE_COPY(Overlay) + public: - Overlay() = delete; - explicit Overlay(QWidget* parent, Qt::ArrowType direction=Qt::NoArrow); + Overlay(const Overlay&) = delete; + Overlay& operator=(const Overlay&) = delete; + explicit Overlay(QWidget* parent, Qt::ArrowType direction = Qt::NoArrow); static Qt::ArrowType invertArrow(Qt::ArrowType arrow); @@ -16,13 +18,15 @@ class Overlay final : public QLabel Qt::ArrowType arrowshape(); void reposition(); +protected: + void paintEvent(QPaintEvent*) override; + private: void makeArrowshape(); +private: QPolygon arrow; - Qt::ArrowType arrowtype; - -protected: - void paintEvent(QPaintEvent *) override; }; + +#endif diff --git a/src/blendsplitter/RegistryItem.cpp b/src/blendsplitter/RegistryItem.cpp index e32780be..21b15859 100644 --- a/src/blendsplitter/RegistryItem.cpp +++ b/src/blendsplitter/RegistryItem.cpp @@ -1,3 +1,10 @@ #include "RegistryItem.h" -RegistryItem::RegistryItem(QString name, QWidget* (*widget) (), void (*populateBar) (SwitchingBar*, QWidget*)) : name{name}, widget{widget}, populateBar{populateBar} {} +RegistryItem::RegistryItem(const QString& name, + std::function widget, + std::function populateBar) + : name{name} + , widget{widget} + , populateBar{populateBar} +{ +} diff --git a/src/blendsplitter/RegistryItem.h b/src/blendsplitter/RegistryItem.h index a4134440..7e06626f 100644 --- a/src/blendsplitter/RegistryItem.h +++ b/src/blendsplitter/RegistryItem.h @@ -1,7 +1,10 @@ -#pragma once +#ifndef REGISTRYITEM_H +#define REGISTRYITEM_H #include +#include + class SwitchingBar; /** \brief An item intended to be put into WidgetRegistry @@ -12,25 +15,32 @@ class RegistryItem { public: QString name; /**< The name of the widget, used in the SwitchingBar combo box. */ + /** \brief A function constructing the widget * * A pointer to a function returning QWidget*. This function is called to construct the widget each time it is selected in any SwitchingWidget. Usually in this function the widget is dynamically created using `new` operator and the pointer is returned. * \return A pointer to the newly-created QWidget */ - QWidget* (*widget) (); + std::function widget; + /** \brief A function populating the SwitchingBar * * A pointer to a function populating the SwitchingBar. This function is called each time this widget is selected in any SwitchingWidget. Usually this function makes use of the interface provided by SwitchingBar to populate it. * \param A pointer to the SwitchingBar to be populated * \param A pointer to the newly-created widget in the SwitchingWidget */ - void (*populateBar) (SwitchingBar*, QWidget*); + std::function populateBar; + /** \brief A constructor setting all the internal values * - * This constructor takes 3 parameters corresponding to the 3 members of the RegistryItem class. See their desription for more details. + * This constructor takes 3 parameters corresponding to the 3 members of the RegistryItem class. See their description for more details. * \param name The name of the widget, used in the SwitchingBar combo box * \param widget A pointer to a function constructing the widget * \param populateBar A pointer to a function populating the SwitchingBar */ - RegistryItem(QString name = "Default", QWidget* (*widget) () = []()->QWidget* {return new QLabel{"Default Widget"};}, void (*populateBar) (SwitchingBar*, QWidget*) = [](SwitchingBar*, QWidget*)->void {}); + RegistryItem(const QString& name, + std::function widget, + std::function populateBar = {}); }; + +#endif diff --git a/src/blendsplitter/SplitterDecorator.cpp b/src/blendsplitter/SplitterDecorator.cpp index d13d73a8..8ff6ccc2 100644 --- a/src/blendsplitter/SplitterDecorator.cpp +++ b/src/blendsplitter/SplitterDecorator.cpp @@ -2,9 +2,10 @@ #include "BlendSplitter.h" -SplitterDecorator::SplitterDecorator(BlendSplitter* splitter) : QWidget{}, splitter{splitter} +SplitterDecorator::SplitterDecorator(BlendSplitter* splitter) + : splitter{splitter} { - QHBoxLayout* layout{new QHBoxLayout{}}; + auto* layout = new QHBoxLayout{}; layout->addWidget(splitter); layout->setMargin(0); setLayout(layout); diff --git a/src/blendsplitter/SplitterDecorator.h b/src/blendsplitter/SplitterDecorator.h index 9b9edae5..e752ef64 100644 --- a/src/blendsplitter/SplitterDecorator.h +++ b/src/blendsplitter/SplitterDecorator.h @@ -1,4 +1,5 @@ -#pragma once +#ifndef SPLITTERDECORATOR_H +#define SPLITTERDECORATOR_H #include "Global.h" @@ -7,11 +8,15 @@ class BlendSplitter; class SplitterDecorator : public QWidget { Q_OBJECT - Q_DISABLE_COPY(SplitterDecorator) + public: - SplitterDecorator() = delete; + SplitterDecorator(const SplitterDecorator&) = delete; + SplitterDecorator& operator=(const SplitterDecorator&) = delete; explicit SplitterDecorator(BlendSplitter* splitter); ~SplitterDecorator(); + private: BlendSplitter* splitter; }; + +#endif diff --git a/src/blendsplitter/SplitterHandle.cpp b/src/blendsplitter/SplitterHandle.cpp index ffe780f8..4f10f1b3 100644 --- a/src/blendsplitter/SplitterHandle.cpp +++ b/src/blendsplitter/SplitterHandle.cpp @@ -6,19 +6,21 @@ #include #include -SplitterHandle::SplitterHandle(Qt::Orientation orientation, QSplitter* parent) : QSplitterHandle(orientation, parent), - popupmenu{nullptr},joinBeforeAction{nullptr},joinAfterAction{nullptr}, - splitHoriBeforeAction{nullptr},splitHoriAfterAction{nullptr}, - splitVertBeforeAction{nullptr},splitVertAfterAction{nullptr} +SplitterHandle::SplitterHandle(Qt::Orientation orientation, QSplitter* parent) + : QSplitterHandle(orientation, parent) + , popupmenu{nullptr} + , joinBeforeAction{nullptr}, joinAfterAction{nullptr} + , splitHoriBeforeAction{nullptr}, splitHoriAfterAction{nullptr} + , splitVertBeforeAction{nullptr}, splitVertAfterAction{nullptr} { } SplitterHandle::~SplitterHandle() { - if (popupmenu){ + if (popupmenu) { delete popupmenu; //Qmenu has ownership of the actions - popupmenu=nullptr; - }; + popupmenu = nullptr; + } /* delete popupmenu; This sometimes causes a crash???? @@ -68,10 +70,10 @@ SplitterHandle::~SplitterHandle() */ } -void SplitterHandle::mousePressEvent(QMouseEvent *event) +void SplitterHandle::mousePressEvent(QMouseEvent* event) { - if (false && event->button() == Qt::RightButton){ //this causes too much crashes so disabled for now + if (false && event->button() == Qt::RightButton) { //this causes too much crashes so disabled for now // Probably the QT internal code deletes the handler when we remove widgets from // the QSplitters and the rest of the Qt internals event handlers are then calling invalidated memory. // It is never a good idea to delete objects while they are still needed :-) @@ -80,10 +82,8 @@ void SplitterHandle::mousePressEvent(QMouseEvent *event) // like setting it up with a QTimer so that the main Qt loop will trigger the deletion while there is no handler code active... - - createPopupMenu(); - QPoint pos=event->globalPos(); + QPoint pos = event->globalPos(); // When positioning a menu with exec() or popup(), bear in mind that you // cannot rely on the menu's current size(). For performance reasons, // the menu adapts its size only when necessary, so in many cases, the @@ -91,108 +91,107 @@ void SplitterHandle::mousePressEvent(QMouseEvent *event) // which calculates the proper size depending on the menu's current // contents. pos.setX(pos.x() - popupmenu->sizeHint().width() / 2); // - QAction* act=popupmenu->exec(pos); - if (act==nullptr){ + QAction* act = popupmenu->exec(pos); + if (act == nullptr) { //if nothing select and some action are nullpointers.... - } else if (act==joinBeforeAction){ + } else if (act == joinBeforeAction) { releaseMouse(); event->accept(); int index = splitter()->indexOf(this); - removeFromSplitter(index,index-1); - } else if (act==joinAfterAction){ + removeFromSplitter(index, index - 1); + } else if (act == joinAfterAction) { releaseMouse(); event->accept(); //calling this will cause a segfault, so disabled... - QMessageBox::information(this,"function disabled","The current code would crash the program, so this function is disabled for now.If you are a developper please help us out..."); + QMessageBox::information(this, "function disabled", "The current code would crash the program, so this function is disabled for now.If you are a developper please help us out..."); //int index = splitter()->indexOf(this); - //removeFromSplitter(index-1,index); + //removeFromSplitter(index - 1, index); } else { QSplitterHandle::mousePressEvent(event); - }; + } destroyPopupMenu(); -// setFocus(); -// grabMouse(); + //setFocus(); + //grabMouse(); } else { QSplitterHandle::mousePressEvent(event); } } + void SplitterHandle::mouseReleaseEvent(QMouseEvent* event) { QSplitterHandle::mouseReleaseEvent(event); releaseMouse(); } -bool SplitterHandle::event(QEvent *event) +bool SplitterHandle::event(QEvent* event) { -// qDebug() << " SplitterHandle::event " << event ; + //qDebug() << " SplitterHandle::event " << event; return QSplitterHandle::event(event); } void SplitterHandle::createPopupMenu() { - int index=splitter()->indexOf(this); - bool joinBeforePossible=splitter()->widget(index-1)->inherits("WidgetDecorator"); //do not join over splitters! - bool joinAfterPossible=splitter()->widget(index)->inherits("WidgetDecorator"); //do not join over splitters! + int index = splitter()->indexOf(this); + bool joinBeforePossible = splitter()->widget(index - 1)->inherits("WidgetDecorator"); //do not join over splitters! + bool joinAfterPossible = splitter()->widget(index )->inherits("WidgetDecorator"); //do not join over splitters! // given all the crashes with joining and the simplicity of dragsplitting // maybe we should simply drop the idea of reimplementing this blender functionality? - bool splitHoriBeforePossible=false; - bool splitVertBeforePossible=false; - bool splitHoriAfterPossible=false; - bool splitVertAfterPossible=false; - - popupmenu= new QMenu(this); - bool hori = orientation()==Qt::Horizontal; - if (joinBeforePossible){ + bool splitHoriBeforePossible = false; + bool splitVertBeforePossible = false; + bool splitHoriAfterPossible = false; + bool splitVertAfterPossible = false; + + popupmenu = new QMenu(this); + bool hori = orientation() == Qt::Horizontal; + if (joinBeforePossible) { joinBeforeAction = popupmenu->addAction(hori ? tr("remove left") : tr("remove above")); - }; - if (joinAfterPossible){ + } + if (joinAfterPossible) { joinAfterAction = popupmenu->addAction(hori ? tr("remove right") : tr("remove below")); } - if (joinAfterPossible || joinBeforePossible){ + if (joinAfterPossible || joinBeforePossible) { popupmenu->addSeparator(); - }; + } - if (splitHoriBeforePossible){ + if (splitHoriBeforePossible) { splitHoriBeforeAction = popupmenu->addAction(hori ? tr("split left horizontal") : tr("split above horizontal")); - }; - if (splitVertBeforePossible){ + } + if (splitVertBeforePossible) { splitVertBeforeAction = popupmenu->addAction(hori ? tr("split left vertical") : tr("split above vertical")); - }; - if (splitHoriAfterPossible){ + } + if (splitHoriAfterPossible) { splitHoriAfterAction = popupmenu->addAction(hori ? tr("split right horizontal") : tr("split below horizontal")); - }; - if (splitVertAfterPossible){ + } + if (splitVertAfterPossible) { splitVertAfterAction = popupmenu->addAction(hori ? tr("split right horizontal") : tr("split below horizontal")); } } void SplitterHandle::destroyPopupMenu() { - if (popupmenu){ - delete popupmenu; - popupmenu=nullptr; - joinBeforeAction=nullptr; - joinAfterAction=nullptr; - splitHoriAfterAction=nullptr; - splitVertAfterAction=nullptr; - splitHoriBeforeAction=nullptr; - splitHoriAfterAction=nullptr; - } + if (popupmenu) { + delete popupmenu; + popupmenu = nullptr; + joinBeforeAction = nullptr; + joinAfterAction = nullptr; + splitHoriAfterAction = nullptr; + splitVertAfterAction = nullptr; + splitHoriBeforeAction = nullptr; + splitHoriAfterAction = nullptr; + } } void SplitterHandle::removeFromSplitter(int toKeepIndex, int toRemoveIndex) { - QSplitter* parentSplitter=splitter(); - if(parentSplitter == nullptr) - { + auto* parentSplitter = splitter(); + if (!parentSplitter) { qCritical("A BlendSplitter library error occurred. Error code: 20"); return; } - WidgetDecorator* toKeepDecorator{qobject_cast(parentSplitter->widget(toKeepIndex))}; - if(!(toKeepDecorator || parentSplitter->widget(toKeepIndex)->inherits("SplitterDecorator") )) - { + auto* toKeepDecorator = qobject_cast(parentSplitter->widget(toKeepIndex)); + if (!(toKeepDecorator || parentSplitter->widget(toKeepIndex)->inherits("SplitterDecorator"))) { qCritical("A BlendSplitter library error occurred. Error code: 21"); return; } @@ -201,18 +200,16 @@ void SplitterHandle::removeFromSplitter(int toKeepIndex, int toRemoveIndex) QList sizes{parentSplitter->sizes()}; sizes[toKeepIndex] += sizes[toRemoveIndex] + 1; sizes.removeAt(toRemoveIndex); - QWidget* oldcontent = parentSplitter->widget(toRemoveIndex); + auto* oldcontent = parentSplitter->widget(toRemoveIndex); // we now avoid delete parentSplitter->widget(toRemoveIndex); // we hope this also impacts the handler... oldcontent->hide(); oldcontent->setParent(nullptr); //removes it from splitter and makes it standalone (already hidden) window. oldcontent->deleteLater(); - if(parentSplitter->count() == 1 and - parentSplitter->parentWidget()->inherits("SplitterDecorator")) - { - BlendSplitter* newParent{qobject_cast(parentSplitter->parentWidget()->parentWidget())}; - if(newParent == nullptr) - { + if (parentSplitter->count() == 1 && + parentSplitter->parentWidget()->inherits("SplitterDecorator")) { + auto* newParent = qobject_cast(parentSplitter->parentWidget()->parentWidget()); + if (!newParent) { qCritical("A BlendSplitter library error occurred. Error code: 3"); return; } @@ -220,10 +217,7 @@ void SplitterHandle::removeFromSplitter(int toKeepIndex, int toRemoveIndex) newParent->insertDecoratedWidget(newParent->indexOf(parentSplitter->parentWidget()), toKeepDecorator); delete parentSplitter->parentWidget(); newParent->setSizes(sizes2); - } - else - { + } else { parentSplitter->setSizes(sizes); } - } diff --git a/src/blendsplitter/SplitterHandle.h b/src/blendsplitter/SplitterHandle.h index 84966b11..c5d7fedf 100644 --- a/src/blendsplitter/SplitterHandle.h +++ b/src/blendsplitter/SplitterHandle.h @@ -1,4 +1,5 @@ -#pragma once +#ifndef SPLITTERHANDLE_H +#define SPLITTERHANDLE_H #include "Global.h" @@ -9,9 +10,10 @@ class QMenu; class SplitterHandle final : public QSplitterHandle { Q_OBJECT - Q_DISABLE_COPY(SplitterHandle) + public: - SplitterHandle() = delete; + SplitterHandle(const SplitterHandle&) = delete; + SplitterHandle& operator=(const SplitterHandle&) = delete; SplitterHandle(Qt::Orientation orientation, QSplitter* parent); ~SplitterHandle(); @@ -19,15 +21,12 @@ class SplitterHandle final : public QSplitterHandle void createPopupMenu(); void destroyPopupMenu(); - void removeFromSplitter(int toKeepIndex,int toRemoveIndex); + void removeFromSplitter(int toKeepIndex, int toRemoveIndex); protected slots: - virtual void mousePressEvent(QMouseEvent* event) override; - virtual void mouseReleaseEvent(QMouseEvent* event) override; - virtual bool event(QEvent *event) override; - - - + void mousePressEvent(QMouseEvent* event) override; + void mouseReleaseEvent(QMouseEvent* event) override; + bool event(QEvent* event) override; private: QMenu* popupmenu; @@ -38,3 +37,5 @@ protected slots: QAction* splitVertBeforeAction; QAction* splitVertAfterAction; }; + +#endif diff --git a/src/blendsplitter/SwitchingBar.cpp b/src/blendsplitter/SwitchingBar.cpp index 036e8db8..ffc215f6 100644 --- a/src/blendsplitter/SwitchingBar.cpp +++ b/src/blendsplitter/SwitchingBar.cpp @@ -6,7 +6,7 @@ void SwitchingBar::addMenu(QMenu* menu) { - QMenuBar* menuBar{new QMenuBar}; + auto* menuBar = new QMenuBar; menuBar->setDefaultUp(true); layout->insertWidget(layout->count() - 1, menuBar); layout->setAlignment(menuBar, Qt::AlignVCenter); @@ -19,29 +19,33 @@ void SwitchingBar::addWidget(QWidget* widget) layout->insertWidget(layout->count() - 1, widget); } -SwitchingBar::SwitchingBar(QWidget* parent) : QWidget(parent), layout{new QHBoxLayout{}}, combo{new SwitchingCombo{}} +SwitchingBar::SwitchingBar(QWidget* parent) + : QWidget(parent) + , layout{new QHBoxLayout{}} + , combo{new SwitchingCombo{}} { layout->setContentsMargins(BlendSplitter::expanderSize * 3 / 4, 0, BlendSplitter::expanderSize * 3 / 4, 0); setLayout(layout); -// setMinimumHeight(BlendSplitter::switchingBarHeight); + //setMinimumHeight(BlendSplitter::switchingBarHeight); setMaximumHeight(BlendSplitter::switchingBarHeight); setMinimumHeight(combo->minimumHeight()); -// setMaximumHeight(combo->maximumHeight()); -// setMaximumHeight(combo->minimumHeight()); + //setMaximumHeight(combo->maximumHeight()); + //setMaximumHeight(combo->minimumHeight()); layout->addWidget(combo); layout->addStretch(); } -void SwitchingBar::reconstruct(void (*populateBar) (SwitchingBar*, QWidget*), QWidget* widget) +void SwitchingBar::reconstruct(std::function populateBar, QWidget* widget) { int count{layout->count() - 1}; - for(int i = 1; i < count; i++) - { - QLayoutItem* it{layout->takeAt(1)}; + for (int i = 1; i < count; i++) { + auto* it = layout->takeAt(1); delete it->widget(); delete it; } - (*populateBar) (this, widget); + if (populateBar) { + populateBar(this, widget); + } } SwitchingBar::~SwitchingBar() diff --git a/src/blendsplitter/SwitchingBar.h b/src/blendsplitter/SwitchingBar.h index 239d0c6c..851efb51 100644 --- a/src/blendsplitter/SwitchingBar.h +++ b/src/blendsplitter/SwitchingBar.h @@ -1,9 +1,12 @@ -#pragma once +#ifndef SWITCHINGBAR_H +#define SWITCHINGBAR_H #include #include #include +#include + class SwitchingWidget; class SwitchingCombo; @@ -13,26 +16,36 @@ class SwitchingCombo; */ class SwitchingBar : public QWidget { + friend SwitchingWidget; + Q_OBJECT - Q_DISABLE_COPY(SwitchingBar) + public: + SwitchingBar(const SwitchingBar&) = delete; + SwitchingBar& operator=(const SwitchingBar&) = delete; + /** \brief Add a QMenu * * This function adds a QMenu to the very right of the SwitchingBar. The menu is wrapped in an invisible QMenuBar. * \param menu A pointer to the QMenu to be added */ void addMenu(QMenu* menu); + /** \brief Add a QWidget * * This function adds a QWidget to the very right of the SwitchingBar. The widget is placed in a QHBoxLayout. * @param widget A pointer to the QWidget to be added */ void addWidget(QWidget* widget); + private: - friend SwitchingWidget; - QHBoxLayout* layout; - SwitchingCombo* combo; explicit SwitchingBar(QWidget* parent = nullptr); - void reconstruct(void (*populateBar) (SwitchingBar*, QWidget*), QWidget* widget); + void reconstruct(std::function populateBar, QWidget* widget); ~SwitchingBar(); + +private: + QHBoxLayout* layout; + SwitchingCombo* combo; }; + +#endif diff --git a/src/blendsplitter/SwitchingCombo.cpp b/src/blendsplitter/SwitchingCombo.cpp index a8ff75ad..97b0e4c2 100644 --- a/src/blendsplitter/SwitchingCombo.cpp +++ b/src/blendsplitter/SwitchingCombo.cpp @@ -5,24 +5,21 @@ SwitchingCombo::SwitchingCombo() { - connect(WidgetRegistry::getRegistry(), &WidgetRegistry::registryChanged, this, &SwitchingCombo::repopulate); + connect(&WidgetRegistry::instance(), &WidgetRegistry::registryChanged, this, &SwitchingCombo::repopulate); repopulate(); } void SwitchingCombo::repopulate() { - RegistryItem* current{WidgetRegistry::getRegistry()->item(currentIndex())}; + auto& registry = WidgetRegistry::instance(); + auto* current = registry.item(currentIndex()); clear(); - for(int i{0}; i < WidgetRegistry::getRegistry()->size(); i++) - { - QComboBox::addItem(WidgetRegistry::getRegistry()->item(i)->name); + for (int i = 0; i < registry.size(); ++i) { + QComboBox::addItem(registry.item(i)->name); } - if(current != 0) - { + if (current) { setCurrentIndex(findText(current->name)); - } - else - { - setCurrentIndex(findText(WidgetRegistry::getRegistry()->getDefault()->name)); + } else { + setCurrentIndex(findText(registry.getDefault()->name)); } } diff --git a/src/blendsplitter/SwitchingCombo.h b/src/blendsplitter/SwitchingCombo.h index 225a5d6f..6c8394c5 100644 --- a/src/blendsplitter/SwitchingCombo.h +++ b/src/blendsplitter/SwitchingCombo.h @@ -1,15 +1,19 @@ -#pragma once +#ifndef SWITCHINGCOMBO_H +#define SWITCHINGCOMBO_H #include "Global.h" -class SwitchingBar; - class SwitchingCombo : public QComboBox { Q_OBJECT - Q_DISABLE_COPY(SwitchingCombo) + public: + SwitchingCombo(const SwitchingCombo&) = delete; + SwitchingCombo& operator=(const SwitchingCombo&) = delete; SwitchingCombo(); + public slots: void repopulate(); }; + +#endif diff --git a/src/blendsplitter/SwitchingWidget.cpp b/src/blendsplitter/SwitchingWidget.cpp index 8362af23..4ddfa2f5 100644 --- a/src/blendsplitter/SwitchingWidget.cpp +++ b/src/blendsplitter/SwitchingWidget.cpp @@ -4,46 +4,50 @@ #include "RegistryItem.h" #include "SwitchingBar.h" #include "SwitchingCombo.h" +#include "qscrollarea.h" #include #include #include -SwitchingWidget::SwitchingWidget(RegistryItem* item, QWidget* parent,bool menuAtTop) : QSplitter(Qt::Vertical, parent), - bar{new SwitchingBar{}}, widgetEnabled(true),isWidgetAlwaysEnabled(false),barAtTop(menuAtTop) +SwitchingWidget::SwitchingWidget(RegistryItem* item, QWidget* parent, bool menuAtTop) + : QSplitter(Qt::Vertical, parent) + , bar{new SwitchingBar{}} + , widgetEnabled(true), isWidgetAlwaysEnabled(false) + , barAtTop(menuAtTop) { setChildrenCollapsible(true); setHandleWidth(1); setStyleSheet("QSplitter::handle{background: grey;}"); - if (barAtTop){ + + auto* defaultItem = WidgetRegistry::instance().getDefault(); + if (barAtTop) { addWidget(bar); - addWidget(wrapInScrollArea( (*WidgetRegistry::getRegistry()->getDefault()->widget) () ) ); + addWidget(wrapInScrollArea((defaultItem->widget)())); } else { - addWidget(wrapInScrollArea( (*WidgetRegistry::getRegistry()->getDefault()->widget) () ) ); + addWidget(wrapInScrollArea((defaultItem->widget)())); addWidget(bar); - } - bar->reconstruct(*WidgetRegistry::getRegistry()->getDefault()->populateBar, widget(widgetIndex())); + bar->reconstruct(defaultItem->populateBar, widget(widgetIndex())); connect(bar->combo, static_cast(&QComboBox::activated), this, &SwitchingWidget::changeCurrentWidget); setCurrentWidget(item); } void SwitchingWidget::setCurrentWidget(RegistryItem *item) { - if(item == nullptr) - { - item = WidgetRegistry::getRegistry()->getDefault(); + auto& registry = WidgetRegistry::instance(); + if (item == nullptr) { + item = registry.getDefault(); } - if(WidgetRegistry::getRegistry()->indexOf(item) >= 0) - { + if (registry.indexOf(item) >= 0) { delete widget(widgetIndex()); - insertWidget(widgetIndex(),wrapInScrollArea( (*item->widget) ())); - bar->reconstruct(*item->populateBar, widget(widgetIndex())); + insertWidget(widgetIndex(), wrapInScrollArea((item->widget)())); + bar->reconstruct(item->populateBar, widget(widgetIndex())); bar->combo->setCurrentIndex(bar->combo->findText(item->name)); widget(widgetIndex())->setEnabled(widgetEnabled); } //hack to have manual always enabled - //qDebug() << "WidgetRegistry::getRegistry()->indexOf(item) " << WidgetRegistry::getRegistry()->indexOf(item); - setWidgetAlwaysEnabled(WidgetRegistry::getRegistry()->indexOf(item)==14); + //qDebug() << "WidgetRegistry::getRegistry()->indexOf(item) " << registry->indexOf(item); + setWidgetAlwaysEnabled(registry.indexOf(item) == 14); } bool SwitchingWidget::getEnableWidget() @@ -53,7 +57,7 @@ bool SwitchingWidget::getEnableWidget() void SwitchingWidget::setCurrentIndex(int index) { - setCurrentWidget(WidgetRegistry::getRegistry()->item(index)); + setCurrentWidget(WidgetRegistry::instance().item(index)); } int SwitchingWidget::getCurrentIndex() @@ -64,75 +68,72 @@ int SwitchingWidget::getCurrentIndex() QJsonObject SwitchingWidget::save2json() { QJsonObject obj; - obj["type"]="SwitchingWidget"; - obj["item"]=bar->combo->currentIndex(); - obj["size_width"]=size().width(); - obj["size_height"]=size().height(); + obj["type"] = "SwitchingWidget"; + obj["item"] = bar->combo->currentIndex(); + obj["size_width"] = size().width(); + obj["size_height"] = size().height(); return obj; } -SwitchingWidget *SwitchingWidget::createFromJson(const QJsonObject &obj) +SwitchingWidget* SwitchingWidget::createFromJson(const QJsonObject &obj) { - int i=obj["item"].toInt(); - SwitchingWidget* wdgt= new SwitchingWidget{WidgetRegistry::getRegistry()->item(i)}; - wdgt->resize(obj["size_width"].toInt(),obj["size_height"].toInt()); - + int i = obj["item"].toInt(); + auto* wdgt = new SwitchingWidget{WidgetRegistry::instance().item(i)}; + wdgt->resize(obj["size_width"].toInt(), obj["size_height"].toInt()); return wdgt; } void SwitchingWidget::setEnableWidget(bool enable) { - widgetEnabled=enable; - - QWidget* wdgt=widget(widgetIndex()); - - if (isWrappedInScrollArea){ - static_cast(wdgt)->setAutoFillBackground(true); -// static_cast(wdgt)->setBackgroundRole(QPalette::Text); //trying to force repaint of background -// static_cast(wdgt)->update(); - /*static_cast(wdgt)->setBackgroundRole(enable ? QPalette::Window : QPalette::Dark);*/ - if (static_cast(wdgt)->viewport()){ - static_cast(wdgt)->viewport()->update(); - }; - wdgt=static_cast(wdgt)->widget(); - }; - - if (wdgt != nullptr){ - bool finalstatus=enable||isWidgetAlwaysEnabled; -// qDebug() << "wdgt->setEnabled(" << enable << "||" << isWidgetAlwaysEnabled << "= "<< finalstatus<< " ) "; + widgetEnabled = enable; + + auto* wdgt = widget(widgetIndex()); + + if (isWrappedInScrollArea) { + auto* sa = static_cast(wdgt); + sa->setAutoFillBackground(true); + //sa->setBackgroundRole(QPalette::Text); //trying to force repaint of background + //sa->update(); + //sa->setBackgroundRole(enable ? QPalette::Window : QPalette::Dark); + if (auto* vp = sa->viewport()) { + vp->update(); + } + wdgt = sa->widget(); + } + if (wdgt != nullptr) { + bool finalstatus = enable || isWidgetAlwaysEnabled; + //qDebug() << "wdgt->setEnabled(" << enable << "||" << isWidgetAlwaysEnabled << "= " << finalstatus << " ) "; wdgt->setEnabled(finalstatus); wdgt->update(); } - } void SwitchingWidget::setWidgetAlwaysEnabled(bool enable) { - isWidgetAlwaysEnabled=enable; -// qDebug() << "SwitchingWidget::setWidgetAlwaysEnabled(bool "<= 0) - { - setCurrentWidget(WidgetRegistry::getRegistry()->item(index)); + if (index >= 0) { + setCurrentWidget(WidgetRegistry::instance().item(index)); } } -QWidget *SwitchingWidget::wrapInScrollArea(QWidget *wdgt, bool dowrap) +QWidget* SwitchingWidget::wrapInScrollArea(QWidget* wdgt, bool dowrap) { - isWrappedInScrollArea=dowrap; - if (!dowrap){ + isWrappedInScrollArea = dowrap; + if (!dowrap) { return wdgt; - }; + } - QScrollArea* scrollArea = new QScrollArea; + auto* scrollArea = new QScrollArea; //scrollArea->setBackgroundRole(QPalette::Dark); scrollArea->setSizePolicy(QSizePolicy::Expanding , QSizePolicy::Expanding); - scrollArea->setContentsMargins(0,0,0,0); + scrollArea->setContentsMargins(0, 0, 0, 0); scrollArea->setWidget(wdgt); scrollArea->setWidgetResizable(true); return scrollArea; @@ -140,10 +141,10 @@ QWidget *SwitchingWidget::wrapInScrollArea(QWidget *wdgt, bool dowrap) int SwitchingWidget::barIndex() { - return barAtTop?0:1; + return barAtTop ? 0 : 1; } int SwitchingWidget::widgetIndex() { - return barAtTop?1:0; + return barAtTop ? 1 : 0; } diff --git a/src/blendsplitter/SwitchingWidget.h b/src/blendsplitter/SwitchingWidget.h index dc7f2c60..e753f259 100644 --- a/src/blendsplitter/SwitchingWidget.h +++ b/src/blendsplitter/SwitchingWidget.h @@ -1,4 +1,5 @@ -#pragma once +#ifndef SWITCHINGWIDGET_H +#define SWITCHINGWIDGET_H #include @@ -15,15 +16,19 @@ class QJsonObject; class SwitchingWidget : public QSplitter { Q_OBJECT - Q_DISABLE_COPY(SwitchingWidget) + public: + SwitchingWidget(const SwitchingWidget&) = delete; + SwitchingWidget& operator=(const SwitchingWidget&) = delete; + /** \brief A default constructor similar to that of QWidget * - * Creates a SwitchingWidget containg the default widget specified in WidgetRegistry + * Creates a SwitchingWidget containing the default widget specified in WidgetRegistry * \param item A RegistryItem to display in the widget. If nullptr, then WidgetRegistry::getDefault() is used. * \param parent A parent widget */ - SwitchingWidget(RegistryItem* item = nullptr, QWidget* parent = nullptr,bool menuAtTop=true); + SwitchingWidget(RegistryItem* item = nullptr, QWidget* parent = nullptr, bool menuAtTop = true); + /** \brief Set the current Widget displayed. * * Sets the current widget to be the item @@ -37,20 +42,24 @@ class SwitchingWidget : public QSplitter QJsonObject save2json(); static SwitchingWidget* createFromJson(const QJsonObject& obj); - public slots: void setEnableWidget(bool enable = true); void setWidgetAlwaysEnabled(bool enable = true); private slots: void changeCurrentWidget(int index); + private: - QWidget* wrapInScrollArea(QWidget* wdgt, bool dowrap=true); + QWidget* wrapInScrollArea(QWidget* wdgt, bool dowrap = true); int barIndex(); int widgetIndex(); + +private: SwitchingBar* bar; bool widgetEnabled; bool isWidgetAlwaysEnabled; //some widgets need to be always enabled even if disconnect from openMSX bool barAtTop; bool isWrappedInScrollArea; }; + +#endif diff --git a/src/blendsplitter/WidgetDecorator.cpp b/src/blendsplitter/WidgetDecorator.cpp index 1562dcf4..3913b103 100644 --- a/src/blendsplitter/WidgetDecorator.cpp +++ b/src/blendsplitter/WidgetDecorator.cpp @@ -6,21 +6,21 @@ #include #include -WidgetDecorator::WidgetDecorator(QWidget* widget) : QWidget{}, widget{widget}, -// expanderBottom{new ExpanderBottom{this}}, -// expanderTop{new ExpanderTop{this}}, - expanderCorner1{new ExpanderCorner{this,Qt::TopLeftCorner}}, - expanderCorner2{new ExpanderCorner{this,Qt::BottomRightCorner}}, - expanderCorner3{new ExpanderCorner{this,Qt::TopRightCorner}}, - expanderCorner4{new ExpanderCorner{this,Qt::BottomLeftCorner}}, - dropzone(dropregions::center) +WidgetDecorator::WidgetDecorator(QWidget* widget) + : widget{widget} + //, expanderBottom{new ExpanderBottom{this}} + //, expanderTop{new ExpanderTop{this}} + , expanderCorner1{new ExpanderCorner{this, Qt::TopLeftCorner}} + , expanderCorner2{new ExpanderCorner{this, Qt::BottomRightCorner}} + , expanderCorner3{new ExpanderCorner{this, Qt::TopRightCorner}} + , expanderCorner4{new ExpanderCorner{this, Qt::BottomLeftCorner}} + , dropzone(dropregions::center) { - QHBoxLayout* layout{new QHBoxLayout{}}; + auto* layout = new QHBoxLayout{}; layout->addWidget(widget); layout->setMargin(0); setLayout(layout); setMinimumSize(2 * BlendSplitter::expanderSize, 2 * BlendSplitter::expanderSize); - } WidgetDecorator::~WidgetDecorator() @@ -30,8 +30,8 @@ WidgetDecorator::~WidgetDecorator() void WidgetDecorator::resizeEvent(QResizeEvent*) { -// expanderBottom->reposition(); -// expanderTop->reposition(); + //expanderBottom->reposition(); + //expanderTop->reposition(); expanderCorner1->reposition(); expanderCorner2->reposition(); expanderCorner3->reposition(); @@ -46,60 +46,60 @@ void WidgetDecorator::resizeEvent(QResizeEvent*) void WidgetDecorator::determineDropZone(QPoint pos) { - int x=width()/3; - int y=height()/3; - if (pos.x()>x && pos.x()<(width()-x) && pos.y()>y && pos.y()<(height()-y) ){ - dropzone=dropregions::center; + int x = width() / 3; + int y = height() / 3; + if (pos.x() > x && pos.x() < (width() - x) && pos.y() > y && pos.y() < (height() - y)) { + dropzone = dropregions::center; return; } // now if we are not center then use the diagonals of the rect to see in which of the 4 triangles we are - //normal on diagnal (0,0) -> (width,height) - x=-height(); - y=width(); + //normal on diagonal (0, 0) -> (width, height) + x = -height(); + y = width(); //we use the sign of the dot product to determine if we are above/below the diagonal - int side=(x*pos.x()+y*pos.y())>0?1:0; + int side = (x * pos.x() + y * pos.y()) > 0 ? 1 : 0; - //normal on diagnal (0,height) -> (width,0) == (0,0)-(width,-height) - x=height(); - y=width(); + //normal on diagonal (0, height) -> (width, 0) == (0, 0)-(width, -height) + x = height(); + y = width(); //we use the sign of the dot product to determine if we are above/below the diagonal - side+=(x*pos.x()+y*(pos.y()-height()))>0?2:0; - dropzone=static_cast(side); + side += (x * pos.x() + y * (pos.y() - height())) > 0 ? 2 : 0; + dropzone = static_cast(side); } -//void WidgetDecorator::paintEvent(QPaintEvent *event) +//void WidgetDecorator::paintEvent(QPaintEvent* event) //{ // QWidget::paintEvent(event); - -//// qDebug() << "WidgetDecorator::paintEvent"; - +// +// //qDebug() << "WidgetDecorator::paintEvent"; +// // QPainter painter(this); // painter.setPen(Qt::black); // painter.setBrush(Qt::NoBrush); -// int x=width()/3; -// int y=height()/3; -// painter.drawLine(0,0,x,y); -// painter.drawLine(width(),0,width()-x,y); -// painter.drawLine(0,height(),x,height()-y); -// painter.drawLine(width(),height(),width()-x,height()-y); -// painter.drawRect(x,y,x,y); - +// int x = width() / 3; +// int y = height() / 3; +// painter.drawLine(0, 0, x, y); +// painter.drawLine(width(), 0, width() - x, y); +// painter.drawLine(0, height(), x, height() - y); +// painter.drawLine(width(), height(), width() - x, height() - y); +// painter.drawRect(x, y, x, y); +// // switch (dropzone) { // case dropregions::top: -// painter.drawText(QRect(x,0,x,y),Qt::AlignCenter,"top"); +// painter.drawText(QRect(x, 0, x, y), Qt::AlignCenter, "top"); // break; // case dropregions::left: -// painter.drawText(QRect(0,y,x,y),Qt::AlignCenter,"left"); +// painter.drawText(QRect(0, y, x, y), Qt::AlignCenter, "left"); // break; // case dropregions::right: -// painter.drawText(QRect(width()-x,y,x,y),Qt::AlignCenter,"right"); +// painter.drawText(QRect(width()-x, y, x, y), Qt::AlignCenter, "right"); // break; // case dropregions::bottom: -// painter.drawText(QRect(x,height()-y,x,y),Qt::AlignCenter,"bottom"); +// painter.drawText(QRect(x, height()-y, x, y), Qt::AlignCenter, "bottom"); // break; // case dropregions::center: -// painter.drawText(QRect(x,y,x,y),Qt::AlignCenter,"center"); +// painter.drawText(QRect(x, y, x, y), Qt::AlignCenter, "center"); // break; // default: // break; diff --git a/src/blendsplitter/WidgetDecorator.h b/src/blendsplitter/WidgetDecorator.h index e672c850..25fcd69c 100644 --- a/src/blendsplitter/WidgetDecorator.h +++ b/src/blendsplitter/WidgetDecorator.h @@ -1,4 +1,5 @@ -#pragma once +#ifndef WIDGETDECORATOR_H +#define WIDGETDECORATOR_H #include "Global.h" @@ -8,11 +9,16 @@ class ExpanderCorner; class WidgetDecorator final : public QWidget { Q_OBJECT - Q_DISABLE_COPY(WidgetDecorator) + public: - WidgetDecorator() = delete; + WidgetDecorator(const WidgetDecorator&) = delete; + WidgetDecorator& operator=(const WidgetDecorator&) = delete; explicit WidgetDecorator(QWidget* widget); ~WidgetDecorator(); + +private: + void determineDropZone(QPoint pos); + private: QWidget* widget; ExpanderCorner* expanderCorner1; @@ -21,20 +27,18 @@ class WidgetDecorator final : public QWidget ExpanderCorner* expanderCorner4; enum class dropregions { - top=0, - left=1, - right=2, - bottom=3, - center=4 + top = 0, + left = 1, + right = 2, + bottom = 3, + center = 4 }; - dropregions dropzone; - void determineDropZone(QPoint pos); - protected slots: - virtual void resizeEvent(QResizeEvent*) override; -// virtual void mouseMoveEvent(QMouseEvent* event) override; -// virtual void paintEvent(QPaintEvent* event) override; - + void resizeEvent(QResizeEvent*) override; + //void mouseMoveEvent(QMouseEvent* event) override; + //void paintEvent(QPaintEvent* event) override; }; + +#endif diff --git a/src/blendsplitter/WidgetRegistry.cpp b/src/blendsplitter/WidgetRegistry.cpp index b33d0cdf..de4e4d86 100644 --- a/src/blendsplitter/WidgetRegistry.cpp +++ b/src/blendsplitter/WidgetRegistry.cpp @@ -2,15 +2,15 @@ #include "RegistryItem.h" -WidgetRegistry* WidgetRegistry::theRegistry; +WidgetRegistry::WidgetRegistry() + : defaultItem{nullptr} +{ +} -WidgetRegistry* WidgetRegistry::getRegistry() +WidgetRegistry& WidgetRegistry::instance() { - if(theRegistry == nullptr) - { - theRegistry = new WidgetRegistry{}; - } - return theRegistry; + static WidgetRegistry oneInstance; + return oneInstance; } RegistryItem* WidgetRegistry::item(int i) const @@ -25,11 +25,10 @@ int WidgetRegistry::indexOf(RegistryItem* item) const RegistryItem* WidgetRegistry::getDefault() { - if(defaultItem == nullptr) - { - if(list.size() == 0) - { - addItem(); + if (defaultItem == nullptr) { + if (list.size() == 0) { + addItem(new RegistryItem{"Default", + []()->QWidget* { return new QLabel{"Default widget"}; }}); } defaultItem = item(0); } @@ -38,8 +37,7 @@ RegistryItem* WidgetRegistry::getDefault() void WidgetRegistry::setDefault(RegistryItem* item) { - if(!list.contains(item)) - { + if (!list.contains(item)) { addItem(item); } defaultItem = item; @@ -47,8 +45,7 @@ void WidgetRegistry::setDefault(RegistryItem* item) void WidgetRegistry::setDefault(int index) { - if(index < size()) - { + if (index < size()) { setDefault(item(index)); } } @@ -59,22 +56,12 @@ void WidgetRegistry::addItem(RegistryItem* item) emit registryChanged(); } -void WidgetRegistry::addItem(QString name, QWidget* (*widget) (), void (*populateBar) (SwitchingBar*, QWidget*)) -{ - addItem(new RegistryItem{name, widget, populateBar}); -} - void WidgetRegistry::insertItem(int index, RegistryItem* item) { list.insert(index, item); emit registryChanged(); } -void WidgetRegistry::insertItem(int index, QString name, QWidget* (*widget) (), void (*populateBar) (SwitchingBar*, QWidget*)) -{ - insertItem(index, new RegistryItem{name, widget, populateBar}); -} - void WidgetRegistry::removeItem(RegistryItem* item) { removeItem(indexOf(item)); @@ -90,5 +77,3 @@ int WidgetRegistry::size() const { return list.size(); } - -WidgetRegistry::WidgetRegistry() : list{}, defaultItem{nullptr} {} diff --git a/src/blendsplitter/WidgetRegistry.h b/src/blendsplitter/WidgetRegistry.h index ec99a561..22714cd0 100644 --- a/src/blendsplitter/WidgetRegistry.h +++ b/src/blendsplitter/WidgetRegistry.h @@ -1,4 +1,5 @@ -#pragma once +#ifndef WIDGETREGISTRY_H +#define WIDGETREGISTRY_H #include @@ -12,14 +13,18 @@ class SwitchingBar; class WidgetRegistry : public QObject { Q_OBJECT - Q_DISABLE_COPY(WidgetRegistry) + public: + WidgetRegistry(const WidgetRegistry&) = delete; + WidgetRegistry& operator=(const WidgetRegistry&) = delete; + /** \brief Registry getter * - * This is a singleton class, i. e. you can't construct any object yourself. To get the one-and-only instance of this class, you need to call WidgetRegistry::getRegistry(). The function will create the object if neccessary (= when called for the first time) and return a pointer to it. + * This is a singleton class, i. e. you can't construct any object yourself. To get the one-and-only instance of this class, you need to call WidgetRegistry::getRegistry(). The function will create the object if necessary (= when called for the first time) and return a pointer to it. * \return A pointer to the one-and-only instance of WidgetRegistry */ - static WidgetRegistry* getRegistry(); + static WidgetRegistry& instance(); + /** \brief Get the item at position i. * * This function gives you the item at position i (counting starts at 0). @@ -27,6 +32,7 @@ class WidgetRegistry : public QObject * \return A pointer to the RegistryItem at position i */ RegistryItem* item(int i) const; + /** \brief Get the position of an item in WidgetRegistry * * Get the index (counting starts at 0) of an item. Often used together with item(int i) const. @@ -34,38 +40,35 @@ class WidgetRegistry : public QObject * \return Index of the item */ int indexOf(RegistryItem* item) const; + /** \brief Get the default RegistryItem * * This function gives you the default RegistryItem. Note that if no item was set as default, the currently first item is set as default by this function. If the registry is empty, a RegistryItem is added to the registry (using the default constructor) and set as default. * \return A pointer to the default RegistryItem */ RegistryItem* getDefault(); + /** \brief Set the default RegistryItem * * This function sets the default RegistryItem. Note that if the item is not in WidgetRegistry, it is added as the last entry. The default item is used when a new SwitchingWidget is created as the displayed widget. * \param item A pointer to the RegistryItem to be set as default */ void setDefault(RegistryItem* item); + /** \brief Set the default RegistryItem * * This function sets the default RegistryItem to be the RegistryItem at given index. This is equal to calling setDefault(item(index)). * \param index Index of the RegistryItem to be set as default (counting starts at 0) */ void setDefault(int index = 0); + /** \brief Add an item to WidgetRegistry * * Adds a given RegistryItem at the end of WidgetRegistry. * \param item A pointer to the RegistryItem to be added */ void addItem(RegistryItem* item); - /** \brief Add an item to WidgetRegistry - * - * Adds a RegistryItem constructed with the given parameters at the end of WidgetRegistry. This is equal to calling addItem(new RegistryItem{name, widget, populateBar}). - * \param name The name of the widget, used in the SwitchingBar combo box - * \param widget A pointer to a function constructing the widget - * \param populateBar A pointer to a function populating the SwitchingBar - */ - void addItem(QString name = "Default", QWidget* (*widget) () = []()->QWidget* {return new QLabel{"Default widget"};}, void (*populateBar) (SwitchingBar*, QWidget*) = [](SwitchingBar*, QWidget*)->void {}); + /** \brief Insert an item into WidgetRegistry * * Inserts a given RegistryItem into WidgetRegistry at a given index. @@ -73,42 +76,39 @@ class WidgetRegistry : public QObject * \param item A pointer to the RegistryItem to be added */ void insertItem(int index, RegistryItem* item); - /** \brief Insert an item into widgetRegistry - * - * Inserts a RegistryItem constructed with the given parameters into WidgetRegistry at a given index. This is equal to calling insertItem(index, new RegistryItem{name, widget, populateBar}). - * \param index The desired index of the inserted RegistryItem (counting starts at 0) - * \param name The name of the widget, used in the SwitchingBar combo box - * \param widget A pointer to a function constructing the widget - * \param populateBar A pointer to a function populating the SwitchingBar - */ - void insertItem(int index, QString name = "Default", QWidget* (*widget) () = []()->QWidget* {return new QLabel{"Default widget"};}, void (*populateBar) (SwitchingBar*, QWidget*) = [](SwitchingBar*, QWidget*)->void {}); + /** \brief Remove a RegistryItem from WidgetRegistry * * Removes a given RegistryItem from WidgetRegistry. If this is also the default RegistryItem, the first RegistryItem is set as default if it exists. This is equal to calling removeItem(indexOf(item)). * \param item */ void removeItem(RegistryItem* item); + /** \brief Remove a RegistryItem from WidgetRegistry * * Removes the RegistryItem at position index (counting starts at 0) from WidgetRegistry. If this is also the default RegistryItem, the first RegistryItem is set as default if it exists. * \param index Index of the RegistryItem to be removed */ void removeItem(int index); + /** \brief Get the size of WidgetRegistry * * This function returns the number of RegistryItems currently in WidgetRegistry. Note that these are indexed as 0, ..., (size() - 1). * \return Number of RegistryItems in WidgetRegistry */ int size() const; + signals: - /** \brief Signal emited when WidgetRegistry changes its contents + /** \brief Signal emitted when WidgetRegistry changes its contents * - * This signal is emited when a RegistryItem is added, inserted or removed from WidgetRegistry. It is NOT emited when the default item is changed unless this change requires adding a RegistryItem. + * This signal is emitted when a RegistryItem is added, inserted or removed from WidgetRegistry. It is NOT emitted when the default item is changed unless this change requires adding a RegistryItem. */ void registryChanged(); + private: - static WidgetRegistry* theRegistry; QList list; RegistryItem* defaultItem; WidgetRegistry(); }; + +#endif From bc0b493d4b7034018f54623b8f4b7082264867ef Mon Sep 17 00:00:00 2001 From: David Heremans Date: Tue, 3 May 2022 14:41:37 +0200 Subject: [PATCH 18/63] debugmessages --- src/DebuggerForm.cpp | 5 +++++ src/StackViewer.cpp | 4 ++++ src/blendsplitter/SwitchingWidget.cpp | 6 ++++-- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/DebuggerForm.cpp b/src/DebuggerForm.cpp index bfcf73f0..3d9f7770 100644 --- a/src/DebuggerForm.cpp +++ b/src/DebuggerForm.cpp @@ -767,6 +767,11 @@ QWidget* DebuggerForm::widgetFactory(factoryclasses fctwidget) wdgt = new StackViewer(); static_cast(wdgt)->setData(SignalDispatcher::getDispatcher()->getMainMemory(), 65536); connect(SignalDispatcher::getDispatcher(), SIGNAL(spChanged(quint16)), wdgt, SLOT(setStackPointer(quint16))); + { + static int c=1; + wdgt->setObjectName(QString("stackViewer_%1").arg(c++)); + } + qDebug()<<"case stackViewer wdgt->objectName() "<objectName(); break; case slotViewer: wdgt = new SlotViewer(); diff --git a/src/StackViewer.cpp b/src/StackViewer.cpp index 43de2eb7..5f469411 100644 --- a/src/StackViewer.cpp +++ b/src/StackViewer.cpp @@ -167,6 +167,7 @@ void StackViewer::setData(unsigned char* memPtr, int memLength) void StackViewer::setLocation(int addr) { + qDebug()<<"StackViewer::setLocation(int "<< addr<<") wdgt->objectName() "<< objectName(); if (waitingForData) { return; // ignore } @@ -183,6 +184,7 @@ void StackViewer::setLocation(int addr) void StackViewer::setStackPointer(quint16 addr) { + qDebug()<<"StackViewer::setStackPointer(quint16 "<< addr<<") wdgt->objectName() "<< objectName(); stackPointer = addr; setScrollBarValues(); vertScrollBar->setValue(addr); @@ -191,6 +193,8 @@ void StackViewer::setStackPointer(quint16 addr) void StackViewer::memdataTransfered(StackRequest* r) { + qDebug()<<"StackViewer::memdataTransfered() wdgt->objectName() "<< objectName(); + topAddress = r->offset; update(); diff --git a/src/blendsplitter/SwitchingWidget.cpp b/src/blendsplitter/SwitchingWidget.cpp index 4ddfa2f5..8d1a7545 100644 --- a/src/blendsplitter/SwitchingWidget.cpp +++ b/src/blendsplitter/SwitchingWidget.cpp @@ -43,7 +43,9 @@ void SwitchingWidget::setCurrentWidget(RegistryItem *item) insertWidget(widgetIndex(), wrapInScrollArea((item->widget)())); bar->reconstruct(item->populateBar, widget(widgetIndex())); bar->combo->setCurrentIndex(bar->combo->findText(item->name)); - widget(widgetIndex())->setEnabled(widgetEnabled); +// widget(widgetIndex())->setEnabled(widgetEnabled); + setEnableWidget(widgetEnabled); + qDebug() << widget(widgetIndex()); } //hack to have manual always enabled //qDebug() << "WidgetRegistry::getRegistry()->indexOf(item) " << registry->indexOf(item); @@ -103,7 +105,7 @@ void SwitchingWidget::setEnableWidget(bool enable) if (wdgt != nullptr) { bool finalstatus = enable || isWidgetAlwaysEnabled; - //qDebug() << "wdgt->setEnabled(" << enable << "||" << isWidgetAlwaysEnabled << "= " << finalstatus << " ) "; + qDebug() << "wdgt->setEnabled(" << enable << "||" << isWidgetAlwaysEnabled << "= " << finalstatus << " ) " << wdgt->objectName(); wdgt->setEnabled(finalstatus); wdgt->update(); } From 0782d3e5b87aee1ba887b032868e6730b07f7d71 Mon Sep 17 00:00:00 2001 From: david Date: Tue, 3 May 2022 19:37:52 +0200 Subject: [PATCH 19/63] Add objectnames Since there is code that doesn't use ui files, we now manually set the QObject names to make debugging simpler --- src/CPURegsViewer.cpp | 1 + src/DebuggableViewer.cpp | 1 + src/FlagsViewer.cpp | 1 + src/MainMemoryViewer.cpp | 1 + src/StackViewer.cpp | 1 + 5 files changed, 5 insertions(+) diff --git a/src/CPURegsViewer.cpp b/src/CPURegsViewer.cpp index 8768fe75..4ca5590f 100644 --- a/src/CPURegsViewer.cpp +++ b/src/CPURegsViewer.cpp @@ -10,6 +10,7 @@ CPURegsViewer::CPURegsViewer(QWidget* parent) : QFrame(parent) { + setObjectName("CPURegsViewer"); // avoid UMR memset(®s, 0, sizeof(regs)); memset(®sChanged, 0, sizeof(regsChanged)); diff --git a/src/DebuggableViewer.cpp b/src/DebuggableViewer.cpp index 5f96566d..bfd35011 100644 --- a/src/DebuggableViewer.cpp +++ b/src/DebuggableViewer.cpp @@ -6,6 +6,7 @@ DebuggableViewer::DebuggableViewer(QWidget* parent) : QWidget(parent) { + setObjectName("DebuggableViewer"); // create selection list and viewer debuggableList = new QComboBox(); debuggableList->setEditable(false); diff --git a/src/FlagsViewer.cpp b/src/FlagsViewer.cpp index 13839f82..9c017b44 100644 --- a/src/FlagsViewer.cpp +++ b/src/FlagsViewer.cpp @@ -6,6 +6,7 @@ FlagsViewer::FlagsViewer(QWidget* parent) : QFrame(parent) { + setObjectName("FlagsViewer"); flags = flagsChanged = 0; // avoid UMR setFrameStyle(WinPanel | Sunken); diff --git a/src/MainMemoryViewer.cpp b/src/MainMemoryViewer.cpp index 26ade268..628f16d1 100644 --- a/src/MainMemoryViewer.cpp +++ b/src/MainMemoryViewer.cpp @@ -21,6 +21,7 @@ static const int linkRegisters[] = { MainMemoryViewer::MainMemoryViewer(QWidget* parent) : QWidget(parent) { + setObjectName("MainMemoryViewer"); // create selection list, address edit line and viewer addressSourceList = new QComboBox(); addressSourceList->setEditable(false); diff --git a/src/StackViewer.cpp b/src/StackViewer.cpp index 5f469411..ffde4a15 100644 --- a/src/StackViewer.cpp +++ b/src/StackViewer.cpp @@ -41,6 +41,7 @@ StackViewer::StackViewer(QWidget* parent) : QFrame(parent) , wheelRemainder(0) { + setObjectName("StackViewer"); setFrameStyle(WinPanel | Sunken); setFocusPolicy(Qt::StrongFocus); setBackgroundRole(QPalette::Base); From 5338939898afd722e42a36ee12e79a0945abe671 Mon Sep 17 00:00:00 2001 From: David Heremans Date: Wed, 4 May 2022 19:02:13 +0200 Subject: [PATCH 20/63] SignalDispatcher becomes responsible for VDPDataStore --- src/SignalDispatcher.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/SignalDispatcher.cpp b/src/SignalDispatcher.cpp index a1c35ce6..419e92eb 100644 --- a/src/SignalDispatcher.cpp +++ b/src/SignalDispatcher.cpp @@ -1,6 +1,7 @@ #include "SignalDispatcher.h" #include "OpenMSXConnection.h" #include "CommClient.h" +#include "VDPDataStore.h" class DispatchDebugMemMapperHandler : public SimpleCommand { @@ -88,6 +89,7 @@ bool SignalDispatcher::getEnableWidget() void SignalDispatcher::refresh() { CommClient::instance().sendCommand(new DispatchDebugMemMapperHandler(*this)); + VDPDataStore::instance().refresh(); } From 45e98003dca8719dedf163277d7d247e65c4340d Mon Sep 17 00:00:00 2001 From: David Heremans Date: Wed, 4 May 2022 19:03:20 +0200 Subject: [PATCH 21/63] Fixes mouseover bug in tileviewer --- src/VramTiledView.cpp | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/VramTiledView.cpp b/src/VramTiledView.cpp index 445cfc78..1966b57e 100644 --- a/src/VramTiledView.cpp +++ b/src/VramTiledView.cpp @@ -506,15 +506,17 @@ std::optional VramTiledView::infoFromMouseEvent(Q if (!vramBase) return {}; // I see negative y-coords sometimes, so for safety clip the coords - int x = std::clamp(int(float(e->x()) / zoomFactor), 0, 511); - int y = std::clamp(int(float(e->y()) / zoomFactor) / 2, 0, 255); - if (x >= horiStep * screenWidth) return {}; - if (y >= 8 * screenHeight) return {}; + int x = std::clamp(int(float(e->x()) / zoomFactor), 0, 511) / horiStep; + int y = std::clamp(int(float(e->y()) / zoomFactor) / 2, 0, 255) / 8; + + if (x >= screenWidth) return {}; + if (y >= screenHeight) return {}; int character = 0; + switch (tableToShow) { case 0: - character = x + y * screenWidth; + character = x + y * screenWidth; if (!(screenMode == 2 || screenMode == 4)) { character &= 255; } @@ -523,11 +525,11 @@ std::optional VramTiledView::infoFromMouseEvent(Q case 2: character = vramBase[nameTableAddress + x + y * screenWidth]; if (screenMode == 2 || screenMode == 4) { - character += 256 * int(y / 8); + character += 256 * int(y / 8); } break; } - return MouseEventInfo{int(x / horiStep), int(y / 8), character}; + return MouseEventInfo{x, y, character}; } void VramTiledView::setBorderColor(int value) From 301d36afbbeaa56bcb42aedb03bb4bde469e5578 Mon Sep 17 00:00:00 2001 From: David Heremans Date: Wed, 4 May 2022 19:05:28 +0200 Subject: [PATCH 22/63] Trying to improve StackViewer --- src/DebuggerForm.cpp | 8 +++----- src/StackViewer.cpp | 13 +++++++++---- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/DebuggerForm.cpp b/src/DebuggerForm.cpp index 3d9f7770..73043b82 100644 --- a/src/DebuggerForm.cpp +++ b/src/DebuggerForm.cpp @@ -766,12 +766,10 @@ QWidget* DebuggerForm::widgetFactory(factoryclasses fctwidget) case stackViewer: wdgt = new StackViewer(); static_cast(wdgt)->setData(SignalDispatcher::getDispatcher()->getMainMemory(), 65536); + static_cast(wdgt)->setStackPointer( + SignalDispatcher::getDispatcher()->readRegister(CpuRegs::REG_SP) + ); connect(SignalDispatcher::getDispatcher(), SIGNAL(spChanged(quint16)), wdgt, SLOT(setStackPointer(quint16))); - { - static int c=1; - wdgt->setObjectName(QString("stackViewer_%1").arg(c++)); - } - qDebug()<<"case stackViewer wdgt->objectName() "<objectName(); break; case slotViewer: wdgt = new SlotViewer(); diff --git a/src/StackViewer.cpp b/src/StackViewer.cpp index ffde4a15..ede92214 100644 --- a/src/StackViewer.cpp +++ b/src/StackViewer.cpp @@ -41,7 +41,8 @@ StackViewer::StackViewer(QWidget* parent) : QFrame(parent) , wheelRemainder(0) { - setObjectName("StackViewer"); + static int count=0; + setObjectName(QString("StackViewer_%1").arg(count++)); setFrameStyle(WinPanel | Sunken); setFocusPolicy(Qt::StrongFocus); setBackgroundRole(QPalette::Base); @@ -178,9 +179,12 @@ void StackViewer::setLocation(int addr) if (start + size >= memoryLength) { size = memoryLength - start; } - auto* req = new StackRequest(start, size, &memory[start], *this); - CommClient::instance().sendCommand(req); - waitingForData = true; + qDebug()<<"StackViewer::setLocation isEnabled() "<< isEnabled(); + if (isEnabled()) { //only request data when enabled + auto* req = new StackRequest(start, size, &memory[start], *this); + CommClient::instance().sendCommand(req); + waitingForData = true; + } } void StackViewer::setStackPointer(quint16 addr) @@ -189,6 +193,7 @@ void StackViewer::setStackPointer(quint16 addr) stackPointer = addr; setScrollBarValues(); vertScrollBar->setValue(addr); + qDebug()<<"StackViewer::setStackPointer is now calling "; setLocation(addr); } From cbb077e68d0959a692eb358601e897dad6ef13e9 Mon Sep 17 00:00:00 2001 From: David Heremans Date: Wed, 4 May 2022 19:08:11 +0200 Subject: [PATCH 23/63] Some debug texts --- src/CommClient.cpp | 3 +++ src/blendsplitter/SwitchingWidget.cpp | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/CommClient.cpp b/src/CommClient.cpp index 51768664..c9b4b4d2 100644 --- a/src/CommClient.cpp +++ b/src/CommClient.cpp @@ -1,5 +1,6 @@ #include "CommClient.h" #include "OpenMSXConnection.h" +#include CommClient::~CommClient() { @@ -38,8 +39,10 @@ void CommClient::closeConnection() void CommClient::sendCommand(CommandBase* command) { if (connection) { + //qDebug() << "CommClient::sendCommand(CommandBase* " << command << ") connection available"; connection->sendCommand(command); } else { + //qDebug() << "CommClient::sendCommand(CommandBase* " << command << ") connection NOT available"; command->cancel(); } } diff --git a/src/blendsplitter/SwitchingWidget.cpp b/src/blendsplitter/SwitchingWidget.cpp index 8d1a7545..24e16a52 100644 --- a/src/blendsplitter/SwitchingWidget.cpp +++ b/src/blendsplitter/SwitchingWidget.cpp @@ -45,7 +45,7 @@ void SwitchingWidget::setCurrentWidget(RegistryItem *item) bar->combo->setCurrentIndex(bar->combo->findText(item->name)); // widget(widgetIndex())->setEnabled(widgetEnabled); setEnableWidget(widgetEnabled); - qDebug() << widget(widgetIndex()); + //qDebug() << widget(widgetIndex()); } //hack to have manual always enabled //qDebug() << "WidgetRegistry::getRegistry()->indexOf(item) " << registry->indexOf(item); @@ -105,7 +105,7 @@ void SwitchingWidget::setEnableWidget(bool enable) if (wdgt != nullptr) { bool finalstatus = enable || isWidgetAlwaysEnabled; - qDebug() << "wdgt->setEnabled(" << enable << "||" << isWidgetAlwaysEnabled << "= " << finalstatus << " ) " << wdgt->objectName(); + //qDebug() << "wdgt->setEnabled(" << enable << "||" << isWidgetAlwaysEnabled << "= " << finalstatus << " ) " << wdgt->objectName(); wdgt->setEnabled(finalstatus); wdgt->update(); } From 3f33b0487d73b1370e51761d2e9663686cbff7e5 Mon Sep 17 00:00:00 2001 From: m9710797 Date: Tue, 3 May 2022 18:09:41 +0200 Subject: [PATCH 24/63] replace 'override final' with just 'final' --- src/DebuggerForm.cpp | 1 - src/blendsplitter/Expander.h | 4 ++-- src/blendsplitter/ExpanderCorner.h | 6 +++--- src/blendsplitter/SwitchingWidget.cpp | 2 +- 4 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/DebuggerForm.cpp b/src/DebuggerForm.cpp index 73043b82..57059515 100644 --- a/src/DebuggerForm.cpp +++ b/src/DebuggerForm.cpp @@ -590,7 +590,6 @@ void DebuggerForm::tabCloseRequest(int index) } } - void DebuggerForm::addInfoWorkspace() { auto* split = new BlendSplitter([]()->QWidget* {return new SwitchingWidget{};},Qt::Horizontal); diff --git a/src/blendsplitter/Expander.h b/src/blendsplitter/Expander.h index b908172e..5876a4d7 100644 --- a/src/blendsplitter/Expander.h +++ b/src/blendsplitter/Expander.h @@ -20,8 +20,8 @@ class Expander : public QLabel ~Expander(); protected slots: - //void enterEvent(QEvent* event) override final; - //void leaveEvent(QEvent* event) override final; + //void enterEvent(QEvent* event) final; + //void leaveEvent(QEvent* event) final; //void mousePressEvent(QMouseEvent* event) override; //void mouseMoveEvent(QMouseEvent* event) override = 0; //void mouseReleaseEvent(QMouseEvent* event) override; diff --git a/src/blendsplitter/ExpanderCorner.h b/src/blendsplitter/ExpanderCorner.h index d60c2aef..02b2265f 100644 --- a/src/blendsplitter/ExpanderCorner.h +++ b/src/blendsplitter/ExpanderCorner.h @@ -20,8 +20,8 @@ class ExpanderCorner final : public Expander protected slots: void mouseMoveEvent(QMouseEvent* event) override; - void mousePressEvent(QMouseEvent* event) override final; - void mouseReleaseEvent(QMouseEvent* event) override final; + void mousePressEvent(QMouseEvent* event) final; + void mouseReleaseEvent(QMouseEvent* event) final; private: void decideDragAction(QMouseEvent* event, WidgetDecorator* parentDecorator, BlendSplitter* parentSplitter); @@ -53,7 +53,7 @@ protected slots: Qt::ArrowType joinarrow; protected slots: - void enterEvent(QEvent* event) override final; + void enterEvent(QEvent* event) final; }; #endif diff --git a/src/blendsplitter/SwitchingWidget.cpp b/src/blendsplitter/SwitchingWidget.cpp index 24e16a52..2c6a24c1 100644 --- a/src/blendsplitter/SwitchingWidget.cpp +++ b/src/blendsplitter/SwitchingWidget.cpp @@ -32,7 +32,7 @@ SwitchingWidget::SwitchingWidget(RegistryItem* item, QWidget* parent, bool menuA setCurrentWidget(item); } -void SwitchingWidget::setCurrentWidget(RegistryItem *item) +void SwitchingWidget::setCurrentWidget(RegistryItem* item) { auto& registry = WidgetRegistry::instance(); if (item == nullptr) { From c63ba22c8d7458d5268c4f2264e988894c96a7af Mon Sep 17 00:00:00 2001 From: m9710797 Date: Tue, 3 May 2022 19:28:24 +0200 Subject: [PATCH 25/63] Fixup after cleanup BlendSplitter construction --- src/DebuggerForm.cpp | 26 +++++++++++++------------- src/blendsplitter/BlendSplitter.cpp | 6 +++--- src/blendsplitter/BlendSplitter.h | 4 ++-- src/blendsplitter/ExpanderCorner.cpp | 2 +- 4 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/DebuggerForm.cpp b/src/DebuggerForm.cpp index 57059515..9db78c39 100644 --- a/src/DebuggerForm.cpp +++ b/src/DebuggerForm.cpp @@ -527,17 +527,17 @@ BlendSplitter* DebuggerForm::createWorkspaceCPU() { auto& registry = WidgetRegistry::instance(); - auto* split = new BlendSplitter({}, Qt::Horizontal); + auto* split = new BlendSplitter(Qt::Horizontal); split->addWidget(registry.item(2)); //2: the register viewer split->addWidget(registry.item(3)); //3: the flags viewer split->addWidget(registry.item(5)); //5: the slot viewer - auto* split2 = new BlendSplitter({}, Qt::Vertical); + auto* split2 = new BlendSplitter(Qt::Vertical); split2->addSplitter(split); split2->addWidget(registry.item(1)); //1: the memory view widget split2->addWidget(registry.item(6)); //6: the breakpoints viewer - auto* split3 = new BlendSplitter({}, Qt::Horizontal); + auto* split3 = new BlendSplitter(Qt::Horizontal); split3->addWidget(registry.item(0)); //0: the disasm viewer split3->addSplitter(split2); split3->addWidget(registry.item(4)); //4: the stack viewer @@ -549,11 +549,11 @@ BlendSplitter* DebuggerForm::createWorkspaceVDPRegs() { auto& registry = WidgetRegistry::instance(); - auto* split2 = new BlendSplitter({}, Qt::Vertical); + auto* split2 = new BlendSplitter(Qt::Vertical); split2->addWidget(registry.item(8)); //8: the VDP Status Registers split2->addWidget(registry.item(9)); //9: the VDP command registers view - auto* split3 = new BlendSplitter({}, Qt::Horizontal); + auto* split3 = new BlendSplitter(Qt::Horizontal); split3->addWidget(registry.item(13)); //13: the general VDP registers split3->addSplitter(split2); @@ -563,7 +563,7 @@ BlendSplitter* DebuggerForm::createWorkspaceVDPRegs() BlendSplitter *DebuggerForm::createWorkspaceVDPTiles() { auto& registry = WidgetRegistry::instance(); - auto* split3 = new BlendSplitter({}, Qt::Horizontal); + auto* split3 = new BlendSplitter(Qt::Horizontal); split3->addWidget(registry.item(11)); //11: the Tile VRAM View split3->addWidget(registry.item(12)); //12: the Sprites View return split3; @@ -572,7 +572,7 @@ BlendSplitter *DebuggerForm::createWorkspaceVDPTiles() BlendSplitter *DebuggerForm::createWorkspaceVDPBitmap() { auto& registry = WidgetRegistry::instance(); - auto* split3 = new BlendSplitter({}, Qt::Horizontal); + auto* split3 = new BlendSplitter(Qt::Horizontal); split3->addWidget(registry.item(10)); //10: the Bitmapped VRAM View split3->addWidget(registry.item(12)); //12: the Sprites View return split3; @@ -592,7 +592,7 @@ void DebuggerForm::tabCloseRequest(int index) void DebuggerForm::addInfoWorkspace() { - auto* split = new BlendSplitter([]()->QWidget* {return new SwitchingWidget{};},Qt::Horizontal); + auto* split = new BlendSplitter(Qt::Horizontal); split->addWidget(WidgetRegistry::instance().item(14)); //14: the quick guide manuel workspaces->addTab(split, "Welcome new user"); } @@ -618,14 +618,14 @@ void DebuggerForm::addVDPBitmapWorkspace(){ void DebuggerForm::addEmptyWorkspace() { - auto* split = new BlendSplitter({}, Qt::Horizontal); + auto* split = new BlendSplitter(Qt::Horizontal); split->addWidget(); workspaces->addTab(split, "custom"); } void DebuggerForm::addFloatingSwitchingWidget() { - SwitchingWidget* wdg=new SwitchingWidget(); + auto* wdg = new SwitchingWidget(); connect(SignalDispatcher::getDispatcher(), SIGNAL(enableWidget(bool)), wdg, SLOT(setEnableWidget(bool))); wdg->setEnableWidget(SignalDispatcher::getDispatcher()->getEnableWidget()); wdg->show(); @@ -1430,11 +1430,11 @@ bool DebuggerForm::loadWorkspaces(const QString &filename) }; //now recreate workspaces QJsonObject obj = jsonDoc.object(); - foreach (const QJsonValue & value, obj["workspaces"].toArray()) { + for (const auto& value : obj["workspaces"].toArray()) { QJsonObject obj = value.toObject(); - BlendSplitter* splitter=BlendSplitter::createFromJson(obj["workspace"].toObject()); + auto* splitter = BlendSplitter::createFromJson(obj["workspace"].toObject()); workspaces->addTab(splitter, obj["name"].toString()); - }; + } return true; } diff --git a/src/blendsplitter/BlendSplitter.cpp b/src/blendsplitter/BlendSplitter.cpp index 1470b00b..055148e7 100644 --- a/src/blendsplitter/BlendSplitter.cpp +++ b/src/blendsplitter/BlendSplitter.cpp @@ -13,7 +13,7 @@ #include #include -BlendSplitter::BlendSplitter(std::function defaultWidget, Qt::Orientation orientation) +BlendSplitter::BlendSplitter(Qt::Orientation orientation, std::function defaultWidget) : QSplitter{orientation, nullptr} , defaultWidget{defaultWidget} { @@ -124,7 +124,7 @@ QJsonObject BlendSplitter::save2json() const BlendSplitter* BlendSplitter::createFromJson(const QJsonObject &obj) { - auto* split = new BlendSplitter({}, obj["orientation"].toInt(1) == 1 ? Qt::Horizontal : Qt::Vertical); + auto* split = new BlendSplitter(obj["orientation"].toInt(1) == 1 ? Qt::Horizontal : Qt::Vertical); for (const QJsonValue& value : obj["subs"].toArray()) { QJsonObject obj = value.toObject(); @@ -140,7 +140,7 @@ BlendSplitter* BlendSplitter::createFromJson(const QJsonObject &obj) QList sizes; split->resize(obj["size_width"].toInt(), obj["size_height"].toInt()); - for (const QJsonValue& value : obj["sizes"].toArray()) { + for (const auto& value : obj["sizes"].toArray()) { sizes.append(value.toInt()); } split->setSizes(sizes); diff --git a/src/blendsplitter/BlendSplitter.h b/src/blendsplitter/BlendSplitter.h index cda49e38..f6d931b7 100644 --- a/src/blendsplitter/BlendSplitter.h +++ b/src/blendsplitter/BlendSplitter.h @@ -44,8 +44,8 @@ class BlendSplitter : public QSplitter * \param defaultWidget A pointer to function constructing the default widget. This function is called when a new widget is added to BlendSplitter. * \param orientation Orientation of the main BlendSplitter */ - BlendSplitter(std::function defaultWidget = [] { return new SwitchingWidget{}; }, - Qt::Orientation orientation = Qt::Horizontal); + BlendSplitter(Qt::Orientation orientation, + std::function defaultWidget = [] { return new SwitchingWidget{}; }); /** \brief Add a widget to the BlendSplitter * diff --git a/src/blendsplitter/ExpanderCorner.cpp b/src/blendsplitter/ExpanderCorner.cpp index 44e5df80..5fb96371 100644 --- a/src/blendsplitter/ExpanderCorner.cpp +++ b/src/blendsplitter/ExpanderCorner.cpp @@ -153,7 +153,7 @@ void ExpanderCorner::performInnerSplit(WidgetDecorator* parentDecorator, BlendSp } else { //add a new splitter orthogonal to the current one Qt::Orientation newOrientation{parentSplitter->orientation() == Qt::Horizontal ? Qt::Vertical : Qt::Horizontal}; - auto* newSplitter = new BlendSplitter{parentSplitter->defaultWidget, newOrientation}; + auto* newSplitter = new BlendSplitter{newOrientation, parentSplitter->defaultWidget}; QList sizes{parentSplitter->sizes()}; parentSplitter->insertSplitter(parentSplitter->indexOf(parentDecorator), newSplitter); // add a widget in current splitter but on the correct side From 3d13e28788d59c79a99ceecedf31960e4693aceb Mon Sep 17 00:00:00 2001 From: David Heremans Date: Wed, 4 May 2022 19:22:26 +0200 Subject: [PATCH 26/63] removed deletes since widget owns the layout --- src/blendsplitter/SplitterDecorator.cpp | 2 +- src/blendsplitter/SwitchingBar.cpp | 2 +- src/blendsplitter/WidgetDecorator.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/blendsplitter/SplitterDecorator.cpp b/src/blendsplitter/SplitterDecorator.cpp index 8ff6ccc2..c90639c6 100644 --- a/src/blendsplitter/SplitterDecorator.cpp +++ b/src/blendsplitter/SplitterDecorator.cpp @@ -13,5 +13,5 @@ SplitterDecorator::SplitterDecorator(BlendSplitter* splitter) SplitterDecorator::~SplitterDecorator() { - delete layout(); + //delete layout(); } diff --git a/src/blendsplitter/SwitchingBar.cpp b/src/blendsplitter/SwitchingBar.cpp index ffc215f6..95e6e509 100644 --- a/src/blendsplitter/SwitchingBar.cpp +++ b/src/blendsplitter/SwitchingBar.cpp @@ -50,5 +50,5 @@ void SwitchingBar::reconstruct(std::function popu SwitchingBar::~SwitchingBar() { - delete layout; + //delete layout; } diff --git a/src/blendsplitter/WidgetDecorator.cpp b/src/blendsplitter/WidgetDecorator.cpp index 3913b103..77a92092 100644 --- a/src/blendsplitter/WidgetDecorator.cpp +++ b/src/blendsplitter/WidgetDecorator.cpp @@ -25,7 +25,7 @@ WidgetDecorator::WidgetDecorator(QWidget* widget) WidgetDecorator::~WidgetDecorator() { - delete layout(); + //delete layout(); } void WidgetDecorator::resizeEvent(QResizeEvent*) From 9b80f5ff72892d3a96761dfa0e1ed390d660d618 Mon Sep 17 00:00:00 2001 From: David Heremans Date: Wed, 4 May 2022 20:05:28 +0200 Subject: [PATCH 27/63] Improved saved layout preferences --- src/DebuggerForm.cpp | 10 +++++++--- src/DebuggerForm.h | 8 +++++--- src/PreferencesDialog.cpp | 27 +++++++++++++++++++++++++++ src/PreferencesDialog.h | 1 + src/PreferencesDialog.ui | 2 +- 5 files changed, 41 insertions(+), 7 deletions(-) diff --git a/src/DebuggerForm.cpp b/src/DebuggerForm.cpp index 9db78c39..c04c47b4 100644 --- a/src/DebuggerForm.cpp +++ b/src/DebuggerForm.cpp @@ -679,7 +679,8 @@ void DebuggerForm::createForm() addDefaultWorkspaces(); break; default: - if (!loadWorkspaces(s.value("creatingWorkspaceFile", 0).toString())){ + if (s.value("creatingWorkspaceFile", "").toString().isEmpty() + || !loadWorkspaces(s.value("creatingWorkspaceFile", "").toString())) { addDefaultWorkspaces(); } break; @@ -1156,7 +1157,7 @@ void DebuggerForm::fileSaveWorkspace() } -void DebuggerForm::fileSaveWorkspaceAs() +QString DebuggerForm::fileSaveWorkspaceAs() { QFileDialog d(this, tr("Save workspace layout")); d.setNameFilter(tr("Debug Workspace Layout Files (*.omdl)")); @@ -1164,15 +1165,18 @@ void DebuggerForm::fileSaveWorkspaceAs() d.setDirectory(QDir::currentPath()); d.setAcceptMode(QFileDialog::AcceptSave); d.setFileMode(QFileDialog::AnyFile); + QString filename; if (d.exec()) { // session->saveAs(d.selectedFiles().at(0)); - saveWorkspacesAs(d.selectedFiles().at(0)); + filename=d.selectedFiles().at(0); + saveWorkspacesAs(filename); // update recent // if (session->existsAsFile()) { // addRecentFile(session->filename()); // } } updateWindowTitle(); + return filename; } void DebuggerForm::systemConnect() diff --git a/src/DebuggerForm.h b/src/DebuggerForm.h index 75eed5ee..6b9d719a 100644 --- a/src/DebuggerForm.h +++ b/src/DebuggerForm.h @@ -53,6 +53,10 @@ class DebuggerForm : public QMainWindow quickguide }; + bool saveWorkspacesAs(const QString& newFileName); + bool loadWorkspaces(const QString& filename); + QString fileSaveWorkspaceAs(); + private: void closeEvent(QCloseEvent* e) override; @@ -152,8 +156,6 @@ class DebuggerForm : public QMainWindow enum {RESET = 0, SLOTS_CHECKED, PC_CHANGED, SLOTS_CHANGED} disasmStatus = RESET; uint16_t disasmAddress; - bool saveWorkspacesAs(const QString& newFileName); - bool loadWorkspaces(const QString& filename); void fileNewSession(); void fileOpenSession(); @@ -162,7 +164,7 @@ class DebuggerForm : public QMainWindow void fileRecentOpen(); void fileOpenWorkspace(); void fileSaveWorkspace(); - void fileSaveWorkspaceAs(); + void systemConnect(); void systemDisconnect(); void systemPause(); diff --git a/src/PreferencesDialog.cpp b/src/PreferencesDialog.cpp index 143342ec..426f9eb5 100644 --- a/src/PreferencesDialog.cpp +++ b/src/PreferencesDialog.cpp @@ -1,5 +1,7 @@ #include "PreferencesDialog.h" #include "Settings.h" +#include "DebuggerForm.h" + #include #include #include @@ -172,6 +174,31 @@ void PreferencesDialog::on_btnBrowseLayout_clicked() void PreferencesDialog::on_leFileName_textChanged(const QString &arg1) { if (updating) return; + Settings& s = Settings::get(); + s.setValue("creatingWorkspaceFile",arg1); + rbLayoutFromFile->setChecked(true); } + +void PreferencesDialog::on_btnSaveLayout_clicked() +{ + Settings& s = Settings::get(); + + QString savefilename=leFileName->text(); + if (savefilename.isEmpty()){ + //maybe the user cleared the lineEdit or first time launch or something went wrong :-) + savefilename=s.value("creatingWorkspaceFile","").toString(); + } + if (savefilename.isEmpty()) { + savefilename=static_cast(parent())->fileSaveWorkspaceAs(); + } else { + static_cast(parent())->saveWorkspacesAs(savefilename); + } + //update filename in case of fileSaveWorkspaceAs + if (!savefilename.isEmpty()) { + leFileName->setText(savefilename); + s.setValue("creatingWorkspaceFile",savefilename); + } +} + diff --git a/src/PreferencesDialog.h b/src/PreferencesDialog.h index fb1a4d05..7e5a19d1 100644 --- a/src/PreferencesDialog.h +++ b/src/PreferencesDialog.h @@ -26,6 +26,7 @@ private slots: void on_btnBrowseLayout_clicked(); void on_leFileName_textChanged(const QString &arg1); + void on_btnSaveLayout_clicked(); }; #endif // PREFERENCESDIALOG_OPENMSX_H diff --git a/src/PreferencesDialog.ui b/src/PreferencesDialog.ui index 4df17ffa..95d1c18b 100644 --- a/src/PreferencesDialog.ui +++ b/src/PreferencesDialog.ui @@ -227,7 +227,7 @@ - Save current layout... + Overwrite with current layout... From ff79f082d55eae281cb100bd3cac5727fd087625 Mon Sep 17 00:00:00 2001 From: David Heremans Date: Tue, 10 May 2022 17:44:57 +0200 Subject: [PATCH 28/63] Added PaletteView This is going to replace the PaletteDialog that is now called from the TileViewer and SpriteViewer, but was not yet used in the bitmapviewer... As soon as those viewers are adapted, we will remove the PaletteDialog --- src/DebuggerForm.cpp | 12 ++ src/DebuggerForm.h | 3 +- src/MSXPalette.cpp | 145 +++++++++++++++++ src/MSXPalette.h | 44 ++++++ src/PaletteDialog.cpp | 46 +----- src/PaletteDialog.h | 21 +-- src/PalettePatch.cpp | 63 ++++++++ src/PalettePatch.h | 34 ++++ src/PaletteView.cpp | 196 +++++++++++++++++++++++ src/PaletteView.h | 70 ++++++++ src/PaletteView.ui | 359 ++++++++++++++++++++++++++++++++++++++++++ src/VDPDataStore.cpp | 13 +- src/VDPDataStore.h | 12 ++ src/node.mk | 5 +- 14 files changed, 955 insertions(+), 68 deletions(-) create mode 100644 src/MSXPalette.cpp create mode 100644 src/MSXPalette.h create mode 100644 src/PalettePatch.cpp create mode 100644 src/PalettePatch.h create mode 100644 src/PaletteView.cpp create mode 100644 src/PaletteView.h create mode 100644 src/PaletteView.ui diff --git a/src/DebuggerForm.cpp b/src/DebuggerForm.cpp index c04c47b4..f40297a9 100644 --- a/src/DebuggerForm.cpp +++ b/src/DebuggerForm.cpp @@ -25,6 +25,7 @@ #include "blendsplitter/BlendSplitter.h" #include "blendsplitter/WidgetRegistry.h" #include "QuickGuide.h" +#include "PaletteView.h" #include "TabRenamerHelper.h" #include #include @@ -521,6 +522,12 @@ void DebuggerForm::createWidgetRegistry() [] { return widgetFactory(quickguide); }}; registry.addItem(item); registry.setDefault(item); + //15: register the palette editor + registry.addItem(new RegistryItem{ + tr("Palette editor"), + [] { return widgetFactory(paletteViewer); }}); + + } BlendSplitter* DebuggerForm::createWorkspaceCPU() @@ -817,6 +824,11 @@ QWidget* DebuggerForm::widgetFactory(factoryclasses fctwidget) case quickguide: wdgt = new QuickGuide(); break; + case paletteViewer: + wdgt = new PaletteView(); + connect(SignalDispatcher::getDispatcher(), SIGNAL(connected()), wdgt, SLOT(refresh())); + connect(SignalDispatcher::getDispatcher(), SIGNAL(breakStateEntered()), wdgt, SLOT(refresh())); + break; default: wdgt = new QLabel("Not yet implemented in widgetFactory!"); break; diff --git a/src/DebuggerForm.h b/src/DebuggerForm.h index 6b9d719a..efb4c106 100644 --- a/src/DebuggerForm.h +++ b/src/DebuggerForm.h @@ -50,7 +50,8 @@ class DebuggerForm : public QMainWindow tileViewer, spriteViewer, vdpRegisters, - quickguide + quickguide, + paletteViewer }; bool saveWorkspacesAs(const QString& newFileName); diff --git a/src/MSXPalette.cpp b/src/MSXPalette.cpp new file mode 100644 index 00000000..90e7a7f5 --- /dev/null +++ b/src/MSXPalette.cpp @@ -0,0 +1,145 @@ +#include "MSXPalette.h" +#include + +#include "CommClient.h" + +// static default MSX palette +const uint8_t MSXPalette::defaultPalette[32] = { +// RB G + 0x00, 0, + 0x00, 0, + 0x11, 6, + 0x33, 7, + 0x17, 1, + 0x27, 3, + 0x51, 1, + 0x27, 6, + 0x71, 1, + 0x73, 3, + 0x61, 6, + 0x64, 6, + 0x11, 4, + 0x65, 2, + 0x55, 5, + 0x77, 7, +}; + +MSXPalette::MSXPalette(QObject *parent) + : QObject{parent} +{ + memcpy(myPal,defaultPalette,sizeof(myPal)); + for (int i = 0; i < 16; ++i) { + setColor(i,myPal[2 *i]>>4,myPal[2 *i + 1],myPal[2 *i]&15); + }; +} + +MSXPalette &MSXPalette::operator=(const MSXPalette &source) +{ + memcpy(myPal, source.myPal, sizeof(myPal)); + memcpy(msxPalette, source.msxPalette, sizeof(msxPalette)); + emit paletteChanged(); + return *this; +} + +void MSXPalette::setPalette(uint8_t *pal) +{ + int palchanged=memcmp(myPal, pal, sizeof(myPal)); + sourcePal = pal; + if (palchanged != 0) { + for (int i = 0; i < 16; ++i) { + calculateColor(i,pal[2 *i]>>4,pal[2 *i + 1],pal[2 *i]&15); + }; + emit paletteChanged(); + } +} + +uint8_t *MSXPalette::getPalette() +{ + return myPal; +} + +void MSXPalette::syncToSource() +{ + if (sourcePal == nullptr) { + return; + } + memcpy(sourcePal, myPal, sizeof(myPal)); + + if (syncToMSX) { + syncToOpenMSX(); + } + emit paletteSynced(); +} + +void MSXPalette::syncToSource(int i) +{ + if (sourcePal == nullptr) { + return; + } + memcpy(sourcePal+2*i, myPal+2*i, 2); + if (syncToMSX) { + syncColorToOpenMSX(i); + } + emit paletteSynced(); + +} + +void MSXPalette::setAutoSync(bool value) +{ + if (autoSync == value){ + return; + } + autoSync = value; + if (value) { + syncToSource(); + } +} + +void MSXPalette::setColor(int i, int r, int g, int b) +{ + calculateColor(i,r,g,b); + emit paletteChanged(); + + if (autoSync) { + syncToSource(i); + } +} + +QRgb MSXPalette::color(int i) +{ + return msxPalette[std::clamp(i,0,15)]; +} + +void MSXPalette::calculateColor(int i, int r, int g, int b) +{ + i=std::clamp(i,0,15); //C++17 is nice :-) + r=std::clamp(r,0,7); + g=std::clamp(g,0,7); + b=std::clamp(b,0,7); + + myPal[2 * i + 0] = 16 * r + b; + myPal[2 * i + 1] = g; + + auto scale = [](int x) { return (x >> 1) | (x << 2) | (x << 5); }; + msxPalette[i] = qRgb(scale(r), scale(g), scale(b)); +} + +void MSXPalette::syncToOpenMSX() +{ + for (int i = 0; i < 16; ++i) { + syncColorToOpenMSX(i); + } +} + +void MSXPalette::syncColorToOpenMSX(int colornr) +{ + + CommClient::instance().sendCommand( + new SimpleCommand( + QString("setcolor %1 %2%3%4").arg(colornr) + .arg(myPal[2 *colornr]>>4) + .arg(myPal[2 *colornr +1]) + .arg(myPal[2 *colornr]&15) + )); +} + diff --git a/src/MSXPalette.h b/src/MSXPalette.h new file mode 100644 index 00000000..11b696e9 --- /dev/null +++ b/src/MSXPalette.h @@ -0,0 +1,44 @@ +#ifndef MSXPALETTE_H +#define MSXPALETTE_H + +#include +#include +#include + +class MSXPalette : public QObject +{ + Q_OBJECT +public: + explicit MSXPalette(QObject *parent = nullptr); + MSXPalette& operator=(const MSXPalette& source); + + void setPalette(uint8_t* pal); + uint8_t* getPalette(); + void syncToSource(); + void syncToSource(int i); + void setAutoSync(bool value); + + void setColor(int i, int r, int g, int b); + QRgb color(int i); + + bool syncToMSX = false; + +signals: + void paletteChanged(); + void paletteSynced(); + +private: + uint8_t* sourcePal = nullptr; + uint8_t myPal[32]; + + void calculateColor(int i, int r, int g, int b); + void syncToOpenMSX(); + void syncColorToOpenMSX(int colornr); + + QRgb msxPalette[16]; + bool autoSync = false; + + static const uint8_t defaultPalette[32]; +}; + +#endif // MSXPALETTE_H diff --git a/src/PaletteDialog.cpp b/src/PaletteDialog.cpp index 1bb19894..5cfe4487 100644 --- a/src/PaletteDialog.cpp +++ b/src/PaletteDialog.cpp @@ -3,51 +3,11 @@ #include #include #include "PaletteDialog.h" +#include "PalettePatch.h" #include "Convert.h" #include "ranges.h" -PalettePatch::PalettePatch(QWidget* parent, int palNr) - : QPushButton(parent), msxPalNr(palNr) -{ -} - -//void PalettePatch::setColor(QRgb c) -//{ -// myColor = c; -// update(); -//} - -void PalettePatch::updatePaletteChanged(const uint8_t* pal) -{ - int r = (pal[2 * msxPalNr + 0] & 0xf0) >> 4; - int b = (pal[2 * msxPalNr + 0] & 0x0f); - int g = (pal[2 * msxPalNr + 1] & 0x0f); - auto scale = [](int x) { return (x >> 1) | (x << 2) | (x << 5); }; - myColor = qRgb(scale(r), scale(g), scale(b)); - setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding)); - update(); - //printf("PalettePatch::updatePaletteChanged %i\n", msxPalNr); -} - -void PalettePatch::setHighlightTest(int colorNr) -{ - bool s = colorNr == msxPalNr; - if (isSelected == s) return; - isSelected = s; - update(); -} - -void PalettePatch::paintEvent(QPaintEvent* /*event*/) -{ - QPainter painter(this); - painter.setPen(isSelected ? Qt::white : QColor(myColor)); - painter.setBrush(QBrush(myColor)); - painter.drawRect(0, 0, this->width() - 1, this->height() - 1); -} - - - PaletteDialog::PaletteDialog(QWidget* parent) : QDialog(parent), ui(std::make_unique()) { @@ -68,8 +28,8 @@ PaletteDialog::PaletteDialog(QWidget* parent) connect(button, SIGNAL(clicked(bool)), signalMapper, SLOT(map())); signalMapper->setMapping(button, i); gridLayout->addWidget(button, i / 8, i % 8); - connect(this, SIGNAL(paletteChanged(uint8_t*)), - button, SLOT(updatePaletteChanged(uint8_t*))); + connect(this, SIGNAL(paletteChanged(const uint8_t*)), + button, SLOT(updatePaletteChanged(const uint8_t*))); connect(signalMapper, SIGNAL(mapped(int)), button, SLOT(setHighlightTest(int))); } diff --git a/src/PaletteDialog.h b/src/PaletteDialog.h index 20f9ac9f..76c58787 100644 --- a/src/PaletteDialog.h +++ b/src/PaletteDialog.h @@ -12,25 +12,6 @@ namespace Ui { class PaletteDialog; } -class PalettePatch: public QPushButton -{ - Q_OBJECT -public: - explicit PalettePatch(QWidget* parent = nullptr, int palNr = 0); - //void setColor(QRgb c); -public slots: - void updatePaletteChanged(const uint8_t* pal); - void setHighlightTest(int colorNr); - -protected: - void paintEvent(QPaintEvent* event) override; - -private: - QRgb myColor = Qt::green; - bool isSelected = false; - int msxPalNr; -}; - class PaletteDialog : public QDialog { @@ -45,7 +26,7 @@ class PaletteDialog : public QDialog void setAutoSync(bool value); signals: - void paletteChanged(uint8_t* pal); + void paletteChanged(const uint8_t* pal); void paletteSynced(); private slots: diff --git a/src/PalettePatch.cpp b/src/PalettePatch.cpp new file mode 100644 index 00000000..401faf89 --- /dev/null +++ b/src/PalettePatch.cpp @@ -0,0 +1,63 @@ +#include "PalettePatch.h" +#include +#include "MSXPalette.h" + +PalettePatch::PalettePatch(QWidget* parent, int palNr) + : QPushButton(parent), msxPalNr(palNr), mypal(nullptr) +{ + setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding)); + +} + +void PalettePatch::setMSXPalette(MSXPalette *pal) +{ + if (mypal != nullptr){ + disconnect(pal,SIGNAL(paletteChanged()), + this,SLOT(paletteChanged())); + } + mypal=pal; + connect(pal,SIGNAL(paletteChanged()), + this,SLOT(paletteChanged())); + paletteChanged(); +} + +//old method for PaletteDialog +void PalettePatch::updatePaletteChanged(const uint8_t* pal) +{ + int r = (pal[2 * msxPalNr + 0] & 0xf0) >> 4; + int b = (pal[2 * msxPalNr + 0] & 0x0f); + int g = (pal[2 * msxPalNr + 1] & 0x0f); + auto scale = [](int x) { return (x >> 1) | (x << 2) | (x << 5); }; + myColor = qRgb(scale(r), scale(g), scale(b)); + //setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding)); + update(); + //printf("PalettePatch::updatePaletteChanged %i\n", msxPalNr); +} +//new method for PaletteView +void PalettePatch::paletteChanged() +{ + myColor=mypal->color(msxPalNr); + update(); +} + +void PalettePatch::setHighlightTest(int colorNr) +{ + bool s = colorNr == msxPalNr; + if (isSelected == s) return; + isSelected = s; + update(); +} + +void PalettePatch::paintEvent(QPaintEvent* /*event*/) +{ + QPainter painter(this); + if (isEnabled()) { + painter.setPen(isSelected ? Qt::white : QColor(myColor)); + painter.setBrush(QBrush(myColor)); + } else { + painter.setPen(Qt::black); + int v = qGray(myColor); + painter.setBrush(QBrush(QColor(v,v,v))); + } + painter.drawRect(0, 0, this->width() - 1, this->height() - 1); +} diff --git a/src/PalettePatch.h b/src/PalettePatch.h new file mode 100644 index 00000000..4e1062c7 --- /dev/null +++ b/src/PalettePatch.h @@ -0,0 +1,34 @@ +#ifndef PALETTEPATCH_H +#define PALETTEPATCH_H + +#include +#include + +#include "MSXPalette.h" + +class PalettePatch : public QPushButton +{ + Q_OBJECT + +public: + explicit PalettePatch(QWidget *parent = nullptr, int palNr = 0); + //void setColor(QRgb c); + +public slots: + void setMSXPalette(MSXPalette* pal); + void updatePaletteChanged(const uint8_t* pal); + void setHighlightTest(int colorNr); + void paletteChanged(); + +protected: + void paintEvent(QPaintEvent* event) override; + +private: + QRgb myColor = Qt::green; + bool isSelected = false; + int msxPalNr; + MSXPalette* mypal; +}; + + +#endif // PALETTEPATCH_H diff --git a/src/PaletteView.cpp b/src/PaletteView.cpp new file mode 100644 index 00000000..e26fb3be --- /dev/null +++ b/src/PaletteView.cpp @@ -0,0 +1,196 @@ +#include "PaletteView.h" +#include "PalettePatch.h" +#include "VDPDataStore.h" + +#include "Convert.h" +#include "ui_PaletteView.h" +#include + +PaletteView::PaletteView(QWidget *parent) : + QWidget(parent), + ui(std::make_unique()),myPal(nullptr) +{ + ui->setupUi(this); + autoSync = ui->cb_autosync->isChecked(); + + const QFont fixedFont = QFontDatabase::systemFont(QFontDatabase::FixedFont); + ui->plainTextEdit->setFont(fixedFont); + + setPalette(VDPDataStore::instance().getPalette(0)); + + + signalMapper = new QSignalMapper(this); + auto* gridLayout = new QGridLayout; + gridLayout->setSpacing(0); + for (int i = 0; i < 16; ++i) { + auto* button = new PalettePatch(nullptr, i); + button->setMSXPalette(myPal); + connect(button, SIGNAL(clicked(bool)), signalMapper, SLOT(map())); + signalMapper->setMapping(button, i); + gridLayout->addWidget(button, i / 8, i % 8); + connect(this, SIGNAL(paletteReplaced(MSXPalette*)), + button, SLOT(setMSXPalette(MSXPalette*))); + connect(this, SIGNAL(paletteChanged()), + button, SLOT(paletteChanged())); + connect(signalMapper, SIGNAL(mapped(int)), + button, SLOT(setHighlightTest(int))); + } + + connect(signalMapper, SIGNAL(mapped(int)), + this, SLOT(colorSelected(int))); + + ui->colorsframe->setLayout(gridLayout); + connect(this, SIGNAL(paletteChanged()), + this, SLOT(updateText())); + updateText(); + + //select color 0 + emit signalMapper->mapped(0); +} + + +void PaletteView::setPalette(MSXPalette *sourcePal) +{ + if (myPal != nullptr){ + connect(myPal,SIGNAL(paletteChanged()), + this,SIGNAL(paletteChanged())); + }; + + myPal = sourcePal; + myOriginalPal = *sourcePal; + connect(myPal,SIGNAL(paletteChanged()), + this,SIGNAL(paletteChanged())); + emit paletteReplaced(sourcePal); +} + +MSXPalette *PaletteView::getPalette() +{ + return myPal; +} + +void PaletteView::syncToSource() +{ + myPal->syncToSource(); + myOriginalPal=*myPal; +} + +void PaletteView::setAutoSync(bool value) +{ + if (autoSync == value) return; + autoSync = value; + ui->cb_autosync->setChecked(value); + if (value) { + syncToSource(); + } +} + +void PaletteView::refresh() +{ + +} + +void PaletteView::colorSelected(int colorNumber) +{ + currentColor = colorNumber; + QRgb c = myPal->color(colorNumber); + ui->horizontalSlider_R->setValue(qRed(c)>>5); + ui->horizontalSlider_G->setValue(qGreen(c)>>5); + ui->horizontalSlider_B->setValue(qBlue(c)>>5); + ui->label_colornr->setText(QString("Color %1").arg(colorNumber)); +} + +void PaletteView::on_horizontalSlider_R_valueChanged(int value) +{ + ui->label_R->setText(QString("R=%1").arg(value)); + combineRGB(); +} + +void PaletteView::on_horizontalSlider_G_valueChanged(int value) +{ + ui->label_G->setText(QString("G=%1").arg(value)); + combineRGB(); +} + +void PaletteView::on_horizontalSlider_B_valueChanged(int value) +{ + ui->label_B->setText(QString("B=%1").arg(value)); + combineRGB(); +} + +void PaletteView::restorePalette() +{ + isDisplayUpdating=true; + *myPal=myOriginalPal; + colorSelected(currentColor); + isDisplayUpdating=false; +} + +void PaletteView::on_buttonBox_clicked(QAbstractButton *button) +{ + if (button == ui->buttonBox->button(QDialogButtonBox::Apply) || + button == ui->buttonBox->button(QDialogButtonBox::Ok)) { + syncToSource(); + } else if (button == ui->buttonBox->button(QDialogButtonBox::Reset) || + button == ui->buttonBox->button(QDialogButtonBox::Cancel)) { + restorePalette(); + } + +} + +void PaletteView::on_cb_autosync_stateChanged(int arg1) +{ + autoSync = arg1 != Qt::Unchecked; + if (autoSync) { + syncToSource(); + } +} + +void PaletteView::on_cbPalette_currentIndexChanged(int index) +{ + ui->pbCopyPaletteVDP->setEnabled(index!=0); + isDisplayUpdating=true; + setPalette(VDPDataStore::instance().getPalette(index)); + colorSelected(currentColor); + isDisplayUpdating=false; +} + +void PaletteView::on_pbCopyPaletteVDP_clicked() +{ + isDisplayUpdating=true; + *myPal = *VDPDataStore::instance().getPalette(0); // operator=() copies the byte and qrgb values + emit myPal->paletteChanged(); + isDisplayUpdating=false; +} + +void PaletteView::updateText() +{ + ui->plainTextEdit->clear(); + for (int i = 0; i < 4; ++i) { + QString txt(" db "); + for (int j = 0; j < 4; ++j) { + QRgb c = myPal->color(j + 4 * i); + txt.append(QString("%1,%2 ").arg( + hexValue((qRed(c)>>5)*16+(qBlue(c)>>5) , 2) , + hexValue((qGreen(c)>>5) , 2)) + ); + if (j < 3) txt.append(','); + } + ui->plainTextEdit->appendPlainText(txt); + } +} + +void PaletteView::combineRGB() +{ + if (isDisplayUpdating) { + return; + } + + int r = ui->horizontalSlider_R->value(); + int g = ui->horizontalSlider_G->value(); + int b = ui->horizontalSlider_B->value(); + myPal->setColor(currentColor,r,g,b); + emit paletteChanged(); + if (autoSync) { + syncToSource(); + } +} diff --git a/src/PaletteView.h b/src/PaletteView.h new file mode 100644 index 00000000..c33470a1 --- /dev/null +++ b/src/PaletteView.h @@ -0,0 +1,70 @@ +#ifndef PALETTEVIEW_H +#define PALETTEVIEW_H + +#include "ui_PaletteView.h" +#include +#include +#include +#include +#include "MSXPalette.h" + +class QAbstractButton; + +namespace Ui { +class PaletteView; +} + +class PaletteView : public QWidget +{ + Q_OBJECT + +public: + explicit PaletteView(QWidget *parent = nullptr); + + void setPalette(MSXPalette* sourcePal); + MSXPalette* getPalette(); + + void syncToSource(); + void setAutoSync(bool value); + +public slots: + void refresh(); + +signals: + void paletteReplaced(MSXPalette* sourcePal); + void paletteChanged(); + void paletteSynced(); + +private slots: + void colorSelected(int colorNumber); + void on_horizontalSlider_R_valueChanged(int value); + void on_horizontalSlider_G_valueChanged(int value); + void on_horizontalSlider_B_valueChanged(int value); + void restorePalette(); + + void on_buttonBox_clicked(QAbstractButton* button); + + void on_cb_autosync_stateChanged(int arg1); + void on_cbPalette_currentIndexChanged(int index); + void on_pbCopyPaletteVDP_clicked(); + + void updateText(); + + + +private: + std::unique_ptr ui; + QSignalMapper* signalMapper; + void combineRGB(); + + MSXPalette* myPal; + MSXPalette myOriginalPal; + + int currentColor = 0; + + bool autoSync = false; + bool isDisplayUpdating=false; + +}; + +#endif // PALETTEVIEW_H diff --git a/src/PaletteView.ui b/src/PaletteView.ui new file mode 100644 index 00000000..441d6570 --- /dev/null +++ b/src/PaletteView.ui @@ -0,0 +1,359 @@ + + + PaletteView + + + + 0 + 0 + 521 + 357 + + + + Form + + + + + + + + + 0 + 0 + + + + + 150 + 20 + + + + QFrame::StyledPanel + + + QFrame::Sunken + + + + + + + 0 + + + + + + + + 0 + 0 + + + + B=0 + + + + + + + + 0 + 0 + + + + G=0 + + + + + + + + 0 + 0 + + + + 7 + + + 1 + + + Qt::Horizontal + + + QSlider::TicksBothSides + + + + + + + + 0 + 0 + + + + R=0 + + + + + + + + 0 + 0 + + + + 7 + + + 1 + + + Qt::Horizontal + + + QSlider::TicksBothSides + + + + + + + + 0 + 0 + + + + 7 + + + 1 + + + Qt::Horizontal + + + QSlider::TicksBothSides + + + + + + + Color 0 + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + 0 + 0 + + + + + + + + + + Qt::Horizontal + + + + 0 + 0 + + + + + + + + + VDP palette + + + + + Sprite palette + + + + + Tileview palette + + + + + Bitmap palette + + + + + + + + false + + + Copy current VDP palette + + + + + + + Qt::Horizontal + + + + 0 + 0 + + + + + + + + + + + + View text + + + true + + + + + + + Qt::Horizontal + + + + 0 + 0 + + + + + + + + Qt::Horizontal + + + + 0 + 0 + + + + + + + + Autosync + + + true + + + + + + + false + + + + 0 + 0 + + + + Qt::Horizontal + + + QDialogButtonBox::Apply|QDialogButtonBox::Reset + + + + + + + + + + + cb_autosync + toggled(bool) + buttonBox + setDisabled(bool) + + + 58 + 273 + + + 439 + 273 + + + + + cb_viewtext + toggled(bool) + plainTextEdit + setVisible(bool) + + + 129 + 404 + + + 479 + 256 + + + + + diff --git a/src/VDPDataStore.cpp b/src/VDPDataStore.cpp index 1652b5dc..42c3aa7d 100644 --- a/src/VDPDataStore.cpp +++ b/src/VDPDataStore.cpp @@ -41,7 +41,7 @@ class VDPDataStoreVRAMSizeCheck : public SimpleCommand //printf("dataStore.vramSize %i\n",dataStore.vramSize); dataStore.vramSize = message.toInt(); //printf("dataStore.vramSize %i\n",dataStore.vramSize); - dataStore.refresh2(); + dataStore.refresh2(); delete this; } void replyNok(const QString& /*message*/) override @@ -100,6 +100,10 @@ void VDPDataStore::refresh2() void VDPDataStore::DataHexRequestReceived() { + //update MSXPalette that contains VDP palette + palettes[0].setPalette(&vram[vramSize]); + palettes[0].syncToMSX = true; //NO AUTOSYNC UNTIL WE GET THE PALETTE! + emit dataRefreshed(); } @@ -121,7 +125,12 @@ const uint8_t* VDPDataStore::getRegsPointer() const } const uint8_t* VDPDataStore::getVdpVramPointer() const { - return &vram[vramSize + 32 + 16 + 64]; + return &vram[vramSize + 32 + 16 + 64]; +} + +MSXPalette *VDPDataStore::getPalette(int index) +{ + return &palettes[index]; } size_t VDPDataStore::getVRAMSize() const diff --git a/src/VDPDataStore.h b/src/VDPDataStore.h index 1117679c..4b7778e0 100644 --- a/src/VDPDataStore.h +++ b/src/VDPDataStore.h @@ -8,6 +8,16 @@ #include #include +#include "MSXPalette.h" + +/** + * @brief The VDPDataStore class is a singleton that keeps track of all VDP related data for all the viewers + * + * It does keep track of the VRAM, registers, palettes and statusregisters + * For the viewers it keeps track of 4 palettes. + * The actual openMSX paletter, a pallete or the tileviewers, the bitmap viewers and the spriteviewers + * + */ class VDPDataStore : public QObject, public SimpleHexRequestUser { Q_OBJECT @@ -20,9 +30,11 @@ class VDPDataStore : public QObject, public SimpleHexRequestUser const uint8_t* getStatusRegsPointer() const; const uint8_t* getVdpVramPointer() const; + MSXPalette* getPalette(int index); size_t getVRAMSize() const; private: + MSXPalette palettes[4]; VDPDataStore(); void DataHexRequestReceived() override; diff --git a/src/node.mk b/src/node.mk index 24351ba0..0650e56c 100644 --- a/src/node.mk +++ b/src/node.mk @@ -18,7 +18,8 @@ MOC_SRC_HDR:= \ blendsplitter/WidgetRegistry blendsplitter/ExpanderCorner \ blendsplitter/RegistryItem \ blendsplitter/SplitterHandle blendsplitter/SwitchingCombo \ - blendsplitter/WidgetDecorator QuickGuide TabRenamerHelper + blendsplitter/WidgetDecorator QuickGuide TabRenamerHelper \ + PaletteView PalettePatch MSXPalette @@ -33,6 +34,6 @@ UI:= \ ConnectDialog SymbolManager PreferencesDialog BreakpointDialog \ BitMapViewer VDPStatusRegisters VDPRegistersExplained VDPCommandRegisters \ GotoDialog TileViewer PaletteDialog SpriteViewer BreakpointViewer \ - QuickGuide + QuickGuide PaletteView include build/node-end.mk From 249fb58ced6d71bf6f48b0b578aaeb62b319690d Mon Sep 17 00:00:00 2001 From: david Date: Wed, 11 May 2022 21:23:57 +0200 Subject: [PATCH 29/63] SlotLayout changes now handled by SignalDispatcher The code viewer now tracks the PC register again. Unfortunately the old code had some implicit assumptions about the order in which the signals arrived (hence the disasmStatus enum) For now the DisasmViewer::setProgramCounter is called twice with a different infoLine parameter, which may cause the code displayed to "jump up and down" during debugging --- src/DebuggerForm.cpp | 31 ++---------------- src/DebuggerForm.h | 6 +--- src/DisasmViewer.cpp | 2 ++ src/SignalDispatcher.cpp | 71 +++++++++++++++++++++++++++++++++++++--- src/SignalDispatcher.h | 12 +++++-- src/SlotViewer.cpp | 63 ++--------------------------------- src/SlotViewer.h | 4 +-- 7 files changed, 86 insertions(+), 103 deletions(-) diff --git a/src/DebuggerForm.cpp b/src/DebuggerForm.cpp index f40297a9..40c7467b 100644 --- a/src/DebuggerForm.cpp +++ b/src/DebuggerForm.cpp @@ -737,7 +737,7 @@ QWidget* DebuggerForm::widgetFactory(factoryclasses fctwidget) connect(SignalDispatcher::getDispatcher(), SIGNAL(symbolsChanged()), wdgt, SLOT(refresh())); connect(SignalDispatcher::getDispatcher(), SIGNAL(settingsChanged()), wdgt, SLOT(updateLayout())); connect(SignalDispatcher::getDispatcher(), SIGNAL(setCursorAddress(uint16_t, int, int)), wdgt, SLOT(setCursorAddress(uint16_t, int, int))); - connect(SignalDispatcher::getDispatcher(), SIGNAL(setProgramCounter(uint16_t, bool)), wdgt, SLOT(setProgramCounter(uint16_t, bool))); + connect(SignalDispatcher::getDispatcher(), SIGNAL(setProgramCounter(uint16_t,bool)), wdgt, SLOT(setProgramCounter(uint16_t,bool))); connect(SignalDispatcher::getDispatcher(), SIGNAL(breakpointsUpdated()), wdgt, SLOT(update())); static_cast(wdgt)->setMemory(SignalDispatcher::getDispatcher()->getMainMemory()); static_cast(wdgt)->setBreakpoints(&DebugSession::getDebugSession()->breakpoints()); @@ -782,12 +782,8 @@ QWidget* DebuggerForm::widgetFactory(factoryclasses fctwidget) wdgt = new SlotViewer(); connect(SignalDispatcher::getDispatcher(), SIGNAL(connected()), wdgt, SLOT(refresh())); connect(SignalDispatcher::getDispatcher(), SIGNAL(breakStateEntered()), wdgt, SLOT(refresh())); + connect(SignalDispatcher::getDispatcher(), SIGNAL(slotsUpdated(bool)), wdgt, SLOT(refresh())); static_cast(wdgt)->setMemoryLayout(SignalDispatcher::getDispatcher()->getMemLayout()); - connect(SignalDispatcher::getDispatcher(), SIGNAL(updateSlots(const QString&)), wdgt, SLOT(updateSlots(const QString&))); - // Received status update back from widget after breakStateEntered/connected - //TODO has to move to SignalDispatcher just as the register stuff!!!! -// connect(slotView, &SlotViewer::slotsUpdated, this, &DebuggerForm::onSlotsUpdated); - break; case breakpointViewer: wdgt = new BreakpointViewer(); @@ -1487,26 +1483,3 @@ void DebuggerForm::processMerge(const QString& message) } } -void DebuggerForm::onSlotsUpdated(bool slotsChanged) -{ - if (disasmStatus == PC_CHANGED) { - //disasmView->setProgramCounter(disasmAddress, slotsChanged); - SignalDispatcher::getDispatcher()->setProgramCounter(disasmAddress, slotsChanged); - disasmStatus = RESET; - } else { - disasmStatus = slotsChanged ? SLOTS_CHANGED : SLOTS_CHECKED; - } -} - -void DebuggerForm::onPCChanged(uint16_t address) -{ - // PC shouldn't update twice. - assert(disasmStatus != PC_CHANGED); - if (disasmStatus != RESET) { - //disasmView->setProgramCounter(address, disasmStatus == SLOTS_CHANGED); - SignalDispatcher::getDispatcher()->setProgramCounter(address, disasmStatus == SLOTS_CHANGED); - } else { - disasmStatus = PC_CHANGED; - disasmAddress = address; - } -} diff --git a/src/DebuggerForm.h b/src/DebuggerForm.h index efb4c106..75c05faa 100644 --- a/src/DebuggerForm.h +++ b/src/DebuggerForm.h @@ -33,7 +33,6 @@ class DebuggerForm : public QMainWindow void showAbout(); void reloadBreakpoints(bool merge = false); void onSlotsUpdated(bool slotsChanged); - void onPCChanged(uint16_t address); enum factoryclasses { disasmViewer, @@ -154,8 +153,7 @@ class DebuggerForm : public QMainWindow static QMap debuggables; static int counter; - enum {RESET = 0, SLOTS_CHECKED, PC_CHANGED, SLOTS_CHANGED} disasmStatus = RESET; - uint16_t disasmAddress; + uint16_t disasmAddress; void fileNewSession(); @@ -244,8 +242,6 @@ private slots: void addFloatingSwitchingWidget(); void addDefaultWorkspaces(); - - protected slots: void tabCloseRequest(int index); diff --git a/src/DisasmViewer.cpp b/src/DisasmViewer.cpp index 143cfa82..fa9b19dd 100644 --- a/src/DisasmViewer.cpp +++ b/src/DisasmViewer.cpp @@ -328,6 +328,7 @@ int DisasmViewer::findPosition(uint16_t addr, int infoLine, int method) void DisasmViewer::setAddress(uint16_t addr, int infoLine, int method) { + qDebug() << "void DisasmViewer::setAddress(uint16_t addr "<setProgramCounter(address, disasmStatus == SLOTS_CHANGED); + } else { + disasmStatus = PC_CHANGED; + } + emit setProgramCounter(regs[CpuRegs::REG_PC], disasmStatus == SLOTS_CHANGED); + +} + +void SignalDispatcher::updateSlots(const QString& message) +{ + QStringList lines = message.split('\n'); + bool changed = false; + + // parse page slots and segments + for (int p = 0; p < 4; ++p) { + bool subSlotted = (lines[p * 2][1] != 'X'); + slotsChanged[p] = (memLayout.primarySlot [p] != lines[p * 2][0].toLatin1()-'0') || + (memLayout.secondarySlot[p] != (subSlotted ? lines[p * 2][1].toLatin1() - '0' : -1)); + changed |= slotsChanged[p]; + memLayout.primarySlot [p] = lines[p * 2][0].toLatin1()-'0'; + memLayout.secondarySlot[p] = subSlotted + ? lines[p * 2][1].toLatin1() - '0' : -1; + segmentsChanged[p] = memLayout.mapperSegment[p] != + lines[p * 2 + 1].toInt(); + memLayout.mapperSegment[p] = lines[p * 2 + 1].toInt(); + } + // parse slot layout + int l = 8; + for (int ps = 0; ps < 4; ++ps) { + memLayout.isSubslotted[ps] = lines[l++][0] == '1'; + if (memLayout.isSubslotted[ps]) { + for (int ss = 0; ss < 4; ++ss) { + memLayout.mapperSize[ps][ss] = lines[l++].toUShort(); + } + } else { + memLayout.mapperSize[ps][0] = lines[l++].toUShort(); + } + } + // parse rom blocks + for (int i = 0; i < 8; ++i, ++l) { + if (lines[l][0] == 'X') + memLayout.romBlock[i] = -1; + else + memLayout.romBlock[i] = lines[l].toInt(); + } + + //signals to update disasmview + if (disasmStatus == PC_CHANGED) { + //disasmView->setProgramCounter(disasmAddress, slotsChanged); + emit setProgramCounter(regs[CpuRegs::REG_PC], changed); + disasmStatus = RESET; + } else { + disasmStatus = changed ? SLOTS_CHANGED : SLOTS_CHECKED; + } + + emit slotsUpdated(changed); + + } + + bool SignalDispatcher::getEnableWidget() { return isEnableWidget; diff --git a/src/SignalDispatcher.h b/src/SignalDispatcher.h index 4b05edb0..a5513b3d 100644 --- a/src/SignalDispatcher.h +++ b/src/SignalDispatcher.h @@ -39,6 +39,7 @@ class SignalDispatcher : public QObject public slots: void refresh(); void setEnableWidget(bool value); + void updateSlots(const QString& message); private: SignalDispatcher(); @@ -46,6 +47,7 @@ public slots: void setRegister(int id, int value); void getRegister(int id, unsigned char* data); + signals: void enableWidget(bool enable); void connected(); @@ -61,8 +63,8 @@ public slots: void pcChanged(uint16_t); void flagsChanged(quint8); void spChanged(quint16); - // signals concerning slotselection - void updateSlots(const QString& message); + // signals concerning slotselection + void slotsUpdated(bool slotsChanged); //signals from/for the diasmView void toggleBreakpoint(uint16_t adr); void breakpointToggled(uint16_t adr); @@ -82,6 +84,12 @@ public slots: bool regsModified[16]; bool regsChanged[16]; + //buffers to handle tracking of the slots layout + enum {RESET = 0, SLOTS_CHECKED, PC_CHANGED, SLOTS_CHANGED} disasmStatus = RESET; + bool slotsChanged[4]; + bool segmentsChanged[4]; + + bool isEnableWidget; }; diff --git a/src/SlotViewer.cpp b/src/SlotViewer.cpp index 5abcf843..3d3680b1 100644 --- a/src/SlotViewer.cpp +++ b/src/SlotViewer.cpp @@ -9,27 +9,6 @@ -class DebugMemMapperHandler : public SimpleCommand -{ -public: - DebugMemMapperHandler(SlotViewer& viewer_) - : SimpleCommand("debug_memmapper") - , viewer(viewer_) - { - } - - void replyOk(const QString& message) override - { - viewer.updateSlots(message); - SignalDispatcher::getDispatcher()->updateSlots(message); - delete this; - } - -private: - SlotViewer& viewer; -}; - - SlotViewer::SlotViewer(QWidget* parent) : QFrame(parent) { @@ -189,7 +168,8 @@ QSize SlotViewer::sizeHint() const void SlotViewer::refresh() { - CommClient::instance().sendCommand(new DebugMemMapperHandler(*this)); + //CommClient::instance().sendCommand(new DebugMemMapperHandler(*this)); + update(); } void SlotViewer::setMemoryLayout(MemoryLayout* ml) @@ -197,43 +177,4 @@ void SlotViewer::setMemoryLayout(MemoryLayout* ml) memLayout = ml; } -void SlotViewer::updateSlots(const QString& message) -{ - QStringList lines = message.split('\n'); - bool changed = false; - // parse page slots and segments - for (int p = 0; p < 4; ++p) { - bool subSlotted = (lines[p * 2][1] != 'X'); - slotsChanged[p] = (memLayout->primarySlot [p] != lines[p * 2][0].toLatin1()-'0') || - (memLayout->secondarySlot[p] != (subSlotted ? lines[p * 2][1].toLatin1() - '0' : -1)); - changed |= slotsChanged[p]; - memLayout->primarySlot [p] = lines[p * 2][0].toLatin1()-'0'; - memLayout->secondarySlot[p] = subSlotted - ? lines[p * 2][1].toLatin1() - '0' : -1; - segmentsChanged[p] = memLayout->mapperSegment[p] != - lines[p * 2 + 1].toInt(); - memLayout->mapperSegment[p] = lines[p * 2 + 1].toInt(); - } - // parse slot layout - int l = 8; - for (int ps = 0; ps < 4; ++ps) { - memLayout->isSubslotted[ps] = lines[l++][0] == '1'; - if (memLayout->isSubslotted[ps]) { - for (int ss = 0; ss < 4; ++ss) { - memLayout->mapperSize[ps][ss] = lines[l++].toUShort(); - } - } else { - memLayout->mapperSize[ps][0] = lines[l++].toUShort(); - } - } - // parse rom blocks - for (int i = 0; i < 8; ++i, ++l) { - if (lines[l][0] == 'X') - memLayout->romBlock[i] = -1; - else - memLayout->romBlock[i] = lines[l].toInt(); - } - update(); - emit slotsUpdated(changed); -} diff --git a/src/SlotViewer.h b/src/SlotViewer.h index 80efd20d..01b2ca6c 100644 --- a/src/SlotViewer.h +++ b/src/SlotViewer.h @@ -17,7 +17,7 @@ class SlotViewer : public QFrame QSize sizeHint() const override; public slots: - void updateSlots(const QString& message); +// void updateSlots(const QString& message); void refresh(); private: @@ -34,7 +34,7 @@ public slots: bool segmentsChanged[4]; signals: - void slotsUpdated(bool slotsChanged); +// void slotsUpdated(bool slotsChanged); void contentsChanged(); }; From 7e025bde9b49f0e4cad9dbd2a82c423fdee99c18 Mon Sep 17 00:00:00 2001 From: m9710797 Date: Thu, 12 May 2022 19:27:54 +0200 Subject: [PATCH 30/63] layout fixes --- src/DebuggerForm.cpp | 6 ++-- src/MSXPalette.cpp | 61 ++++++++++++++++++---------------------- src/MSXPalette.h | 14 ++++----- src/PalettePatch.cpp | 22 +++++++-------- src/PalettePatch.h | 8 ++---- src/PaletteView.cpp | 60 ++++++++++++++++----------------------- src/PaletteView.h | 15 ++++------ src/SignalDispatcher.cpp | 34 +++++++++------------- src/SignalDispatcher.h | 8 ++---- src/SlotViewer.cpp | 10 ++----- src/SlotViewer.h | 3 +- src/VDPDataStore.cpp | 8 +++--- src/VDPDataStore.h | 12 ++++---- 13 files changed, 112 insertions(+), 149 deletions(-) diff --git a/src/DebuggerForm.cpp b/src/DebuggerForm.cpp index 40c7467b..772df30a 100644 --- a/src/DebuggerForm.cpp +++ b/src/DebuggerForm.cpp @@ -522,12 +522,11 @@ void DebuggerForm::createWidgetRegistry() [] { return widgetFactory(quickguide); }}; registry.addItem(item); registry.setDefault(item); + //15: register the palette editor registry.addItem(new RegistryItem{ tr("Palette editor"), [] { return widgetFactory(paletteViewer); }}); - - } BlendSplitter* DebuggerForm::createWorkspaceCPU() @@ -828,7 +827,7 @@ QWidget* DebuggerForm::widgetFactory(factoryclasses fctwidget) default: wdgt = new QLabel("Not yet implemented in widgetFactory!"); break; - }; + } return wdgt; } @@ -1482,4 +1481,3 @@ void DebuggerForm::processMerge(const QString& message) processBreakpoints(message); } } - diff --git a/src/MSXPalette.cpp b/src/MSXPalette.cpp index 90e7a7f5..180a3a5f 100644 --- a/src/MSXPalette.cpp +++ b/src/MSXPalette.cpp @@ -1,10 +1,9 @@ #include "MSXPalette.h" -#include - #include "CommClient.h" +#include -// static default MSX palette -const uint8_t MSXPalette::defaultPalette[32] = { +// default MSX palette +static const uint8_t defaultPalette[32] = { // RB G 0x00, 0, 0x00, 0, @@ -24,16 +23,16 @@ const uint8_t MSXPalette::defaultPalette[32] = { 0x77, 7, }; -MSXPalette::MSXPalette(QObject *parent) +MSXPalette::MSXPalette(QObject* parent) : QObject{parent} { - memcpy(myPal,defaultPalette,sizeof(myPal)); + memcpy(myPal, defaultPalette, sizeof(myPal)); for (int i = 0; i < 16; ++i) { - setColor(i,myPal[2 *i]>>4,myPal[2 *i + 1],myPal[2 *i]&15); - }; + setColor(i, myPal[2 * i] >> 4, myPal[2 * i + 1], myPal[2 * i] & 15); + } } -MSXPalette &MSXPalette::operator=(const MSXPalette &source) +MSXPalette& MSXPalette::operator=(const MSXPalette& source) { memcpy(myPal, source.myPal, sizeof(myPal)); memcpy(msxPalette, source.msxPalette, sizeof(msxPalette)); @@ -41,19 +40,19 @@ MSXPalette &MSXPalette::operator=(const MSXPalette &source) return *this; } -void MSXPalette::setPalette(uint8_t *pal) +void MSXPalette::setPalette(uint8_t* pal) { - int palchanged=memcmp(myPal, pal, sizeof(myPal)); + int palchanged = memcmp(myPal, pal, sizeof(myPal)); sourcePal = pal; if (palchanged != 0) { for (int i = 0; i < 16; ++i) { - calculateColor(i,pal[2 *i]>>4,pal[2 *i + 1],pal[2 *i]&15); - }; + calculateColor(i, pal[2 * i] >> 4, pal[2 * i + 1], pal[2 * i] & 15); + } emit paletteChanged(); } } -uint8_t *MSXPalette::getPalette() +uint8_t* MSXPalette::getPalette() { return myPal; } @@ -76,46 +75,45 @@ void MSXPalette::syncToSource(int i) if (sourcePal == nullptr) { return; } - memcpy(sourcePal+2*i, myPal+2*i, 2); + memcpy(sourcePal + 2 * i, myPal + 2 * i, 2); if (syncToMSX) { syncColorToOpenMSX(i); } emit paletteSynced(); - } void MSXPalette::setAutoSync(bool value) { - if (autoSync == value){ + if (autoSync == value) { return; } autoSync = value; if (value) { - syncToSource(); + syncToSource(); } } void MSXPalette::setColor(int i, int r, int g, int b) { - calculateColor(i,r,g,b); + calculateColor(i, r, g, b); emit paletteChanged(); - if (autoSync) { + if (autoSync) { syncToSource(i); } } QRgb MSXPalette::color(int i) { - return msxPalette[std::clamp(i,0,15)]; + return msxPalette[std::clamp(i, 0, 15)]; } void MSXPalette::calculateColor(int i, int r, int g, int b) { - i=std::clamp(i,0,15); //C++17 is nice :-) - r=std::clamp(r,0,7); - g=std::clamp(g,0,7); - b=std::clamp(b,0,7); + i = std::clamp(i, 0, 15); + r = std::clamp(r, 0, 7); + g = std::clamp(g, 0, 7); + b = std::clamp(b, 0, 7); myPal[2 * i + 0] = 16 * r + b; myPal[2 * i + 1] = g; @@ -131,15 +129,12 @@ void MSXPalette::syncToOpenMSX() } } -void MSXPalette::syncColorToOpenMSX(int colornr) +void MSXPalette::syncColorToOpenMSX(int colorNr) { - CommClient::instance().sendCommand( new SimpleCommand( - QString("setcolor %1 %2%3%4").arg(colornr) - .arg(myPal[2 *colornr]>>4) - .arg(myPal[2 *colornr +1]) - .arg(myPal[2 *colornr]&15) - )); + QString("setcolor %1 %2%3%4").arg(colorNr) + .arg(myPal[2 * colorNr] >> 4) + .arg(myPal[2 * colorNr + 1]) + .arg(myPal[2 * colorNr] & 15))); } - diff --git a/src/MSXPalette.h b/src/MSXPalette.h index 11b696e9..d7cfe414 100644 --- a/src/MSXPalette.h +++ b/src/MSXPalette.h @@ -9,7 +9,7 @@ class MSXPalette : public QObject { Q_OBJECT public: - explicit MSXPalette(QObject *parent = nullptr); + explicit MSXPalette(QObject* parent = nullptr); MSXPalette& operator=(const MSXPalette& source); void setPalette(uint8_t* pal); @@ -21,24 +21,22 @@ class MSXPalette : public QObject void setColor(int i, int r, int g, int b); QRgb color(int i); - bool syncToMSX = false; + bool syncToMSX = false; // TODO avoid public data members signals: void paletteChanged(); void paletteSynced(); private: - uint8_t* sourcePal = nullptr; - uint8_t myPal[32]; - void calculateColor(int i, int r, int g, int b); void syncToOpenMSX(); - void syncColorToOpenMSX(int colornr); + void syncColorToOpenMSX(int colorNr); +private: + uint8_t* sourcePal = nullptr; + uint8_t myPal[32]; QRgb msxPalette[16]; bool autoSync = false; - - static const uint8_t defaultPalette[32]; }; #endif // MSXPALETTE_H diff --git a/src/PalettePatch.cpp b/src/PalettePatch.cpp index 401faf89..8b3ff2b9 100644 --- a/src/PalettePatch.cpp +++ b/src/PalettePatch.cpp @@ -3,21 +3,20 @@ #include "MSXPalette.h" PalettePatch::PalettePatch(QWidget* parent, int palNr) - : QPushButton(parent), msxPalNr(palNr), mypal(nullptr) + : QPushButton(parent), msxPalNr(palNr) { setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding)); - } -void PalettePatch::setMSXPalette(MSXPalette *pal) +void PalettePatch::setMSXPalette(MSXPalette* pal) { - if (mypal != nullptr){ - disconnect(pal,SIGNAL(paletteChanged()), - this,SLOT(paletteChanged())); + if (myPal != nullptr) { + disconnect(pal, SIGNAL(paletteChanged()), + this, SLOT(paletteChanged())); } - mypal=pal; - connect(pal,SIGNAL(paletteChanged()), - this,SLOT(paletteChanged())); + myPal = pal; + connect(pal, SIGNAL(paletteChanged()), + this, SLOT(paletteChanged())); paletteChanged(); } @@ -33,10 +32,11 @@ void PalettePatch::updatePaletteChanged(const uint8_t* pal) update(); //printf("PalettePatch::updatePaletteChanged %i\n", msxPalNr); } + //new method for PaletteView void PalettePatch::paletteChanged() { - myColor=mypal->color(msxPalNr); + myColor = myPal->color(msxPalNr); update(); } @@ -57,7 +57,7 @@ void PalettePatch::paintEvent(QPaintEvent* /*event*/) } else { painter.setPen(Qt::black); int v = qGray(myColor); - painter.setBrush(QBrush(QColor(v,v,v))); + painter.setBrush(QBrush(QColor(v, v, v))); } painter.drawRect(0, 0, this->width() - 1, this->height() - 1); } diff --git a/src/PalettePatch.h b/src/PalettePatch.h index 4e1062c7..a5857100 100644 --- a/src/PalettePatch.h +++ b/src/PalettePatch.h @@ -2,16 +2,15 @@ #define PALETTEPATCH_H #include -#include - #include "MSXPalette.h" +#include class PalettePatch : public QPushButton { Q_OBJECT public: - explicit PalettePatch(QWidget *parent = nullptr, int palNr = 0); + explicit PalettePatch(QWidget* parent = nullptr, int palNr = 0); //void setColor(QRgb c); public slots: @@ -27,8 +26,7 @@ public slots: QRgb myColor = Qt::green; bool isSelected = false; int msxPalNr; - MSXPalette* mypal; + MSXPalette* myPal = nullptr; }; - #endif // PALETTEPATCH_H diff --git a/src/PaletteView.cpp b/src/PaletteView.cpp index e26fb3be..b0c49fd3 100644 --- a/src/PaletteView.cpp +++ b/src/PaletteView.cpp @@ -1,14 +1,14 @@ #include "PaletteView.h" #include "PalettePatch.h" #include "VDPDataStore.h" - #include "Convert.h" +#include "ScopedAssign.h" #include "ui_PaletteView.h" #include -PaletteView::PaletteView(QWidget *parent) : - QWidget(parent), - ui(std::make_unique()),myPal(nullptr) +PaletteView::PaletteView(QWidget* parent) + : QWidget(parent) + , ui(std::make_unique()) { ui->setupUi(this); autoSync = ui->cb_autosync->isChecked(); @@ -18,7 +18,6 @@ PaletteView::PaletteView(QWidget *parent) : setPalette(VDPDataStore::instance().getPalette(0)); - signalMapper = new QSignalMapper(this); auto* gridLayout = new QGridLayout; gridLayout->setSpacing(0); @@ -48,22 +47,21 @@ PaletteView::PaletteView(QWidget *parent) : emit signalMapper->mapped(0); } - -void PaletteView::setPalette(MSXPalette *sourcePal) +void PaletteView::setPalette(MSXPalette* sourcePal) { - if (myPal != nullptr){ - connect(myPal,SIGNAL(paletteChanged()), - this,SIGNAL(paletteChanged())); - }; + if (myPal != nullptr) { + connect(myPal, SIGNAL(paletteChanged()), + this, SIGNAL(paletteChanged())); + } myPal = sourcePal; myOriginalPal = *sourcePal; - connect(myPal,SIGNAL(paletteChanged()), - this,SIGNAL(paletteChanged())); + connect(myPal, SIGNAL(paletteChanged()), + this, SIGNAL(paletteChanged())); emit paletteReplaced(sourcePal); } -MSXPalette *PaletteView::getPalette() +MSXPalette* PaletteView::getPalette() { return myPal; } @@ -71,7 +69,7 @@ MSXPalette *PaletteView::getPalette() void PaletteView::syncToSource() { myPal->syncToSource(); - myOriginalPal=*myPal; + myOriginalPal = *myPal; } void PaletteView::setAutoSync(bool value) @@ -86,16 +84,15 @@ void PaletteView::setAutoSync(bool value) void PaletteView::refresh() { - } void PaletteView::colorSelected(int colorNumber) { currentColor = colorNumber; QRgb c = myPal->color(colorNumber); - ui->horizontalSlider_R->setValue(qRed(c)>>5); - ui->horizontalSlider_G->setValue(qGreen(c)>>5); - ui->horizontalSlider_B->setValue(qBlue(c)>>5); + ui->horizontalSlider_R->setValue(qRed (c) >> 5); + ui->horizontalSlider_G->setValue(qGreen(c) >> 5); + ui->horizontalSlider_B->setValue(qBlue (c) >> 5); ui->label_colornr->setText(QString("Color %1").arg(colorNumber)); } @@ -119,10 +116,9 @@ void PaletteView::on_horizontalSlider_B_valueChanged(int value) void PaletteView::restorePalette() { - isDisplayUpdating=true; - *myPal=myOriginalPal; + ScopedAssign sa(isDisplayUpdating, true); + *myPal = myOriginalPal; colorSelected(currentColor); - isDisplayUpdating=false; } void PaletteView::on_buttonBox_clicked(QAbstractButton *button) @@ -134,7 +130,6 @@ void PaletteView::on_buttonBox_clicked(QAbstractButton *button) button == ui->buttonBox->button(QDialogButtonBox::Cancel)) { restorePalette(); } - } void PaletteView::on_cb_autosync_stateChanged(int arg1) @@ -147,19 +142,17 @@ void PaletteView::on_cb_autosync_stateChanged(int arg1) void PaletteView::on_cbPalette_currentIndexChanged(int index) { - ui->pbCopyPaletteVDP->setEnabled(index!=0); - isDisplayUpdating=true; + ui->pbCopyPaletteVDP->setEnabled(index != 0); + ScopedAssign sa(isDisplayUpdating, true); setPalette(VDPDataStore::instance().getPalette(index)); colorSelected(currentColor); - isDisplayUpdating=false; } void PaletteView::on_pbCopyPaletteVDP_clicked() { - isDisplayUpdating=true; - *myPal = *VDPDataStore::instance().getPalette(0); // operator=() copies the byte and qrgb values + ScopedAssign sa(isDisplayUpdating, true); + *myPal = *VDPDataStore::instance().getPalette(0); // operator=() copies the byte and qRgb values emit myPal->paletteChanged(); - isDisplayUpdating=false; } void PaletteView::updateText() @@ -170,9 +163,8 @@ void PaletteView::updateText() for (int j = 0; j < 4; ++j) { QRgb c = myPal->color(j + 4 * i); txt.append(QString("%1,%2 ").arg( - hexValue((qRed(c)>>5)*16+(qBlue(c)>>5) , 2) , - hexValue((qGreen(c)>>5) , 2)) - ); + hexValue((qRed (c) >> 5) * 16 + (qBlue(c) >> 5), 2), + hexValue((qGreen(c) >> 5), 2))); if (j < 3) txt.append(','); } ui->plainTextEdit->appendPlainText(txt); @@ -181,9 +173,7 @@ void PaletteView::updateText() void PaletteView::combineRGB() { - if (isDisplayUpdating) { - return; - } + if (isDisplayUpdating) return; int r = ui->horizontalSlider_R->value(); int g = ui->horizontalSlider_G->value(); diff --git a/src/PaletteView.h b/src/PaletteView.h index c33470a1..e7d9e823 100644 --- a/src/PaletteView.h +++ b/src/PaletteView.h @@ -2,16 +2,16 @@ #define PALETTEVIEW_H #include "ui_PaletteView.h" +#include "MSXPalette.h" #include +#include #include #include -#include -#include "MSXPalette.h" class QAbstractButton; namespace Ui { -class PaletteView; + class PaletteView; } class PaletteView : public QWidget @@ -19,7 +19,7 @@ class PaletteView : public QWidget Q_OBJECT public: - explicit PaletteView(QWidget *parent = nullptr); + explicit PaletteView(QWidget* parent = nullptr); void setPalette(MSXPalette* sourcePal); MSXPalette* getPalette(); @@ -50,21 +50,18 @@ private slots: void updateText(); - - private: std::unique_ptr ui; QSignalMapper* signalMapper; void combineRGB(); - MSXPalette* myPal; + MSXPalette* myPal = nullptr; MSXPalette myOriginalPal; int currentColor = 0; bool autoSync = false; - bool isDisplayUpdating=false; - + bool isDisplayUpdating = false; }; #endif // PALETTEVIEW_H diff --git a/src/SignalDispatcher.cpp b/src/SignalDispatcher.cpp index 478a5e71..ce3df2f8 100644 --- a/src/SignalDispatcher.cpp +++ b/src/SignalDispatcher.cpp @@ -17,17 +17,18 @@ class DispatchDebugMemMapperHandler : public SimpleCommand dispatcher.updateSlots(message); delete this; } + private: SignalDispatcher& dispatcher; }; -SignalDispatcher* SignalDispatcher::theDispatcher=nullptr; +SignalDispatcher* SignalDispatcher::theDispatcher = nullptr; SignalDispatcher* SignalDispatcher::getDispatcher() { - if (theDispatcher==nullptr) { + if (theDispatcher == nullptr) { theDispatcher = new SignalDispatcher{}; - }; + } return theDispatcher; } @@ -36,9 +37,6 @@ SignalDispatcher::~SignalDispatcher() delete[] mainMemory; } - - - unsigned char *SignalDispatcher::getMainMemory() { return mainMemory; @@ -87,7 +85,6 @@ void SignalDispatcher::setData(unsigned char *datPtr) disasmStatus = PC_CHANGED; } emit setProgramCounter(regs[CpuRegs::REG_PC], disasmStatus == SLOTS_CHANGED); - } void SignalDispatcher::updateSlots(const QString& message) @@ -122,10 +119,11 @@ void SignalDispatcher::updateSlots(const QString& message) } // parse rom blocks for (int i = 0; i < 8; ++i, ++l) { - if (lines[l][0] == 'X') + if (lines[l][0] == 'X') { memLayout.romBlock[i] = -1; - else + } else { memLayout.romBlock[i] = lines[l].toInt(); + } } //signals to update disasmview @@ -138,12 +136,8 @@ void SignalDispatcher::updateSlots(const QString& message) } emit slotsUpdated(changed); - - } - - bool SignalDispatcher::getEnableWidget() { return isEnableWidget; @@ -153,13 +147,12 @@ void SignalDispatcher::refresh() { CommClient::instance().sendCommand(new DispatchDebugMemMapperHandler(*this)); VDPDataStore::instance().refresh(); - } void SignalDispatcher::setEnableWidget(bool value) { - if (isEnableWidget != value){ - isEnableWidget=value; + if (isEnableWidget != value) { + isEnableWidget = value; emit enableWidget(value); } } @@ -169,7 +162,8 @@ int SignalDispatcher::readRegister(int id) return regs[id]; } -SignalDispatcher::SignalDispatcher(): isEnableWidget(false) { +SignalDispatcher::SignalDispatcher() +{ // avoid UMR memset(®s, 0, sizeof(regs)); memset(®sChanged, 0, sizeof(regsChanged)); @@ -177,10 +171,9 @@ SignalDispatcher::SignalDispatcher(): isEnableWidget(false) { // init main memory // added four bytes as runover buffer for dasm - // otherwise dasm would need to check the buffer end continously. + // otherwise dasm would need to check the buffer end continuously. mainMemory = new unsigned char[65536 + 4]; memset(mainMemory, 0, 65536 + 4); - } void SignalDispatcher::setRegister(int id, int value) @@ -192,9 +185,8 @@ void SignalDispatcher::setRegister(int id, int value) } } -void SignalDispatcher::getRegister(int id, unsigned char *data) +void SignalDispatcher::getRegister(int id, unsigned char* data) { data[0] = regs[id] >> 8; data[1] = regs[id] & 255; } - diff --git a/src/SignalDispatcher.h b/src/SignalDispatcher.h index a5513b3d..ec433276 100644 --- a/src/SignalDispatcher.h +++ b/src/SignalDispatcher.h @@ -47,7 +47,6 @@ public slots: void setRegister(int id, int value); void getRegister(int id, unsigned char* data); - signals: void enableWidget(bool enable); void connected(); @@ -63,9 +62,9 @@ public slots: void pcChanged(uint16_t); void flagsChanged(quint8); void spChanged(quint16); - // signals concerning slotselection + // signals concerning slotselection void slotsUpdated(bool slotsChanged); - //signals from/for the diasmView + //signals from/for the disasmView void toggleBreakpoint(uint16_t adr); void breakpointToggled(uint16_t adr); void setProgramCounter(uint16_t pc, bool reload = false); @@ -89,8 +88,7 @@ public slots: bool slotsChanged[4]; bool segmentsChanged[4]; - - bool isEnableWidget; + bool isEnableWidget = false; }; #endif diff --git a/src/SlotViewer.cpp b/src/SlotViewer.cpp index 3d3680b1..83e3a32d 100644 --- a/src/SlotViewer.cpp +++ b/src/SlotViewer.cpp @@ -7,8 +7,6 @@ #include #include - - SlotViewer::SlotViewer(QWidget* parent) : QFrame(parent) { @@ -163,18 +161,16 @@ void SlotViewer::paintEvent(QPaintEvent* e) QSize SlotViewer::sizeHint() const { return {headerSize1 + headerSize2 + headerSize3 + headerSize4 + frameL + frameR, - headerHeight + 4*fontMetrics().height()}; + headerHeight + 4 * fontMetrics().height()}; } void SlotViewer::refresh() { - //CommClient::instance().sendCommand(new DebugMemMapperHandler(*this)); - update(); + //CommClient::instance().sendCommand(new DebugMemMapperHandler(*this)); + update(); } void SlotViewer::setMemoryLayout(MemoryLayout* ml) { memLayout = ml; } - - diff --git a/src/SlotViewer.h b/src/SlotViewer.h index 01b2ca6c..168eb806 100644 --- a/src/SlotViewer.h +++ b/src/SlotViewer.h @@ -17,13 +17,14 @@ class SlotViewer : public QFrame QSize sizeHint() const override; public slots: -// void updateSlots(const QString& message); + //void updateSlots(const QString& message); void refresh(); private: void resizeEvent(QResizeEvent* e) override; void paintEvent(QPaintEvent* e) override; +private: int frameL, frameR, frameT, frameB; int headerSize1, headerSize2, headerSize3, headerSize4; int headerHeight; diff --git a/src/VDPDataStore.cpp b/src/VDPDataStore.cpp index 42c3aa7d..b3ddab81 100644 --- a/src/VDPDataStore.cpp +++ b/src/VDPDataStore.cpp @@ -100,9 +100,9 @@ void VDPDataStore::refresh2() void VDPDataStore::DataHexRequestReceived() { - //update MSXPalette that contains VDP palette - palettes[0].setPalette(&vram[vramSize]); - palettes[0].syncToMSX = true; //NO AUTOSYNC UNTIL WE GET THE PALETTE! + //update MSXPalette that contains VDP palette + palettes[0].setPalette(&vram[vramSize]); + palettes[0].syncToMSX = true; //NO AUTOSYNC UNTIL WE GET THE PALETTE! emit dataRefreshed(); } @@ -128,7 +128,7 @@ const uint8_t* VDPDataStore::getVdpVramPointer() const return &vram[vramSize + 32 + 16 + 64]; } -MSXPalette *VDPDataStore::getPalette(int index) +MSXPalette* VDPDataStore::getPalette(int index) { return &palettes[index]; } diff --git a/src/VDPDataStore.h b/src/VDPDataStore.h index 4b7778e0..b1231b88 100644 --- a/src/VDPDataStore.h +++ b/src/VDPDataStore.h @@ -1,6 +1,7 @@ #ifndef VDPDATASTORE_H #define VDPDATASTORE_H +#include "MSXPalette.h" #include "SimpleHexRequest.h" #include #include @@ -8,15 +9,12 @@ #include #include -#include "MSXPalette.h" - /** * @brief The VDPDataStore class is a singleton that keeps track of all VDP related data for all the viewers * * It does keep track of the VRAM, registers, palettes and statusregisters * For the viewers it keeps track of 4 palettes. - * The actual openMSX paletter, a pallete or the tileviewers, the bitmap viewers and the spriteviewers - * + * The actual openMSX palette, a palette or the tileviewers, the bitmap viewers and the spriteviewers */ class VDPDataStore : public QObject, public SimpleHexRequestUser { @@ -30,11 +28,10 @@ class VDPDataStore : public QObject, public SimpleHexRequestUser const uint8_t* getStatusRegsPointer() const; const uint8_t* getVdpVramPointer() const; - MSXPalette* getPalette(int index); + MSXPalette* getPalette(int index); size_t getVRAMSize() const; private: - MSXPalette palettes[4]; VDPDataStore(); void DataHexRequestReceived() override; @@ -42,6 +39,9 @@ class VDPDataStore : public QObject, public SimpleHexRequestUser void refresh1(); void refresh2(); +private: + MSXPalette palettes[4]; + std::vector vram; size_t vramSize; From 749f07c591b2e5a3a7492dfc3dd8a3403bfcfc7f Mon Sep 17 00:00:00 2001 From: m9710797 Date: Thu, 12 May 2022 19:54:54 +0200 Subject: [PATCH 31/63] Cleanup singleton implementation of SignalDispatcher --- src/DebuggerForm.cpp | 162 ++++++++++++++-------------- src/DebuggerForm.h | 119 ++++++++++---------- src/MainMemoryViewer.cpp | 8 +- src/SignalDispatcher.cpp | 44 ++++---- src/SignalDispatcher.h | 18 ++-- src/blendsplitter/BlendSplitter.cpp | 5 +- 6 files changed, 175 insertions(+), 181 deletions(-) diff --git a/src/DebuggerForm.cpp b/src/DebuggerForm.cpp index 772df30a..9e9af2b0 100644 --- a/src/DebuggerForm.cpp +++ b/src/DebuggerForm.cpp @@ -97,21 +97,21 @@ class QueryBreakedHandler : public SimpleCommand class CPURegRequest : public ReadDebugBlockCommand { public: - CPURegRequest(DebuggerForm& /*form_*/) + CPURegRequest(DebuggerForm& /*form_*/) : ReadDebugBlockCommand("{CPU regs}", 0, 28, buf) -// , form(form_) + //, form(form_) { } void replyOk(const QString& message) override { copyData(message); - SignalDispatcher::getDispatcher()->setData(buf); + SignalDispatcher::instance().setData(buf); delete this; } private: -// DebuggerForm& form; + //DebuggerForm& form; unsigned char buf[28]; }; @@ -631,17 +631,18 @@ void DebuggerForm::addEmptyWorkspace() void DebuggerForm::addFloatingSwitchingWidget() { + auto& dispatcher = SignalDispatcher::instance(); auto* wdg = new SwitchingWidget(); - connect(SignalDispatcher::getDispatcher(), SIGNAL(enableWidget(bool)), wdg, SLOT(setEnableWidget(bool))); - wdg->setEnableWidget(SignalDispatcher::getDispatcher()->getEnableWidget()); + connect(&dispatcher, SIGNAL(enableWidget(bool)), wdg, SLOT(setEnableWidget(bool))); + wdg->setEnableWidget(dispatcher.getEnableWidget()); wdg->show(); } void DebuggerForm::createForm() { - updateWindowTitle(); + updateWindowTitle(); - createWidgetRegistry(); + createWidgetRegistry(); workspaces = new QTabWidget(); tabRenamer = new TabRenamerHelper{workspaces}; @@ -661,7 +662,6 @@ void DebuggerForm::createForm() workspacemenu->addSeparator(); workspacemenu->addAction(addFloatingSwitchingWidgetAction); - QIcon icon = QIcon::fromTheme(QLatin1String("window-new")); QToolButton *btn = new QToolButton(); btn->setIcon(icon); @@ -690,29 +690,29 @@ void DebuggerForm::createForm() addDefaultWorkspaces(); } break; - }; + } setCentralWidget(window); - //have the SignalDispatcher refresh it data for the widgets in the blendsplitter - connect(this, SIGNAL(connected()), SignalDispatcher::getDispatcher(), SLOT(refresh())); - connect(this, SIGNAL(breakStateEntered()), SignalDispatcher::getDispatcher(), SLOT(refresh())); + // Have the SignalDispatcher refresh it data for the widgets in the blendsplitter + auto& dispatcher = SignalDispatcher::instance(); + connect(this, SIGNAL(connected()), &dispatcher, SLOT(refresh())); + connect(this, SIGNAL(breakStateEntered()), &dispatcher, SLOT(refresh())); //and have it propagate the signals - connect(this, SIGNAL(connected()), SignalDispatcher::getDispatcher(), SIGNAL(connected())); - connect(this, SIGNAL(breakStateEntered()), SignalDispatcher::getDispatcher(), SIGNAL(breakStateEntered())); + connect(this, SIGNAL(connected()), &dispatcher, SIGNAL(connected())); + connect(this, SIGNAL(breakStateEntered()), &dispatcher, SIGNAL(breakStateEntered())); connect(this, SIGNAL(debuggablesChanged(const QMap&)), - SignalDispatcher::getDispatcher(), SIGNAL(debuggablesChanged(const QMap&)) ); - connect(this, &DebuggerForm::breakpointsUpdated, SignalDispatcher::getDispatcher(), &SignalDispatcher::breakpointsUpdated); + &dispatcher, SIGNAL(debuggablesChanged(const QMap&)) ); + connect(this, &DebuggerForm::breakpointsUpdated, &dispatcher, &SignalDispatcher::breakpointsUpdated); + // disable all widgets + connectionClosed(); - // disable all widgets - connectionClosed(); + connect(&comm, &CommClient::connectionReady, this, &DebuggerForm::initConnection); + connect(&comm, &CommClient::updateParsed, this, &DebuggerForm::handleUpdate); + connect(&comm, &CommClient::connectionTerminated, this, &DebuggerForm::connectionClosed); - connect(&comm, &CommClient::connectionReady, this, &DebuggerForm::initConnection); - connect(&comm, &CommClient::updateParsed, this, &DebuggerForm::handleUpdate); - connect(&comm, &CommClient::connectionTerminated, this, &DebuggerForm::connectionClosed); - - session->breakpoints().setMemoryLayout(SignalDispatcher::getDispatcher()->getMemLayout()); + session->breakpoints().setMemoryLayout(dispatcher.getMemLayout()); } void DebuggerForm::addDefaultWorkspaces() @@ -725,22 +725,24 @@ void DebuggerForm::addDefaultWorkspaces() QWidget* DebuggerForm::widgetFactory(factoryclasses fctwidget) { + auto& dispatcher = SignalDispatcher::instance(); + QWidget* wdgt; switch (fctwidget) { case disasmViewer: { - wdgt= new DisasmViewer(); - connect(wdgt, SIGNAL(breakpointToggled(uint16_t)), SignalDispatcher::getDispatcher(), SIGNAL(breakpointToggled(uint16_t))); - connect(SignalDispatcher::getDispatcher(), SIGNAL(connected()), wdgt, SLOT(refresh())); - connect(SignalDispatcher::getDispatcher(), SIGNAL(breakStateEntered()), wdgt, SLOT(refresh())); - connect(SignalDispatcher::getDispatcher(), SIGNAL(symbolsChanged()), wdgt, SLOT(refresh())); - connect(SignalDispatcher::getDispatcher(), SIGNAL(settingsChanged()), wdgt, SLOT(updateLayout())); - connect(SignalDispatcher::getDispatcher(), SIGNAL(setCursorAddress(uint16_t, int, int)), wdgt, SLOT(setCursorAddress(uint16_t, int, int))); - connect(SignalDispatcher::getDispatcher(), SIGNAL(setProgramCounter(uint16_t,bool)), wdgt, SLOT(setProgramCounter(uint16_t,bool))); - connect(SignalDispatcher::getDispatcher(), SIGNAL(breakpointsUpdated()), wdgt, SLOT(update())); - static_cast(wdgt)->setMemory(SignalDispatcher::getDispatcher()->getMainMemory()); + wdgt = new DisasmViewer(); + connect(wdgt, SIGNAL(breakpointToggled(uint16_t)), &dispatcher, SIGNAL(breakpointToggled(uint16_t))); + connect(&dispatcher, SIGNAL(connected()), wdgt, SLOT(refresh())); + connect(&dispatcher, SIGNAL(breakStateEntered()), wdgt, SLOT(refresh())); + connect(&dispatcher, SIGNAL(symbolsChanged()), wdgt, SLOT(refresh())); + connect(&dispatcher, SIGNAL(settingsChanged()), wdgt, SLOT(updateLayout())); + connect(&dispatcher, SIGNAL(setCursorAddress(uint16_t, int, int)), wdgt, SLOT(setCursorAddress(uint16_t, int, int))); + connect(&dispatcher, SIGNAL(setProgramCounter(uint16_t,bool)), wdgt, SLOT(setProgramCounter(uint16_t,bool))); + connect(&dispatcher, SIGNAL(breakpointsUpdated()), wdgt, SLOT(update())); + static_cast(wdgt)->setMemory(dispatcher.getMainMemory()); static_cast(wdgt)->setBreakpoints(&DebugSession::getDebugSession()->breakpoints()); - static_cast(wdgt)->setMemoryLayout(SignalDispatcher::getDispatcher()->getMemLayout()); + static_cast(wdgt)->setMemoryLayout(dispatcher.getMemLayout()); static_cast(wdgt)->setSymbolTable(&DebugSession::getDebugSession()->symbolTable()); }; @@ -748,9 +750,9 @@ QWidget* DebuggerForm::widgetFactory(factoryclasses fctwidget) case mainMemoryViewer: wdgt = new MainMemoryViewer(); // Main memory viewer - connect(SignalDispatcher::getDispatcher(), SIGNAL(connected()), wdgt, SLOT(refresh())); - connect(SignalDispatcher::getDispatcher(), SIGNAL(breakStateEntered()), wdgt, SLOT(refresh())); - connect(SignalDispatcher::getDispatcher(), SIGNAL(registerChanged(int, int)), wdgt, SLOT(registerChanged(int, int))); + connect(&dispatcher, SIGNAL(connected()), wdgt, SLOT(refresh())); + connect(&dispatcher, SIGNAL(breakStateEntered()), wdgt, SLOT(refresh())); + connect(&dispatcher, SIGNAL(registerChanged(int, int)), wdgt, SLOT(registerChanged(int, int))); //mainMemoryView->setRegsView(regsView); static_cast(wdgt)->setSymbolTable(&DebugSession::getDebugSession()->symbolTable()); static_cast(wdgt)->setDebuggable("memory", 65536); @@ -758,45 +760,42 @@ QWidget* DebuggerForm::widgetFactory(factoryclasses fctwidget) case cpuRegsViewer: wdgt = new CPURegsViewer(); //copy current registers to new widget - for(int id=0;id<15;id++){ // CpuRegs::REG_AF up to CpuRegs::REG_IFF - static_cast(wdgt)->setRegister(id, - SignalDispatcher::getDispatcher()->readRegister(id)); - }; - connect(SignalDispatcher::getDispatcher(), SIGNAL(registersUpdate(unsigned char*)), wdgt, SLOT(setData(unsigned char*))); + for (int id = 0; id < 15; ++id) { // CpuRegs::REG_AF up to CpuRegs::REG_IFF + static_cast(wdgt)->setRegister(id, dispatcher.readRegister(id)); + } + connect(&dispatcher, SIGNAL(registersUpdate(unsigned char*)), wdgt, SLOT(setData(unsigned char*))); break; case flagsViewer: wdgt = new FlagsViewer(); - static_cast(wdgt)->setFlags(SignalDispatcher::getDispatcher()->readRegister(CpuRegs::REG_AF) & 0xFF); - connect(SignalDispatcher::getDispatcher(), SIGNAL(flagsChanged(quint8)), wdgt, SLOT(setFlags(quint8))); + static_cast(wdgt)->setFlags(dispatcher.readRegister(CpuRegs::REG_AF) & 0xFF); + connect(&dispatcher, SIGNAL(flagsChanged(quint8)), wdgt, SLOT(setFlags(quint8))); break; case stackViewer: wdgt = new StackViewer(); - static_cast(wdgt)->setData(SignalDispatcher::getDispatcher()->getMainMemory(), 65536); - static_cast(wdgt)->setStackPointer( - SignalDispatcher::getDispatcher()->readRegister(CpuRegs::REG_SP) - ); - connect(SignalDispatcher::getDispatcher(), SIGNAL(spChanged(quint16)), wdgt, SLOT(setStackPointer(quint16))); + static_cast(wdgt)->setData(dispatcher.getMainMemory(), 65536); + static_cast(wdgt)->setStackPointer(dispatcher.readRegister(CpuRegs::REG_SP)); + connect(&dispatcher, SIGNAL(spChanged(quint16)), wdgt, SLOT(setStackPointer(quint16))); break; case slotViewer: wdgt = new SlotViewer(); - connect(SignalDispatcher::getDispatcher(), SIGNAL(connected()), wdgt, SLOT(refresh())); - connect(SignalDispatcher::getDispatcher(), SIGNAL(breakStateEntered()), wdgt, SLOT(refresh())); - connect(SignalDispatcher::getDispatcher(), SIGNAL(slotsUpdated(bool)), wdgt, SLOT(refresh())); - static_cast(wdgt)->setMemoryLayout(SignalDispatcher::getDispatcher()->getMemLayout()); + connect(&dispatcher, SIGNAL(connected()), wdgt, SLOT(refresh())); + connect(&dispatcher, SIGNAL(breakStateEntered()), wdgt, SLOT(refresh())); + connect(&dispatcher, SIGNAL(slotsUpdated(bool)), wdgt, SLOT(refresh())); + static_cast(wdgt)->setMemoryLayout(dispatcher.getMemLayout()); break; case breakpointViewer: wdgt = new BreakpointViewer(); break; case debuggableViewer: wdgt = new DebuggableViewer(); - connect(SignalDispatcher::getDispatcher(), SIGNAL(breakStateEntered()), wdgt, SLOT(refresh())); - connect(SignalDispatcher::getDispatcher(), SIGNAL(debuggablesChanged(const QMap&)), + connect(&dispatcher, SIGNAL(breakStateEntered()), wdgt, SLOT(refresh())); + connect(&dispatcher, SIGNAL(debuggablesChanged(const QMap&)), wdgt, SLOT(setDebuggables(const QMap&))); static_cast(wdgt)->setDebuggables(debuggables); - if (!debuggables.isEmpty()){ + if (!debuggables.isEmpty()) { static_cast(wdgt)->debuggableSelected(0); static_cast(wdgt)->refresh(); - }; + } break; case vdpStatusRegViewer: wdgt = new VDPStatusRegViewer(); @@ -821,8 +820,8 @@ QWidget* DebuggerForm::widgetFactory(factoryclasses fctwidget) break; case paletteViewer: wdgt = new PaletteView(); - connect(SignalDispatcher::getDispatcher(), SIGNAL(connected()), wdgt, SLOT(refresh())); - connect(SignalDispatcher::getDispatcher(), SIGNAL(breakStateEntered()), wdgt, SLOT(refresh())); + connect(&dispatcher, SIGNAL(connected()), wdgt, SLOT(refresh())); + connect(&dispatcher, SIGNAL(breakStateEntered()), wdgt, SLOT(refresh())); break; default: wdgt = new QLabel("Not yet implemented in widgetFactory!"); @@ -841,7 +840,7 @@ void DebuggerForm::closeEvent(QCloseEvent* e) // handle unsaved session fileNewSession(); // cancel if session is still modified - if (session->isModified()) { + if (session->isModified()) { e->ignore(); return; } @@ -998,7 +997,7 @@ void DebuggerForm::connectionClosed() systemConnectAction->setEnabled(true); breakpointAddAction->setEnabled(false); - SignalDispatcher::getDispatcher()->setEnableWidget(false); + SignalDispatcher::instance().setEnableWidget(false); } void DebuggerForm::finalizeConnection(bool halted) @@ -1009,7 +1008,7 @@ void DebuggerForm::finalizeConnection(bool halted) // merge breakpoints on connect mergeBreakpoints = true; if (halted) { - breakOccured(); + breakOccurred(); } else { setRunMode(); updateData(); @@ -1017,7 +1016,7 @@ void DebuggerForm::finalizeConnection(bool halted) emit connected(); - SignalDispatcher::getDispatcher()->setEnableWidget(true); + SignalDispatcher::instance().setEnableWidget(true); } void DebuggerForm::handleUpdate(const QString& type, const QString& name, @@ -1027,7 +1026,7 @@ void DebuggerForm::handleUpdate(const QString& type, const QString& name, if (name == "cpu") { // running state by default. if (message == "suspended") { - breakOccured(); + breakOccurred(); } } else if (name == "paused") { pauseStatusChanged(message == "true"); @@ -1040,7 +1039,7 @@ void DebuggerForm::pauseStatusChanged(bool isPaused) systemPauseAction->setChecked(isPaused); } -void DebuggerForm::breakOccured() +void DebuggerForm::breakOccurred() { emit breakStateEntered(); updateData(); @@ -1234,12 +1233,12 @@ void DebuggerForm::systemPreferences() void DebuggerForm::searchGoto() { - GotoDialog gtd(*SignalDispatcher::getDispatcher()->getMemLayout(), session, this); + auto& dispatcher = SignalDispatcher::instance(); + GotoDialog gtd(*dispatcher.getMemLayout(), session, this); if (gtd.exec()) { - int addr = gtd.address(); - if (addr >= 0) { - //disasmView->setCursorAddress(addr, 0, DisasmViewer::MiddleAlways); - SignalDispatcher::getDispatcher()->setCursorAddress(addr, 0, DisasmViewer::MiddleAlways); + if (int addr = gtd.address(); addr >= 0) { + //disasmView->setCursorAddress(addr, 0, DisasmViewer::MiddleAlways); + dispatcher.setCursorAddress(addr, 0, DisasmViewer::MiddleAlways); } } } @@ -1302,8 +1301,8 @@ void DebuggerForm::toggleBreakpoint(uint16_t addr) void DebuggerForm::addBreakpoint(uint16_t cursorAddress) { - BreakpointDialog bpd(*SignalDispatcher::getDispatcher()->getMemLayout(), session, this); - int addr = cursorAddress; + BreakpointDialog bpd(*SignalDispatcher::instance().getMemLayout(), session, this); + int addr = cursorAddress; auto [ps, ss, seg] = addressSlot(addr); bpd.setData(Breakpoint::BREAKPOINT, addr, ps, ss, seg); if (bpd.exec()) { @@ -1353,8 +1352,8 @@ void DebuggerForm::setDebuggableSize(const QString& debuggable, int size) debuggables[debuggable] = size; // emit update if size of last debuggable was set if (debuggable == debuggables.keys().last()) { - emit debuggablesChanged(debuggables); - emit SignalDispatcher::getDispatcher()->debuggablesChanged(debuggables); + emit debuggablesChanged(debuggables); + emit SignalDispatcher::instance().debuggablesChanged(debuggables); } } @@ -1374,19 +1373,20 @@ void DebuggerForm::symbolFileChanged() DebuggerForm::AddressSlotResult DebuggerForm::addressSlot(int addr) const { + auto& dispatcher = SignalDispatcher::instance(); int p = (addr & 0xC000) >> 14; - auto ps = qint8(SignalDispatcher::getDispatcher()->getMemLayout()->primarySlot[p]); - auto ss = qint8(SignalDispatcher::getDispatcher()->getMemLayout()->secondarySlot[p]); + auto ps = qint8(dispatcher.getMemLayout()->primarySlot[p]); + auto ss = qint8(dispatcher.getMemLayout()->secondarySlot[p]); int segment = [&] { // figure out (rom) mapper segment - if (SignalDispatcher::getDispatcher()->getMemLayout()->mapperSize[ps][ss == -1 ? 0 : ss] > 0) { - return SignalDispatcher::getDispatcher()->getMemLayout()->mapperSegment[p]; + if (dispatcher.getMemLayout()->mapperSize[ps][ss == -1 ? 0 : ss] > 0) { + return dispatcher.getMemLayout()->mapperSegment[p]; } else { int q = 2 * p + ((addr & 0x2000) >> 13); - int b = SignalDispatcher::getDispatcher()->getMemLayout()->romBlock[q]; + int b = dispatcher.getMemLayout()->romBlock[q]; return (b >= 0) ? b : -1; } }(); - return {ps, ss, segment}; + return {ps, ss, segment}; } bool DebuggerForm::saveWorkspacesAs(const QString &newFileName) diff --git a/src/DebuggerForm.h b/src/DebuggerForm.h index 75c05faa..1973b5a7 100644 --- a/src/DebuggerForm.h +++ b/src/DebuggerForm.h @@ -34,28 +34,28 @@ class DebuggerForm : public QMainWindow void reloadBreakpoints(bool merge = false); void onSlotsUpdated(bool slotsChanged); - enum factoryclasses { - disasmViewer, - mainMemoryViewer, - cpuRegsViewer, - flagsViewer, - stackViewer, - slotViewer, - breakpointViewer, - debuggableViewer, - vdpStatusRegViewer, - vdpCommandRegViewer, - bitMapViewer, - tileViewer, - spriteViewer, - vdpRegisters, - quickguide, - paletteViewer - }; - - bool saveWorkspacesAs(const QString& newFileName); - bool loadWorkspaces(const QString& filename); - QString fileSaveWorkspaceAs(); + enum factoryclasses { + disasmViewer, + mainMemoryViewer, + cpuRegsViewer, + flagsViewer, + stackViewer, + slotViewer, + breakpointViewer, + debuggableViewer, + vdpStatusRegViewer, + vdpCommandRegViewer, + bitMapViewer, + tileViewer, + spriteViewer, + vdpRegisters, + quickguide, + paletteViewer + }; + + bool saveWorkspacesAs(const QString& newFileName); + bool loadWorkspaces(const QString& filename); + QString fileSaveWorkspaceAs(); private: void closeEvent(QCloseEvent* e) override; @@ -67,7 +67,7 @@ class DebuggerForm : public QMainWindow void createStatusbar(); void createForm(); - static QWidget* widgetFactory(factoryclasses fctwidget); + static QWidget* widgetFactory(factoryclasses fctwidget); void openSession(const QString& file); void updateRecentFiles(); @@ -76,7 +76,7 @@ class DebuggerForm : public QMainWindow void finalizeConnection(bool halted); void pauseStatusChanged(bool isPaused); - void breakOccured(); + void breakOccurred(); void setRunMode(); void updateData(); @@ -105,13 +105,13 @@ class DebuggerForm : public QMainWindow QAction* fileSaveSessionAction; QAction* fileSaveSessionAsAction; - QAction* fileOpenWorkspaceLayoutAction; - QAction* fileSaveWorkspaceLayoutAction; - QAction* fileSaveWorkspaceLayoutAsAction; + QAction* fileOpenWorkspaceLayoutAction; + QAction* fileSaveWorkspaceLayoutAction; + QAction* fileSaveWorkspaceLayoutAsAction; QAction* fileQuitAction; - static const int MaxRecentFiles = 5; + static const int MaxRecentFiles = 5; QAction* recentFileActions[MaxRecentFiles]; QAction* recentFileSeparator; @@ -134,35 +134,34 @@ class DebuggerForm : public QMainWindow QAction* helpAboutAction; - QAction* addCPUWorkspaceAction; - QAction* addVDPRegsWorkspaceAction; - QAction* addVDPTilesWorkspaceAction; - QAction* addVDPBitmapWorkspaceAction; - QAction* addEmptyWorkspaceAction; - QAction* addFloatingSwitchingWidgetAction; + QAction* addCPUWorkspaceAction; + QAction* addVDPRegsWorkspaceAction; + QAction* addVDPTilesWorkspaceAction; + QAction* addVDPBitmapWorkspaceAction; + QAction* addEmptyWorkspaceAction; + QAction* addFloatingSwitchingWidgetAction; QStringList recentFiles; CommClient& comm; - DebugSession* session; + DebugSession* session; - QTabWidget *workspaces; - TabRenamerHelper *tabRenamer; + QTabWidget *workspaces; + TabRenamerHelper *tabRenamer; bool mergeBreakpoints; - static QMap debuggables; + static QMap debuggables; static int counter; - uint16_t disasmAddress; - + uint16_t disasmAddress; void fileNewSession(); void fileOpenSession(); void fileSaveSession(); void fileSaveSessionAs(); void fileRecentOpen(); - void fileOpenWorkspace(); - void fileSaveWorkspace(); + void fileOpenWorkspace(); + void fileSaveWorkspace(); void systemConnect(); void systemDisconnect(); @@ -191,10 +190,11 @@ class DebuggerForm : public QMainWindow // void executeRunTo(); void executeStepOut(); void executeStepBack(); + private slots: - void toggleBreakpoint(uint16_t addr); + void toggleBreakpoint(uint16_t addr); private: - void addBreakpoint(uint16_t cursorAddress); + void addBreakpoint(uint16_t cursorAddress); void initConnection(); void handleUpdate(const QString& type, const QString& name, const QString& message); @@ -217,7 +217,7 @@ private slots: friend class ListDebuggablesHandler; friend class DebuggableSizeHandler; - friend class TabRenamerHelper; + friend class TabRenamerHelper; signals: void connected(); @@ -226,25 +226,24 @@ private slots: void runStateEntered(); void breakStateEntered(); void breakpointsUpdated(); - void debuggablesChanged(const QMap& list); + void debuggablesChanged(const QMap& list); protected: - BlendSplitter *createWorkspaceCPU(); - BlendSplitter *createWorkspaceVDPRegs(); - BlendSplitter *createWorkspaceVDPTiles(); - BlendSplitter *createWorkspaceVDPBitmap(); - void addInfoWorkspace(); - void addCPUWorkspace(); - void addVDPRegsWorkspace(); - void addVDPTilesWorkspace(); - void addVDPBitmapWorkspace(); - void addEmptyWorkspace(); - void addFloatingSwitchingWidget(); - void addDefaultWorkspaces(); + BlendSplitter *createWorkspaceCPU(); + BlendSplitter *createWorkspaceVDPRegs(); + BlendSplitter *createWorkspaceVDPTiles(); + BlendSplitter *createWorkspaceVDPBitmap(); + void addInfoWorkspace(); + void addCPUWorkspace(); + void addVDPRegsWorkspace(); + void addVDPTilesWorkspace(); + void addVDPBitmapWorkspace(); + void addEmptyWorkspace(); + void addFloatingSwitchingWidget(); + void addDefaultWorkspaces(); protected slots: - void tabCloseRequest(int index); - + void tabCloseRequest(int index); }; #endif // DEBUGGERFORM_H diff --git a/src/MainMemoryViewer.cpp b/src/MainMemoryViewer.cpp index 628f16d1..b979efe7 100644 --- a/src/MainMemoryViewer.cpp +++ b/src/MainMemoryViewer.cpp @@ -138,9 +138,9 @@ void MainMemoryViewer::addressSourceListChanged(int index) linkedId = linkRegisters[index - 1]; addressValue->setReadOnly(true); hexView->setIsInteractive(false); -// if (regsViewer) { -// setLocation(regsViewer->readRegister(linkedId)); -// } - setLocation(SignalDispatcher::getDispatcher()->readRegister(linkedId)); + //if (regsViewer) { + // setLocation(regsViewer->readRegister(linkedId)); + //} + setLocation(SignalDispatcher::instance().readRegister(linkedId)); } } diff --git a/src/SignalDispatcher.cpp b/src/SignalDispatcher.cpp index ce3df2f8..4bf1e795 100644 --- a/src/SignalDispatcher.cpp +++ b/src/SignalDispatcher.cpp @@ -22,14 +22,18 @@ class DispatchDebugMemMapperHandler : public SimpleCommand SignalDispatcher& dispatcher; }; -SignalDispatcher* SignalDispatcher::theDispatcher = nullptr; - -SignalDispatcher* SignalDispatcher::getDispatcher() +SignalDispatcher::SignalDispatcher() { - if (theDispatcher == nullptr) { - theDispatcher = new SignalDispatcher{}; - } - return theDispatcher; + // avoid UMR + memset(®s, 0, sizeof(regs)); + memset(®sChanged, 0, sizeof(regsChanged)); + memset(®sModified, 0, sizeof(regsModified)); + + // init main memory + // added four bytes as runover buffer for dasm + // otherwise dasm would need to check the buffer end continuously. + mainMemory = new uint8_t[65536 + 4]; + memset(mainMemory, 0, 65536 + 4); } SignalDispatcher::~SignalDispatcher() @@ -37,7 +41,13 @@ SignalDispatcher::~SignalDispatcher() delete[] mainMemory; } -unsigned char *SignalDispatcher::getMainMemory() +SignalDispatcher& SignalDispatcher::instance() +{ + static SignalDispatcher oneInstance; + return oneInstance; +} + +uint8_t* SignalDispatcher::getMainMemory() { return mainMemory; } @@ -47,7 +57,7 @@ MemoryLayout* SignalDispatcher::getMemLayout() return &memLayout; } -void SignalDispatcher::setData(unsigned char *datPtr) +void SignalDispatcher::setData(uint8_t* datPtr) { setRegister(CpuRegs::REG_AF , datPtr[ 0] * 256 + datPtr[ 1]); setRegister(CpuRegs::REG_BC , datPtr[ 2] * 256 + datPtr[ 3]); @@ -162,20 +172,6 @@ int SignalDispatcher::readRegister(int id) return regs[id]; } -SignalDispatcher::SignalDispatcher() -{ - // avoid UMR - memset(®s, 0, sizeof(regs)); - memset(®sChanged, 0, sizeof(regsChanged)); - memset(®sModified, 0, sizeof(regsModified)); - - // init main memory - // added four bytes as runover buffer for dasm - // otherwise dasm would need to check the buffer end continuously. - mainMemory = new unsigned char[65536 + 4]; - memset(mainMemory, 0, 65536 + 4); -} - void SignalDispatcher::setRegister(int id, int value) { regsChanged[id] = regs[id] != value; @@ -185,7 +181,7 @@ void SignalDispatcher::setRegister(int id, int value) } } -void SignalDispatcher::getRegister(int id, unsigned char* data) +void SignalDispatcher::getRegister(int id, uint8_t* data) { data[0] = regs[id] >> 8; data[1] = regs[id] & 255; diff --git a/src/SignalDispatcher.h b/src/SignalDispatcher.h index ec433276..003fbe0f 100644 --- a/src/SignalDispatcher.h +++ b/src/SignalDispatcher.h @@ -3,8 +3,8 @@ #include "CPURegs.h" #include "DebuggerData.h" - #include +#include /** \brief A singleton signal dispatcher @@ -25,14 +25,14 @@ class SignalDispatcher : public QObject * This is a singleton class, i. e. you can't construct any object yourself. To get the one-and-only instance of this class, you need to call SignalDispatcher::getDispatcher(). The function will create the object if neccessary (= when called for the first time) and return a pointer to it. * \return A pointer to the one-and-only instance of SignalDispatcher */ - static SignalDispatcher* getDispatcher(); + static SignalDispatcher& instance(); ~SignalDispatcher(); - unsigned char* getMainMemory(); - MemoryLayout* getMemLayout(); + uint8_t* getMainMemory(); + MemoryLayout* getMemLayout(); int readRegister(int id); - void setData(unsigned char* datPtr); + void setData(uint8_t* datPtr); bool getEnableWidget(); @@ -45,7 +45,7 @@ public slots: SignalDispatcher(); void setRegister(int id, int value); - void getRegister(int id, unsigned char* data); + void getRegister(int id, uint8_t* data); signals: void enableWidget(bool enable); @@ -57,7 +57,7 @@ public slots: void breakpointsUpdated(); void debuggablesChanged(const QMap& list); // signals concerning CPU registers - void registersUpdate(unsigned char* datPtr); + void registersUpdate(uint8_t* datPtr); void registerChanged(int id, int value); void pcChanged(uint16_t); void flagsChanged(quint8); @@ -72,10 +72,8 @@ public slots: void setCursorAddress(uint16_t addr, int infoLine, int method); private: - static SignalDispatcher* theDispatcher; - //main 64K used by disasmview and stack - unsigned char* mainMemory; + uint8_t* mainMemory; MemoryLayout memLayout; //buffers to handle tracking of the CPU registers diff --git a/src/blendsplitter/BlendSplitter.cpp b/src/blendsplitter/BlendSplitter.cpp index 055148e7..f58217f3 100644 --- a/src/blendsplitter/BlendSplitter.cpp +++ b/src/blendsplitter/BlendSplitter.cpp @@ -47,9 +47,10 @@ void BlendSplitter::insertWidget(int index, QWidget* widget) { if (widget->inherits("SwitchingWidget")) { auto* sw = static_cast(widget); - connect(SignalDispatcher::getDispatcher(), &SignalDispatcher::enableWidget, + auto& dispatcher = SignalDispatcher::instance(); + connect(&dispatcher, &SignalDispatcher::enableWidget, sw, &SwitchingWidget::setEnableWidget); - sw->setEnableWidget(SignalDispatcher::getDispatcher()->getEnableWidget()); + sw->setEnableWidget(dispatcher.getEnableWidget()); } auto* decorator = new WidgetDecorator{widget}; QSplitter::insertWidget(index, decorator); From 9b6873b91457736b95ad934010be8fc397effcac Mon Sep 17 00:00:00 2001 From: m9710797 Date: Thu, 12 May 2022 20:00:30 +0200 Subject: [PATCH 32/63] simplify SignalDispatcher construction/destruction --- src/SignalDispatcher.cpp | 19 ------------------- src/SignalDispatcher.h | 18 +++++++----------- 2 files changed, 7 insertions(+), 30 deletions(-) diff --git a/src/SignalDispatcher.cpp b/src/SignalDispatcher.cpp index 4bf1e795..6a2275f3 100644 --- a/src/SignalDispatcher.cpp +++ b/src/SignalDispatcher.cpp @@ -22,25 +22,6 @@ class DispatchDebugMemMapperHandler : public SimpleCommand SignalDispatcher& dispatcher; }; -SignalDispatcher::SignalDispatcher() -{ - // avoid UMR - memset(®s, 0, sizeof(regs)); - memset(®sChanged, 0, sizeof(regsChanged)); - memset(®sModified, 0, sizeof(regsModified)); - - // init main memory - // added four bytes as runover buffer for dasm - // otherwise dasm would need to check the buffer end continuously. - mainMemory = new uint8_t[65536 + 4]; - memset(mainMemory, 0, 65536 + 4); -} - -SignalDispatcher::~SignalDispatcher() -{ - delete[] mainMemory; -} - SignalDispatcher& SignalDispatcher::instance() { static SignalDispatcher oneInstance; diff --git a/src/SignalDispatcher.h b/src/SignalDispatcher.h index 003fbe0f..c9994776 100644 --- a/src/SignalDispatcher.h +++ b/src/SignalDispatcher.h @@ -20,13 +20,7 @@ class SignalDispatcher : public QObject SignalDispatcher(const SignalDispatcher&) = delete; SignalDispatcher& operator=(const SignalDispatcher&) = delete; - /** \brief Dispatcher getter - * - * This is a singleton class, i. e. you can't construct any object yourself. To get the one-and-only instance of this class, you need to call SignalDispatcher::getDispatcher(). The function will create the object if neccessary (= when called for the first time) and return a pointer to it. - * \return A pointer to the one-and-only instance of SignalDispatcher - */ static SignalDispatcher& instance(); - ~SignalDispatcher(); uint8_t* getMainMemory(); MemoryLayout* getMemLayout(); @@ -42,7 +36,8 @@ public slots: void updateSlots(const QString& message); private: - SignalDispatcher(); + SignalDispatcher() = default; + ~SignalDispatcher() = default; void setRegister(int id, int value); void getRegister(int id, uint8_t* data); @@ -73,13 +68,14 @@ public slots: private: //main 64K used by disasmview and stack - uint8_t* mainMemory; + uint8_t mainMemory[65536 + 4] = {}; // 4 extra to avoid bound-checks during disassembly MemoryLayout memLayout; //buffers to handle tracking of the CPU registers - int regs[16], regsCopy[16]; - bool regsModified[16]; - bool regsChanged[16]; + int regs[16] = {}; + int regsCopy[16]; + bool regsModified[16] = {}; + bool regsChanged[16] = {}; //buffers to handle tracking of the slots layout enum {RESET = 0, SLOTS_CHECKED, PC_CHANGED, SLOTS_CHANGED} disasmStatus = RESET; From 4620811d775421400fe403d49d9eec851af18b1a Mon Sep 17 00:00:00 2001 From: m9710797 Date: Thu, 12 May 2022 20:09:32 +0200 Subject: [PATCH 33/63] Don't use copy-assignment-operator in MSXPalette Because it doesn't make a full copy. That is after the assignment source and destination aren't equal. --- src/MSXPalette.cpp | 3 +-- src/MSXPalette.h | 3 ++- src/PaletteView.cpp | 10 +++++----- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/MSXPalette.cpp b/src/MSXPalette.cpp index 180a3a5f..a2bbd820 100644 --- a/src/MSXPalette.cpp +++ b/src/MSXPalette.cpp @@ -32,12 +32,11 @@ MSXPalette::MSXPalette(QObject* parent) } } -MSXPalette& MSXPalette::operator=(const MSXPalette& source) +void MSXPalette::copyDataFrom(const MSXPalette& source) { memcpy(myPal, source.myPal, sizeof(myPal)); memcpy(msxPalette, source.msxPalette, sizeof(msxPalette)); emit paletteChanged(); - return *this; } void MSXPalette::setPalette(uint8_t* pal) diff --git a/src/MSXPalette.h b/src/MSXPalette.h index d7cfe414..27fc08bd 100644 --- a/src/MSXPalette.h +++ b/src/MSXPalette.h @@ -10,7 +10,8 @@ class MSXPalette : public QObject Q_OBJECT public: explicit MSXPalette(QObject* parent = nullptr); - MSXPalette& operator=(const MSXPalette& source); + + void copyDataFrom(const MSXPalette& source); void setPalette(uint8_t* pal); uint8_t* getPalette(); diff --git a/src/PaletteView.cpp b/src/PaletteView.cpp index b0c49fd3..40cb0217 100644 --- a/src/PaletteView.cpp +++ b/src/PaletteView.cpp @@ -55,7 +55,7 @@ void PaletteView::setPalette(MSXPalette* sourcePal) } myPal = sourcePal; - myOriginalPal = *sourcePal; + myOriginalPal.copyDataFrom(*sourcePal); connect(myPal, SIGNAL(paletteChanged()), this, SIGNAL(paletteChanged())); emit paletteReplaced(sourcePal); @@ -69,7 +69,7 @@ MSXPalette* PaletteView::getPalette() void PaletteView::syncToSource() { myPal->syncToSource(); - myOriginalPal = *myPal; + myOriginalPal.copyDataFrom(*myPal); } void PaletteView::setAutoSync(bool value) @@ -117,11 +117,11 @@ void PaletteView::on_horizontalSlider_B_valueChanged(int value) void PaletteView::restorePalette() { ScopedAssign sa(isDisplayUpdating, true); - *myPal = myOriginalPal; + myPal->copyDataFrom(myOriginalPal); colorSelected(currentColor); } -void PaletteView::on_buttonBox_clicked(QAbstractButton *button) +void PaletteView::on_buttonBox_clicked(QAbstractButton* button) { if (button == ui->buttonBox->button(QDialogButtonBox::Apply) || button == ui->buttonBox->button(QDialogButtonBox::Ok)) { @@ -151,7 +151,7 @@ void PaletteView::on_cbPalette_currentIndexChanged(int index) void PaletteView::on_pbCopyPaletteVDP_clicked() { ScopedAssign sa(isDisplayUpdating, true); - *myPal = *VDPDataStore::instance().getPalette(0); // operator=() copies the byte and qRgb values + myPal->copyDataFrom(*VDPDataStore::instance().getPalette(0)); emit myPal->paletteChanged(); } From b5a9d4ade66dcfd3da0f677d98769191ce1c0140 Mon Sep 17 00:00:00 2001 From: m9710797 Date: Thu, 12 May 2022 20:33:08 +0200 Subject: [PATCH 34/63] Don't store redundant msxPalette[] in MSXPalette It can be trivially calculated from myPal[]. And not having to keep this array up-to-date allowed to simplify various other functions. --- src/MSXPalette.cpp | 65 ++++++++++++++++--------------------------- src/MSXPalette.h | 7 ++--- src/PaletteDialog.cpp | 11 ++------ src/PaletteDialog.h | 1 - src/PalettePatch.cpp | 6 ++-- src/PalettePatch.h | 3 +- src/PaletteView.cpp | 8 +++--- 7 files changed, 37 insertions(+), 64 deletions(-) diff --git a/src/MSXPalette.cpp b/src/MSXPalette.cpp index a2bbd820..8e830de0 100644 --- a/src/MSXPalette.cpp +++ b/src/MSXPalette.cpp @@ -1,6 +1,7 @@ #include "MSXPalette.h" #include "CommClient.h" #include +#include // default MSX palette static const uint8_t defaultPalette[32] = { @@ -27,42 +28,29 @@ MSXPalette::MSXPalette(QObject* parent) : QObject{parent} { memcpy(myPal, defaultPalette, sizeof(myPal)); - for (int i = 0; i < 16; ++i) { - setColor(i, myPal[2 * i] >> 4, myPal[2 * i + 1], myPal[2 * i] & 15); - } + emit paletteChanged(); } void MSXPalette::copyDataFrom(const MSXPalette& source) { memcpy(myPal, source.myPal, sizeof(myPal)); - memcpy(msxPalette, source.msxPalette, sizeof(msxPalette)); emit paletteChanged(); } void MSXPalette::setPalette(uint8_t* pal) { - int palchanged = memcmp(myPal, pal, sizeof(myPal)); sourcePal = pal; - if (palchanged != 0) { - for (int i = 0; i < 16; ++i) { - calculateColor(i, pal[2 * i] >> 4, pal[2 * i + 1], pal[2 * i] & 15); - } + if (memcmp(myPal, pal, sizeof(myPal)) != 0) { + memcpy(myPal, pal, sizeof(myPal)); emit paletteChanged(); } } -uint8_t* MSXPalette::getPalette() -{ - return myPal; -} - void MSXPalette::syncToSource() { - if (sourcePal == nullptr) { - return; - } - memcpy(sourcePal, myPal, sizeof(myPal)); + if (!sourcePal) return; + memcpy(sourcePal, myPal, sizeof(myPal)); if (syncToMSX) { syncToOpenMSX(); } @@ -71,9 +59,8 @@ void MSXPalette::syncToSource() void MSXPalette::syncToSource(int i) { - if (sourcePal == nullptr) { - return; - } + if (!sourcePal) return; + memcpy(sourcePal + 2 * i, myPal + 2 * i, 2); if (syncToMSX) { syncColorToOpenMSX(i); @@ -83,18 +70,23 @@ void MSXPalette::syncToSource(int i) void MSXPalette::setAutoSync(bool value) { - if (autoSync == value) { - return; - } + if (autoSync == value) return; + autoSync = value; if (value) { syncToSource(); } } -void MSXPalette::setColor(int i, int r, int g, int b) +void MSXPalette::setColor(unsigned i, unsigned r, unsigned g, unsigned b) { - calculateColor(i, r, g, b); + assert(i < 16); + assert(r < 8); + assert(g < 8); + assert(b < 8); + myPal[2 * i + 0] = (r << 4) | b; + myPal[2 * i + 1] = g; + emit paletteChanged(); if (autoSync) { @@ -102,23 +94,14 @@ void MSXPalette::setColor(int i, int r, int g, int b) } } -QRgb MSXPalette::color(int i) -{ - return msxPalette[std::clamp(i, 0, 15)]; -} - -void MSXPalette::calculateColor(int i, int r, int g, int b) +QRgb MSXPalette::color(unsigned i) const { - i = std::clamp(i, 0, 15); - r = std::clamp(r, 0, 7); - g = std::clamp(g, 0, 7); - b = std::clamp(b, 0, 7); - - myPal[2 * i + 0] = 16 * r + b; - myPal[2 * i + 1] = g; - + assert(i < 16); + int r = (myPal[2 * i + 0] >> 4) & 7; + int g = (myPal[2 * i + 1] >> 0) & 7; + int b = (myPal[2 * i + 0] >> 0) & 7; auto scale = [](int x) { return (x >> 1) | (x << 2) | (x << 5); }; - msxPalette[i] = qRgb(scale(r), scale(g), scale(b)); + return qRgb(scale(r), scale(g), scale(b)); } void MSXPalette::syncToOpenMSX() diff --git a/src/MSXPalette.h b/src/MSXPalette.h index 27fc08bd..38313f59 100644 --- a/src/MSXPalette.h +++ b/src/MSXPalette.h @@ -14,13 +14,12 @@ class MSXPalette : public QObject void copyDataFrom(const MSXPalette& source); void setPalette(uint8_t* pal); - uint8_t* getPalette(); void syncToSource(); void syncToSource(int i); void setAutoSync(bool value); - void setColor(int i, int r, int g, int b); - QRgb color(int i); + void setColor(unsigned i, unsigned r, unsigned g, unsigned b); + QRgb color(unsigned i) const; bool syncToMSX = false; // TODO avoid public data members @@ -29,14 +28,12 @@ class MSXPalette : public QObject void paletteSynced(); private: - void calculateColor(int i, int r, int g, int b); void syncToOpenMSX(); void syncColorToOpenMSX(int colorNr); private: uint8_t* sourcePal = nullptr; uint8_t myPal[32]; - QRgb msxPalette[16]; bool autoSync = false; }; diff --git a/src/PaletteDialog.cpp b/src/PaletteDialog.cpp index 5cfe4487..441cdbb3 100644 --- a/src/PaletteDialog.cpp +++ b/src/PaletteDialog.cpp @@ -70,9 +70,9 @@ void PaletteDialog::restoreOpeningsPalette() void PaletteDialog::colorSelected(int colorNumber) { currentColor = colorNumber; - int r = (myPal[2 * currentColor + 0] & 0xf0) >> 4; - int b = (myPal[2 * currentColor + 0] & 0x0f); - int g = (myPal[2 * currentColor + 1] & 0x0f); + int r = (myPal[2 * currentColor + 0] & 0x70) >> 4; + int b = (myPal[2 * currentColor + 0] & 0x07); + int g = (myPal[2 * currentColor + 1] & 0x07); ui->horizontalSlider_R->setValue(r); ui->horizontalSlider_G->setValue(g); ui->horizontalSlider_B->setValue(b); @@ -87,11 +87,6 @@ void PaletteDialog::setPalette(uint8_t* pal) emit paletteChanged(myPal); } -uint8_t* PaletteDialog::getPalette() -{ - return myPal; -} - //void PaletteDialog::decodepalette() //{ // for (int i = 0; i < 16; ++i) { diff --git a/src/PaletteDialog.h b/src/PaletteDialog.h index 76c58787..34f4654f 100644 --- a/src/PaletteDialog.h +++ b/src/PaletteDialog.h @@ -21,7 +21,6 @@ class PaletteDialog : public QDialog explicit PaletteDialog(QWidget* parent = nullptr); void setPalette(uint8_t* pal); - uint8_t* getPalette(); void syncToSource(); void setAutoSync(bool value); diff --git a/src/PalettePatch.cpp b/src/PalettePatch.cpp index 8b3ff2b9..ca5c21d0 100644 --- a/src/PalettePatch.cpp +++ b/src/PalettePatch.cpp @@ -23,9 +23,9 @@ void PalettePatch::setMSXPalette(MSXPalette* pal) //old method for PaletteDialog void PalettePatch::updatePaletteChanged(const uint8_t* pal) { - int r = (pal[2 * msxPalNr + 0] & 0xf0) >> 4; - int b = (pal[2 * msxPalNr + 0] & 0x0f); - int g = (pal[2 * msxPalNr + 1] & 0x0f); + int r = (pal[2 * msxPalNr + 0] & 0x70) >> 4; + int b = (pal[2 * msxPalNr + 0] & 0x07); + int g = (pal[2 * msxPalNr + 1] & 0x07); auto scale = [](int x) { return (x >> 1) | (x << 2) | (x << 5); }; myColor = qRgb(scale(r), scale(g), scale(b)); //setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding)); diff --git a/src/PalettePatch.h b/src/PalettePatch.h index a5857100..73373399 100644 --- a/src/PalettePatch.h +++ b/src/PalettePatch.h @@ -10,8 +10,7 @@ class PalettePatch : public QPushButton Q_OBJECT public: - explicit PalettePatch(QWidget* parent = nullptr, int palNr = 0); - //void setColor(QRgb c); + PalettePatch(QWidget* parent, int palNr); public slots: void setMSXPalette(MSXPalette* pal); diff --git a/src/PaletteView.cpp b/src/PaletteView.cpp index 40cb0217..f0dceeaf 100644 --- a/src/PaletteView.cpp +++ b/src/PaletteView.cpp @@ -175,10 +175,10 @@ void PaletteView::combineRGB() { if (isDisplayUpdating) return; - int r = ui->horizontalSlider_R->value(); - int g = ui->horizontalSlider_G->value(); - int b = ui->horizontalSlider_B->value(); - myPal->setColor(currentColor,r,g,b); + int r = ui->horizontalSlider_R->value() & 7; + int g = ui->horizontalSlider_G->value() & 7; + int b = ui->horizontalSlider_B->value() & 7; + myPal->setColor(currentColor, r, g, b); emit paletteChanged(); if (autoSync) { syncToSource(); From 920176777ea7cd1fef84f19f5b9a81f07bb6886e Mon Sep 17 00:00:00 2001 From: David Heremans Date: Tue, 17 May 2022 00:03:23 +0200 Subject: [PATCH 35/63] Json save and load of widget in SwitchingWidget. This way we can 'correctly' perfom a split so that both the old and new widgets have the same options selected. We can also save some of these settings when we save layouts. Unfortunately for stuff like the DebuggableViewer the actual text of the combobox depends on the debuggables that the selected openMSX presents to the debugger, so saving the selection in a layout will not work. (Unless we connect to an openMSX that presents the same debuggables before we even try to restore the layout? That would be a nice improvement...) --- src/DebuggableViewer.cpp | 18 ++++++++++- src/DebuggableViewer.h | 6 +++- src/MainMemoryViewer.cpp | 24 +++++++++++++-- src/MainMemoryViewer.h | 7 ++++- src/PaletteView.cpp | 31 ++++++++++++++++++- src/PaletteView.h | 8 ++++- src/SavesJsonInterface.cpp | 6 ++++ src/SavesJsonInterface.h | 14 +++++++++ src/SignalDispatcher.h | 2 +- src/blendsplitter/ExpanderCorner.cpp | 4 +++ src/blendsplitter/SwitchingWidget.cpp | 43 +++++++++++++++++++++++++++ src/blendsplitter/SwitchingWidget.h | 4 +++ src/node.mk | 2 +- 13 files changed, 160 insertions(+), 9 deletions(-) create mode 100644 src/SavesJsonInterface.cpp create mode 100644 src/SavesJsonInterface.h diff --git a/src/DebuggableViewer.cpp b/src/DebuggableViewer.cpp index bfd35011..a116fff5 100644 --- a/src/DebuggableViewer.cpp +++ b/src/DebuggableViewer.cpp @@ -2,6 +2,7 @@ #include "HexViewer.h" #include #include +#include DebuggableViewer::DebuggableViewer(QWidget* parent) : QWidget(parent) @@ -22,7 +23,22 @@ DebuggableViewer::DebuggableViewer(QWidget* parent) setLayout(vbox); connect(hexView, SIGNAL(locationChanged(int)), - this, SLOT(locationChanged(int))); + this, SLOT(locationChanged(int))); +} + +QJsonObject DebuggableViewer::save2json() +{ + QJsonObject obj; + obj["debuggable"]=debuggableList->currentText(); + return obj; +} + +bool DebuggableViewer::loadFromJson(const QJsonObject &obj) +{ + if ( obj["debuggable"] == QJsonValue::Undefined ) return false; + + debuggableList->setCurrentText(obj["debuggable"].toString() ); + return true; } void DebuggableViewer::settingsChanged() diff --git a/src/DebuggableViewer.h b/src/DebuggableViewer.h index 3662f3b6..c4a7576b 100644 --- a/src/DebuggableViewer.h +++ b/src/DebuggableViewer.h @@ -1,17 +1,21 @@ #ifndef DEBUGGABLEVIEWER_H #define DEBUGGABLEVIEWER_H +#include "SavesJsonInterface.h" #include class HexViewer; class QComboBox; -class DebuggableViewer : public QWidget +class DebuggableViewer : public QWidget , public SavesJsonInterface { Q_OBJECT public: DebuggableViewer(QWidget* parent = nullptr); + QJsonObject save2json() override; + bool loadFromJson(const QJsonObject& obj) override; + public slots: void settingsChanged(); void setDebuggables(const QMap& list); diff --git a/src/MainMemoryViewer.cpp b/src/MainMemoryViewer.cpp index b979efe7..3962132a 100644 --- a/src/MainMemoryViewer.cpp +++ b/src/MainMemoryViewer.cpp @@ -10,6 +10,7 @@ #include #include #include +#include static const int linkRegisters[] = { CpuRegs::REG_BC, CpuRegs::REG_DE, CpuRegs::REG_HL, @@ -19,7 +20,7 @@ static const int linkRegisters[] = { }; MainMemoryViewer::MainMemoryViewer(QWidget* parent) - : QWidget(parent) + : QWidget(parent),SavesJsonInterface() { setObjectName("MainMemoryViewer"); // create selection list, address edit line and viewer @@ -88,7 +89,26 @@ void MainMemoryViewer::setDebuggable(const QString& name, int size) void MainMemoryViewer::setSymbolTable(SymbolTable* symtable) { - symTable = symtable; + symTable = symtable; +} + +QJsonObject MainMemoryViewer::save2json() +{ + QJsonObject obj; + obj["addressValue"]=addressValue->text(); + obj["addressSourceList"]=addressSourceList->currentIndex(); + return obj; +} + +bool MainMemoryViewer::loadFromJson(const QJsonObject &obj) +{ + if ( obj["addressSourceList"] == QJsonValue::Undefined || + obj["addressValue"] == QJsonValue::Undefined ) return false; + + addressSourceList->setCurrentIndex( obj["addressSourceList"].toInt() ); + addressValue->setText( obj["addressValue"].toString() ); + hexView->setLocation(stringToValue(addressValue->text())); + return true; } void MainMemoryViewer::refresh() diff --git a/src/MainMemoryViewer.h b/src/MainMemoryViewer.h index d1c00685..d34fe39d 100644 --- a/src/MainMemoryViewer.h +++ b/src/MainMemoryViewer.h @@ -1,6 +1,7 @@ #ifndef MAINMEMORYVIEWER_H #define MAINMEMORYVIEWER_H +#include "SavesJsonInterface.h" #include class HexViewer; @@ -8,8 +9,9 @@ class CPURegsViewer; class SymbolTable; class QComboBox; class QLineEdit; +class QJsonObject; -class MainMemoryViewer : public QWidget +class MainMemoryViewer : public QWidget , public SavesJsonInterface { Q_OBJECT public: @@ -19,6 +21,9 @@ class MainMemoryViewer : public QWidget // void setRegsView(CPURegsViewer* viewer); void setSymbolTable(SymbolTable* symtable); + QJsonObject save2json() final; + bool loadFromJson(const QJsonObject& obj) final; + public slots: void setLocation(int addr); void settingsChanged(); diff --git a/src/PaletteView.cpp b/src/PaletteView.cpp index f0dceeaf..49820adb 100644 --- a/src/PaletteView.cpp +++ b/src/PaletteView.cpp @@ -5,9 +5,10 @@ #include "ScopedAssign.h" #include "ui_PaletteView.h" #include +#include PaletteView::PaletteView(QWidget* parent) - : QWidget(parent) + : QWidget(parent),SavesJsonInterface() , ui(std::make_unique()) { ui->setupUi(this); @@ -82,6 +83,34 @@ void PaletteView::setAutoSync(bool value) } } +QJsonObject PaletteView::save2json() +{ + QJsonObject obj; + obj["viewtext"]=ui->cb_viewtext->isChecked(); + obj["autosync"]=ui->cb_autosync->isChecked(); + obj["palette"]=ui->cbPalette->currentIndex(); + return obj; +} + +bool PaletteView::loadFromJson(const QJsonObject &obj) +{ + int i=0; + if ( obj["viewtext"] != QJsonValue::Undefined ) { + ui->cb_viewtext->setChecked( obj["viewtext"].toBool() ); + i++; + }; + if ( obj["autosync"] != QJsonValue::Undefined ) { + ui->cb_autosync->setChecked( obj["autosync"].toBool() ); + i++; + }; + if ( obj["palette"] != QJsonValue::Undefined ) { + ui->cbPalette->setCurrentIndex( obj["palette"].toInt() ); + i++; + }; + + return i==3; +} + void PaletteView::refresh() { } diff --git a/src/PaletteView.h b/src/PaletteView.h index e7d9e823..36b75b85 100644 --- a/src/PaletteView.h +++ b/src/PaletteView.h @@ -3,18 +3,21 @@ #include "ui_PaletteView.h" #include "MSXPalette.h" +#include "SavesJsonInterface.h" #include #include #include #include class QAbstractButton; +class QJsonObject; + namespace Ui { class PaletteView; } -class PaletteView : public QWidget +class PaletteView : public QWidget , public SavesJsonInterface { Q_OBJECT @@ -27,6 +30,9 @@ class PaletteView : public QWidget void syncToSource(); void setAutoSync(bool value); + QJsonObject save2json() final; + bool loadFromJson(const QJsonObject& obj) final; + public slots: void refresh(); diff --git a/src/SavesJsonInterface.cpp b/src/SavesJsonInterface.cpp new file mode 100644 index 00000000..7ac0578b --- /dev/null +++ b/src/SavesJsonInterface.cpp @@ -0,0 +1,6 @@ +#include "SavesJsonInterface.h" + +SavesJsonInterface::SavesJsonInterface() +{ + +} diff --git a/src/SavesJsonInterface.h b/src/SavesJsonInterface.h new file mode 100644 index 00000000..df3437cf --- /dev/null +++ b/src/SavesJsonInterface.h @@ -0,0 +1,14 @@ +#ifndef SAVESJSONINTERFACE_H +#define SAVESJSONINTERFACE_H + +class QJsonObject; + +class SavesJsonInterface +{ +public: + SavesJsonInterface(); + virtual QJsonObject save2json()=0 ; + virtual bool loadFromJson(const QJsonObject& obj)=0; +}; + +#endif // SAVESJSONINTERFACE_H diff --git a/src/SignalDispatcher.h b/src/SignalDispatcher.h index c9994776..ec6a79e2 100644 --- a/src/SignalDispatcher.h +++ b/src/SignalDispatcher.h @@ -52,7 +52,7 @@ public slots: void breakpointsUpdated(); void debuggablesChanged(const QMap& list); // signals concerning CPU registers - void registersUpdate(uint8_t* datPtr); + void registersUpdate(unsigned char* datPtr); void registerChanged(int id, int value); void pcChanged(uint16_t); void flagsChanged(quint8); diff --git a/src/blendsplitter/ExpanderCorner.cpp b/src/blendsplitter/ExpanderCorner.cpp index 5fb96371..ecac74bf 100644 --- a/src/blendsplitter/ExpanderCorner.cpp +++ b/src/blendsplitter/ExpanderCorner.cpp @@ -8,6 +8,9 @@ #include "SignalDispatcher.h" #include "Settings.h" +#include "SavesJsonInterface.h" +#include + #include ExpanderCorner::ExpanderCorner(WidgetDecorator* parent, Qt::Corner location) @@ -179,6 +182,7 @@ void ExpanderCorner::performInnerSplit(WidgetDecorator* parentDecorator, BlendSp auto& s = Settings::get(); if (s.value("creatingWorkspaceType", 0).toInt()) { addedWidget->setCurrentIndex(switchwdg->getCurrentIndex()); + addedWidget->setWidgetSettings(switchwdg->getWidgetSettings()); } } diff --git a/src/blendsplitter/SwitchingWidget.cpp b/src/blendsplitter/SwitchingWidget.cpp index 2c6a24c1..5005f2d3 100644 --- a/src/blendsplitter/SwitchingWidget.cpp +++ b/src/blendsplitter/SwitchingWidget.cpp @@ -5,6 +5,8 @@ #include "SwitchingBar.h" #include "SwitchingCombo.h" #include "qscrollarea.h" +#include "SavesJsonInterface.h" + #include #include #include @@ -74,6 +76,10 @@ QJsonObject SwitchingWidget::save2json() obj["item"] = bar->combo->currentIndex(); obj["size_width"] = size().width(); obj["size_height"] = size().height(); + QJsonObject childobj = getWidgetSettings(); + if (!childobj.isEmpty()) { + obj["childwidget"] = childobj; + } return obj; } @@ -82,9 +88,46 @@ SwitchingWidget* SwitchingWidget::createFromJson(const QJsonObject &obj) int i = obj["item"].toInt(); auto* wdgt = new SwitchingWidget{WidgetRegistry::instance().item(i)}; wdgt->resize(obj["size_width"].toInt(), obj["size_height"].toInt()); + + + auto* childwdgt = dynamic_cast(wdgt->getWidget()); + if (childwdgt && obj["childwidget"] != QJsonValue::Undefined ) { + childwdgt->loadFromJson(obj["childwidget"].toObject()); + } + return wdgt; } +QWidget *SwitchingWidget::getWidget() +{ + auto* wdgt = widget(widgetIndex()); + + if (isWrappedInScrollArea) { + auto* sa = static_cast(wdgt); + wdgt = sa->widget(); + }; + return wdgt; +} + +QJsonObject SwitchingWidget::getWidgetSettings() +{ + QJsonObject obj; + auto* wd = dynamic_cast(getWidget()); + if (wd) { + obj=wd->save2json(); + } + return obj; +} + +bool SwitchingWidget::setWidgetSettings(const QJsonObject &obj) +{ + auto* wd = dynamic_cast(getWidget()); + if (wd) { + return wd->loadFromJson(obj); + } + return false; +} + void SwitchingWidget::setEnableWidget(bool enable) { widgetEnabled = enable; diff --git a/src/blendsplitter/SwitchingWidget.h b/src/blendsplitter/SwitchingWidget.h index e753f259..61fedcc8 100644 --- a/src/blendsplitter/SwitchingWidget.h +++ b/src/blendsplitter/SwitchingWidget.h @@ -42,6 +42,10 @@ class SwitchingWidget : public QSplitter QJsonObject save2json(); static SwitchingWidget* createFromJson(const QJsonObject& obj); + QWidget* getWidget(); + QJsonObject getWidgetSettings(); + bool setWidgetSettings(const QJsonObject& obj); + public slots: void setEnableWidget(bool enable = true); void setWidgetAlwaysEnabled(bool enable = true); diff --git a/src/node.mk b/src/node.mk index 0650e56c..8531919b 100644 --- a/src/node.mk +++ b/src/node.mk @@ -25,7 +25,7 @@ MOC_SRC_HDR:= \ SRC_HDR:= \ Dasm DasmTables DebuggerData SymbolTable Convert Version \ - CPURegs SimpleHexRequest + CPURegs SimpleHexRequest SavesJsonInterface SRC_ONLY:= \ main From 54d9a0751fe05c43e8bc59b6e90eb54db03c902c Mon Sep 17 00:00:00 2001 From: David Heremans Date: Wed, 18 May 2022 07:48:03 +0200 Subject: [PATCH 36/63] More signal/slot connect rewrites --- src/DebuggerForm.cpp | 145 ++++++++++++++++++++++----------------- src/DisasmViewer.cpp | 7 +- src/DisasmViewer.h | 1 + src/PalettePatch.cpp | 6 +- src/PaletteView.cpp | 23 +++---- src/TabRenamerHelper.cpp | 6 +- 6 files changed, 101 insertions(+), 87 deletions(-) diff --git a/src/DebuggerForm.cpp b/src/DebuggerForm.cpp index 448fbd91..74da8c24 100644 --- a/src/DebuggerForm.cpp +++ b/src/DebuggerForm.cpp @@ -633,7 +633,7 @@ void DebuggerForm::addFloatingSwitchingWidget() { auto& dispatcher = SignalDispatcher::instance(); auto* wdg = new SwitchingWidget(); - connect(&dispatcher, SIGNAL(enableWidget(bool)), wdg, SLOT(setEnableWidget(bool))); + connect(&dispatcher, &SignalDispatcher::enableWidget, wdg, &SwitchingWidget::setEnableWidget); wdg->setEnableWidget(dispatcher.getEnableWidget()); wdg->show(); } @@ -696,13 +696,12 @@ void DebuggerForm::createForm() // Have the SignalDispatcher refresh it data for the widgets in the blendsplitter auto& dispatcher = SignalDispatcher::instance(); - connect(this, SIGNAL(connected()), &dispatcher, SLOT(refresh())); - connect(this, SIGNAL(breakStateEntered()), &dispatcher, SLOT(refresh())); + connect(this, &DebuggerForm::connected, &dispatcher, &SignalDispatcher::refresh); + connect(this, &DebuggerForm::breakStateEntered, &dispatcher, &SignalDispatcher::refresh); //and have it propagate the signals - connect(this, SIGNAL(connected()), &dispatcher, SIGNAL(connected())); - connect(this, SIGNAL(breakStateEntered()), &dispatcher, SIGNAL(breakStateEntered())); - connect(this, SIGNAL(debuggablesChanged(const QMap&)), - &dispatcher, SIGNAL(debuggablesChanged(const QMap&)) ); + connect(this, &DebuggerForm::connected, &dispatcher, &SignalDispatcher::connected); + connect(this, &DebuggerForm::breakStateEntered, &dispatcher, &SignalDispatcher::breakStateEntered); + connect(this, &DebuggerForm::debuggablesChanged, &dispatcher, &SignalDispatcher::debuggablesChanged); connect(this, &DebuggerForm::breakpointsUpdated, &dispatcher, &SignalDispatcher::breakpointsUpdated); // disable all widgets @@ -727,107 +726,127 @@ QWidget* DebuggerForm::widgetFactory(factoryclasses fctwidget) { auto& dispatcher = SignalDispatcher::instance(); - QWidget* wdgt; + QWidget* retwdgt; switch (fctwidget) { case disasmViewer: { - wdgt = new DisasmViewer(); - connect(wdgt, SIGNAL(breakpointToggled(uint16_t)), &dispatcher, SIGNAL(breakpointToggled(uint16_t))); - connect(&dispatcher, SIGNAL(connected()), wdgt, SLOT(refresh())); - connect(&dispatcher, SIGNAL(breakStateEntered()), wdgt, SLOT(refresh())); - connect(&dispatcher, SIGNAL(symbolsChanged()), wdgt, SLOT(refresh())); - connect(&dispatcher, SIGNAL(settingsChanged()), wdgt, SLOT(updateLayout())); - connect(&dispatcher, SIGNAL(setCursorAddress(uint16_t, int, int)), wdgt, SLOT(setCursorAddress(uint16_t, int, int))); - connect(&dispatcher, SIGNAL(setProgramCounter(uint16_t,bool)), wdgt, SLOT(setProgramCounter(uint16_t,bool))); - connect(&dispatcher, SIGNAL(breakpointsUpdated()), wdgt, SLOT(update())); - static_cast(wdgt)->setMemory(dispatcher.getMainMemory()); - static_cast(wdgt)->setBreakpoints(&DebugSession::getDebugSession()->breakpoints()); - static_cast(wdgt)->setMemoryLayout(dispatcher.getMemLayout()); - static_cast(wdgt)->setSymbolTable(&DebugSession::getDebugSession()->symbolTable()); - + DisasmViewer* wdgt = new DisasmViewer(); + connect(wdgt, &DisasmViewer::breakpointToggled, &dispatcher, &SignalDispatcher::breakpointToggled); + connect(&dispatcher, &SignalDispatcher::connected, wdgt, &DisasmViewer::refresh); + connect(&dispatcher, &SignalDispatcher::breakStateEntered, wdgt, &DisasmViewer::refresh); + connect(&dispatcher, &SignalDispatcher::symbolsChanged, wdgt, &DisasmViewer::refresh); + connect(&dispatcher, &SignalDispatcher::settingsChanged, wdgt, &DisasmViewer::updateLayout); + connect(&dispatcher, &SignalDispatcher::setCursorAddress, wdgt, &DisasmViewer::setCursorAddress); + connect(&dispatcher, &SignalDispatcher::setProgramCounter, wdgt, &DisasmViewer::setProgramCounter); + connect(&dispatcher, &SignalDispatcher::breakpointsUpdated, wdgt, &DisasmViewer::update); + wdgt->setMemory(dispatcher.getMainMemory()); + wdgt->setBreakpoints(&DebugSession::getDebugSession()->breakpoints()); + wdgt->setMemoryLayout(dispatcher.getMemLayout()); + wdgt->setSymbolTable(&DebugSession::getDebugSession()->symbolTable()); + retwdgt=wdgt; }; break; case mainMemoryViewer: - wdgt = new MainMemoryViewer(); + { + MainMemoryViewer* wdgt = new MainMemoryViewer(); // Main memory viewer - connect(&dispatcher, SIGNAL(connected()), wdgt, SLOT(refresh())); - connect(&dispatcher, SIGNAL(breakStateEntered()), wdgt, SLOT(refresh())); - connect(&dispatcher, SIGNAL(registerChanged(int, int)), wdgt, SLOT(registerChanged(int, int))); + connect(&dispatcher, &SignalDispatcher::connected, wdgt, &MainMemoryViewer::refresh); + connect(&dispatcher, &SignalDispatcher::breakStateEntered, wdgt, &MainMemoryViewer::refresh); + connect(&dispatcher, &SignalDispatcher::registerChanged, wdgt, &MainMemoryViewer::registerChanged); //mainMemoryView->setRegsView(regsView); - static_cast(wdgt)->setSymbolTable(&DebugSession::getDebugSession()->symbolTable()); - static_cast(wdgt)->setDebuggable("memory", 65536); + wdgt->setSymbolTable(&DebugSession::getDebugSession()->symbolTable()); + wdgt->setDebuggable("memory", 65536); + retwdgt=wdgt; + } break; case cpuRegsViewer: - wdgt = new CPURegsViewer(); + { + CPURegsViewer* wdgt = new CPURegsViewer(); //copy current registers to new widget for (int id = 0; id < 15; ++id) { // CpuRegs::REG_AF up to CpuRegs::REG_IFF static_cast(wdgt)->setRegister(id, dispatcher.readRegister(id)); } - connect(&dispatcher, SIGNAL(registersUpdate(unsigned char*)), wdgt, SLOT(setData(unsigned char*))); + connect(&dispatcher, &SignalDispatcher::registersUpdate, wdgt, &CPURegsViewer::setData); + retwdgt=wdgt; + } break; case flagsViewer: - wdgt = new FlagsViewer(); - static_cast(wdgt)->setFlags(dispatcher.readRegister(CpuRegs::REG_AF) & 0xFF); - connect(&dispatcher, SIGNAL(flagsChanged(quint8)), wdgt, SLOT(setFlags(quint8))); - break; + { + FlagsViewer* wdgt = new FlagsViewer(); + wdgt->setFlags(dispatcher.readRegister(CpuRegs::REG_AF) & 0xFF); + connect(&dispatcher, &SignalDispatcher::flagsChanged, wdgt, &FlagsViewer::setFlags); + retwdgt=wdgt; + } + break; case stackViewer: - wdgt = new StackViewer(); - static_cast(wdgt)->setData(dispatcher.getMainMemory(), 65536); - static_cast(wdgt)->setStackPointer(dispatcher.readRegister(CpuRegs::REG_SP)); - connect(&dispatcher, SIGNAL(spChanged(quint16)), wdgt, SLOT(setStackPointer(quint16))); + { + StackViewer* wdgt = new StackViewer(); + wdgt->setData(dispatcher.getMainMemory(), 65536); + wdgt->setStackPointer(dispatcher.readRegister(CpuRegs::REG_SP)); + connect(&dispatcher, &SignalDispatcher::spChanged, wdgt, &StackViewer::setStackPointer); + retwdgt=wdgt; + } break; case slotViewer: - wdgt = new SlotViewer(); - connect(&dispatcher, SIGNAL(connected()), wdgt, SLOT(refresh())); - connect(&dispatcher, SIGNAL(breakStateEntered()), wdgt, SLOT(refresh())); - connect(&dispatcher, SIGNAL(slotsUpdated(bool)), wdgt, SLOT(refresh())); - static_cast(wdgt)->setMemoryLayout(dispatcher.getMemLayout()); + { + SlotViewer* wdgt = new SlotViewer(); + connect(&dispatcher, &SignalDispatcher::connected, wdgt, &SlotViewer::refresh); + connect(&dispatcher, &SignalDispatcher::breakStateEntered, wdgt, &SlotViewer::refresh); + connect(&dispatcher, &SignalDispatcher::slotsUpdated, wdgt, &SlotViewer::refresh); + wdgt->setMemoryLayout(dispatcher.getMemLayout()); + retwdgt=wdgt; + } break; case breakpointViewer: - wdgt = new BreakpointViewer(); + retwdgt = new BreakpointViewer(); break; case debuggableViewer: - wdgt = new DebuggableViewer(); - connect(&dispatcher, SIGNAL(breakStateEntered()), wdgt, SLOT(refresh())); - connect(&dispatcher, SIGNAL(debuggablesChanged(const QMap&)), - wdgt, SLOT(setDebuggables(const QMap&))); - static_cast(wdgt)->setDebuggables(debuggables); + { + DebuggableViewer* wdgt = new DebuggableViewer(); + connect(&dispatcher, &SignalDispatcher::breakStateEntered, wdgt, &DebuggableViewer::refresh); + connect(&dispatcher, &SignalDispatcher::debuggablesChanged, wdgt, &DebuggableViewer::setDebuggables); + wdgt->setDebuggables(debuggables); if (!debuggables.isEmpty()) { - static_cast(wdgt)->debuggableSelected(0); - static_cast(wdgt)->refresh(); + wdgt->debuggableSelected(0); + wdgt->refresh(); } + retwdgt=wdgt; + } break; case vdpStatusRegViewer: - wdgt = new VDPStatusRegViewer(); + retwdgt = new VDPStatusRegViewer(); break; case vdpCommandRegViewer: - wdgt = new VDPCommandRegViewer(); + retwdgt = new VDPCommandRegViewer(); break; case bitMapViewer: - wdgt = new BitMapViewer(); + retwdgt = new BitMapViewer(); break; case tileViewer: - wdgt = new TileViewer(); + retwdgt = new TileViewer(); break; case spriteViewer: - wdgt = new SpriteViewer(); + retwdgt = new SpriteViewer(); break; case vdpRegisters: - wdgt = new VDPRegViewer(); + retwdgt = new VDPRegViewer(); break; case quickguide: - wdgt = new QuickGuide(); + retwdgt = new QuickGuide(); break; case paletteViewer: - wdgt = new PaletteView(); - connect(&dispatcher, SIGNAL(connected()), wdgt, SLOT(refresh())); - connect(&dispatcher, SIGNAL(breakStateEntered()), wdgt, SLOT(refresh())); + { + PaletteView* wdgt = new PaletteView(); + connect(&dispatcher, &SignalDispatcher::connected, wdgt, &PaletteView::refresh); + connect(&dispatcher, &SignalDispatcher::breakStateEntered, wdgt, &PaletteView::refresh); + retwdgt=wdgt; + } break; default: - wdgt = new QLabel("Not yet implemented in widgetFactory!"); + retwdgt = new QLabel("Not yet implemented in widgetFactory!"); break; } - return wdgt; + return retwdgt; } void DebuggerForm::closeEvent(QCloseEvent* e) diff --git a/src/DisasmViewer.cpp b/src/DisasmViewer.cpp index 60355f3d..21e4ff79 100644 --- a/src/DisasmViewer.cpp +++ b/src/DisasmViewer.cpp @@ -157,7 +157,12 @@ void DisasmViewer::refresh() int end = disasmLines.back().addr + disasmLines.back().numBytes; int infoLine = disasmLines[disasmTopLine].infoLine; - requestMemory(start, end, disasmLines[disasmTopLine].addr, infoLine, TopAlways); + requestMemory(start, end, disasmLines[disasmTopLine].addr, infoLine, TopAlways); +} + +void DisasmViewer::update() +{ + QFrame::update(); } void DisasmViewer::paintEvent(QPaintEvent* e) diff --git a/src/DisasmViewer.h b/src/DisasmViewer.h index 896c5ff4..6332b0ba 100644 --- a/src/DisasmViewer.h +++ b/src/DisasmViewer.h @@ -38,6 +38,7 @@ class DisasmViewer : public QFrame void updateLayout(); void refresh(); + void update(); //connect in DebuggerForm::widgetFactory coudln't directly connect to update of QWidget ?? private: void requestMemory(uint16_t start, uint16_t end, uint16_t addr, int infoLine, int method); int findPosition(uint16_t addr, int infoLine, int method); diff --git a/src/PalettePatch.cpp b/src/PalettePatch.cpp index ca5c21d0..d537a592 100644 --- a/src/PalettePatch.cpp +++ b/src/PalettePatch.cpp @@ -11,12 +11,10 @@ PalettePatch::PalettePatch(QWidget* parent, int palNr) void PalettePatch::setMSXPalette(MSXPalette* pal) { if (myPal != nullptr) { - disconnect(pal, SIGNAL(paletteChanged()), - this, SLOT(paletteChanged())); + disconnect(myPal, &MSXPalette::paletteChanged, this, &PalettePatch::paletteChanged); } myPal = pal; - connect(pal, SIGNAL(paletteChanged()), - this, SLOT(paletteChanged())); + connect(myPal, &MSXPalette::paletteChanged, this, &PalettePatch::paletteChanged); paletteChanged(); } diff --git a/src/PaletteView.cpp b/src/PaletteView.cpp index cdf87dae..d963b771 100644 --- a/src/PaletteView.cpp +++ b/src/PaletteView.cpp @@ -25,23 +25,18 @@ PaletteView::PaletteView(QWidget* parent) for (int i = 0; i < 16; ++i) { auto* button = new PalettePatch(nullptr, i); button->setMSXPalette(myPal); - connect(button, SIGNAL(clicked(bool)), signalMapper, SLOT(map())); + connect(button, &PalettePatch::clicked, signalMapper, qOverload<>(&QSignalMapper::map)); signalMapper->setMapping(button, i); gridLayout->addWidget(button, i / 8, i % 8); - connect(this, SIGNAL(paletteReplaced(MSXPalette*)), - button, SLOT(setMSXPalette(MSXPalette*))); - connect(this, SIGNAL(paletteChanged()), - button, SLOT(paletteChanged())); - connect(signalMapper, SIGNAL(mapped(int)), - button, SLOT(setHighlightTest(int))); + connect(this, &PaletteView::paletteReplaced, button, &PalettePatch::setMSXPalette); + connect(this, &PaletteView::paletteChanged, button, &PalettePatch::paletteChanged); + connect(signalMapper, &QSignalMapper::mappedInt, button, &PalettePatch::setHighlightTest); } - connect(signalMapper, SIGNAL(mapped(int)), - this, SLOT(colorSelected(int))); + connect(signalMapper, &QSignalMapper::mappedInt, this, &PaletteView::colorSelected); ui->colorsframe->setLayout(gridLayout); - connect(this, SIGNAL(paletteChanged()), - this, SLOT(updateText())); + connect(this, &PaletteView::paletteChanged, this, &PaletteView::updateText); updateText(); //select color 0 @@ -51,14 +46,12 @@ PaletteView::PaletteView(QWidget* parent) void PaletteView::setPalette(MSXPalette* sourcePal) { if (myPal != nullptr) { - connect(myPal, SIGNAL(paletteChanged()), - this, SIGNAL(paletteChanged())); + disconnect(myPal, &MSXPalette::paletteChanged, this, &PaletteView::paletteChanged); } myPal = sourcePal; myOriginalPal.copyDataFrom(*sourcePal); - connect(myPal, SIGNAL(paletteChanged()), - this, SIGNAL(paletteChanged())); + connect(myPal, &MSXPalette::paletteChanged, this, &PaletteView::paletteChanged); emit paletteReplaced(sourcePal); } diff --git a/src/TabRenamerHelper.cpp b/src/TabRenamerHelper.cpp index 7972f523..2e8a58a3 100644 --- a/src/TabRenamerHelper.cpp +++ b/src/TabRenamerHelper.cpp @@ -32,8 +32,7 @@ void TabRenamerHelper::tabBarDoubleClicked(int index) tabLineEdit->selectAll(); tabLineEdit->setFocus(); tabLineEdit->installEventFilter(this); - connect(tabLineEdit,SIGNAL(editingFinished()), - this,SLOT(tabNameEditingFinished())); + connect(tabLineEdit,&QLineEdit::editingFinished, this, &TabRenamerHelper::tabNameEditingFinished); } @@ -79,8 +78,7 @@ bool TabRenamerHelper::eventFilter(QObject *obj, QEvent *event) if (obj == tabLineEdit && event->type() == QEvent::KeyPress) { QKeyEvent* ke = static_cast(event); if (ke->key() == Qt::Key_Escape) { - disconnect(tabLineEdit,SIGNAL(editingFinished()), - this,SLOT(tabNameEditingFinished())); + disconnect(tabLineEdit,&QLineEdit::editingFinished, this, &TabRenamerHelper::tabNameEditingFinished); tabLineEdit->deleteLater(); tabLineEdit=nullptr; return true; //no further handling of this event is required From 40e2c9323864ee674840c09536d4e7fd35f2e472 Mon Sep 17 00:00:00 2001 From: David Heremans Date: Thu, 19 May 2022 23:04:34 +0200 Subject: [PATCH 37/63] Extra preferences for autoconnect to openMSX First steps towards an autoconnect feature. The idea is that the debugger can autoconnect if there is only one openMSX running. If there is no running openMSX we should start one. In case of two or more the dialog should pop up. --- src/DebuggerForm.cpp | 12 ++++ src/DebuggerForm.h | 2 + src/PreferencesDialog.cpp | 66 +++++++++++++++-- src/PreferencesDialog.h | 4 ++ src/PreferencesDialog.ui | 146 +++++++++++++++++++++++++++++++++++++- 5 files changed, 223 insertions(+), 7 deletions(-) diff --git a/src/DebuggerForm.cpp b/src/DebuggerForm.cpp index 74da8c24..d325d68f 100644 --- a/src/DebuggerForm.cpp +++ b/src/DebuggerForm.cpp @@ -174,6 +174,9 @@ DebuggerForm::DebuggerForm(QWidget* parent) updateRecentFiles(); connect(&(session->symbolTable()), &SymbolTable::symbolFileChanged, this, &DebuggerForm::symbolFileChanged); + + autoConnectToOpenMSX(); + } void DebuggerForm::createActions() @@ -714,6 +717,15 @@ void DebuggerForm::createForm() session->breakpoints().setMemoryLayout(dispatcher.getMemLayout()); } +void DebuggerForm::autoConnectToOpenMSX() +{ + //TODO actually find out if there is only one connection instead of going through the dialog... + if (Settings::get().value("autoconnect").toBool()) { + systemConnect(); + }; + +} + void DebuggerForm::addDefaultWorkspaces() { addCPUWorkspace(); diff --git a/src/DebuggerForm.h b/src/DebuggerForm.h index 49b0b892..1f694634 100644 --- a/src/DebuggerForm.h +++ b/src/DebuggerForm.h @@ -68,6 +68,8 @@ class DebuggerForm : public QMainWindow void createStatusbar(); void createForm(); + void autoConnectToOpenMSX(); + static QWidget* widgetFactory(factoryclasses fctwidget); void openSession(const QString& file); diff --git a/src/PreferencesDialog.cpp b/src/PreferencesDialog.cpp index c2eb0e8f..dbf0bec7 100644 --- a/src/PreferencesDialog.cpp +++ b/src/PreferencesDialog.cpp @@ -1,17 +1,34 @@ #include "PreferencesDialog.h" #include "Settings.h" #include "DebuggerForm.h" +#include #include #include #include #include +#include +#include PreferencesDialog::PreferencesDialog(QWidget* parent) : QDialog(parent) { setupUi(this); + // Since there is no 'slots' definition in the header anymore we can not use the QMetaObject::connectSlotsByName() in setupUi anymore + // So now we do it explicitely here + connect(leFileName, &QLineEdit::textChanged, this, &PreferencesDialog::on_leFileName_textChanged); + connect(btnSaveLayout, &QPushButton::clicked, this, &PreferencesDialog::on_btnSaveLayout_clicked); + connect(btnBrowseLayout, &QPushButton::clicked, this, &PreferencesDialog::on_btnBrowseLayout_clicked); + + + //openMSX connection stuff + connect(cbAutoconnect, &QCheckBox::toggled, this, &PreferencesDialog::openMSXConnectionChanged); + connect(cbStartIfNoConnection, &QCheckBox::toggled, this, &PreferencesDialog::openMSXConnectionChanged); + connect(leOpenMSXbin, &QLineEdit::editingFinished, this, &PreferencesDialog::openMSXConnectionChanged); + connect(leOpenMSXargs, &QLineEdit::editingFinished, this, &PreferencesDialog::openMSXConnectionChanged); + connect(pbTestCLI, &QPushButton::clicked, this, &PreferencesDialog::testOpenMSXCommandLine); + //font stuff connect(listFonts, &QListWidget::currentRowChanged, @@ -36,14 +53,20 @@ PreferencesDialog::PreferencesDialog(QWidget* parent) connect(rb, &QRadioButton::toggled, this, &PreferencesDialog::layoutTypeChanged); }; -// connect(rbDefaultWorkspaces, &QRadioButton::toggled, -// this, &PreferencesDialog::layoutTypeChanged); -// connect(rbLayoutFromFile, &QRadioButton::toggled, -// this, &PreferencesDialog::layoutTypeChanged); + + //update ui with saved settings updating=true; Settings& s = Settings::get(); rblayouttypes.at(s.value("creatingWorkspaceType",0).toInt())->setChecked(true); leFileName->setText(s.value("creatingWorkspaceFile","").toString()); + + cbAutoconnect->setChecked(s.value("autoconnect",true).toBool()); + cbStartIfNoConnection->setChecked(s.value("startOpenMSX",false).toBool()); + leOpenMSXbin->setText(s.value("openMSXbin","").toString()); + leOpenMSXargs->setText(s.value("openMSXargs","").toString()); + + createCLI(); + updating=false; } @@ -170,6 +193,18 @@ void PreferencesDialog::on_btnBrowseLayout_clicked() } } +void PreferencesDialog::openMSXConnectionChanged() +{ + if (updating) return; + + createCLI(); + Settings& s = Settings::get(); + s.setValue("autoconnect",cbAutoconnect->isChecked()); + s.setValue("startOpenMSX",cbStartIfNoConnection->isChecked()); + s.setValue("openMSXbin",leOpenMSXbin->text()); + s.setValue("openMSXargs",leOpenMSXargs->text()); +} + void PreferencesDialog::on_leFileName_textChanged(const QString &arg1) { if (updating) return; @@ -201,3 +236,26 @@ void PreferencesDialog::on_btnSaveLayout_clicked() } } +void PreferencesDialog::createCLI() +{ + labelCLI->setText(QString("%1 %2") + .arg(leOpenMSXbin->text(),leOpenMSXargs->text()) + ); +} + +void PreferencesDialog::testOpenMSXCommandLine() +{ + QString program = leOpenMSXbin->text(); + QStringList arguments; + if (!leOpenMSXargs->text().trimmed().isEmpty()) { + arguments=leOpenMSXargs->text().trimmed().split(QChar(' '),Qt::SkipEmptyParts); + }; + QProcess *myProcess = new QProcess(qApp); + myProcess->start(program, arguments); + if (!myProcess->waitForStarted() || myProcess->state()!=QProcess::Running) { + QMessageBox::critical(this,"Can not start openMSX", + QString("The command line '%1' doesn't seem to work.\n\n%2").arg(program).arg(myProcess->errorString()) + ); + } +} + diff --git a/src/PreferencesDialog.h b/src/PreferencesDialog.h index 0f8516e9..2717685f 100644 --- a/src/PreferencesDialog.h +++ b/src/PreferencesDialog.h @@ -21,10 +21,14 @@ class PreferencesDialog : public QDialog, private Ui::PreferencesDialog void layoutTypeChanged(bool state); void on_btnBrowseLayout_clicked(); + void openMSXConnectionChanged(); void on_leFileName_textChanged(const QString &arg1); void on_btnSaveLayout_clicked(); + void createCLI(); + void testOpenMSXCommandLine(); + bool updating; }; diff --git a/src/PreferencesDialog.ui b/src/PreferencesDialog.ui index 95d1c18b..70135c9e 100644 --- a/src/PreferencesDialog.ui +++ b/src/PreferencesDialog.ui @@ -23,7 +23,7 @@ - 0 + 1 @@ -162,13 +162,13 @@ - Workspace Layout + Launch options - Behavior at startup + Workspaces at startup @@ -236,6 +236,114 @@ + + + + OpenMSX connection + + + + + + Autoconnect at startup + + + true + + + + + + + true + + + Start openMSX if no connection available at startup + + + + + + + QFrame::NoFrame + + + QFrame::Raised + + + + + + + + + + + + 0 + 0 + + + + + true + + + + Command Line to start openMSX + + + + + + + Test commandline + + + + + + + + + openMSX binary + + + + + + + DO NOT USE FILENAMES WITH SPACES! +There is no way to enter those correctly at the moment + + + + + + + options + + + + + + + + 0 + 0 + + + + command: + + + + + + + + + @@ -303,5 +411,37 @@ + + cbAutoconnect + toggled(bool) + cbStartIfNoConnection + setEnabled(bool) + + + 326 + 258 + + + 326 + 287 + + + + + cbAutoconnect + toggled(bool) + frameCLI + setEnabled(bool) + + + 326 + 258 + + + 326 + 333 + + + From 4f892e3f7b108184f1e761b362a8f777b1f1690b Mon Sep 17 00:00:00 2001 From: David Heremans Date: Thu, 19 May 2022 23:14:12 +0200 Subject: [PATCH 38/63] Fixed missing QMetaObject::connectSlotsByName When the 'slots:' indicator is removed in the header files the names do no longer end up in the QMetaObject. This is not needed with the new Qt5 way of hooking up signal/slots, but the ui files use this to autoconnect the slots to GUI elements by the on__ naming convention. This no longer worked so we are fixing that here. The VDPCommandRegViewer will be fixed more correctly later :-) --- src/BitMapViewer.cpp | 13 +++++++++++++ src/SpriteViewer.cpp | 14 ++++++++++++++ src/TileViewer.cpp | 24 ++++++++++++++++++++++++ src/VDPCommandRegViewer.h | 1 + 4 files changed, 52 insertions(+) diff --git a/src/BitMapViewer.cpp b/src/BitMapViewer.cpp index 109ac2e1..ac0edd48 100644 --- a/src/BitMapViewer.cpp +++ b/src/BitMapViewer.cpp @@ -29,6 +29,19 @@ BitMapViewer::BitMapViewer(QWidget* parent) , screenMod(0) // avoid UMR { setupUi(this); + //no connect slot byname anymore + connect(screenMode, QOverload::of(&QComboBox:: currentIndexChanged), this, &BitMapViewer::on_screenMode_currentIndexChanged); + connect(showPage, QOverload::of(&QComboBox:: currentIndexChanged), this, &BitMapViewer::on_showPage_currentIndexChanged); + connect(linesVisible, QOverload::of(&QComboBox:: currentIndexChanged), this, &BitMapViewer::on_linesVisible_currentIndexChanged); + connect(bgColor, QOverload::of(&QSpinBox::valueChanged), this, &BitMapViewer::on_bgColor_valueChanged); + + connect(useVDPRegisters, &QCheckBox::stateChanged,this, &BitMapViewer::on_useVDPRegisters_stateChanged); + + connect(saveImageButton, &QPushButton::clicked, this, &BitMapViewer::on_saveImageButton_clicked); + connect(editPaletteButton, &QPushButton::clicked, this, &BitMapViewer::on_editPaletteButton_clicked); + connect(useVDPPalette, &QCheckBox::stateChanged, this, &BitMapViewer::on_useVDPPalette_stateChanged); + connect(zoomLevel, QOverload::of(&QDoubleSpinBox::valueChanged), this, &BitMapViewer::on_zoomLevel_valueChanged); + // hand code entering the actual display widget in the scrollarea With // the designer-qt4 there is an extra scrollAreaWidget between the // imageWidget and the QScrollArea so the scrollbars are not correctly diff --git a/src/SpriteViewer.cpp b/src/SpriteViewer.cpp index b8939c67..d615c969 100644 --- a/src/SpriteViewer.cpp +++ b/src/SpriteViewer.cpp @@ -30,6 +30,20 @@ SpriteViewer::SpriteViewer(QWidget* parent) , ui(std::make_unique()) { ui->setupUi(this); + // no more connectbyname + connect(ui->le_patterntable, &QLineEdit::textChanged, this, &SpriteViewer::on_le_patterntable_textChanged); + connect(ui->le_attributentable, &QLineEdit::textChanged, this, &SpriteViewer::on_le_attributentable_textChanged); + connect(ui->useVDPRegisters, &QCheckBox::toggled, this, &SpriteViewer::on_useVDPRegisters_toggled); + connect(ui->cb_size, QOverload::of(&QComboBox::currentIndexChanged), this, &SpriteViewer::on_cb_size_currentIndexChanged); + connect(ui->cb_spritemode, QOverload::of(&QComboBox::currentIndexChanged), this, &SpriteViewer::on_cb_spritemode_currentIndexChanged); + connect(ui->le_colortable, &QLineEdit::textChanged, this, &SpriteViewer::on_le_colortable_textChanged); + connect(ui->sp_zoom, QOverload::of(&QSpinBox::valueChanged), this, &SpriteViewer::on_sp_zoom_valueChanged); + connect(ui->cb_ecinfluence, &QCheckBox::toggled, this, &SpriteViewer::on_cb_ecinfluence_toggled); + connect(ui->cb_mag, QOverload::of(&QComboBox::currentIndexChanged), this, &SpriteViewer::on_cb_mag_currentIndexChanged); + connect(ui->cb_alwaysShowColorTable, &QCheckBox::toggled, this, &SpriteViewer::on_cb_alwaysShowColorTable_toggled); + connect(ui->useVDPPalette, &QCheckBox::stateChanged, this, &SpriteViewer::on_useVDPPalette_stateChanged); + connect(ui->editPaletteButton, &QPushButton::clicked, this, &SpriteViewer::on_editPaletteButton_clicked); + const QFont fixedFont = QFontDatabase::systemFont(QFontDatabase::FixedFont); ui->plainTextEdit->setFont(fixedFont); diff --git a/src/TileViewer.cpp b/src/TileViewer.cpp index 4f8bd986..0f59ecd9 100644 --- a/src/TileViewer.cpp +++ b/src/TileViewer.cpp @@ -33,6 +33,30 @@ TileViewer::TileViewer(QWidget* parent) : QDialog(parent), image4label(32, 32, QImage::Format_RGB32) { setupUi(this); + // No QMetaObject::connectSlotsByName available now since we dropped the slots: in the header; + connect(cb_tilemapsource, QOverload::of(&QComboBox::currentIndexChanged), this, &TileViewer::on_cb_tilemapsource_currentIndexChanged); + connect(cb_screen, QOverload::of(&QComboBox::currentIndexChanged) ,this ,&TileViewer::on_cb_screen_currentIndexChanged); + connect(le_nametable, &QLineEdit::textChanged, this, &TileViewer::on_le_nametable_textChanged); + connect(le_colortable, &QLineEdit::textChanged, this, &TileViewer::on_le_colortable_textChanged); + connect(le_patterntable, &QLineEdit::textChanged, this, &TileViewer::on_le_patterntable_textChanged); + + connect(cb_color0, &QCheckBox::stateChanged, this, &TileViewer::on_cb_color0_stateChanged); + connect(useVDPRegisters, &QCheckBox::stateChanged, this, &TileViewer::on_useVDPRegisters_stateChanged); + + connect(editPaletteButton, &QPushButton::clicked, this, &TileViewer::on_editPaletteButton_clicked); + connect(useVDPPalette, &QCheckBox::stateChanged, this, &TileViewer::on_useVDPPalette_stateChanged); + connect(zoomLevel, QOverload::of(&QDoubleSpinBox::valueChanged), this, &TileViewer::on_zoomLevel_valueChanged); + + connect(cb_drawgrid, &QCheckBox::stateChanged, this, &TileViewer::on_cb_drawgrid_stateChanged); + connect(cb_highlight, &QCheckBox::stateChanged, this, &TileViewer::on_cb_highlight_stateChanged); + connect(sp_highlight, QOverload::of(&QSpinBox::valueChanged), this, &TileViewer::on_sp_highlight_valueChanged); + connect(sp_bordercolor, QOverload::of(&QSpinBox::valueChanged), this, &TileViewer::on_sp_bordercolor_valueChanged); + + connect(cb_blinkcolors, &QCheckBox::stateChanged, this, &TileViewer::on_cb_blinkcolors_stateChanged); + connect(cb_screenrows, QOverload::of(&QComboBox::currentIndexChanged), this, &TileViewer::on_cb_screenrows_currentIndexChanged); + + + const QFont fixedFont = QFontDatabase::systemFont(QFontDatabase::FixedFont); plainTextEdit->setFont(fixedFont); label_charpat->setFont(fixedFont); diff --git a/src/VDPCommandRegViewer.h b/src/VDPCommandRegViewer.h index 696dad00..fc08c131 100644 --- a/src/VDPCommandRegViewer.h +++ b/src/VDPCommandRegViewer.h @@ -143,6 +143,7 @@ class VDPCommandRegViewer : public QDialog, public SimpleHexRequestUser, void refresh(); void R45BitChanged(int); +public slots: //TODO: replace this with qt5 connects void on_lineEdit_r44_editingFinished(); void on_lineEdit_r45_editingFinished(); void on_lineEdit_r46_editingFinished(); From de7df5203e852133483cc9df97a0578af0d6fa18 Mon Sep 17 00:00:00 2001 From: m9710797 Date: Wed, 18 May 2022 19:15:07 +0200 Subject: [PATCH 39/63] layout fixes * Consistent indentation: We currently have a mix of indentation style: sometimes we use 1 tab, sometimes we use 4 spaces. I don't have a strong preference. But do use the same style within a single function (preferably also within the whole file). I guess some code was edited using an editor which did not have tab-stops at 8 spaces. This lead to horribly inconsistent (unreadable) indentation in some functions. * Various typographical conventions: ** no space before comma, space after comma ** space before and after operators ** no space before or after parenthesis --- src/BitMapViewer.cpp | 38 ++-- src/BreakpointViewer.cpp | 8 +- src/ConnectDialog.cpp | 6 +- src/DasmTables.cpp | 4 +- src/DebugSession.h | 1 - src/DebuggableViewer.cpp | 14 +- src/DebuggableViewer.h | 9 +- src/DebuggerForm.cpp | 242 ++++++++++++-------------- src/DisasmViewer.cpp | 18 +- src/DisasmViewer.h | 9 +- src/HexViewer.cpp | 10 +- src/InteractiveButton.cpp | 2 +- src/InteractiveLabel.h | 1 - src/MainMemoryViewer.cpp | 24 +-- src/MainMemoryViewer.h | 2 +- src/PaletteView.cpp | 30 ++-- src/PaletteView.h | 2 +- src/PreferencesDialog.cpp | 176 +++++++++---------- src/PreferencesDialog.h | 18 +- src/SavesJsonInterface.h | 4 +- src/Settings.cpp | 2 +- src/SimpleHexRequest.h | 2 +- src/SlotViewer.cpp | 6 +- src/StackViewer.cpp | 53 +++--- src/SymbolTable.cpp | 14 +- src/TabRenamerHelper.cpp | 71 ++++---- src/TabRenamerHelper.h | 5 +- src/TileViewer.cpp | 2 +- src/VDPCommandRegViewer.cpp | 4 +- src/VDPDataStore.cpp | 6 +- src/VDPRegViewer.cpp | 85 ++++----- src/VramBitMappedView.cpp | 2 +- src/VramTiledView.cpp | 16 +- src/blendsplitter/ExpanderCorner.cpp | 4 +- src/blendsplitter/SwitchingWidget.cpp | 9 +- 35 files changed, 441 insertions(+), 458 deletions(-) diff --git a/src/BitMapViewer.cpp b/src/BitMapViewer.cpp index ac0edd48..302a9720 100644 --- a/src/BitMapViewer.cpp +++ b/src/BitMapViewer.cpp @@ -103,25 +103,25 @@ void BitMapViewer::decodeVDPregs() // Get current screenmode static const int bits_modetxt[128] = { - 1, 3, 0, 255, 2, 255, 255, 255, - 4, 255, 80, 255, 5, 255, 255, 255, - 6, 255, 255, 255, 7, 255, 255, 255, - 255, 255, 255, 255, 8, 255, 255, 255, - - 255, 255, 255, 255,255, 255, 255, 255, - 255, 255, 255, 255,255, 255, 255, 255, - 255, 255, 255, 255,255, 255, 255, 255, - 255, 255, 255, 255, 12, 255, 255, 255, - - 255, 255, 255, 255,255, 255, 255, 255, - 255, 255, 255, 255,255, 255, 255, 255, - 255, 255, 255, 255,255, 255, 255, 255, - 255, 255, 255, 255,255, 255, 255, 255, - - 255, 255, 255, 255,255, 255, 255, 255, - 255, 255, 255, 255,255, 255, 255, 255, - 255, 255, 255, 255,255, 255, 255, 255, - 255, 255, 255, 255, 11, 255, 255, 255, + 1, 3, 0, 255, 2, 255, 255, 255, + 4, 255, 80, 255, 5, 255, 255, 255, + 6, 255, 255, 255, 7, 255, 255, 255, + 255, 255, 255, 255, 8, 255, 255, 255, + + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 12, 255, 255, 255, + + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 11, 255, 255, 255, }; static const int bits_mode[128] = { 0, 0, 0, 0, 0, 0, 0, 0, diff --git a/src/BreakpointViewer.cpp b/src/BreakpointViewer.cpp index 0731e25a..95b183f3 100644 --- a/src/BreakpointViewer.cpp +++ b/src/BreakpointViewer.cpp @@ -315,7 +315,7 @@ std::optional BreakpointViewer::parseLocationField( QStringList s = field.simplified().split(":", Qt::SplitBehaviorFlags::SkipEmptyParts); auto begin = s.size() >= 1 ? stringToValue(s[0]) : std::nullopt; - auto end = s.size() == 2 ? stringToValue(s[1]) : std::nullopt; + auto end = s.size() == 2 ? stringToValue(s[1]) : std::nullopt; auto it = ranges::find(ComboTypeNames, comboTxt); auto wType = static_cast(std::distance(ComboTypeNames, it) + 1); if ((wType == Breakpoint::WATCHPOINT_IOREAD || wType == Breakpoint::WATCHPOINT_IOWRITE) @@ -430,16 +430,16 @@ void BreakpointViewer::changeTableItem(BreakpointRef::Type type, QTableWidgetIte void BreakpointViewer::disableSorting(BreakpointRef::Type type) { - auto unsort = [](auto* table) { + auto unSort = [](auto* table) { table->sortByColumn(-1, Qt::AscendingOrder); }; if (type == BreakpointRef::ALL) { for (auto* table : tables) { - unsort(table); + unSort(table); } } else { - unsort(tables[type]); + unSort(tables[type]); } } diff --git a/src/ConnectDialog.cpp b/src/ConnectDialog.cpp index cfa7085c..42f755b5 100644 --- a/src/ConnectDialog.cpp +++ b/src/ConnectDialog.cpp @@ -149,9 +149,9 @@ static std::vector> collectServers() #ifdef _WIN32 DWORD len = GetTempPathW(0, nullptr); assert(len > 0); // nothing we can do to recover this - //VLA(wchar_t, bufW, (len+1)); - //wchar_t bufW[len+1]; - auto bufW = static_cast(_alloca(sizeof(wchar_t) * (len+1))); + //VLA(wchar_t, bufW, (len + 1)); + //wchar_t bufW[len + 1]; + auto bufW = static_cast(_alloca(sizeof(wchar_t) * (len + 1))); len = GetTempPathW(len, bufW); assert(len > 0); // nothing we can do to recover this diff --git a/src/DasmTables.cpp b/src/DasmTables.cpp index f1e7ef86..17a1f61f 100644 --- a/src/DasmTables.cpp +++ b/src/DasmTables.cpp @@ -7,8 +7,8 @@ * B - Byte value * R - Relative jump offset * W - Word value - * X - Indexed address ( 3 byte ) - * Y - Indexed address ( 4 byte ) + * X - Indexed address (3 byte) + * Y - Indexed address (4 byte) * I - IX or IY register * ! - Invalid opcode * @ - Invalid opcode diff --git a/src/DebugSession.h b/src/DebugSession.h index c65f0b76..dc74cc82 100644 --- a/src/DebugSession.h +++ b/src/DebugSession.h @@ -29,7 +29,6 @@ class DebugSession : public QObject Breakpoints& breakpoints(); SymbolTable& symbolTable(); -// slots: void sessionModified(); private: diff --git a/src/DebuggableViewer.cpp b/src/DebuggableViewer.cpp index 1aff90b2..aaa9daee 100644 --- a/src/DebuggableViewer.cpp +++ b/src/DebuggableViewer.cpp @@ -21,24 +21,24 @@ DebuggableViewer::DebuggableViewer(QWidget* parent) vbox->addWidget(debuggableList); vbox->addWidget(hexView); setLayout(vbox); - + connect(hexView, &HexViewer::locationChanged, this, &DebuggableViewer::locationChanged); } QJsonObject DebuggableViewer::save2json() { - QJsonObject obj; - obj["debuggable"]=debuggableList->currentText(); - return obj; + QJsonObject obj; + obj["debuggable"] = debuggableList->currentText(); + return obj; } bool DebuggableViewer::loadFromJson(const QJsonObject &obj) { - if ( obj["debuggable"] == QJsonValue::Undefined ) return false; + if (obj["debuggable"] == QJsonValue::Undefined) return false; - debuggableList->setCurrentText(obj["debuggable"].toString() ); - return true; + debuggableList->setCurrentText(obj["debuggable"].toString()); + return true; } void DebuggableViewer::settingsChanged() diff --git a/src/DebuggableViewer.h b/src/DebuggableViewer.h index e0601a7f..fbf0ebf6 100644 --- a/src/DebuggableViewer.h +++ b/src/DebuggableViewer.h @@ -7,16 +7,15 @@ class HexViewer; class QComboBox; -class DebuggableViewer : public QWidget , public SavesJsonInterface +class DebuggableViewer : public QWidget, public SavesJsonInterface { Q_OBJECT public: DebuggableViewer(QWidget* parent = nullptr); - QJsonObject save2json() override; - bool loadFromJson(const QJsonObject& obj) override; + QJsonObject save2json() override; + bool loadFromJson(const QJsonObject& obj) override; -//slots void settingsChanged(); void setDebuggables(const QMap& list); void refresh(); @@ -30,7 +29,7 @@ class DebuggableViewer : public QWidget , public SavesJsonInterface QString lastSelected; int lastLocation; -friend class DebuggerForm; // to get to debuggableSelected from the widgetFactory + friend class DebuggerForm; // to get to debuggableSelected from the widgetFactory }; #endif // DEBUGGABLEVIEWER_H diff --git a/src/DebuggerForm.cpp b/src/DebuggerForm.cpp index d325d68f..d3eb2320 100644 --- a/src/DebuggerForm.cpp +++ b/src/DebuggerForm.cpp @@ -160,9 +160,9 @@ int DebuggerForm::counter = 0; DebuggerForm::DebuggerForm(QWidget* parent) : QMainWindow(parent) - , comm(CommClient::instance()) + , comm(CommClient::instance()) { - session = DebugSession::getDebugSession(); + session = DebugSession::getDebugSession(); createActions(); createMenus(); @@ -173,9 +173,9 @@ DebuggerForm::DebuggerForm(QWidget* parent) recentFiles = Settings::get().value("MainWindow/RecentFiles").toStringList(); updateRecentFiles(); - connect(&(session->symbolTable()), &SymbolTable::symbolFileChanged, this, &DebuggerForm::symbolFileChanged); + connect(&(session->symbolTable()), &SymbolTable::symbolFileChanged, this, &DebuggerForm::symbolFileChanged); - autoConnectToOpenMSX(); + autoConnectToOpenMSX(); } @@ -190,21 +190,19 @@ void DebuggerForm::createActions() fileSaveSessionAction = new QAction(tr("&Save Session"), this); fileSaveSessionAction->setShortcut(tr("Ctrl+S")); - fileSaveSessionAction->setStatusTip(tr("Save the current debug session")); + fileSaveSessionAction->setStatusTip(tr("Save the current debug session")); fileSaveSessionAsAction = new QAction(tr("Save Session &As"), this); fileSaveSessionAsAction->setStatusTip(tr("Save the debug session in a selected file")); - fileOpenWorkspaceLayoutAction = new QAction(tr("&Open workspaces"), this); - fileOpenWorkspaceLayoutAction->setStatusTip(tr("Load a workspace layout.")); - - fileSaveWorkspaceLayoutAction = new QAction(tr("&Save workspaces"), this); - fileSaveWorkspaceLayoutAction->setStatusTip(tr("Save the current workspaces and splitters layout")); - - fileSaveWorkspaceLayoutAsAction = new QAction(tr("Save workspaces &As"), this); - fileSaveWorkspaceLayoutAsAction->setStatusTip(tr("Save the current workspaces and splitters in a selected file")); + fileOpenWorkspaceLayoutAction = new QAction(tr("&Open workspaces"), this); + fileOpenWorkspaceLayoutAction->setStatusTip(tr("Load a workspace layout.")); + fileSaveWorkspaceLayoutAction = new QAction(tr("&Save workspaces"), this); + fileSaveWorkspaceLayoutAction->setStatusTip(tr("Save the current workspaces and splitters layout")); + fileSaveWorkspaceLayoutAsAction = new QAction(tr("Save workspaces &As"), this); + fileSaveWorkspaceLayoutAsAction->setStatusTip(tr("Save the current workspaces and splitters in a selected file")); fileQuitAction = new QAction(tr("&Quit"), this); @@ -249,7 +247,7 @@ void DebuggerForm::createActions() searchGotoAction->setStatusTip(tr("Jump to a specific address or label in the disassembly view")); searchGotoAction->setShortcut(tr("Ctrl+G")); - executeBreakAction = new QAction(tr("Break"), this); + executeBreakAction = new QAction(tr("Break"), this); executeBreakAction->setShortcut(tr("CRTL+B")); executeBreakAction->setStatusTip(tr("Halt the execution and enter debug mode")); executeBreakAction->setIcon(QIcon(":/icons/break.png")); @@ -298,30 +296,30 @@ void DebuggerForm::createActions() connect(this, &DebuggerForm::breakStateEntered, [this]{ executeStepBackAction->setEnabled(true); }); breakpointAddAction = new QAction(tr("Add ..."), this); - //now that we have possible multiple disasmviewers the disasmview->getCursorAddr() will not work anymore -// breakpointAddAction->setShortcut(tr("CTRL+B")); -// breakpointAddAction->setStatusTip(tr("Add a breakpoint at a location")); -// breakpointAddAction->setEnabled(false); + // now that we have possible multiple disasmviewers the disasmview->getCursorAddr() will not work anymore + //breakpointAddAction->setShortcut(tr("CTRL+B")); + //breakpointAddAction->setStatusTip(tr("Add a breakpoint at a location")); + //breakpointAddAction->setEnabled(false); helpAboutAction = new QAction(tr("&About"), this); - addCPUWorkspaceAction = new QAction(tr("&Code debugger"), this); - addCPUWorkspaceAction->setStatusTip(tr("The default way of debugging CPU code")); + addCPUWorkspaceAction = new QAction(tr("&Code debugger"), this); + addCPUWorkspaceAction->setStatusTip(tr("The default way of debugging CPU code")); - addVDPRegsWorkspaceAction = new QAction(tr("VDP &Regs"), this); - addVDPRegsWorkspaceAction->setStatusTip(tr("Show the regular VDP registers")); + addVDPRegsWorkspaceAction = new QAction(tr("VDP &Regs"), this); + addVDPRegsWorkspaceAction->setStatusTip(tr("Show the regular VDP registers")); - addVDPTilesWorkspaceAction = new QAction(tr("VDP &Tiles"), this); - addVDPTilesWorkspaceAction->setStatusTip(tr("Show the VRAM in tiles")); + addVDPTilesWorkspaceAction = new QAction(tr("VDP &Tiles"), this); + addVDPTilesWorkspaceAction->setStatusTip(tr("Show the VRAM in tiles")); - addVDPBitmapWorkspaceAction = new QAction(tr("VDP &Bitmap"), this); - addVDPBitmapWorkspaceAction->setStatusTip(tr("Show the VRAM in bitmap mode")); + addVDPBitmapWorkspaceAction = new QAction(tr("VDP &Bitmap"), this); + addVDPBitmapWorkspaceAction->setStatusTip(tr("Show the VRAM in bitmap mode")); - addEmptyWorkspaceAction = new QAction(tr("&Empty workspace"), this); - addEmptyWorkspaceAction->setStatusTip(tr("create an almost empty workspace")); + addEmptyWorkspaceAction = new QAction(tr("&Empty workspace"), this); + addEmptyWorkspaceAction->setStatusTip(tr("create an almost empty workspace")); - addFloatingSwitchingWidgetAction = new QAction(tr("&Create floating item"), this); - addFloatingSwitchingWidgetAction->setStatusTip(tr("Create item in seperate window")); + addFloatingSwitchingWidgetAction = new QAction(tr("&Create floating item"), this); + addFloatingSwitchingWidgetAction->setStatusTip(tr("Create item in seperate window")); connect(fileNewSessionAction, &QAction::triggered, this, &DebuggerForm::fileNewSession); @@ -329,9 +327,9 @@ void DebuggerForm::createActions() connect(fileSaveSessionAction, &QAction::triggered, this, &DebuggerForm::fileSaveSession); connect(fileSaveSessionAsAction, &QAction::triggered, this, &DebuggerForm::fileSaveSessionAs); - connect(fileOpenWorkspaceLayoutAction, &QAction::triggered, this, &DebuggerForm::fileOpenWorkspace); - connect(fileSaveWorkspaceLayoutAction, &QAction::triggered, this, &DebuggerForm::fileSaveWorkspace); - connect(fileSaveWorkspaceLayoutAsAction, &QAction::triggered, this, &DebuggerForm::fileSaveWorkspaceAs); + connect(fileOpenWorkspaceLayoutAction, &QAction::triggered, this, &DebuggerForm::fileOpenWorkspace); + connect(fileSaveWorkspaceLayoutAction, &QAction::triggered, this, &DebuggerForm::fileSaveWorkspace); + connect(fileSaveWorkspaceLayoutAsAction, &QAction::triggered, this, &DebuggerForm::fileSaveWorkspaceAs); connect(fileQuitAction, &QAction::triggered, this, &DebuggerForm::close); connect(systemConnectAction, &QAction::triggered, this, &DebuggerForm::systemConnect); @@ -342,19 +340,19 @@ void DebuggerForm::createActions() connect(systemPreferencesAction, &QAction::triggered, this, &DebuggerForm::systemPreferences); connect(searchGotoAction, &QAction::triggered, this, &DebuggerForm::searchGoto); - connect(executeBreakAction, &QAction::triggered, this, &DebuggerForm::executeBreak); + connect(executeBreakAction, &QAction::triggered, this, &DebuggerForm::executeBreak); connect(executeRunAction, &QAction::triggered, this, &DebuggerForm::executeRun); connect(executeStepAction, &QAction::triggered, this, &DebuggerForm::executeStep); connect(executeStepOverAction, &QAction::triggered, this, &DebuggerForm::executeStepOver); connect(executeStepOutAction, &QAction::triggered, this, &DebuggerForm::executeStepOut); connect(executeStepBackAction, &QAction::triggered, this, &DebuggerForm::executeStepBack); connect(helpAboutAction, &QAction::triggered, this, &DebuggerForm::showAbout); - connect(addCPUWorkspaceAction, &QAction::triggered, this, &DebuggerForm::addCPUWorkspace); - connect(addVDPRegsWorkspaceAction, &QAction::triggered, this, &DebuggerForm::addVDPRegsWorkspace); - connect(addVDPTilesWorkspaceAction, &QAction::triggered, this, &DebuggerForm::addVDPTilesWorkspace); - connect(addVDPBitmapWorkspaceAction, &QAction::triggered, this, &DebuggerForm::addVDPBitmapWorkspace); - connect(addEmptyWorkspaceAction, &QAction::triggered, this, &DebuggerForm::addEmptyWorkspace); - connect(addFloatingSwitchingWidgetAction, &QAction::triggered, this, &DebuggerForm::addFloatingSwitchingWidget); + connect(addCPUWorkspaceAction, &QAction::triggered, this, &DebuggerForm::addCPUWorkspace); + connect(addVDPRegsWorkspaceAction, &QAction::triggered, this, &DebuggerForm::addVDPRegsWorkspace); + connect(addVDPTilesWorkspaceAction, &QAction::triggered, this, &DebuggerForm::addVDPTilesWorkspace); + connect(addVDPBitmapWorkspaceAction, &QAction::triggered, this, &DebuggerForm::addVDPBitmapWorkspace); + connect(addEmptyWorkspaceAction, &QAction::triggered, this, &DebuggerForm::addEmptyWorkspace); + connect(addFloatingSwitchingWidgetAction, &QAction::triggered, this, &DebuggerForm::addFloatingSwitchingWidget); } void DebuggerForm::createMenus() @@ -365,16 +363,16 @@ void DebuggerForm::createMenus() fileMenu->addAction(fileOpenSessionAction); fileMenu->addAction(fileSaveSessionAction); fileMenu->addAction(fileSaveSessionAsAction); - fileMenu->addSeparator(); - fileMenu->addAction(fileOpenWorkspaceLayoutAction); -// fileMenu->addAction(fileSaveWorkspaceLayoutAction); - fileMenu->addAction(fileSaveWorkspaceLayoutAsAction); - fileMenu->addSeparator(); + fileMenu->addSeparator(); + fileMenu->addAction(fileOpenWorkspaceLayoutAction); + //fileMenu->addAction(fileSaveWorkspaceLayoutAction); + fileMenu->addAction(fileSaveWorkspaceLayoutAsAction); + fileMenu->addSeparator(); recentFileSeparator = fileMenu->addSeparator(); - for (auto* rfa : recentFileActions) + for (auto* rfa : recentFileActions) { fileMenu->addAction(rfa); - + } fileMenu->addSeparator(); fileMenu->addAction(fileQuitAction); @@ -407,7 +405,7 @@ void DebuggerForm::createMenus() // create breakpoint menu breakpointMenu = menuBar()->addMenu(tr("&Breakpoint")); - //breakpointMenu->addAction(breakpointToggleAction); + //breakpointMenu->addAction(breakpointToggleAction); breakpointMenu->addAction(breakpointAddAction); // create help menu @@ -435,7 +433,7 @@ void DebuggerForm::createToolbars() executeToolbar->addAction(executeStepOverAction); executeToolbar->addAction(executeStepOutAction); executeToolbar->addAction(executeStepBackAction); - //executeToolbar->addAction(executeRunToAction); + //executeToolbar->addAction(executeRunToAction); } void DebuggerForm::createStatusbar() @@ -451,12 +449,12 @@ void DebuggerForm::createWidgetRegistry() //0: register the disasm viewer widget registry.addItem(new RegistryItem{ tr("Code view"), - [] { return widgetFactory( disasmViewer); }}); + [] { return widgetFactory(disasmViewer); }}); //1: register the memory view widget registry.addItem(new RegistryItem{ tr("Main memory"), - [] { return widgetFactory( mainMemoryViewer); }}); + [] { return widgetFactory(mainMemoryViewer); }}); //2: register the register viewer registry.addItem(new RegistryItem{ @@ -593,7 +591,7 @@ void DebuggerForm::tabCloseRequest(int index) return; } if (workspaces->count() > 1) { - QWidget *splitter=workspaces->widget(index); + QWidget* splitter = workspaces->widget(index); workspaces->removeTab(index); delete splitter; } @@ -653,8 +651,8 @@ void DebuggerForm::createForm() workspaces->setMinimumHeight(500); workspaces->setTabsClosable(true); workspaces->setMovable(true); - QMenu *workspacemenu=new QMenu(); - QMenu *workspacesubmenu=new QMenu("Predefined layouts"); + QMenu* workspacemenu = new QMenu(); + QMenu* workspacesubmenu = new QMenu("Predefined layouts"); workspacesubmenu->addAction(addCPUWorkspaceAction); workspacesubmenu->addAction(addVDPRegsWorkspaceAction); workspacesubmenu->addAction(addVDPTilesWorkspaceAction); @@ -666,20 +664,20 @@ void DebuggerForm::createForm() workspacemenu->addAction(addFloatingSwitchingWidgetAction); QIcon icon = QIcon::fromTheme(QLatin1String("window-new")); - QToolButton *btn = new QToolButton(); + QToolButton* btn = new QToolButton(); btn->setIcon(icon); btn->setMenu(workspacemenu); btn->setPopupMode(QToolButton::InstantPopup); workspaces->setCornerWidget(btn, Qt::TopRightCorner); connect(workspaces, &QTabWidget::tabCloseRequested, this, &DebuggerForm::tabCloseRequest); - QWidget *window = new QWidget; - QVBoxLayout *layout = new QVBoxLayout; + QWidget* window = new QWidget; + QVBoxLayout* layout = new QVBoxLayout; layout->addWidget(workspaces); window->setLayout(layout); Settings& s = Settings::get(); - int workspacetype =s.value("creatingWorkspaceType", 0).toInt(); + int workspacetype = s.value("creatingWorkspaceType", 0).toInt(); switch (workspacetype) { case 0: addInfoWorkspace(); @@ -740,8 +738,7 @@ QWidget* DebuggerForm::widgetFactory(factoryclasses fctwidget) QWidget* retwdgt; switch (fctwidget) { - case disasmViewer: - { + case disasmViewer: { DisasmViewer* wdgt = new DisasmViewer(); connect(wdgt, &DisasmViewer::breakpointToggled, &dispatcher, &SignalDispatcher::breakpointToggled); connect(&dispatcher, &SignalDispatcher::connected, wdgt, &DisasmViewer::refresh); @@ -755,11 +752,10 @@ QWidget* DebuggerForm::widgetFactory(factoryclasses fctwidget) wdgt->setBreakpoints(&DebugSession::getDebugSession()->breakpoints()); wdgt->setMemoryLayout(dispatcher.getMemLayout()); wdgt->setSymbolTable(&DebugSession::getDebugSession()->symbolTable()); - retwdgt=wdgt; - }; + retwdgt = wdgt; break; - case mainMemoryViewer: - { + } + case mainMemoryViewer: { MainMemoryViewer* wdgt = new MainMemoryViewer(); // Main memory viewer connect(&dispatcher, &SignalDispatcher::connected, wdgt, &MainMemoryViewer::refresh); @@ -768,52 +764,47 @@ QWidget* DebuggerForm::widgetFactory(factoryclasses fctwidget) //mainMemoryView->setRegsView(regsView); wdgt->setSymbolTable(&DebugSession::getDebugSession()->symbolTable()); wdgt->setDebuggable("memory", 65536); - retwdgt=wdgt; - } + retwdgt = wdgt; break; - case cpuRegsViewer: - { + } + case cpuRegsViewer: { CPURegsViewer* wdgt = new CPURegsViewer(); //copy current registers to new widget for (int id = 0; id < 15; ++id) { // CpuRegs::REG_AF up to CpuRegs::REG_IFF static_cast(wdgt)->setRegister(id, dispatcher.readRegister(id)); } connect(&dispatcher, &SignalDispatcher::registersUpdate, wdgt, &CPURegsViewer::setData); - retwdgt=wdgt; - } + retwdgt = wdgt; break; - case flagsViewer: - { + } + case flagsViewer: { FlagsViewer* wdgt = new FlagsViewer(); wdgt->setFlags(dispatcher.readRegister(CpuRegs::REG_AF) & 0xFF); connect(&dispatcher, &SignalDispatcher::flagsChanged, wdgt, &FlagsViewer::setFlags); - retwdgt=wdgt; + retwdgt = wdgt; + break; } - break; - case stackViewer: - { + case stackViewer: { StackViewer* wdgt = new StackViewer(); wdgt->setData(dispatcher.getMainMemory(), 65536); wdgt->setStackPointer(dispatcher.readRegister(CpuRegs::REG_SP)); connect(&dispatcher, &SignalDispatcher::spChanged, wdgt, &StackViewer::setStackPointer); - retwdgt=wdgt; - } + retwdgt = wdgt; break; - case slotViewer: - { + } + case slotViewer: { SlotViewer* wdgt = new SlotViewer(); connect(&dispatcher, &SignalDispatcher::connected, wdgt, &SlotViewer::refresh); connect(&dispatcher, &SignalDispatcher::breakStateEntered, wdgt, &SlotViewer::refresh); connect(&dispatcher, &SignalDispatcher::slotsUpdated, wdgt, &SlotViewer::refresh); wdgt->setMemoryLayout(dispatcher.getMemLayout()); - retwdgt=wdgt; - } + retwdgt = wdgt; break; + } case breakpointViewer: retwdgt = new BreakpointViewer(); break; - case debuggableViewer: - { + case debuggableViewer: { DebuggableViewer* wdgt = new DebuggableViewer(); connect(&dispatcher, &SignalDispatcher::breakStateEntered, wdgt, &DebuggableViewer::refresh); connect(&dispatcher, &SignalDispatcher::debuggablesChanged, wdgt, &DebuggableViewer::setDebuggables); @@ -822,9 +813,9 @@ QWidget* DebuggerForm::widgetFactory(factoryclasses fctwidget) wdgt->debuggableSelected(0); wdgt->refresh(); } - retwdgt=wdgt; - } + retwdgt = wdgt; break; + } case vdpStatusRegViewer: retwdgt = new VDPStatusRegViewer(); break; @@ -846,14 +837,13 @@ QWidget* DebuggerForm::widgetFactory(factoryclasses fctwidget) case quickguide: retwdgt = new QuickGuide(); break; - case paletteViewer: - { + case paletteViewer: { PaletteView* wdgt = new PaletteView(); connect(&dispatcher, &SignalDispatcher::connected, wdgt, &PaletteView::refresh); connect(&dispatcher, &SignalDispatcher::breakStateEntered, wdgt, &PaletteView::refresh); - retwdgt=wdgt; - } + retwdgt = wdgt; break; + } default: retwdgt = new QLabel("Not yet implemented in widgetFactory!"); break; @@ -1191,24 +1181,24 @@ void DebuggerForm::fileSaveWorkspace() QString DebuggerForm::fileSaveWorkspaceAs() { - QFileDialog d(this, tr("Save workspace layout")); - d.setNameFilter(tr("Debug Workspace Layout Files (*.omdl)")); - d.setDefaultSuffix("omdl"); - d.setDirectory(QDir::currentPath()); - d.setAcceptMode(QFileDialog::AcceptSave); - d.setFileMode(QFileDialog::AnyFile); - QString filename; - if (d.exec()) { -// session->saveAs(d.selectedFiles().at(0)); - filename=d.selectedFiles().at(0); - saveWorkspacesAs(filename); - // update recent -// if (session->existsAsFile()) { -// addRecentFile(session->filename()); -// } - } - updateWindowTitle(); - return filename; + QFileDialog d(this, tr("Save workspace layout")); + d.setNameFilter(tr("Debug Workspace Layout Files (*.omdl)")); + d.setDefaultSuffix("omdl"); + d.setDirectory(QDir::currentPath()); + d.setAcceptMode(QFileDialog::AcceptSave); + d.setFileMode(QFileDialog::AnyFile); + QString filename; + if (d.exec()) { + //session->saveAs(d.selectedFiles().at(0)); + filename = d.selectedFiles().at(0); + saveWorkspacesAs(filename); + // update recent + //if (session->existsAsFile()) { + // addRecentFile(session->filename()); + //} + } + updateWindowTitle(); + return filename; } void DebuggerForm::systemConnect() @@ -1262,11 +1252,11 @@ void DebuggerForm::searchGoto() auto& dispatcher = SignalDispatcher::instance(); GotoDialog gtd(*dispatcher.getMemLayout(), session, this); if (gtd.exec()) { - if (auto addr = gtd.address() ){ - if (addr.has_value()) { - //disasmView->setCursorAddress(addr, 0, DisasmViewer::MiddleAlways); - dispatcher.setCursorAddress(addr.value(), 0, DisasmViewer::MiddleAlways); - } + if (auto addr = gtd.address()) { + if (addr.has_value()) { + //disasmView->setCursorAddress(addr, 0, DisasmViewer::MiddleAlways); + dispatcher.setCursorAddress(addr.value(), 0, DisasmViewer::MiddleAlways); + } } } } @@ -1433,22 +1423,21 @@ bool DebuggerForm::saveWorkspacesAs(const QString &newFileName) tr("Cannot write file %1:\n%2.") .arg(newFileName, file.errorString())); return false; - }; + } QJsonObject jsonObj; QJsonArray spacesArray; //iterate over workspaces - for (int i=0;icount();i++){ + for (int i = 0; i < workspaces->count(); ++i) { QJsonObject jsonTab; - jsonTab["name"]=workspaces->tabText(i); - jsonTab["workspace"]=static_cast(workspaces->widget(i))->save2json(); + jsonTab["name"] = workspaces->tabText(i); + jsonTab["workspace"] = static_cast(workspaces->widget(i))->save2json(); spacesArray.append(jsonTab); - }; - jsonObj["workspaces"]=spacesArray; + } + jsonObj["workspaces"] = spacesArray; QJsonDocument jsonDoc(jsonObj); file.write(jsonDoc.toJson()); // file.close(); done automatically when going out of scope return true; - } bool DebuggerForm::loadWorkspaces(const QString &filename) @@ -1459,21 +1448,20 @@ bool DebuggerForm::loadWorkspaces(const QString &filename) tr("Cannot read file %1:\n%2.") .arg(filename, file.errorString())); return false; - }; + } //Now try to parse the json file QJsonParseError parseError; - QJsonDocument jsonDoc=QJsonDocument::fromJson(file.readAll(), &parseError); + QJsonDocument jsonDoc = QJsonDocument::fromJson(file.readAll(), &parseError); if (parseError.error != QJsonParseError::NoError) { QMessageBox::warning(nullptr, tr("Open workspaces ..."), - tr("Parse error at %1:%2.").arg(QString::number(parseError.offset), parseError.errorString()) - ); + tr("Parse error at %1:%2.").arg(QString::number(parseError.offset), parseError.errorString())); return false; - }; + } // delete all the current tabs before reading the new ones - while(workspaces->count()) { + while (workspaces->count()) { delete workspaces->widget(0); - }; + } //now recreate workspaces QJsonObject obj = jsonDoc.object(); for (const auto& value : obj["workspaces"].toArray()) { diff --git a/src/DisasmViewer.cpp b/src/DisasmViewer.cpp index 21e4ff79..7589742f 100644 --- a/src/DisasmViewer.cpp +++ b/src/DisasmViewer.cpp @@ -197,7 +197,7 @@ void DisasmViewer::paintEvent(QPaintEvent* e) while (y < height() - frameB) { // fetch the data for this line row = displayDisasm - ? &disasmLines[disasmTopLine+visibleLines] + ? &disasmLines[disasmTopLine + visibleLines] : &DISABLED_ROW; int h, a; switch (row->rowType) { @@ -212,7 +212,7 @@ void DisasmViewer::paintEvent(QPaintEvent* e) } // draw cursor line - bool isCursorLine = cursorAddr >= row->addr && cursorAddr < row->addr+row->numBytes && + bool isCursorLine = cursorAddr >= row->addr && cursorAddr < row->addr + row->numBytes && row->infoLine == cursorLine; if (isCursorLine) { cursorAddr = row->addr; @@ -280,7 +280,7 @@ void DisasmViewer::paintEvent(QPaintEvent* e) y += h; ++visibleLines; // check for end of data - if (disasmTopLine+visibleLines == int(disasmLines.size())) break; + if (disasmTopLine + visibleLines == int(disasmLines.size())) break; } partialBottomLine = y > height() - frameB; visibleLines -= partialBottomLine; @@ -333,7 +333,7 @@ int DisasmViewer::findPosition(uint16_t addr, int infoLine, int method) void DisasmViewer::setAddress(uint16_t addr, int infoLine, int method) { - qDebug() << "void DisasmViewer::setAddress(uint16_t addr "< 9 ? visibleLines+partialBottomLine : 10); + int extra = 4 * (visibleLines > 9 ? visibleLines + partialBottomLine : 10); switch (method) { case Middle: case MiddleAlways: @@ -591,7 +591,7 @@ void DisasmViewer::keyPressEvent(QKeyEvent* e) } case Qt::Key_PageUp: { int line = findDisasmLine(cursorAddr, cursorLine); - if (line >= disasmTopLine && line < disasmTopLine+visibleLines) { + if (line >= disasmTopLine && line < disasmTopLine + visibleLines) { line -= visibleLines; if (line >= 0) { cursorAddr = disasmLines[line].addr; @@ -611,7 +611,7 @@ void DisasmViewer::keyPressEvent(QKeyEvent* e) } case Qt::Key_PageDown: { int line = findDisasmLine(cursorAddr, cursorLine); - if (line >= disasmTopLine && line < disasmTopLine+visibleLines) { + if (line >= disasmTopLine && line < disasmTopLine + visibleLines) { line += visibleLines; if (line < int(disasmLines.size())) { cursorAddr = disasmLines[line].addr; @@ -729,7 +729,7 @@ int DisasmViewer::lineAtPos(const QPoint& pos) int y = frameT; do { ++line; - switch (disasmLines[disasmTopLine+line].rowType) { + switch (disasmLines[disasmTopLine + line].rowType) { case DisasmRow::LABEL: y += labelFontHeight; break; diff --git a/src/DisasmViewer.h b/src/DisasmViewer.h index 6332b0ba..b4f9e44d 100644 --- a/src/DisasmViewer.h +++ b/src/DisasmViewer.h @@ -38,7 +38,11 @@ class DisasmViewer : public QFrame void updateLayout(); void refresh(); - void update(); //connect in DebuggerForm::widgetFactory coudln't directly connect to update of QWidget ?? + void update(); //connect in DebuggerForm::widgetFactory couldn't directly connect to update of QWidget ?? + +signals: + void breakpointToggled(uint16_t addr); + private: void requestMemory(uint16_t start, uint16_t end, uint16_t addr, int infoLine, int method); int findPosition(uint16_t addr, int infoLine, int method); @@ -83,9 +87,6 @@ class DisasmViewer : public QFrame Breakpoints* breakpoints; MemoryLayout* memLayout; SymbolTable* symTable; - -signals: - void breakpointToggled(uint16_t addr); }; #endif // DISASMVIEWER_H diff --git a/src/HexViewer.cpp b/src/HexViewer.cpp index cef89858..e5fef8bb 100644 --- a/src/HexViewer.cpp +++ b/src/HexViewer.cpp @@ -273,7 +273,7 @@ void HexViewer::paintEvent(QPaintEvent* e) int y = frameT; int address = hexTopAddress; - for (int i = 0; i < visibleLines+partialBottomLine; ++i) { + for (int i = 0; i < visibleLines + partialBottomLine; ++i) { // print address QString hexStr = QString("%1").arg(address, addressLength, 16, QChar('0')); p.setPen(palette().color(QPalette::Text)); @@ -432,7 +432,7 @@ void HexViewer::setLocation(int addr) } hexMarkAddress = addr; int size = horBytes * visibleLines; - if ((addr < hexTopAddress) || (addr >= (hexTopAddress+size))) { + if ((addr < hexTopAddress) || (addr >= (hexTopAddress + size))) { setTopLocation(addr); } refresh(); @@ -638,7 +638,7 @@ int HexViewer::coorToOffset(int x, int y) const } else if (x >= xChar && x < rightCharPos) { offset = (x - xChar) / charWidth; } - int yMaxOffset = frameT + (visibleLines+partialBottomLine) * lineHeight; + int yMaxOffset = frameT + (visibleLines + partialBottomLine) * lineHeight; if (offset >= 0 && y < yMaxOffset) { offset += horBytes * ((y - frameT) / lineHeight); } @@ -688,7 +688,7 @@ bool HexViewer::event(QEvent* e) void HexViewer::mousePressEvent(QMouseEvent* e) { if (e->button() == Qt::LeftButton && isInteractive) { - int offset=coorToOffset(e->x(), e->y()); + int offset = coorToOffset(e->x(), e->y()); if (offset >= 0) { int addr = hexTopAddress + offset; if (useMarker && (hexMarkAddress != addr)) { @@ -699,7 +699,7 @@ void HexViewer::mousePressEvent(QMouseEvent* e) cursorPosition = 0; beingEdited = isEditable; } - editedChars = (e->x() >= xChar); + editedChars = e->x() >= xChar; } update(); } diff --git a/src/InteractiveButton.cpp b/src/InteractiveButton.cpp index 904910d3..7c9a1fc8 100644 --- a/src/InteractiveButton.cpp +++ b/src/InteractiveButton.cpp @@ -60,7 +60,7 @@ void InteractiveButton::leaveEvent(QEvent* /*event*/) void InteractiveButton::newBitValueSlot(bool state) { - _state=state; + _state = state; QString name = objectName(); int bit = name.right(1).toInt(); int reg = name.mid( diff --git a/src/InteractiveLabel.h b/src/InteractiveLabel.h index 0311ac1d..62d0c9a3 100644 --- a/src/InteractiveLabel.h +++ b/src/InteractiveLabel.h @@ -17,7 +17,6 @@ class InteractiveLabel : public QLabel protected: void enterEvent(QEvent* event) override; void leaveEvent(QEvent* event) override; - }; #endif // INTERACTIVELABEL diff --git a/src/MainMemoryViewer.cpp b/src/MainMemoryViewer.cpp index a0c2945d..5d22df5f 100644 --- a/src/MainMemoryViewer.cpp +++ b/src/MainMemoryViewer.cpp @@ -20,7 +20,7 @@ static const int linkRegisters[] = { }; MainMemoryViewer::MainMemoryViewer(QWidget* parent) - : QWidget(parent),SavesJsonInterface() + : QWidget(parent), SavesJsonInterface() { setObjectName("MainMemoryViewer"); // create selection list, address edit line and viewer @@ -89,26 +89,26 @@ void MainMemoryViewer::setDebuggable(const QString& name, int size) void MainMemoryViewer::setSymbolTable(SymbolTable* symtable) { - symTable = symtable; + symTable = symtable; } QJsonObject MainMemoryViewer::save2json() { - QJsonObject obj; - obj["addressValue"]=addressValue->text(); - obj["addressSourceList"]=addressSourceList->currentIndex(); - return obj; + QJsonObject obj; + obj["addressValue"] = addressValue->text(); + obj["addressSourceList"] = addressSourceList->currentIndex(); + return obj; } bool MainMemoryViewer::loadFromJson(const QJsonObject &obj) { - if ( obj["addressSourceList"] == QJsonValue::Undefined || - obj["addressValue"] == QJsonValue::Undefined ) return false; + if (obj["addressSourceList"] == QJsonValue::Undefined || + obj["addressValue"] == QJsonValue::Undefined) return false; - addressSourceList->setCurrentIndex( obj["addressSourceList"].toInt() ); - addressValue->setText( obj["addressValue"].toString() ); - hexView->setLocation(addressValue->text().toInt()); - return true; + addressSourceList->setCurrentIndex(obj["addressSourceList"].toInt()); + addressValue->setText(obj["addressValue"].toString()); + hexView->setLocation(addressValue->text().toInt()); + return true; } void MainMemoryViewer::refresh() diff --git a/src/MainMemoryViewer.h b/src/MainMemoryViewer.h index d34fe39d..b79aa2a6 100644 --- a/src/MainMemoryViewer.h +++ b/src/MainMemoryViewer.h @@ -11,7 +11,7 @@ class QComboBox; class QLineEdit; class QJsonObject; -class MainMemoryViewer : public QWidget , public SavesJsonInterface +class MainMemoryViewer : public QWidget, public SavesJsonInterface { Q_OBJECT public: diff --git a/src/PaletteView.cpp b/src/PaletteView.cpp index d963b771..ced9ef7c 100644 --- a/src/PaletteView.cpp +++ b/src/PaletteView.cpp @@ -8,7 +8,7 @@ #include PaletteView::PaletteView(QWidget* parent) - : QWidget(parent),SavesJsonInterface() + : QWidget(parent), SavesJsonInterface() , ui(std::make_unique()) { ui->setupUi(this); @@ -79,29 +79,29 @@ void PaletteView::setAutoSync(bool value) QJsonObject PaletteView::save2json() { QJsonObject obj; - obj["viewtext"]=ui->cb_viewtext->isChecked(); - obj["autosync"]=ui->cb_autosync->isChecked(); - obj["palette"]=ui->cbPalette->currentIndex(); + obj["viewtext"] = ui->cb_viewtext->isChecked(); + obj["autosync"] = ui->cb_autosync->isChecked(); + obj["palette"] = ui->cbPalette->currentIndex(); return obj; } bool PaletteView::loadFromJson(const QJsonObject &obj) { - int i=0; - if ( obj["viewtext"] != QJsonValue::Undefined ) { - ui->cb_viewtext->setChecked( obj["viewtext"].toBool() ); + int i = 0; + if (obj["viewtext"] != QJsonValue::Undefined) { + ui->cb_viewtext->setChecked(obj["viewtext"].toBool()); i++; - }; - if ( obj["autosync"] != QJsonValue::Undefined ) { - ui->cb_autosync->setChecked( obj["autosync"].toBool() ); + } + if (obj["autosync"] != QJsonValue::Undefined) { + ui->cb_autosync->setChecked(obj["autosync"].toBool()); i++; - }; - if ( obj["palette"] != QJsonValue::Undefined ) { - ui->cbPalette->setCurrentIndex( obj["palette"].toInt() ); + } + if (obj["palette"] != QJsonValue::Undefined) { + ui->cbPalette->setCurrentIndex(obj["palette"].toInt()); i++; - }; + } - return i==3; + return i == 3; } void PaletteView::refresh() diff --git a/src/PaletteView.h b/src/PaletteView.h index 36b75b85..7592f3ca 100644 --- a/src/PaletteView.h +++ b/src/PaletteView.h @@ -17,7 +17,7 @@ namespace Ui { class PaletteView; } -class PaletteView : public QWidget , public SavesJsonInterface +class PaletteView : public QWidget, public SavesJsonInterface { Q_OBJECT diff --git a/src/PreferencesDialog.cpp b/src/PreferencesDialog.cpp index dbf0bec7..1dc28428 100644 --- a/src/PreferencesDialog.cpp +++ b/src/PreferencesDialog.cpp @@ -15,59 +15,59 @@ PreferencesDialog::PreferencesDialog(QWidget* parent) : QDialog(parent) { setupUi(this); - // Since there is no 'slots' definition in the header anymore we can not use the QMetaObject::connectSlotsByName() in setupUi anymore - // So now we do it explicitely here - connect(leFileName, &QLineEdit::textChanged, this, &PreferencesDialog::on_leFileName_textChanged); - connect(btnSaveLayout, &QPushButton::clicked, this, &PreferencesDialog::on_btnSaveLayout_clicked); - connect(btnBrowseLayout, &QPushButton::clicked, this, &PreferencesDialog::on_btnBrowseLayout_clicked); + // Since there is no 'slots' definition in the header anymore we can not use the QMetaObject::connectSlotsByName() in setupUi anymore + // So now we do it explicitely here + connect(leFileName, &QLineEdit::textChanged, this, &PreferencesDialog::on_leFileName_textChanged); + connect(btnSaveLayout, &QPushButton::clicked, this, &PreferencesDialog::on_btnSaveLayout_clicked); + connect(btnBrowseLayout, &QPushButton::clicked, this, &PreferencesDialog::on_btnBrowseLayout_clicked); - //openMSX connection stuff - connect(cbAutoconnect, &QCheckBox::toggled, this, &PreferencesDialog::openMSXConnectionChanged); - connect(cbStartIfNoConnection, &QCheckBox::toggled, this, &PreferencesDialog::openMSXConnectionChanged); - connect(leOpenMSXbin, &QLineEdit::editingFinished, this, &PreferencesDialog::openMSXConnectionChanged); - connect(leOpenMSXargs, &QLineEdit::editingFinished, this, &PreferencesDialog::openMSXConnectionChanged); - connect(pbTestCLI, &QPushButton::clicked, this, &PreferencesDialog::testOpenMSXCommandLine); + //openMSX connection stuff + connect(cbAutoconnect, &QCheckBox::toggled, this, &PreferencesDialog::openMSXConnectionChanged); + connect(cbStartIfNoConnection, &QCheckBox::toggled, this, &PreferencesDialog::openMSXConnectionChanged); + connect(leOpenMSXbin, &QLineEdit::editingFinished, this, &PreferencesDialog::openMSXConnectionChanged); + connect(leOpenMSXargs, &QLineEdit::editingFinished, this, &PreferencesDialog::openMSXConnectionChanged); + connect(pbTestCLI, &QPushButton::clicked, this, &PreferencesDialog::testOpenMSXCommandLine); - //font stuff + //font stuff connect(listFonts, &QListWidget::currentRowChanged, - this, &PreferencesDialog::fontSelectionChange); - connect(rbUseAppFont, &QRadioButton::toggled, - this, &PreferencesDialog::fontTypeChanged); + this, &PreferencesDialog::fontSelectionChange); + connect(rbUseAppFont, &QRadioButton::toggled, + this, &PreferencesDialog::fontTypeChanged); connect(rbUseFixedFont, &QRadioButton::toggled, - this, &PreferencesDialog::fontTypeChanged); + this, &PreferencesDialog::fontTypeChanged); connect(rbUseCustomFont, &QRadioButton::toggled, - this, &PreferencesDialog::fontTypeChanged); + this, &PreferencesDialog::fontTypeChanged); connect(btnSelectFont, &QPushButton::clicked, - this, &PreferencesDialog::fontSelectCustom); + this, &PreferencesDialog::fontSelectCustom); connect(btnFontColor, &QPushButton::clicked, - this, &PreferencesDialog::fontSelectColor); + this, &PreferencesDialog::fontSelectColor); initFontList(); listFonts->setCurrentRow(0); - //layout stuff - QList rblayouttypes; - rblayouttypes << rbFirstTimeUser << rbDefaultWorkspaces << rbLayoutFromFile; - foreach(auto rb, rblayouttypes){ - connect(rb, &QRadioButton::toggled, - this, &PreferencesDialog::layoutTypeChanged); - }; + //layout stuff + QList rblayouttypes; + rblayouttypes << rbFirstTimeUser << rbDefaultWorkspaces << rbLayoutFromFile; + foreach(auto rb, rblayouttypes){ + connect(rb, &QRadioButton::toggled, + this, &PreferencesDialog::layoutTypeChanged); + }; - //update ui with saved settings - updating=true; - Settings& s = Settings::get(); - rblayouttypes.at(s.value("creatingWorkspaceType",0).toInt())->setChecked(true); - leFileName->setText(s.value("creatingWorkspaceFile","").toString()); + //update ui with saved settings + updating=true; + Settings& s = Settings::get(); + rblayouttypes.at(s.value("creatingWorkspaceType",0).toInt())->setChecked(true); + leFileName->setText(s.value("creatingWorkspaceFile","").toString()); - cbAutoconnect->setChecked(s.value("autoconnect",true).toBool()); - cbStartIfNoConnection->setChecked(s.value("startOpenMSX",false).toBool()); - leOpenMSXbin->setText(s.value("openMSXbin","").toString()); - leOpenMSXargs->setText(s.value("openMSXargs","").toString()); + cbAutoconnect->setChecked(s.value("autoconnect",true).toBool()); + cbStartIfNoConnection->setChecked(s.value("startOpenMSX",false).toBool()); + leOpenMSXbin->setText(s.value("openMSXbin","").toString()); + leOpenMSXargs->setText(s.value("openMSXargs","").toString()); - createCLI(); + createCLI(); - updating=false; + updating=false; } /* @@ -150,24 +150,24 @@ void PreferencesDialog::fontSelectColor() if (newColor.isValid()) { Settings::get().setFontColor(f, newColor); setFontPreviewColor(newColor); - } + } } void PreferencesDialog::layoutTypeChanged(bool state) { - if (!state || updating) return; + if (!state || updating) return; - Settings& s = Settings::get(); + Settings& s = Settings::get(); - int wst=2; - if (rbFirstTimeUser->isChecked()){ - wst=0; - } else if (rbDefaultWorkspaces->isChecked()){ - wst=1; - } else { - s.setValue("creatingWorkspaceFile",leFileName->text()); - } - s.setValue("creatingWorkspaceType",wst); + int wst = 2; + if (rbFirstTimeUser->isChecked()) { + wst = 0; + } else if (rbDefaultWorkspaces->isChecked()) { + wst = 1; + } else { + s.setValue("creatingWorkspaceFile", leFileName->text()); + } + s.setValue("creatingWorkspaceType", wst); } void PreferencesDialog::setFontPreviewColor(const QColor& c) @@ -183,64 +183,63 @@ void PreferencesDialog::setFontPreviewColor(const QColor& c) void PreferencesDialog::on_btnBrowseLayout_clicked() { - QString fileName = QFileDialog::getOpenFileName( - this, tr("Select workspace layout"), - QDir::currentPath(), tr("Debug Workspace Layout Files (*.omdl)")); + QString fileName = QFileDialog::getOpenFileName( + this, tr("Select workspace layout"), + QDir::currentPath(), tr("Debug Workspace Layout Files (*.omdl)")); - if (!fileName.isEmpty()){ - leFileName->setText(fileName); - rbLayoutFromFile->setChecked(true); //not sure if setText with already string in lineEdit will trigger the on_leFileName_textChanged - } + if (!fileName.isEmpty()) { + leFileName->setText(fileName); + rbLayoutFromFile->setChecked(true); //not sure if setText with already string in lineEdit will trigger the on_leFileName_textChanged + } } void PreferencesDialog::openMSXConnectionChanged() { - if (updating) return; - - createCLI(); - Settings& s = Settings::get(); - s.setValue("autoconnect",cbAutoconnect->isChecked()); - s.setValue("startOpenMSX",cbStartIfNoConnection->isChecked()); - s.setValue("openMSXbin",leOpenMSXbin->text()); - s.setValue("openMSXargs",leOpenMSXargs->text()); + if (updating) return; + + createCLI(); + Settings& s = Settings::get(); + s.setValue("autoconnect",cbAutoconnect->isChecked()); + s.setValue("startOpenMSX",cbStartIfNoConnection->isChecked()); + s.setValue("openMSXbin",leOpenMSXbin->text()); + s.setValue("openMSXargs",leOpenMSXargs->text()); } void PreferencesDialog::on_leFileName_textChanged(const QString &arg1) { - if (updating) return; - Settings& s = Settings::get(); - s.setValue("creatingWorkspaceFile",arg1); + if (updating) return; + Settings& s = Settings::get(); + s.setValue("creatingWorkspaceFile", arg1); - rbLayoutFromFile->setChecked(true); + rbLayoutFromFile->setChecked(true); } void PreferencesDialog::on_btnSaveLayout_clicked() { - Settings& s = Settings::get(); - - QString savefilename=leFileName->text(); - if (savefilename.isEmpty()){ - //maybe the user cleared the lineEdit or first time launch or something went wrong :-) - savefilename=s.value("creatingWorkspaceFile","").toString(); - } - if (savefilename.isEmpty()) { - savefilename=static_cast(parent())->fileSaveWorkspaceAs(); - } else { - static_cast(parent())->saveWorkspacesAs(savefilename); - } - //update filename in case of fileSaveWorkspaceAs - if (!savefilename.isEmpty()) { - leFileName->setText(savefilename); - s.setValue("creatingWorkspaceFile",savefilename); - } + Settings& s = Settings::get(); + QString savefilename = leFileName->text(); + if (savefilename.isEmpty()) { + // maybe the user cleared the lineEdit or first time launch or something went wrong :-) + savefilename = s.value("creatingWorkspaceFile", "").toString(); + } + if (savefilename.isEmpty()) { + savefilename = static_cast(parent())->fileSaveWorkspaceAs(); + } else { + static_cast(parent())->saveWorkspacesAs(savefilename); + } + // update filename in case of fileSaveWorkspaceAs + if (!savefilename.isEmpty()) { + leFileName->setText(savefilename); + s.setValue("creatingWorkspaceFile", savefilename); + } } void PreferencesDialog::createCLI() { - labelCLI->setText(QString("%1 %2") - .arg(leOpenMSXbin->text(),leOpenMSXargs->text()) - ); + labelCLI->setText(QString("%1 %2") + .arg(leOpenMSXbin->text(),leOpenMSXargs->text()) + ); } void PreferencesDialog::testOpenMSXCommandLine() @@ -258,4 +257,3 @@ void PreferencesDialog::testOpenMSXCommandLine() ); } } - diff --git a/src/PreferencesDialog.h b/src/PreferencesDialog.h index 2717685f..a023bfdf 100644 --- a/src/PreferencesDialog.h +++ b/src/PreferencesDialog.h @@ -19,17 +19,17 @@ class PreferencesDialog : public QDialog, private Ui::PreferencesDialog void fontSelectCustom(); void fontSelectColor(); - void layoutTypeChanged(bool state); - void on_btnBrowseLayout_clicked(); - void openMSXConnectionChanged(); + void layoutTypeChanged(bool state); + void on_btnBrowseLayout_clicked(); + void openMSXConnectionChanged(); - void on_leFileName_textChanged(const QString &arg1); - void on_btnSaveLayout_clicked(); + void on_leFileName_textChanged(const QString& arg1); + void on_btnSaveLayout_clicked(); - void createCLI(); - void testOpenMSXCommandLine(); - - bool updating; +private: + void createCLI(); + void testOpenMSXCommandLine(); + bool updating; }; #endif // PREFERENCESDIALOG_OPENMSX_H diff --git a/src/SavesJsonInterface.h b/src/SavesJsonInterface.h index df3437cf..40813625 100644 --- a/src/SavesJsonInterface.h +++ b/src/SavesJsonInterface.h @@ -7,8 +7,8 @@ class SavesJsonInterface { public: SavesJsonInterface(); - virtual QJsonObject save2json()=0 ; - virtual bool loadFromJson(const QJsonObject& obj)=0; + virtual QJsonObject save2json() = 0; + virtual bool loadFromJson(const QJsonObject& obj) = 0; }; #endif // SAVESJSONINTERFACE_H diff --git a/src/Settings.cpp b/src/Settings.cpp index 547def88..f43484be 100644 --- a/src/Settings.cpp +++ b/src/Settings.cpp @@ -66,7 +66,7 @@ void Settings::getFontsFromSettings() } // read colors - for (int f =CODE_FONT; f < FONT_END; ++f) { + for (int f = CODE_FONT; f < FONT_END; ++f) { fontColors[f] = value(fontColorLocation((DebuggerFont)f), QColor(Qt::black)) .value(); diff --git a/src/SimpleHexRequest.h b/src/SimpleHexRequest.h index 82488419..1e48700c 100644 --- a/src/SimpleHexRequest.h +++ b/src/SimpleHexRequest.h @@ -10,7 +10,7 @@ * - Class A can reimplement the DataHexRequestReceived if it wants to react when new data has arrived * - Class A can reimplement the DataHexRequestCanceled if it wants to react to failures of the request * - to read the debuggable into the memory just create a new SimpleHexRequest, fi. - * new SimpleHexRequest("{VDP status regs}",0,16,statusregs, *this); + * new SimpleHexRequest("{VDP status regs}", 0, 16, statusregs, *this); * */ class SimpleHexRequestUser diff --git a/src/SlotViewer.cpp b/src/SlotViewer.cpp index 83e3a32d..33471cd7 100644 --- a/src/SlotViewer.cpp +++ b/src/SlotViewer.cpp @@ -135,10 +135,10 @@ void SlotViewer::paintEvent(QPaintEvent* e) if (ms > 0) { str = QString("%1").arg(memLayout->mapperSegment[i]); } else if (memLayout->romBlock[2*i] >= 0) { - if (memLayout->romBlock[2*i] == memLayout->romBlock[2*i+1]) { - str = QString("R%1").arg(memLayout->romBlock[2*i]); + if (memLayout->romBlock[2*i] == memLayout->romBlock[2 * i + 1]) { + str = QString("R%1").arg(memLayout->romBlock[2 * i]); } else { - str = QString("R%1/%2").arg(memLayout->romBlock[2*i]).arg(memLayout->romBlock[2*i+1]); + str = QString("R%1/%2").arg(memLayout->romBlock[2 * i]).arg(memLayout->romBlock[2 * i + 1]); } } else { str = "-"; diff --git a/src/StackViewer.cpp b/src/StackViewer.cpp index fc39372d..287533fe 100644 --- a/src/StackViewer.cpp +++ b/src/StackViewer.cpp @@ -41,12 +41,12 @@ StackViewer::StackViewer(QWidget* parent) : QFrame(parent) , wheelRemainder(0) { - static int count=0; + static int count = 0; setObjectName(QString("StackViewer_%1").arg(count++)); setFrameStyle(WinPanel | Sunken); setFocusPolicy(Qt::StrongFocus); setBackgroundRole(QPalette::Base); - setSizePolicy(QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Preferred)); + setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred)); setFont(Settings::get().font(Settings::HEX_FONT)); @@ -60,7 +60,7 @@ StackViewer::StackViewer(QWidget* parent) frameL = frameT = frameB = frameWidth(); frameR = frameL + vertScrollBar->sizeHint().width(); - setMinimumHeight(frameT+frameB+fontMetrics().height()); + setMinimumHeight(frameT + frameB + fontMetrics().height()); connect(vertScrollBar, &QScrollBar::valueChanged, this, &StackViewer::setLocation); @@ -119,7 +119,7 @@ void StackViewer::paintEvent(QPaintEvent* e) int d = fontMetrics().descent(); // set font -// p.setPen(palette().color(QPalette::Text)); + //p.setPen(palette().color(QPalette::Text)); // calc and set drawing bounds QRect r(e->rect()); @@ -134,25 +134,24 @@ void StackViewer::paintEvent(QPaintEvent* e) // calc layout (not optimal) int xAddr = frameL + 8; - int xStack = xAddr + fontMetrics().horizontalAdvance("FFFFFF"); + int xStack = xAddr + fontMetrics().horizontalAdvance("FFFFFF"); int y = frameT + h - 1; int address = topAddress; for (int i = 0; i < int(ceil(visibleLines)); ++i) { - // draw background - if (address==stackPointer){ -// p.fillRect(frameL,y-h,width() - frameL- frameR, h, -// palette().color(QPalette::Highlight)); - p.setPen(palette().color(QPalette::LinkVisited)); - } else { - p.setPen(palette().color(QPalette::Text)); - }; + // draw background + if (address == stackPointer){ + //p.fillRect(frameL, y-h, width() - frameL- frameR, h, + // palette().color(QPalette::Highlight)); + p.setPen(palette().color(QPalette::LinkVisited)); + } else { + p.setPen(palette().color(QPalette::Text)); + } // print address - QString hexStr; - hexStr = QString("%1").arg(isEnabled()?address:0, 4, 16, QChar('0')).toUpper(); + QString hexStr = QString("%1").arg(isEnabled()?address:0, 4, 16, QChar('0')).toUpper(); p.drawText(xAddr, y - d, hexStr); - int val=isEnabled()?(memory[address + 1] << 8 | memory[address]):0; - hexStr = QString("%1").arg(val, 4, 16, QChar('0')).toUpper(); + int val = isEnabled() ? (memory[address + 1] << 8 | memory[address]) : 0; + hexStr = QString("%1").arg(val, 4, 16, QChar('0')).toUpper(); p.drawText(xStack, y - d, hexStr); y += h; address += 2; @@ -169,7 +168,7 @@ void StackViewer::setData(unsigned char* memPtr, int memLength) void StackViewer::setLocation(int addr) { - qDebug()<<"StackViewer::setLocation(int "<< addr<<") wdgt->objectName() "<< objectName(); + qDebug() << "StackViewer::setLocation(int " << addr << ") wdgt->objectName() " << objectName(); if (waitingForData) { return; // ignore } @@ -179,27 +178,27 @@ void StackViewer::setLocation(int addr) if (start + size >= memoryLength) { size = memoryLength - start; } - qDebug()<<"StackViewer::setLocation isEnabled() "<< isEnabled(); - if (isEnabled()) { //only request data when enabled - auto* req = new StackRequest(start, size, &memory[start], *this); - CommClient::instance().sendCommand(req); - waitingForData = true; - } + qDebug() << "StackViewer::setLocation isEnabled() " << isEnabled(); + if (isEnabled()) { //only request data when enabled + auto* req = new StackRequest(start, size, &memory[start], *this); + CommClient::instance().sendCommand(req); + waitingForData = true; + } } void StackViewer::setStackPointer(quint16 addr) { - qDebug()<<"StackViewer::setStackPointer(quint16 "<< addr<<") wdgt->objectName() "<< objectName(); + qDebug() << "StackViewer::setStackPointer(quint16 " << addr << ") wdgt->objectName() " << objectName(); stackPointer = addr; setScrollBarValues(); vertScrollBar->setValue(addr); - qDebug()<<"StackViewer::setStackPointer is now calling "; + qDebug() << "StackViewer::setStackPointer is now calling "; setLocation(addr); } void StackViewer::memDataTransferred(StackRequest* r) { - qDebug()<<"StackViewer::memdataTransfered() wdgt->objectName() "<< objectName(); + qDebug() << "StackViewer::memdataTransfered() wdgt->objectName() " << objectName(); topAddress = r->offset; update(); diff --git a/src/SymbolTable.cpp b/src/SymbolTable.cpp index ee17fb95..a63b26a0 100644 --- a/src/SymbolTable.cpp +++ b/src/SymbolTable.cpp @@ -145,10 +145,12 @@ Symbol* SymbolTable::getAddressSymbol(int addr, MemoryLayout* ml) Symbol* SymbolTable::getAddressSymbol(const QString& label, bool case_sensitive) { for (auto it = addressSymbols.begin(); it != addressSymbols.end(); ++it) { - if (it.value()->text().compare(label, Qt::CaseSensitive)==0) + if (it.value()->text().compare(label, Qt::CaseSensitive) == 0) { return it.value(); - if (!case_sensitive && it.value()->text().compare(label, Qt::CaseInsensitive)==0) + } + if (!case_sensitive && it.value()->text().compare(label, Qt::CaseInsensitive) == 0) { return it.value(); + } } return nullptr; } @@ -606,16 +608,16 @@ void SymbolTable::saveSymbols(QXmlStreamWriter& xml) xml.writeStartElement("SymbolFile"); switch (symbolFiles[i].fileType) { case TNIASM0_FILE: - xml.writeAttribute("type","tniasm0"); + xml.writeAttribute("type", "tniasm0"); break; case TNIASM1_FILE: - xml.writeAttribute("type","tniasm1"); + xml.writeAttribute("type", "tniasm1"); break; case ASMSX_FILE: - xml.writeAttribute("type","asmsx"); + xml.writeAttribute("type", "asmsx"); break; case LINKMAP_FILE: - xml.writeAttribute("type","linkmap"); + xml.writeAttribute("type", "linkmap"); break; default: break; diff --git a/src/TabRenamerHelper.cpp b/src/TabRenamerHelper.cpp index 2e8a58a3..d3437634 100644 --- a/src/TabRenamerHelper.cpp +++ b/src/TabRenamerHelper.cpp @@ -6,11 +6,11 @@ #include TabRenamerHelper::TabRenamerHelper(QTabWidget *parent) - : QObject{parent},workspaces{parent}, - tabLineEdit{nullptr},editedTab{-1} + : QObject{parent}, workspaces{parent}, + tabLineEdit{nullptr}, editedTab{-1} { - connect(workspaces->tabBar(),&QTabBar::tabBarDoubleClicked, - this,&TabRenamerHelper::tabBarDoubleClicked); + connect(workspaces->tabBar(), &QTabBar::tabBarDoubleClicked, + this, &TabRenamerHelper::tabBarDoubleClicked); workspaces->tabBar()->installEventFilter(this); // workspaces->installEventFilter(this); @@ -18,13 +18,13 @@ TabRenamerHelper::TabRenamerHelper(QTabWidget *parent) void TabRenamerHelper::tabBarDoubleClicked(int index) { - editedTab=index; - if (index==-1){ + editedTab = index; + if (index == -1) { return; - }; - QRect r=workspaces->tabBar()->tabRect(index); - QString t=workspaces->tabBar()->tabText(index); - tabLineEdit=new QLineEdit{workspaces->tabBar()}; + } + QRect r = workspaces->tabBar()->tabRect(index); + QString t = workspaces->tabBar()->tabText(index); + tabLineEdit = new QLineEdit{workspaces->tabBar()}; tabLineEdit->show(); tabLineEdit->move(r.topLeft()); tabLineEdit->resize(r.size()); @@ -32,43 +32,42 @@ void TabRenamerHelper::tabBarDoubleClicked(int index) tabLineEdit->selectAll(); tabLineEdit->setFocus(); tabLineEdit->installEventFilter(this); - connect(tabLineEdit,&QLineEdit::editingFinished, this, &TabRenamerHelper::tabNameEditingFinished); - + connect(tabLineEdit, &QLineEdit::editingFinished, this, &TabRenamerHelper::tabNameEditingFinished); } void TabRenamerHelper::tabNameEditingFinished() { - QString newname=tabLineEdit->text(); - if (!newname.isEmpty()){ - workspaces->tabBar()->setTabText(editedTab,newname); - }; + QString newname = tabLineEdit->text(); + if (!newname.isEmpty()) { + workspaces->tabBar()->setTabText(editedTab, newname); + } tabLineEdit->deleteLater(); - tabLineEdit=nullptr; + tabLineEdit = nullptr; } -bool TabRenamerHelper::eventFilter(QObject *obj, QEvent *event) +bool TabRenamerHelper::eventFilter(QObject* obj, QEvent* event) { - bool result=QObject::eventFilter(obj,event); - QTabBar* bar=workspaces->tabBar(); - if (obj == bar){ - if (event->type() == QEvent::MouseButtonPress){ + bool result = QObject::eventFilter(obj, event); + QTabBar* bar = workspaces->tabBar(); + if (obj == bar) { + if (event->type() == QEvent::MouseButtonPress) { // the user is trying to move away from editing by clicking another tab QMouseEvent* me = static_cast(event); int clickedTabId = bar->tabAt(me->pos()); - if (editedTab!=-1 && editedTab!= clickedTabId && tabLineEdit){ + if (editedTab != -1 && editedTab != clickedTabId && tabLineEdit) { emit tabLineEdit->editingFinished(); return false; } - }; - if (event->type() == QEvent::MouseButtonDblClick){ - //perhaps we need to start a new name editing action? + } + if (event->type() == QEvent::MouseButtonDblClick) { + // Perhaps we need to start a new name editing action? QMouseEvent* me = static_cast(event); int clickedTabId = bar->tabAt(me->pos()); - if (clickedTabId == -1){ - return result; + if (clickedTabId == -1) { + return result; } - if (editedTab!=-1 && editedTab!= clickedTabId && tabLineEdit){ + if (editedTab != -1 && editedTab != clickedTabId && tabLineEdit) { emit tabLineEdit->editingFinished(); return false; } @@ -76,13 +75,13 @@ bool TabRenamerHelper::eventFilter(QObject *obj, QEvent *event) } //handle some events on the line edit to make it behave itself nicely as a rename editor if (obj == tabLineEdit && event->type() == QEvent::KeyPress) { - QKeyEvent* ke = static_cast(event); - if (ke->key() == Qt::Key_Escape) { - disconnect(tabLineEdit,&QLineEdit::editingFinished, this, &TabRenamerHelper::tabNameEditingFinished); - tabLineEdit->deleteLater(); - tabLineEdit=nullptr; - return true; //no further handling of this event is required - } + QKeyEvent* ke = static_cast(event); + if (ke->key() == Qt::Key_Escape) { + disconnect(tabLineEdit, &QLineEdit::editingFinished, this, &TabRenamerHelper::tabNameEditingFinished); + tabLineEdit->deleteLater(); + tabLineEdit = nullptr; + return true; // no further handling of this event is required + } } return result; diff --git a/src/TabRenamerHelper.h b/src/TabRenamerHelper.h index 811173d1..86d3b2d9 100644 --- a/src/TabRenamerHelper.h +++ b/src/TabRenamerHelper.h @@ -10,19 +10,18 @@ class TabRenamerHelper : public QObject { Q_OBJECT public: - explicit TabRenamerHelper(QTabWidget *parent = nullptr); + explicit TabRenamerHelper(QTabWidget* parent = nullptr); public slots: void tabBarDoubleClicked(int index); void tabNameEditingFinished(); protected: - bool eventFilter(QObject *obj, QEvent *event) override; + bool eventFilter(QObject* obj, QEvent* event) override; QTabWidget* workspaces; QLineEdit* tabLineEdit; int editedTab; - }; #endif // TABRENAMERHELPER_H diff --git a/src/TileViewer.cpp b/src/TileViewer.cpp index 0f59ecd9..ca59d9fe 100644 --- a/src/TileViewer.cpp +++ b/src/TileViewer.cpp @@ -231,7 +231,7 @@ void TileViewer::decodeVDPregs() le_patterntable->setText(hexValue(patternTable, 4)); le_colortable->setText(hexValue(colorTable, 4)); cb_blinkcolors->setChecked(usesBlink ? regs[13] & 0xf0 : false); - cb_screenrows->setCurrentIndex((regs[9] & 128) ? 1 : 0 ); + cb_screenrows->setCurrentIndex((regs[9] & 128) ? 1 : 0); sp_bordercolor->setValue(regs[7] & 15); cb_color0->setChecked(regs[8] & 32); } diff --git a/src/VDPCommandRegViewer.cpp b/src/VDPCommandRegViewer.cpp index 9b4afa9c..088f1dab 100644 --- a/src/VDPCommandRegViewer.cpp +++ b/src/VDPCommandRegViewer.cpp @@ -242,8 +242,8 @@ void VDPCommandRegViewer::on_lineEdit_r46_editingFinished() void VDPCommandRegViewer::refresh() { - //new SimpleHexRequest("{VDP regs}",0,64,regs, *this); - //new SimpleHexRequest("{VDP status regs}",0,16,regs, *this); + //new SimpleHexRequest("{VDP regs}", 0, 64, regs, *this); + //new SimpleHexRequest("{VDP status regs}", 0, 16, regs, *this); // now combined in one request: new SimpleHexRequest( "debug_bin2hex " diff --git a/src/VDPDataStore.cpp b/src/VDPDataStore.cpp index b3ddab81..e1321034 100644 --- a/src/VDPDataStore.cpp +++ b/src/VDPDataStore.cpp @@ -38,10 +38,10 @@ class VDPDataStoreVRAMSizeCheck : public SimpleCommand void replyOk(const QString& message) override { - //printf("dataStore.vramSize %i\n",dataStore.vramSize); + //printf("dataStore.vramSize %i\n", dataStore.vramSize); dataStore.vramSize = message.toInt(); - //printf("dataStore.vramSize %i\n",dataStore.vramSize); - dataStore.refresh2(); + //printf("dataStore.vramSize %i\n", dataStore.vramSize); + dataStore.refresh2(); delete this; } void replyNok(const QString& /*message*/) override diff --git a/src/VDPRegViewer.cpp b/src/VDPRegViewer.cpp index 4b98a6b4..a7495a7e 100644 --- a/src/VDPRegViewer.cpp +++ b/src/VDPRegViewer.cpp @@ -360,23 +360,24 @@ void VDPRegViewer::decodeVDPRegs() "let's find out 27", "SCREEN 8", "let's find out 29", "let's find out 30", "let's find out 31" }; - int basicscreen; - switch (m) { - case 2: basicscreen=0;break; - case 0: basicscreen=1;break; - case 4: basicscreen=2;break; - case 1: basicscreen=3;break; - case 8: basicscreen=4;break; - case 12: basicscreen=5;break; - case 16: basicscreen=6;break; - case 20: basicscreen=7;break; - case 28: basicscreen=8;break; - case 10: basicscreen=9;break; //screen 0 width 80 - default: basicscreen=10; //not a valid basic screen mode - }; + int basicScreen = [&] { + switch (m) { + case 2: return 0; + case 0: return 1; + case 4: return 2; + case 1: return 3; + case 8: return 4; + case 12: return 5; + case 16: return 6; + case 20: return 7; + case 28: return 8; + case 10: return 9; // screen 0 width 80 + default: return 10; // not a valid basic screen mode + } + }(); // 2 vdps, 11 basic screenmodes, 12 registers - static const int mustbeone[][11][12] = { + static const int mustBeOne[][11][12] = { { // TMS99x8 MSX1 VDP chip {0, 0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0,0,0,0}, // screen 0; {0, 0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0,0,0,0}, // screen 1; @@ -445,12 +446,12 @@ void VDPRegViewer::decodeVDPRegs() auto* i = findChild(name); i->setChecked(regs[r] & (1 << b)); if (r < 12) { - i->mustBeSet(mustbeone[(vdpId == VDP_TMS99X8) ? 0 : 1][basicscreen][r] & (1 << b)); + i->mustBeSet(mustBeOne[(vdpId == VDP_TMS99X8) ? 0 : 1][basicScreen][r] & (1 << b)); // if A8 of R5 is a 'must-be-one' then we indicate this for A9 also // This bit is cleared in the table since it isn't used in the Sprite // Attribute Table address calculation otherwise, but will only impact the // Sprite Color Table - if (r == 5 && b == 2 && vdpId != VDP_TMS99X8 && mustbeone[1][basicscreen][5]) { + if (r == 5 && b == 2 && vdpId != VDP_TMS99X8 && mustBeOne[1][basicScreen][5]) { i->mustBeSet(true); } } @@ -523,17 +524,17 @@ void VDPRegViewer::decodeVDPRegs() // some variables used for readability of the code below int row = vdpId == VDP_TMS99X8 ? 0 : 1; QString regtexttext; - int must,must2; + int must, must2; // the pattern name table address - must=mustbeone[row][basicscreen][2] ; - long nameTable = ((255^must) & bitsused[row][basicscreen][2] & regs[2]) << 10; + must = mustBeOne[row][basicScreen][2] ; + long nameTable = ((255^must) & bitsused[row][basicScreen][2] & regs[2]) << 10; if ((m == 20 || m == 28) && vdpId != VDP_TMS99X8) nameTable = ((nameTable & 0xffff) << 1) | ((nameTable & 0x10000) >> 16); regtexttext = hex5(nameTable); if ((must & regs[2]) != must) { - label_dec_r2->setText("" + regtexttext +""); + label_dec_r2->setText("" + regtexttext + ""); label_dec_r2->setToolTip("Some of the obligatory 1 bits are reset!"); } else { label_dec_r2->setText(regtexttext); @@ -541,17 +542,17 @@ void VDPRegViewer::decodeVDPRegs() } // the color table address - must=mustbeone[row][basicscreen][3] ; - must2=mustbeone[row][basicscreen][10] ; - regtexttext=hex5( + must = mustBeOne[row][basicScreen][3]; + must2 = mustBeOne[row][basicScreen][10]; + regtexttext = hex5( ( - ((255 ^ must ) & bitsused[row][basicscreen][ 3] & regs[ 3]) << 6 + ((255 ^ must ) & bitsused[row][basicScreen][ 3] & regs[ 3]) << 6 ) | ( - ((255 ^ must2) & bitsused[row][basicscreen][10] & regs[10]) << 14 + ((255 ^ must2) & bitsused[row][basicScreen][10] & regs[10]) << 14 ) ); if (((must & regs[3]) != must) || ((must2 & regs[10]) != must2)) { - label_dec_r3->setText("" + regtexttext +""); + label_dec_r3->setText("" + regtexttext + ""); label_dec_r3->setToolTip("Some of the obligatory 1 bits are reset!"); } else { label_dec_r3->setText(regtexttext); @@ -559,13 +560,13 @@ void VDPRegViewer::decodeVDPRegs() } // the pattern generator address - must=mustbeone[row][basicscreen][4] ; - regtexttext=hex5( + must = mustBeOne[row][basicScreen][4] ; + regtexttext = hex5( ( - (255 ^ must) & bitsused[row][basicscreen][4] & regs[4]) << 11 + (255 ^ must) & bitsused[row][basicScreen][4] & regs[4]) << 11 ); if ((must & regs[4]) != must) { - label_dec_r4->setText("" + regtexttext +""); + label_dec_r4->setText("" + regtexttext + ""); label_dec_r4->setToolTip("Some of the obligatory 1 bits are reset!"); } else { label_dec_r4->setText(regtexttext); @@ -573,30 +574,30 @@ void VDPRegViewer::decodeVDPRegs() } // the sprite attribute tabel address - must = mustbeone[row][basicscreen][ 5]; - must2 = mustbeone[row][basicscreen][11]; + must = mustBeOne[row][basicScreen][ 5]; + must2 = mustBeOne[row][basicScreen][11]; regtexttext = hex5( ( - (((255^must) & bitsused[row][basicscreen][ 5] & regs[ 5]) << 7) | - (((255^must2) & bitsused[row][basicscreen][11] & regs[11]) << 15)) + (((255^must) & bitsused[row][basicScreen][ 5] & regs[ 5]) << 7) | + (((255^must2) & bitsused[row][basicScreen][11] & regs[11]) << 15)) ); if (((must & regs[5]) != must) || ((must2 & regs[11]) != must2)) { - label_dec_r5->setText("" + regtexttext +""); + label_dec_r5->setText("" + regtexttext + ""); label_dec_r5->setToolTip("Some of the obligatory 1 bits are reset!"); } else { label_dec_r5->setText(regtexttext); label_dec_r5->setToolTip(nullptr); - }; + } // special case for sprite mode 2 if (must && !(4 & regs[ 5])) { // only in mode2 there are some 'must'-bits :-) - label_dec_r5->setText("" + regtexttext +""); + label_dec_r5->setText("" + regtexttext + ""); label_dec_r5->setToolTip("Bit A9 should be set, to obtain the Sprite Color Table address this bit is masked
With the current bit reset the Color Tabel will use the same address as the Sprite Attribute Table!"); - }; + } // the sprite pattern generator address label_dec_r6->setText(hex5( - ((255^mustbeone[row][basicscreen][6]) & bitsused[row][basicscreen][6] & regs[6]) << 11)); + ((255^mustBeOne[row][basicScreen][6]) & bitsused[row][basicScreen][6] & regs[6]) << 11)); // end of address calculations @@ -905,8 +906,8 @@ void VDPRegViewer::connectHighLights() void VDPRegViewer::refresh() { - //new SimpleHexRequest("{VDP regs}",0,64,regs, *this); - //new SimpleHexRequest("{VDP status regs}",0,16,regs, *this); + //new SimpleHexRequest("{VDP regs}", 0, 64, regs, *this); + //new SimpleHexRequest("{VDP status regs}", 0, 16, regs, *this); // now combined in one request: new SimpleHexRequest( "debug_bin2hex " diff --git a/src/VramBitMappedView.cpp b/src/VramBitMappedView.cpp index 22ea5a79..4ab32eea 100644 --- a/src/VramBitMappedView.cpp +++ b/src/VramBitMappedView.cpp @@ -189,7 +189,7 @@ void VramBitMappedView::paintEvent(QPaintEvent* /*event*/) QRect srcRect(0, 0, 512, 2 * lines); QRect dstRect(0, 0, int(512.0f * zoomFactor), int(2.0f * float(lines) * zoomFactor)); QPainter qp(this); - //qp.drawImage(rect(),image,srcRect); + //qp.drawImage(rect(), image, srcRect); qp.drawPixmap(dstRect, pixImage, srcRect); } diff --git a/src/VramTiledView.cpp b/src/VramTiledView.cpp index 1966b57e..5ff959d3 100644 --- a/src/VramTiledView.cpp +++ b/src/VramTiledView.cpp @@ -463,7 +463,7 @@ QString VramTiledView::textInfo(int x, int y, int character) } else if (screenMode == 1) { colordata = QString("- %1: %2").arg( hexValue(colorTableAddress + (character >> 3), 4), - hexValue(vramBase[colorTableAddress+(character >> 3)], 2)); + hexValue(vramBase[colorTableAddress + (character >> 3)], 2)); } else if (screenMode == 3) { colordata = QString("- not used"); } @@ -506,17 +506,17 @@ std::optional VramTiledView::infoFromMouseEvent(Q if (!vramBase) return {}; // I see negative y-coords sometimes, so for safety clip the coords - int x = std::clamp(int(float(e->x()) / zoomFactor), 0, 511) / horiStep; - int y = std::clamp(int(float(e->y()) / zoomFactor) / 2, 0, 255) / 8; + int x = std::clamp(int(float(e->x()) / zoomFactor), 0, 511) / horiStep; + int y = std::clamp(int(float(e->y()) / zoomFactor) / 2, 0, 255) / 8; - if (x >= screenWidth) return {}; - if (y >= screenHeight) return {}; + if (x >= screenWidth) return {}; + if (y >= screenHeight) return {}; int character = 0; switch (tableToShow) { case 0: - character = x + y * screenWidth; + character = x + y * screenWidth; if (!(screenMode == 2 || screenMode == 4)) { character &= 255; } @@ -525,11 +525,11 @@ std::optional VramTiledView::infoFromMouseEvent(Q case 2: character = vramBase[nameTableAddress + x + y * screenWidth]; if (screenMode == 2 || screenMode == 4) { - character += 256 * int(y / 8); + character += 256 * int(y / 8); } break; } - return MouseEventInfo{x, y, character}; + return MouseEventInfo{x, y, character}; } void VramTiledView::setBorderColor(int value) diff --git a/src/blendsplitter/ExpanderCorner.cpp b/src/blendsplitter/ExpanderCorner.cpp index ecac74bf..c1ad9f8c 100644 --- a/src/blendsplitter/ExpanderCorner.cpp +++ b/src/blendsplitter/ExpanderCorner.cpp @@ -146,9 +146,9 @@ void ExpanderCorner::performInnerSplit(WidgetDecorator* parentDecorator, BlendSp parentSplitter->insertWidget(index); addedWidget = dynamic_cast(parentSplitter->getNestedWidget(index)); } else { - sizes.insert(index +1, BlendSplitter::expanderSize); + sizes.insert(index + 1, BlendSplitter::expanderSize); sizes[index] -= BlendSplitter::expanderSize + 1; - parentSplitter->insertWidget(index+1); + parentSplitter->insertWidget(index + 1); addedWidget = dynamic_cast(parentSplitter->getNestedWidget(index + 1)); } parentSplitter->setSizes(sizes); diff --git a/src/blendsplitter/SwitchingWidget.cpp b/src/blendsplitter/SwitchingWidget.cpp index 5005f2d3..c18300aa 100644 --- a/src/blendsplitter/SwitchingWidget.cpp +++ b/src/blendsplitter/SwitchingWidget.cpp @@ -89,9 +89,8 @@ SwitchingWidget* SwitchingWidget::createFromJson(const QJsonObject &obj) auto* wdgt = new SwitchingWidget{WidgetRegistry::instance().item(i)}; wdgt->resize(obj["size_width"].toInt(), obj["size_height"].toInt()); - auto* childwdgt = dynamic_cast(wdgt->getWidget()); - if (childwdgt && obj["childwidget"] != QJsonValue::Undefined ) { + if (childwdgt && obj["childwidget"] != QJsonValue::Undefined) { childwdgt->loadFromJson(obj["childwidget"].toObject()); } @@ -105,7 +104,7 @@ QWidget *SwitchingWidget::getWidget() if (isWrappedInScrollArea) { auto* sa = static_cast(wdgt); wdgt = sa->widget(); - }; + } return wdgt; } @@ -114,7 +113,7 @@ QJsonObject SwitchingWidget::getWidgetSettings() QJsonObject obj; auto* wd = dynamic_cast(getWidget()); if (wd) { - obj=wd->save2json(); + obj = wd->save2json(); } return obj; } @@ -177,7 +176,7 @@ QWidget* SwitchingWidget::wrapInScrollArea(QWidget* wdgt, bool dowrap) auto* scrollArea = new QScrollArea; //scrollArea->setBackgroundRole(QPalette::Dark); - scrollArea->setSizePolicy(QSizePolicy::Expanding , QSizePolicy::Expanding); + scrollArea->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); scrollArea->setContentsMargins(0, 0, 0, 0); scrollArea->setWidget(wdgt); scrollArea->setWidgetResizable(true); From 65e53fa72c36851a6f35a6ecc8c1139ba40c5538 Mon Sep 17 00:00:00 2001 From: m9710797 Date: Wed, 18 May 2022 19:31:40 +0200 Subject: [PATCH 40/63] Tweak loadFromJson Avoid repeating the same lookup twice (and risk making a typo between the 1st / 2nd string literal). --- src/DebuggableViewer.cpp | 11 ++++++----- src/MainMemoryViewer.cpp | 13 ++++++++----- src/PaletteView.cpp | 28 +++++++++++++-------------- src/blendsplitter/SwitchingWidget.cpp | 13 ++++++------- 4 files changed, 33 insertions(+), 32 deletions(-) diff --git a/src/DebuggableViewer.cpp b/src/DebuggableViewer.cpp index aaa9daee..5288dbad 100644 --- a/src/DebuggableViewer.cpp +++ b/src/DebuggableViewer.cpp @@ -33,11 +33,11 @@ QJsonObject DebuggableViewer::save2json() return obj; } -bool DebuggableViewer::loadFromJson(const QJsonObject &obj) +bool DebuggableViewer::loadFromJson(const QJsonObject& obj) { - if (obj["debuggable"] == QJsonValue::Undefined) return false; - - debuggableList->setCurrentText(obj["debuggable"].toString()); + auto d = obj["debuggable"]; + if (d == QJsonValue::Undefined) return false; + debuggableList->setCurrentText(d.toString()); return true; } @@ -56,8 +56,9 @@ void DebuggableViewer::debuggableSelected(int index) QString name = debuggableList->itemText(index); int size = debuggableList->itemData(index).toInt(); - if (index >= 0) + if (index >= 0) { lastSelected = name; + } // add braces when the name contains a space if (name.contains(QChar(' '))) { name.append(QChar('}')); diff --git a/src/MainMemoryViewer.cpp b/src/MainMemoryViewer.cpp index 5d22df5f..660ee950 100644 --- a/src/MainMemoryViewer.cpp +++ b/src/MainMemoryViewer.cpp @@ -100,13 +100,16 @@ QJsonObject MainMemoryViewer::save2json() return obj; } -bool MainMemoryViewer::loadFromJson(const QJsonObject &obj) +bool MainMemoryViewer::loadFromJson(const QJsonObject& obj) { - if (obj["addressSourceList"] == QJsonValue::Undefined || - obj["addressValue"] == QJsonValue::Undefined) return false; + auto asl = obj["addressSourceList"]; + auto av = obj["addressValue"]; + if (asl == QJsonValue::Undefined || av == QJsonValue::Undefined) { + return false; + } - addressSourceList->setCurrentIndex(obj["addressSourceList"].toInt()); - addressValue->setText(obj["addressValue"].toString()); + addressSourceList->setCurrentIndex(asl.toInt()); + addressValue->setText(av.toString()); hexView->setLocation(addressValue->text().toInt()); return true; } diff --git a/src/PaletteView.cpp b/src/PaletteView.cpp index ced9ef7c..44ce8ca0 100644 --- a/src/PaletteView.cpp +++ b/src/PaletteView.cpp @@ -85,23 +85,21 @@ QJsonObject PaletteView::save2json() return obj; } -bool PaletteView::loadFromJson(const QJsonObject &obj) -{ - int i = 0; - if (obj["viewtext"] != QJsonValue::Undefined) { - ui->cb_viewtext->setChecked(obj["viewtext"].toBool()); - i++; - } - if (obj["autosync"] != QJsonValue::Undefined) { - ui->cb_autosync->setChecked(obj["autosync"].toBool()); - i++; - } - if (obj["palette"] != QJsonValue::Undefined) { - ui->cbPalette->setCurrentIndex(obj["palette"].toInt()); - i++; +bool PaletteView::loadFromJson(const QJsonObject& obj) +{ + auto vt = obj["viewtext"]; + auto as = obj["autosync"]; + auto pa = obj["palette"]; + if (vt == QJsonValue::Undefined || + as == QJsonValue::Undefined || + pa == QJsonValue::Undefined) { + return false; } - return i == 3; + ui->cb_viewtext->setChecked(vt.toBool()); + ui->cb_autosync->setChecked(as.toBool()); + ui->cbPalette->setCurrentIndex(pa.toInt()); + return true; } void PaletteView::refresh() diff --git a/src/blendsplitter/SwitchingWidget.cpp b/src/blendsplitter/SwitchingWidget.cpp index c18300aa..d29da01e 100644 --- a/src/blendsplitter/SwitchingWidget.cpp +++ b/src/blendsplitter/SwitchingWidget.cpp @@ -89,9 +89,10 @@ SwitchingWidget* SwitchingWidget::createFromJson(const QJsonObject &obj) auto* wdgt = new SwitchingWidget{WidgetRegistry::instance().item(i)}; wdgt->resize(obj["size_width"].toInt(), obj["size_height"].toInt()); - auto* childwdgt = dynamic_cast(wdgt->getWidget()); - if (childwdgt && obj["childwidget"] != QJsonValue::Undefined) { - childwdgt->loadFromJson(obj["childwidget"].toObject()); + if (auto* childWdgt = dynamic_cast(wdgt->getWidget())) { + if (auto cw = obj["childwidget"]; cw != QJsonValue::Undefined) { + childWdgt->loadFromJson(cw.toObject()); + } } return wdgt; @@ -111,8 +112,7 @@ QWidget *SwitchingWidget::getWidget() QJsonObject SwitchingWidget::getWidgetSettings() { QJsonObject obj; - auto* wd = dynamic_cast(getWidget()); - if (wd) { + if (auto* wd = dynamic_cast(getWidget())) { obj = wd->save2json(); } return obj; @@ -120,8 +120,7 @@ QJsonObject SwitchingWidget::getWidgetSettings() bool SwitchingWidget::setWidgetSettings(const QJsonObject &obj) { - auto* wd = dynamic_cast(getWidget()); - if (wd) { + if (auto* wd = dynamic_cast(getWidget())) { return wd->loadFromJson(obj); } return false; From 1dd57bb858311b6b62fd7ec49790a4e46948d3fc Mon Sep 17 00:00:00 2001 From: m9710797 Date: Wed, 18 May 2022 19:36:35 +0200 Subject: [PATCH 41/63] Tweak SavesJsonInterface No need to implement an empty default constructor. No need to explicitly call the default constructor of a base-class. --- src/MainMemoryViewer.cpp | 4 ++-- src/PaletteView.cpp | 2 +- src/SavesJsonInterface.cpp | 6 ------ src/SavesJsonInterface.h | 1 - src/node.mk | 2 +- 5 files changed, 4 insertions(+), 11 deletions(-) delete mode 100644 src/SavesJsonInterface.cpp diff --git a/src/MainMemoryViewer.cpp b/src/MainMemoryViewer.cpp index 660ee950..1a4507e5 100644 --- a/src/MainMemoryViewer.cpp +++ b/src/MainMemoryViewer.cpp @@ -20,9 +20,9 @@ static const int linkRegisters[] = { }; MainMemoryViewer::MainMemoryViewer(QWidget* parent) - : QWidget(parent), SavesJsonInterface() + : QWidget(parent) { - setObjectName("MainMemoryViewer"); + setObjectName("MainMemoryViewer"); // create selection list, address edit line and viewer addressSourceList = new QComboBox(); addressSourceList->setEditable(false); diff --git a/src/PaletteView.cpp b/src/PaletteView.cpp index 44ce8ca0..46f07d49 100644 --- a/src/PaletteView.cpp +++ b/src/PaletteView.cpp @@ -8,7 +8,7 @@ #include PaletteView::PaletteView(QWidget* parent) - : QWidget(parent), SavesJsonInterface() + : QWidget(parent) , ui(std::make_unique()) { ui->setupUi(this); diff --git a/src/SavesJsonInterface.cpp b/src/SavesJsonInterface.cpp deleted file mode 100644 index 7ac0578b..00000000 --- a/src/SavesJsonInterface.cpp +++ /dev/null @@ -1,6 +0,0 @@ -#include "SavesJsonInterface.h" - -SavesJsonInterface::SavesJsonInterface() -{ - -} diff --git a/src/SavesJsonInterface.h b/src/SavesJsonInterface.h index 40813625..4824ab91 100644 --- a/src/SavesJsonInterface.h +++ b/src/SavesJsonInterface.h @@ -6,7 +6,6 @@ class QJsonObject; class SavesJsonInterface { public: - SavesJsonInterface(); virtual QJsonObject save2json() = 0; virtual bool loadFromJson(const QJsonObject& obj) = 0; }; diff --git a/src/node.mk b/src/node.mk index 8531919b..0650e56c 100644 --- a/src/node.mk +++ b/src/node.mk @@ -25,7 +25,7 @@ MOC_SRC_HDR:= \ SRC_HDR:= \ Dasm DasmTables DebuggerData SymbolTable Convert Version \ - CPURegs SimpleHexRequest SavesJsonInterface + CPURegs SimpleHexRequest SRC_ONLY:= \ main From 5fda6b0b0f44c7bc561429ce9f0da0df7fa92b22 Mon Sep 17 00:00:00 2001 From: m9710797 Date: Wed, 18 May 2022 19:39:48 +0200 Subject: [PATCH 42/63] Do not use 'symTable' and 'symtable' as two distict symbols within the same scope --- src/MainMemoryViewer.cpp | 4 ++-- src/MainMemoryViewer.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/MainMemoryViewer.cpp b/src/MainMemoryViewer.cpp index 1a4507e5..d55d120f 100644 --- a/src/MainMemoryViewer.cpp +++ b/src/MainMemoryViewer.cpp @@ -87,9 +87,9 @@ void MainMemoryViewer::setDebuggable(const QString& name, int size) // regsViewer = viewer; //} -void MainMemoryViewer::setSymbolTable(SymbolTable* symtable) +void MainMemoryViewer::setSymbolTable(SymbolTable* newTable) { - symTable = symtable; + symTable = newTable; } QJsonObject MainMemoryViewer::save2json() diff --git a/src/MainMemoryViewer.h b/src/MainMemoryViewer.h index b79aa2a6..33942850 100644 --- a/src/MainMemoryViewer.h +++ b/src/MainMemoryViewer.h @@ -19,7 +19,7 @@ class MainMemoryViewer : public QWidget, public SavesJsonInterface void setDebuggable(const QString& name, int size); // void setRegsView(CPURegsViewer* viewer); - void setSymbolTable(SymbolTable* symtable); + void setSymbolTable(SymbolTable* newtable); QJsonObject save2json() final; bool loadFromJson(const QJsonObject& obj) final; From 8bf05ae722eedf4c8aedccd7ae83cc0bda7485e7 Mon Sep 17 00:00:00 2001 From: m9710797 Date: Wed, 18 May 2022 19:46:03 +0200 Subject: [PATCH 43/63] globally replace 'unsigned char' -> 'uint8_t' --- src/BitMapViewer.cpp | 16 ++++++++-------- src/CPURegsViewer.cpp | 6 +++--- src/CPURegsViewer.h | 4 ++-- src/Dasm.cpp | 12 ++++++------ src/Dasm.h | 2 +- src/DisasmViewer.cpp | 4 ++-- src/DisasmViewer.h | 4 ++-- src/FlagsViewer.h | 4 ++-- src/OpenMSXConnection.cpp | 10 +++++----- src/OpenMSXConnection.h | 8 ++++---- src/SignalDispatcher.h | 2 +- src/SimpleHexRequest.cpp | 4 ++-- src/SimpleHexRequest.h | 6 +++--- src/StackViewer.cpp | 4 ++-- src/StackViewer.h | 4 ++-- src/SymbolTable.h | 2 +- 16 files changed, 46 insertions(+), 46 deletions(-) diff --git a/src/BitMapViewer.cpp b/src/BitMapViewer.cpp index 302a9720..f1933fa6 100644 --- a/src/BitMapViewer.cpp +++ b/src/BitMapViewer.cpp @@ -4,7 +4,7 @@ #include "Convert.h" #include -static const unsigned char defaultPalette[32] = { +static const uint8_t defaultPalette[32] = { // RB G 0x00, 0, 0x00, 0, @@ -47,7 +47,7 @@ BitMapViewer::BitMapViewer(QWidget* parent) // imageWidget and the QScrollArea so the scrollbars are not correctly // handled when the image is resized. (since the intermediate widget // stays the same size). I did not try to have this intermediate widget - // resize and all, since it was superflous anyway. + // resize and all, since it was superfluous anyway. imageWidget = new VramBitMappedView(); QSizePolicy sizePolicy1(QSizePolicy::Fixed, QSizePolicy::Fixed); sizePolicy1.setHorizontalStretch(0); @@ -60,8 +60,8 @@ BitMapViewer::BitMapViewer(QWidget* parent) useVDP = useVDPRegisters->isChecked(); - const unsigned char* vram = VDPDataStore::instance().getVramPointer(); - const unsigned char* palette = VDPDataStore::instance().getPalettePointer(); + const uint8_t* vram = VDPDataStore::instance().getVramPointer(); + const uint8_t* palette = VDPDataStore::instance().getPalettePointer(); imageWidget->setVramSource(vram); imageWidget->setVramAddress(0); imageWidget->setPaletteSource(palette); @@ -85,17 +85,17 @@ BitMapViewer::BitMapViewer(QWidget* parent) void BitMapViewer::decodeVDPregs() { - const unsigned char* regs = VDPDataStore::instance().getRegsPointer(); + const uint8_t* regs = VDPDataStore::instance().getRegsPointer(); // Get the number of lines int v1 = (regs[9] & 128) ? 212 : 192; - printf("\nlines acording to the bits %i,: %i\n", (regs[9] & 128), v1); + printf("\nlines according to the bits %i,: %i\n", (regs[9] & 128), v1); linesLabel->setText(QString("%1").arg(v1, 0, 10)); if (useVDP) linesVisible->setCurrentIndex((regs[9] & 128) ? 1 : 0); // Get the border color int v2 = regs[7] & 15; - printf("\nborder acording to the regs %i,: %i\n", regs[7], v2); + printf("\nborder according to the regs %i,: %i\n", regs[7], v2); if (regs[8] & 32) v2 = 0; printf("\ncolor 0 is pallet regs %i,: %i\n", (regs[8] & 32), v2); borderLabel->setText(QString("%1").arg(v2, 0, 10)); @@ -259,7 +259,7 @@ void BitMapViewer::on_editPaletteButton_clicked(bool /*checked*/) void BitMapViewer::on_useVDPPalette_stateChanged(int state) { if (state) { - const unsigned char* palette = VDPDataStore::instance().getPalettePointer(); + const uint8_t* palette = VDPDataStore::instance().getPalettePointer(); imageWidget->setPaletteSource(palette); } else { imageWidget->setPaletteSource(defaultPalette); diff --git a/src/CPURegsViewer.cpp b/src/CPURegsViewer.cpp index 4ca5590f..24023351 100644 --- a/src/CPURegsViewer.cpp +++ b/src/CPURegsViewer.cpp @@ -150,7 +150,7 @@ void CPURegsViewer::setRegister(int id, int value) } } -void CPURegsViewer::setData(unsigned char* datPtr) +void CPURegsViewer::setData(uint8_t* datPtr) { setRegister(CpuRegs::REG_AF , datPtr[ 0] * 256 + datPtr[ 1]); setRegister(CpuRegs::REG_BC , datPtr[ 2] * 256 + datPtr[ 3]); @@ -312,7 +312,7 @@ int CPURegsViewer::readRegister(int id) return regs[id]; } -void CPURegsViewer::getRegister(int id, unsigned char* data) +void CPURegsViewer::getRegister(int id, uint8_t* data) { data[0] = regs[id] >> 8; data[1] = regs[id] & 255; @@ -320,7 +320,7 @@ void CPURegsViewer::getRegister(int id, unsigned char* data) void CPURegsViewer::applyModifications() { - unsigned char data[26]; + uint8_t data[26]; getRegister(CpuRegs::REG_AF, &data[ 0]); getRegister(CpuRegs::REG_BC, &data[ 2]); getRegister(CpuRegs::REG_DE, &data[ 4]); diff --git a/src/CPURegsViewer.h b/src/CPURegsViewer.h index 9fabadc6..84544147 100644 --- a/src/CPURegsViewer.h +++ b/src/CPURegsViewer.h @@ -15,7 +15,7 @@ class CPURegsViewer : public QFrame QSize sizeHint() const override; public slots: - void setData(unsigned char* datPtr); + void setData(uint8_t* datPtr); void setRegister(int id, int value); private: @@ -39,7 +39,7 @@ public slots: int cursorLoc; void drawValue(QPainter& p, int id, int x, int y); - void getRegister(int id, unsigned char* data); + void getRegister(int id, uint8_t* data); void applyModifications(); void cancelModifications(); diff --git a/src/Dasm.cpp b/src/Dasm.cpp index feddecbd..6912db0a 100644 --- a/src/Dasm.cpp +++ b/src/Dasm.cpp @@ -4,12 +4,12 @@ #include #include -static char sign(unsigned char a) +static char sign(uint8_t a) { return (a & 128) ? '-' : '+'; } -static int abs(unsigned char a) +static int abs(uint8_t a) { return (a & 128) ? (256 - a) : a; } @@ -31,12 +31,12 @@ static std::string translateAddress( } } -static int get16(const unsigned char* memBuf, int address) +static int get16(const uint8_t* memBuf, int address) { return memBuf[address] + 256 * memBuf[address + 1]; } -void dasm(const unsigned char* membuf, uint16_t startAddr, uint16_t endAddr, +void dasm(const uint8_t* membuf, uint16_t startAddr, uint16_t endAddr, DisasmLines& disasm, MemoryLayout* memLayout, SymbolTable* symTable, int currentPC) { int pc = startAddr; @@ -116,14 +116,14 @@ void dasm(const unsigned char* membuf, uint16_t startAddr, uint16_t endAddr, dest.numBytes += 2; break; case 'X': { - unsigned char offset = membuf[pc + dest.numBytes]; + uint8_t offset = membuf[pc + dest.numBytes]; dest.instr += '(' + std::string(r) + sign(offset) + '#' + toHex(abs(offset), 2) + ')'; dest.numBytes += 1; break; } case 'Y': { - unsigned char offset = membuf[pc + 2]; + uint8_t offset = membuf[pc + 2]; dest.instr += '(' + std::string(r) + sign(offset) + '#' + toHex(abs(offset), 2) + ')'; break; diff --git a/src/Dasm.h b/src/Dasm.h index c7b073ce..5b75fcbc 100644 --- a/src/Dasm.h +++ b/src/Dasm.h @@ -23,7 +23,7 @@ static const int LAST_INFO_LINE = -65536; using DisasmLines = std::vector; -void dasm(const unsigned char* membuf, uint16_t startAddr, uint16_t endAddr, DisasmLines& disasm, +void dasm(const uint8_t* membuf, uint16_t startAddr, uint16_t endAddr, DisasmLines& disasm, MemoryLayout *memLayout, SymbolTable *symTable, int currentPC); #endif // DASM_H diff --git a/src/DisasmViewer.cpp b/src/DisasmViewer.cpp index 7589742f..8ad46e70 100644 --- a/src/DisasmViewer.cpp +++ b/src/DisasmViewer.cpp @@ -18,7 +18,7 @@ class CommMemoryRequest : public ReadDebugBlockCommand { public: - CommMemoryRequest(uint16_t offset_, uint16_t size_, unsigned char* target, + CommMemoryRequest(uint16_t offset_, uint16_t size_, uint8_t* target, DisasmViewer& viewer_) : ReadDebugBlockCommand("memory", offset_, size_, target) , offset(offset_), size(size_) @@ -534,7 +534,7 @@ void DisasmViewer::scrollBarChanged(int value) setAddress(value, FIRST_INFO_LINE, TopAlways); } -void DisasmViewer::setMemory(unsigned char* memPtr) +void DisasmViewer::setMemory(uint8_t* memPtr) { memory = memPtr; // init disasmLines diff --git a/src/DisasmViewer.h b/src/DisasmViewer.h index b4f9e44d..0f31b1cd 100644 --- a/src/DisasmViewer.h +++ b/src/DisasmViewer.h @@ -17,7 +17,7 @@ class DisasmViewer : public QFrame public: DisasmViewer(QWidget* parent = nullptr); - void setMemory(unsigned char* memPtr); + void setMemory(uint8_t* memPtr); void setBreakpoints(Breakpoints* bps); void setMemoryLayout(MemoryLayout* ml); void setSymbolTable(SymbolTable* st); @@ -81,7 +81,7 @@ class DisasmViewer : public QFrame DisasmLines disasmLines; // display data - unsigned char* memory; + uint8_t* memory; bool waitingForData; CommMemoryRequest* nextRequest; Breakpoints* breakpoints; diff --git a/src/FlagsViewer.h b/src/FlagsViewer.h index e5921f8d..d0ee6d69 100644 --- a/src/FlagsViewer.h +++ b/src/FlagsViewer.h @@ -27,8 +27,8 @@ class FlagsViewer : public QFrame private: int frameL, frameR, frameT, frameB; - unsigned char flags; - unsigned char flagsChanged; + uint8_t flags; + uint8_t flagsChanged; }; #endif // FLAGSVIEWER_H diff --git a/src/OpenMSXConnection.cpp b/src/OpenMSXConnection.cpp index b4f4ca11..dc3e6d67 100644 --- a/src/OpenMSXConnection.cpp +++ b/src/OpenMSXConnection.cpp @@ -59,21 +59,21 @@ static QString createDebugCommand(const QString& debuggable, } ReadDebugBlockCommand::ReadDebugBlockCommand(const QString& commandString, - unsigned size_, unsigned char* target_) + unsigned size_, uint8_t* target_) : SimpleCommand(commandString) , size(size_), target(target_) { } ReadDebugBlockCommand::ReadDebugBlockCommand(const QString& debuggable, - unsigned offset, unsigned size_, unsigned char* target_) + unsigned offset, unsigned size_, uint8_t* target_) : SimpleCommand(createDebugCommand(debuggable, offset, size_)) , size(size_), target(target_) { } static QString createDebugWriteCommand(const QString& debuggable, - unsigned offset, unsigned size, unsigned char *data) + unsigned offset, unsigned size, uint8_t *data) { QString cmd = QString("debug write_block %1 %2 [ debug_hex2bin \"") .arg(debuggable).arg(offset); @@ -84,13 +84,13 @@ static QString createDebugWriteCommand(const QString& debuggable, return cmd; } WriteDebugBlockCommand::WriteDebugBlockCommand(const QString& debuggable, - unsigned offset, unsigned size_, unsigned char* source_) + unsigned offset, unsigned size_, uint8_t* source_) : SimpleCommand(createDebugWriteCommand(debuggable, offset, size_, source_)) { } -static unsigned char hex2val(char c) +static uint8_t hex2val(char c) { return (c <= '9') ? (c - '0') : (c - 'A' + 10); } diff --git a/src/OpenMSXConnection.h b/src/OpenMSXConnection.h index 5a83b804..39f3e1bf 100644 --- a/src/OpenMSXConnection.h +++ b/src/OpenMSXConnection.h @@ -58,23 +58,23 @@ class ReadDebugBlockCommand : public SimpleCommand { public: ReadDebugBlockCommand(const QString& commandString, unsigned size, - unsigned char* target); + uint8_t* target); ReadDebugBlockCommand(const QString& debuggable, unsigned offset, unsigned size, - unsigned char* target); + uint8_t* target); protected: void copyData(const QString& message); private: unsigned size; - unsigned char* target; + uint8_t* target; }; class WriteDebugBlockCommand : public SimpleCommand { public: WriteDebugBlockCommand(const QString& debuggable, unsigned offset, unsigned size, - unsigned char* source); + uint8_t* source); }; class OpenMSXConnection : public QObject diff --git a/src/SignalDispatcher.h b/src/SignalDispatcher.h index ec6a79e2..c9994776 100644 --- a/src/SignalDispatcher.h +++ b/src/SignalDispatcher.h @@ -52,7 +52,7 @@ public slots: void breakpointsUpdated(); void debuggablesChanged(const QMap& list); // signals concerning CPU registers - void registersUpdate(unsigned char* datPtr); + void registersUpdate(uint8_t* datPtr); void registerChanged(int id, int value); void pcChanged(uint16_t); void flagsChanged(quint8); diff --git a/src/SimpleHexRequest.cpp b/src/SimpleHexRequest.cpp index 3edb36d8..67a6f0ef 100644 --- a/src/SimpleHexRequest.cpp +++ b/src/SimpleHexRequest.cpp @@ -6,7 +6,7 @@ SimpleHexRequest::SimpleHexRequest( const QString& debuggable, unsigned size, - unsigned char* target, SimpleHexRequestUser& user_) + uint8_t* target, SimpleHexRequestUser& user_) : ReadDebugBlockCommand(debuggable, size, target) , offset(0) , user(user_) @@ -16,7 +16,7 @@ SimpleHexRequest::SimpleHexRequest( SimpleHexRequest::SimpleHexRequest( const QString& debuggable, unsigned offset_, unsigned size, - unsigned char* target, SimpleHexRequestUser& user_) + uint8_t* target, SimpleHexRequestUser& user_) : ReadDebugBlockCommand(debuggable, offset_, size, target) , offset(offset_) , user(user_) diff --git a/src/SimpleHexRequest.h b/src/SimpleHexRequest.h index 1e48700c..a661e892 100644 --- a/src/SimpleHexRequest.h +++ b/src/SimpleHexRequest.h @@ -4,7 +4,7 @@ #include "OpenMSXConnection.h" /** - * A set of helper classes if code needs to read openMSX debugables into an array of unsigned chars + * A set of helper classes if code needs to read openMSX debugables into an array of uint8_t's * if class A needs to read a given debugable then this schema will suffice * - Class A inherits from SimpleHexRequestUser * - Class A can reimplement the DataHexRequestReceived if it wants to react when new data has arrived @@ -26,9 +26,9 @@ class SimpleHexRequest : public ReadDebugBlockCommand { public: SimpleHexRequest(const QString& debuggable, unsigned size, - unsigned char* target, SimpleHexRequestUser& user); + uint8_t* target, SimpleHexRequestUser& user); SimpleHexRequest(const QString& debuggable, unsigned offset, unsigned size, - unsigned char* target, SimpleHexRequestUser& user); + uint8_t* target, SimpleHexRequestUser& user); void replyOk(const QString& message) override; void cancel() override; diff --git a/src/StackViewer.cpp b/src/StackViewer.cpp index 287533fe..4f6495bc 100644 --- a/src/StackViewer.cpp +++ b/src/StackViewer.cpp @@ -11,7 +11,7 @@ class StackRequest : public ReadDebugBlockCommand { public: StackRequest(unsigned offset_, unsigned size, - unsigned char* target, StackViewer& viewer_) + uint8_t* target, StackViewer& viewer_) : ReadDebugBlockCommand("memory", offset_, size, target) , offset(offset_) , viewer(viewer_) @@ -159,7 +159,7 @@ void StackViewer::paintEvent(QPaintEvent* e) } } -void StackViewer::setData(unsigned char* memPtr, int memLength) +void StackViewer::setData(uint8_t* memPtr, int memLength) { memory = memPtr; memoryLength = memLength; diff --git a/src/StackViewer.h b/src/StackViewer.h index 71d02a01..7cdbc106 100644 --- a/src/StackViewer.h +++ b/src/StackViewer.h @@ -13,7 +13,7 @@ class StackViewer : public QFrame public: StackViewer(QWidget* parent = nullptr); - void setData(unsigned char* memPtr, int memLength); + void setData(uint8_t* memPtr, int memLength); QSize sizeHint() const override; void setLocation(int addr); @@ -39,7 +39,7 @@ class StackViewer : public QFrame int stackPointer; int topAddress; - unsigned char* memory; + uint8_t* memory; int memoryLength; friend class StackRequest; diff --git a/src/SymbolTable.h b/src/SymbolTable.h index 9294437c..51fa09dc 100644 --- a/src/SymbolTable.h +++ b/src/SymbolTable.h @@ -60,7 +60,7 @@ class Symbol QString symText; int symValue; int symSlots; - QList symSegments; + QList symSegments; int symRegisters; const QString* symSource; SymbolStatus symStatus; From a339c42016c652becf3abe2afaf6fa619cb65fbd Mon Sep 17 00:00:00 2001 From: m9710797 Date: Wed, 18 May 2022 20:09:03 +0200 Subject: [PATCH 44/63] Simplify DebuggerForm::widgetFactory() --- src/DebuggerForm.cpp | 143 +++++++++++++++++++------------------------ 1 file changed, 62 insertions(+), 81 deletions(-) diff --git a/src/DebuggerForm.cpp b/src/DebuggerForm.cpp index d3eb2320..22e71eee 100644 --- a/src/DebuggerForm.cpp +++ b/src/DebuggerForm.cpp @@ -732,123 +732,104 @@ void DebuggerForm::addDefaultWorkspaces() addVDPBitmapWorkspace(); } -QWidget* DebuggerForm::widgetFactory(factoryclasses fctwidget) +QWidget* DebuggerForm::widgetFactory(factoryclasses fctWidget) { auto& dispatcher = SignalDispatcher::instance(); - QWidget* retwdgt; - switch (fctwidget) { + switch (fctWidget) { case disasmViewer: { - DisasmViewer* wdgt = new DisasmViewer(); - connect(wdgt, &DisasmViewer::breakpointToggled, &dispatcher, &SignalDispatcher::breakpointToggled); - connect(&dispatcher, &SignalDispatcher::connected, wdgt, &DisasmViewer::refresh); - connect(&dispatcher, &SignalDispatcher::breakStateEntered, wdgt, &DisasmViewer::refresh); - connect(&dispatcher, &SignalDispatcher::symbolsChanged, wdgt, &DisasmViewer::refresh); - connect(&dispatcher, &SignalDispatcher::settingsChanged, wdgt, &DisasmViewer::updateLayout); - connect(&dispatcher, &SignalDispatcher::setCursorAddress, wdgt, &DisasmViewer::setCursorAddress); - connect(&dispatcher, &SignalDispatcher::setProgramCounter, wdgt, &DisasmViewer::setProgramCounter); - connect(&dispatcher, &SignalDispatcher::breakpointsUpdated, wdgt, &DisasmViewer::update); - wdgt->setMemory(dispatcher.getMainMemory()); - wdgt->setBreakpoints(&DebugSession::getDebugSession()->breakpoints()); - wdgt->setMemoryLayout(dispatcher.getMemLayout()); - wdgt->setSymbolTable(&DebugSession::getDebugSession()->symbolTable()); - retwdgt = wdgt; - break; + DisasmViewer* dv = new DisasmViewer(); + connect(dv, &DisasmViewer::breakpointToggled, &dispatcher, &SignalDispatcher::breakpointToggled); + connect(&dispatcher, &SignalDispatcher::connected, dv, &DisasmViewer::refresh); + connect(&dispatcher, &SignalDispatcher::breakStateEntered, dv, &DisasmViewer::refresh); + connect(&dispatcher, &SignalDispatcher::symbolsChanged, dv, &DisasmViewer::refresh); + connect(&dispatcher, &SignalDispatcher::settingsChanged, dv, &DisasmViewer::updateLayout); + connect(&dispatcher, &SignalDispatcher::setCursorAddress, dv, &DisasmViewer::setCursorAddress); + connect(&dispatcher, &SignalDispatcher::setProgramCounter, dv, &DisasmViewer::setProgramCounter); + connect(&dispatcher, &SignalDispatcher::breakpointsUpdated, dv, &DisasmViewer::update); + dv->setMemory(dispatcher.getMainMemory()); + dv->setBreakpoints(&DebugSession::getDebugSession()->breakpoints()); + dv->setMemoryLayout(dispatcher.getMemLayout()); + dv->setSymbolTable(&DebugSession::getDebugSession()->symbolTable()); + return dv; } case mainMemoryViewer: { - MainMemoryViewer* wdgt = new MainMemoryViewer(); + MainMemoryViewer* mmv = new MainMemoryViewer(); // Main memory viewer - connect(&dispatcher, &SignalDispatcher::connected, wdgt, &MainMemoryViewer::refresh); - connect(&dispatcher, &SignalDispatcher::breakStateEntered, wdgt, &MainMemoryViewer::refresh); - connect(&dispatcher, &SignalDispatcher::registerChanged, wdgt, &MainMemoryViewer::registerChanged); + connect(&dispatcher, &SignalDispatcher::connected, mmv, &MainMemoryViewer::refresh); + connect(&dispatcher, &SignalDispatcher::breakStateEntered, mmv, &MainMemoryViewer::refresh); + connect(&dispatcher, &SignalDispatcher::registerChanged, mmv, &MainMemoryViewer::registerChanged); //mainMemoryView->setRegsView(regsView); - wdgt->setSymbolTable(&DebugSession::getDebugSession()->symbolTable()); - wdgt->setDebuggable("memory", 65536); - retwdgt = wdgt; - break; + mmv->setSymbolTable(&DebugSession::getDebugSession()->symbolTable()); + mmv->setDebuggable("memory", 65536); + return mmv; } case cpuRegsViewer: { - CPURegsViewer* wdgt = new CPURegsViewer(); + CPURegsViewer* crv = new CPURegsViewer(); //copy current registers to new widget for (int id = 0; id < 15; ++id) { // CpuRegs::REG_AF up to CpuRegs::REG_IFF - static_cast(wdgt)->setRegister(id, dispatcher.readRegister(id)); + crv->setRegister(id, dispatcher.readRegister(id)); } - connect(&dispatcher, &SignalDispatcher::registersUpdate, wdgt, &CPURegsViewer::setData); - retwdgt = wdgt; - break; + connect(&dispatcher, &SignalDispatcher::registersUpdate, crv, &CPURegsViewer::setData); + return crv; } case flagsViewer: { - FlagsViewer* wdgt = new FlagsViewer(); - wdgt->setFlags(dispatcher.readRegister(CpuRegs::REG_AF) & 0xFF); - connect(&dispatcher, &SignalDispatcher::flagsChanged, wdgt, &FlagsViewer::setFlags); - retwdgt = wdgt; - break; + FlagsViewer* fv = new FlagsViewer(); + fv->setFlags(dispatcher.readRegister(CpuRegs::REG_AF) & 0xFF); + connect(&dispatcher, &SignalDispatcher::flagsChanged, fv, &FlagsViewer::setFlags); + return fv; } case stackViewer: { - StackViewer* wdgt = new StackViewer(); - wdgt->setData(dispatcher.getMainMemory(), 65536); - wdgt->setStackPointer(dispatcher.readRegister(CpuRegs::REG_SP)); - connect(&dispatcher, &SignalDispatcher::spChanged, wdgt, &StackViewer::setStackPointer); - retwdgt = wdgt; - break; + StackViewer* sv = new StackViewer(); + sv->setData(dispatcher.getMainMemory(), 65536); + sv->setStackPointer(dispatcher.readRegister(CpuRegs::REG_SP)); + connect(&dispatcher, &SignalDispatcher::spChanged, sv, &StackViewer::setStackPointer); + return sv; } case slotViewer: { - SlotViewer* wdgt = new SlotViewer(); - connect(&dispatcher, &SignalDispatcher::connected, wdgt, &SlotViewer::refresh); - connect(&dispatcher, &SignalDispatcher::breakStateEntered, wdgt, &SlotViewer::refresh); - connect(&dispatcher, &SignalDispatcher::slotsUpdated, wdgt, &SlotViewer::refresh); - wdgt->setMemoryLayout(dispatcher.getMemLayout()); - retwdgt = wdgt; - break; + SlotViewer* sv = new SlotViewer(); + connect(&dispatcher, &SignalDispatcher::connected, sv, &SlotViewer::refresh); + connect(&dispatcher, &SignalDispatcher::breakStateEntered, sv, &SlotViewer::refresh); + connect(&dispatcher, &SignalDispatcher::slotsUpdated, sv, &SlotViewer::refresh); + sv->setMemoryLayout(dispatcher.getMemLayout()); + return sv; } case breakpointViewer: - retwdgt = new BreakpointViewer(); - break; + return new BreakpointViewer(); case debuggableViewer: { - DebuggableViewer* wdgt = new DebuggableViewer(); - connect(&dispatcher, &SignalDispatcher::breakStateEntered, wdgt, &DebuggableViewer::refresh); - connect(&dispatcher, &SignalDispatcher::debuggablesChanged, wdgt, &DebuggableViewer::setDebuggables); - wdgt->setDebuggables(debuggables); + DebuggableViewer* dv = new DebuggableViewer(); + connect(&dispatcher, &SignalDispatcher::breakStateEntered, dv, &DebuggableViewer::refresh); + connect(&dispatcher, &SignalDispatcher::debuggablesChanged, dv, &DebuggableViewer::setDebuggables); + dv->setDebuggables(debuggables); if (!debuggables.isEmpty()) { - wdgt->debuggableSelected(0); - wdgt->refresh(); + dv->debuggableSelected(0); + dv->refresh(); } - retwdgt = wdgt; - break; + return dv; } case vdpStatusRegViewer: - retwdgt = new VDPStatusRegViewer(); - break; + return new VDPStatusRegViewer(); case vdpCommandRegViewer: - retwdgt = new VDPCommandRegViewer(); - break; + return new VDPCommandRegViewer(); case bitMapViewer: - retwdgt = new BitMapViewer(); - break; + return new BitMapViewer(); case tileViewer: - retwdgt = new TileViewer(); - break; + return new TileViewer(); case spriteViewer: - retwdgt = new SpriteViewer(); - break; + return new SpriteViewer(); case vdpRegisters: - retwdgt = new VDPRegViewer(); - break; + return new VDPRegViewer(); case quickguide: - retwdgt = new QuickGuide(); - break; + return new QuickGuide(); case paletteViewer: { - PaletteView* wdgt = new PaletteView(); - connect(&dispatcher, &SignalDispatcher::connected, wdgt, &PaletteView::refresh); - connect(&dispatcher, &SignalDispatcher::breakStateEntered, wdgt, &PaletteView::refresh); - retwdgt = wdgt; - break; + PaletteView* pv = new PaletteView(); + connect(&dispatcher, &SignalDispatcher::connected, pv, &PaletteView::refresh); + connect(&dispatcher, &SignalDispatcher::breakStateEntered, pv, &PaletteView::refresh); + return pv; } default: - retwdgt = new QLabel("Not yet implemented in widgetFactory!"); - break; + return new QLabel("Not yet implemented in widgetFactory!"); } - return retwdgt; } void DebuggerForm::closeEvent(QCloseEvent* e) From 17208000c8254e423b9ce9d3c0da83b566e89070 Mon Sep 17 00:00:00 2001 From: m9710797 Date: Wed, 18 May 2022 20:12:21 +0200 Subject: [PATCH 45/63] No need for DisasmViewer::update() (instead need qOverload) --- src/DebuggerForm.cpp | 6 +++--- src/DisasmViewer.cpp | 5 ----- src/DisasmViewer.h | 2 -- 3 files changed, 3 insertions(+), 10 deletions(-) diff --git a/src/DebuggerForm.cpp b/src/DebuggerForm.cpp index 22e71eee..24068b33 100644 --- a/src/DebuggerForm.cpp +++ b/src/DebuggerForm.cpp @@ -746,7 +746,7 @@ QWidget* DebuggerForm::widgetFactory(factoryclasses fctWidget) connect(&dispatcher, &SignalDispatcher::settingsChanged, dv, &DisasmViewer::updateLayout); connect(&dispatcher, &SignalDispatcher::setCursorAddress, dv, &DisasmViewer::setCursorAddress); connect(&dispatcher, &SignalDispatcher::setProgramCounter, dv, &DisasmViewer::setProgramCounter); - connect(&dispatcher, &SignalDispatcher::breakpointsUpdated, dv, &DisasmViewer::update); + connect(&dispatcher, &SignalDispatcher::breakpointsUpdated, dv, qOverload<>(&DisasmViewer::update)); dv->setMemory(dispatcher.getMainMemory()); dv->setBreakpoints(&DebugSession::getDebugSession()->breakpoints()); dv->setMemoryLayout(dispatcher.getMemLayout()); @@ -761,7 +761,7 @@ QWidget* DebuggerForm::widgetFactory(factoryclasses fctWidget) connect(&dispatcher, &SignalDispatcher::registerChanged, mmv, &MainMemoryViewer::registerChanged); //mainMemoryView->setRegsView(regsView); mmv->setSymbolTable(&DebugSession::getDebugSession()->symbolTable()); - mmv->setDebuggable("memory", 65536); + mmv->setDebuggable("memory", 0x10000); return mmv; } case cpuRegsViewer: { @@ -781,7 +781,7 @@ QWidget* DebuggerForm::widgetFactory(factoryclasses fctWidget) } case stackViewer: { StackViewer* sv = new StackViewer(); - sv->setData(dispatcher.getMainMemory(), 65536); + sv->setData(dispatcher.getMainMemory(), 0x10000); sv->setStackPointer(dispatcher.readRegister(CpuRegs::REG_SP)); connect(&dispatcher, &SignalDispatcher::spChanged, sv, &StackViewer::setStackPointer); return sv; diff --git a/src/DisasmViewer.cpp b/src/DisasmViewer.cpp index 8ad46e70..83768bb6 100644 --- a/src/DisasmViewer.cpp +++ b/src/DisasmViewer.cpp @@ -160,11 +160,6 @@ void DisasmViewer::refresh() requestMemory(start, end, disasmLines[disasmTopLine].addr, infoLine, TopAlways); } -void DisasmViewer::update() -{ - QFrame::update(); -} - void DisasmViewer::paintEvent(QPaintEvent* e) { // call parent for drawing the actual frame diff --git a/src/DisasmViewer.h b/src/DisasmViewer.h index 0f31b1cd..b1d5fae7 100644 --- a/src/DisasmViewer.h +++ b/src/DisasmViewer.h @@ -38,8 +38,6 @@ class DisasmViewer : public QFrame void updateLayout(); void refresh(); - void update(); //connect in DebuggerForm::widgetFactory couldn't directly connect to update of QWidget ?? - signals: void breakpointToggled(uint16_t addr); From 20e2913f4708ccea6e27cbed018c1f9b5930d57c Mon Sep 17 00:00:00 2001 From: David Heremans Date: Sat, 21 May 2022 22:08:22 +0200 Subject: [PATCH 46/63] Get rid of deprecated signal --- src/BitMapViewer.cpp | 6 +++--- src/BitMapViewer.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/BitMapViewer.cpp b/src/BitMapViewer.cpp index f1933fa6..8bc9286b 100644 --- a/src/BitMapViewer.cpp +++ b/src/BitMapViewer.cpp @@ -30,7 +30,7 @@ BitMapViewer::BitMapViewer(QWidget* parent) { setupUi(this); //no connect slot byname anymore - connect(screenMode, QOverload::of(&QComboBox:: currentIndexChanged), this, &BitMapViewer::on_screenMode_currentIndexChanged); + connect(screenMode, QOverload::of(&QComboBox:: currentIndexChanged), this, &BitMapViewer::on_screenMode_currentIndexChanged); connect(showPage, QOverload::of(&QComboBox:: currentIndexChanged), this, &BitMapViewer::on_showPage_currentIndexChanged); connect(linesVisible, QOverload::of(&QComboBox:: currentIndexChanged), this, &BitMapViewer::on_linesVisible_currentIndexChanged); connect(bgColor, QOverload::of(&QSpinBox::valueChanged), this, &BitMapViewer::on_bgColor_valueChanged); @@ -171,9 +171,9 @@ void BitMapViewer::refresh() VDPDataStore::instance().refresh(); } -void BitMapViewer::on_screenMode_currentIndexChanged(const QString& text) +void BitMapViewer::on_screenMode_currentIndexChanged(int index) { - screenMod = text.toInt(); + screenMod = screenMode->itemText(index).toInt(); printf("\nnew screenMod: %i\n", screenMod); //change then number of visibe pages when this changes imageWidget->setVramAddress(0); diff --git a/src/BitMapViewer.h b/src/BitMapViewer.h index 53dc30ae..e4ce81f5 100644 --- a/src/BitMapViewer.h +++ b/src/BitMapViewer.h @@ -17,7 +17,7 @@ class BitMapViewer : public QDialog, private Ui::BitMapViewer void decodeVDPregs(); void setPages(); - void on_screenMode_currentIndexChanged(const QString& text); + void on_screenMode_currentIndexChanged(int index); void on_showPage_currentIndexChanged(int index); void on_linesVisible_currentIndexChanged(int index); void on_bgColor_valueChanged(int value); From 3c2e4fd9afbd665d1d1fe8431f54a515166b04a7 Mon Sep 17 00:00:00 2001 From: m9710797 Date: Sat, 21 May 2022 09:21:18 +0200 Subject: [PATCH 47/63] Follow-up on 2c3fd4cf5d and 205a992a2d Commit 2c3fd4cf5d removed 'slot' annotations from header files. But this (unintentionally) broke automatic (string-based) connection setup via the 'setupUi()' call. Commit 205a992a2d already partially fixed this. This commit does the rest. --- src/BreakpointViewer.cpp | 7 +++++++ src/ConnectDialog.cpp | 2 ++ src/PaletteDialog.cpp | 6 ++++++ src/VDPCommandRegViewer.cpp | 8 ++++++++ src/VDPCommandRegViewer.h | 2 +- src/VDPRegViewer.cpp | 2 ++ src/VDPRegViewer.h | 2 +- 7 files changed, 27 insertions(+), 2 deletions(-) diff --git a/src/BreakpointViewer.cpp b/src/BreakpointViewer.cpp index 95b183f3..f38acda9 100644 --- a/src/BreakpointViewer.cpp +++ b/src/BreakpointViewer.cpp @@ -31,6 +31,13 @@ BreakpointViewer::BreakpointViewer(QWidget* parent) { setupUi(this); + connect(btnAddBp, &QPushButton::clicked, this, &BreakpointViewer::on_btnAddBp_clicked); + connect(btnRemoveBp, &QPushButton::clicked, this, &BreakpointViewer::on_btnRemoveBp_clicked); + connect(btnAddWp, &QPushButton::clicked, this, &BreakpointViewer::on_btnAddWp_clicked); + connect(btnRemoveWp, &QPushButton::clicked, this, &BreakpointViewer::on_btnRemoveWp_clicked); + connect(btnAddCn, &QPushButton::clicked, this, &BreakpointViewer::on_btnAddCn_clicked); + connect(btnRemoveCn, &QPushButton::clicked, this, &BreakpointViewer::on_btnRemoveCn_clicked); + bpTableWidget->horizontalHeader()->setHighlightSections(false); bpTableWidget->sortByColumn(BP_ADDRESS, Qt::AscendingOrder); bpTableWidget->setColumnHidden(WP_TYPE, true); diff --git a/src/ConnectDialog.cpp b/src/ConnectDialog.cpp index 42f755b5..6b8f5863 100644 --- a/src/ConnectDialog.cpp +++ b/src/ConnectDialog.cpp @@ -269,6 +269,8 @@ ConnectDialog::ConnectDialog(QWidget* parent) , result(nullptr) { ui.setupUi(this); + connect(ui.connectButton, &QPushButton::clicked, this, &ConnectDialog::on_connectButton_clicked); + connect(ui.rescanButton, &QPushButton::clicked, this, &ConnectDialog::on_rescanButton_clicked); on_rescanButton_clicked(); } diff --git a/src/PaletteDialog.cpp b/src/PaletteDialog.cpp index c18149f6..014c6b15 100644 --- a/src/PaletteDialog.cpp +++ b/src/PaletteDialog.cpp @@ -12,6 +12,12 @@ PaletteDialog::PaletteDialog(QWidget* parent) : QDialog(parent), ui(std::make_unique()) { ui->setupUi(this); + connect(ui->horizontalSlider_R, &QSlider::valueChanged, this, &PaletteDialog::on_horizontalSlider_R_valueChanged); + connect(ui->horizontalSlider_G, &QSlider::valueChanged, this, &PaletteDialog::on_horizontalSlider_G_valueChanged); + connect(ui->horizontalSlider_B, &QSlider::valueChanged, this, &PaletteDialog::on_horizontalSlider_B_valueChanged); + connect(ui->buttonBox, &QDialogButtonBox::clicked, this, &PaletteDialog::on_buttonBox_clicked); + connect(ui->cb_autosync, &QCheckBox::stateChanged, this, &PaletteDialog::on_cb_autosync_stateChanged); + const QFont fixedFont = QFontDatabase::systemFont(QFontDatabase::FixedFont); ui->plainTextEdit->setFont(fixedFont); diff --git a/src/VDPCommandRegViewer.cpp b/src/VDPCommandRegViewer.cpp index 088f1dab..1cb60202 100644 --- a/src/VDPCommandRegViewer.cpp +++ b/src/VDPCommandRegViewer.cpp @@ -7,6 +7,14 @@ VDPCommandRegViewer::VDPCommandRegViewer(QWidget* parent) setupUi(this); statusregs = regs + 64; + connect(lineEdit_r44, &QLineEdit::editingFinished, this, &VDPCommandRegViewer::on_lineEdit_r44_editingFinished); + connect(lineEdit_r45, &QLineEdit::editingFinished, this, &VDPCommandRegViewer::on_lineEdit_r45_editingFinished); + connect(lineEdit_r46, &QLineEdit::editingFinished, this, &VDPCommandRegViewer::on_lineEdit_r46_editingFinished); + connect(comboBox_cmd, qOverload(&QComboBox::currentIndexChanged), this, &VDPCommandRegViewer::on_comboBox_cmd_currentIndexChanged); + connect(comboBox_operator, qOverload(&QComboBox::currentIndexChanged), this, &VDPCommandRegViewer::on_comboBox_operator_currentIndexChanged); + connect(syncPushButton, &QPushButton::clicked, this, &VDPCommandRegViewer::on_syncPushButton_clicked); + connect(launchPushButton, &QPushButton::clicked, this, &VDPCommandRegViewer::on_launchPushButton_clicked); + // create the needed groups grp_sx = new view88to16(lineEdit_r32, lineEdit_r33, lineEdit_sx); connect(lineEdit_r32, &QLineEdit::editingFinished, grp_sx, &view88to16::finishRL); diff --git a/src/VDPCommandRegViewer.h b/src/VDPCommandRegViewer.h index fc08c131..43ca0efa 100644 --- a/src/VDPCommandRegViewer.h +++ b/src/VDPCommandRegViewer.h @@ -143,7 +143,7 @@ class VDPCommandRegViewer : public QDialog, public SimpleHexRequestUser, void refresh(); void R45BitChanged(int); -public slots: //TODO: replace this with qt5 connects + void on_lineEdit_r44_editingFinished(); void on_lineEdit_r45_editingFinished(); void on_lineEdit_r46_editingFinished(); diff --git a/src/VDPRegViewer.cpp b/src/VDPRegViewer.cpp index a7495a7e..615e2406 100644 --- a/src/VDPRegViewer.cpp +++ b/src/VDPRegViewer.cpp @@ -37,6 +37,8 @@ VDPRegViewer::VDPRegViewer(QWidget *parent) : QDialog(parent) { setupUi(this); + connect(VDPcomboBox, qOverload(&QComboBox::currentIndexChanged), this, &VDPRegViewer::on_VDPcomboBox_currentIndexChanged); + vdpId = 99; // make sure that we parse the first time the status registers are read vdpId = VDP_V9958; //quick hack for now diff --git a/src/VDPRegViewer.h b/src/VDPRegViewer.h index 98d809e1..3920ae0c 100644 --- a/src/VDPRegViewer.h +++ b/src/VDPRegViewer.h @@ -37,7 +37,7 @@ class VDPRegViewer : public QDialog, public SimpleHexRequestUser, void refresh(); void registerBitChanged(int reg, int bit, bool state); - //quick hack while no autodetection... + //quick hack while no auto-detection... void on_VDPcomboBox_currentIndexChanged(int index); private: From d5005b09e16fdf0286fab0f38fad5e16a4a5d164 Mon Sep 17 00:00:00 2001 From: m9710797 Date: Sat, 21 May 2022 09:30:05 +0200 Subject: [PATCH 48/63] Simplify usage of QOverload -> qOverload --- src/BitMapViewer.cpp | 24 ++++++++++++------------ src/BreakpointViewer.cpp | 2 +- src/SpriteViewer.cpp | 8 ++++---- src/TileViewer.cpp | 12 ++++++------ 4 files changed, 23 insertions(+), 23 deletions(-) diff --git a/src/BitMapViewer.cpp b/src/BitMapViewer.cpp index 8bc9286b..22730295 100644 --- a/src/BitMapViewer.cpp +++ b/src/BitMapViewer.cpp @@ -29,18 +29,18 @@ BitMapViewer::BitMapViewer(QWidget* parent) , screenMod(0) // avoid UMR { setupUi(this); - //no connect slot byname anymore - connect(screenMode, QOverload::of(&QComboBox:: currentIndexChanged), this, &BitMapViewer::on_screenMode_currentIndexChanged); - connect(showPage, QOverload::of(&QComboBox:: currentIndexChanged), this, &BitMapViewer::on_showPage_currentIndexChanged); - connect(linesVisible, QOverload::of(&QComboBox:: currentIndexChanged), this, &BitMapViewer::on_linesVisible_currentIndexChanged); - connect(bgColor, QOverload::of(&QSpinBox::valueChanged), this, &BitMapViewer::on_bgColor_valueChanged); - - connect(useVDPRegisters, &QCheckBox::stateChanged,this, &BitMapViewer::on_useVDPRegisters_stateChanged); - - connect(saveImageButton, &QPushButton::clicked, this, &BitMapViewer::on_saveImageButton_clicked); - connect(editPaletteButton, &QPushButton::clicked, this, &BitMapViewer::on_editPaletteButton_clicked); - connect(useVDPPalette, &QCheckBox::stateChanged, this, &BitMapViewer::on_useVDPPalette_stateChanged); - connect(zoomLevel, QOverload::of(&QDoubleSpinBox::valueChanged), this, &BitMapViewer::on_zoomLevel_valueChanged); + //no connect slot byname anymore + connect(screenMode, qOverload(&QComboBox:: currentIndexChanged), this, &BitMapViewer::on_screenMode_currentIndexChanged); + connect(showPage, qOverload(&QComboBox:: currentIndexChanged), this, &BitMapViewer::on_showPage_currentIndexChanged); + connect(linesVisible, qOverload(&QComboBox:: currentIndexChanged), this, &BitMapViewer::on_linesVisible_currentIndexChanged); + connect(bgColor, qOverload(&QSpinBox::valueChanged), this, &BitMapViewer::on_bgColor_valueChanged); + + connect(useVDPRegisters, &QCheckBox::stateChanged,this, &BitMapViewer::on_useVDPRegisters_stateChanged); + + connect(saveImageButton, &QPushButton::clicked, this, &BitMapViewer::on_saveImageButton_clicked); + connect(editPaletteButton, &QPushButton::clicked, this, &BitMapViewer::on_editPaletteButton_clicked); + connect(useVDPPalette, &QCheckBox::stateChanged, this, &BitMapViewer::on_useVDPPalette_stateChanged); + connect(zoomLevel, qOverload(&QDoubleSpinBox::valueChanged), this, &BitMapViewer::on_zoomLevel_valueChanged); // hand code entering the actual display widget in the scrollarea With // the designer-qt4 there is an extra scrollAreaWidget between the diff --git a/src/BreakpointViewer.cpp b/src/BreakpointViewer.cpp index f38acda9..697532ae 100644 --- a/src/BreakpointViewer.cpp +++ b/src/BreakpointViewer.cpp @@ -666,7 +666,7 @@ void BreakpointViewer::createComboBox(int row) wpTableWidget->setIndexWidget(index, combo); - connect(combo, QOverload::of(&QComboBox::currentIndexChanged), + connect(combo, qOverload(&QComboBox::currentIndexChanged), [this, row](int index){ changeCurrentWpType(row, index); }); } diff --git a/src/SpriteViewer.cpp b/src/SpriteViewer.cpp index d615c969..4fc667a3 100644 --- a/src/SpriteViewer.cpp +++ b/src/SpriteViewer.cpp @@ -34,12 +34,12 @@ SpriteViewer::SpriteViewer(QWidget* parent) connect(ui->le_patterntable, &QLineEdit::textChanged, this, &SpriteViewer::on_le_patterntable_textChanged); connect(ui->le_attributentable, &QLineEdit::textChanged, this, &SpriteViewer::on_le_attributentable_textChanged); connect(ui->useVDPRegisters, &QCheckBox::toggled, this, &SpriteViewer::on_useVDPRegisters_toggled); - connect(ui->cb_size, QOverload::of(&QComboBox::currentIndexChanged), this, &SpriteViewer::on_cb_size_currentIndexChanged); - connect(ui->cb_spritemode, QOverload::of(&QComboBox::currentIndexChanged), this, &SpriteViewer::on_cb_spritemode_currentIndexChanged); + connect(ui->cb_size, qOverload(&QComboBox::currentIndexChanged), this, &SpriteViewer::on_cb_size_currentIndexChanged); + connect(ui->cb_spritemode, qOverload(&QComboBox::currentIndexChanged), this, &SpriteViewer::on_cb_spritemode_currentIndexChanged); connect(ui->le_colortable, &QLineEdit::textChanged, this, &SpriteViewer::on_le_colortable_textChanged); - connect(ui->sp_zoom, QOverload::of(&QSpinBox::valueChanged), this, &SpriteViewer::on_sp_zoom_valueChanged); + connect(ui->sp_zoom, qOverload(&QSpinBox::valueChanged), this, &SpriteViewer::on_sp_zoom_valueChanged); connect(ui->cb_ecinfluence, &QCheckBox::toggled, this, &SpriteViewer::on_cb_ecinfluence_toggled); - connect(ui->cb_mag, QOverload::of(&QComboBox::currentIndexChanged), this, &SpriteViewer::on_cb_mag_currentIndexChanged); + connect(ui->cb_mag, qOverload(&QComboBox::currentIndexChanged), this, &SpriteViewer::on_cb_mag_currentIndexChanged); connect(ui->cb_alwaysShowColorTable, &QCheckBox::toggled, this, &SpriteViewer::on_cb_alwaysShowColorTable_toggled); connect(ui->useVDPPalette, &QCheckBox::stateChanged, this, &SpriteViewer::on_useVDPPalette_stateChanged); connect(ui->editPaletteButton, &QPushButton::clicked, this, &SpriteViewer::on_editPaletteButton_clicked); diff --git a/src/TileViewer.cpp b/src/TileViewer.cpp index ca59d9fe..b2a57be5 100644 --- a/src/TileViewer.cpp +++ b/src/TileViewer.cpp @@ -34,8 +34,8 @@ TileViewer::TileViewer(QWidget* parent) { setupUi(this); // No QMetaObject::connectSlotsByName available now since we dropped the slots: in the header; - connect(cb_tilemapsource, QOverload::of(&QComboBox::currentIndexChanged), this, &TileViewer::on_cb_tilemapsource_currentIndexChanged); - connect(cb_screen, QOverload::of(&QComboBox::currentIndexChanged) ,this ,&TileViewer::on_cb_screen_currentIndexChanged); + connect(cb_tilemapsource, qOverload(&QComboBox::currentIndexChanged), this, &TileViewer::on_cb_tilemapsource_currentIndexChanged); + connect(cb_screen, qOverload(&QComboBox::currentIndexChanged) ,this ,&TileViewer::on_cb_screen_currentIndexChanged); connect(le_nametable, &QLineEdit::textChanged, this, &TileViewer::on_le_nametable_textChanged); connect(le_colortable, &QLineEdit::textChanged, this, &TileViewer::on_le_colortable_textChanged); connect(le_patterntable, &QLineEdit::textChanged, this, &TileViewer::on_le_patterntable_textChanged); @@ -45,15 +45,15 @@ TileViewer::TileViewer(QWidget* parent) connect(editPaletteButton, &QPushButton::clicked, this, &TileViewer::on_editPaletteButton_clicked); connect(useVDPPalette, &QCheckBox::stateChanged, this, &TileViewer::on_useVDPPalette_stateChanged); - connect(zoomLevel, QOverload::of(&QDoubleSpinBox::valueChanged), this, &TileViewer::on_zoomLevel_valueChanged); + connect(zoomLevel, qOverload(&QDoubleSpinBox::valueChanged), this, &TileViewer::on_zoomLevel_valueChanged); connect(cb_drawgrid, &QCheckBox::stateChanged, this, &TileViewer::on_cb_drawgrid_stateChanged); connect(cb_highlight, &QCheckBox::stateChanged, this, &TileViewer::on_cb_highlight_stateChanged); - connect(sp_highlight, QOverload::of(&QSpinBox::valueChanged), this, &TileViewer::on_sp_highlight_valueChanged); - connect(sp_bordercolor, QOverload::of(&QSpinBox::valueChanged), this, &TileViewer::on_sp_bordercolor_valueChanged); + connect(sp_highlight, qOverload(&QSpinBox::valueChanged), this, &TileViewer::on_sp_highlight_valueChanged); + connect(sp_bordercolor, qOverload(&QSpinBox::valueChanged), this, &TileViewer::on_sp_bordercolor_valueChanged); connect(cb_blinkcolors, &QCheckBox::stateChanged, this, &TileViewer::on_cb_blinkcolors_stateChanged); - connect(cb_screenrows, QOverload::of(&QComboBox::currentIndexChanged), this, &TileViewer::on_cb_screenrows_currentIndexChanged); + connect(cb_screenrows, qOverload(&QComboBox::currentIndexChanged), this, &TileViewer::on_cb_screenrows_currentIndexChanged); From 56db34cdf00e8c110fcb45260a804f200c9fb6e6 Mon Sep 17 00:00:00 2001 From: David Heremans Date: Mon, 23 May 2022 12:53:12 +0200 Subject: [PATCH 49/63] Have the SpriteViewer use MSXPalette Let's get rid of the old PaletteDialog and use the MSXPalette as it was intended to be used. --- src/MSXPalette.h | 2 ++ src/PaletteView.cpp | 4 ++-- src/PaletteView.ui | 6 +++--- src/SpriteViewer.cpp | 26 ++++++----------------- src/SpriteViewer.h | 4 ++-- src/SpriteViewer.ui | 10 --------- src/VramSpriteView.cpp | 48 +++++++++++++----------------------------- src/VramSpriteView.h | 9 ++++---- 8 files changed, 34 insertions(+), 75 deletions(-) diff --git a/src/MSXPalette.h b/src/MSXPalette.h index 38313f59..7ceb11a5 100644 --- a/src/MSXPalette.h +++ b/src/MSXPalette.h @@ -5,6 +5,8 @@ #include #include +enum {paletteVDP,paletteTiles,paletteBitmap,paletteSprites}; + class MSXPalette : public QObject { Q_OBJECT diff --git a/src/PaletteView.cpp b/src/PaletteView.cpp index 46f07d49..3d9255e9 100644 --- a/src/PaletteView.cpp +++ b/src/PaletteView.cpp @@ -17,7 +17,7 @@ PaletteView::PaletteView(QWidget* parent) const QFont fixedFont = QFontDatabase::systemFont(QFontDatabase::FixedFont); ui->plainTextEdit->setFont(fixedFont); - setPalette(VDPDataStore::instance().getPalette(0)); + setPalette(VDPDataStore::instance().getPalette(paletteVDP)); signalMapper = new QSignalMapper(this); auto* gridLayout = new QGridLayout; @@ -171,7 +171,7 @@ void PaletteView::on_cbPalette_currentIndexChanged(int index) void PaletteView::on_pbCopyPaletteVDP_clicked() { ScopedAssign sa(isDisplayUpdating, true); - myPal->copyDataFrom(*VDPDataStore::instance().getPalette(0)); + myPal->copyDataFrom(*VDPDataStore::instance().getPalette(paletteVDP)); emit myPal->paletteChanged(); } diff --git a/src/PaletteView.ui b/src/PaletteView.ui index 441d6570..66f25583 100644 --- a/src/PaletteView.ui +++ b/src/PaletteView.ui @@ -210,17 +210,17 @@ - Sprite palette + Tileview palette - Tileview palette + Bitmap palette - Bitmap palette + Sprite palette diff --git a/src/SpriteViewer.cpp b/src/SpriteViewer.cpp index 4fc667a3..a96d9135 100644 --- a/src/SpriteViewer.cpp +++ b/src/SpriteViewer.cpp @@ -1,8 +1,9 @@ #include "SpriteViewer.h" #include "VDPDataStore.h" #include "VramSpriteView.h" -#include "PaletteDialog.h" +//#include "PaletteDialog.h" #include "Convert.h" +#include "MSXPalette.h" // static to feed to PaletteDialog and be used when VDP colors aren't selected uint8_t SpriteViewer::defaultPalette[32] = { @@ -42,7 +43,6 @@ SpriteViewer::SpriteViewer(QWidget* parent) connect(ui->cb_mag, qOverload(&QComboBox::currentIndexChanged), this, &SpriteViewer::on_cb_mag_currentIndexChanged); connect(ui->cb_alwaysShowColorTable, &QCheckBox::toggled, this, &SpriteViewer::on_cb_alwaysShowColorTable_toggled); connect(ui->useVDPPalette, &QCheckBox::stateChanged, this, &SpriteViewer::on_useVDPPalette_stateChanged); - connect(ui->editPaletteButton, &QPushButton::clicked, this, &SpriteViewer::on_editPaletteButton_clicked); const QFont fixedFont = QFontDatabase::systemFont(QFontDatabase::FixedFont); ui->plainTextEdit->setFont(fixedFont); @@ -104,7 +104,7 @@ SpriteViewer::SpriteViewer(QWidget* parent) imageWidgetColor->setVramSource(VDPDataStore::instance().getVramPointer()); - setPaletteSource(VDPDataStore::instance().getPalettePointer(), true); + setPaletteSource(VDPDataStore::instance().getPalette(paletteVDP), true); setCorrectVDPData(); setCorrectEnabled(ui->useVDPRegisters->isChecked()); @@ -156,7 +156,7 @@ SpriteViewer::SpriteViewer(QWidget* parent) VDPDataStore::instance().refresh(); } -void SpriteViewer::setPaletteSource(const uint8_t* palSource, bool useVDP) +void SpriteViewer::setPaletteSource(MSXPalette* palSource, bool useVDP) { imageWidget->setPaletteSource(palSource, useVDP); imageWidgetSingle->setPaletteSource(palSource, useVDP); @@ -423,28 +423,14 @@ void SpriteViewer::on_cb_alwaysShowColorTable_toggled(bool /*checked*/) void SpriteViewer::on_useVDPPalette_stateChanged(int state) { - const uint8_t* palette = VDPDataStore::instance().getPalettePointer(); if (state == Qt::Checked) { - setPaletteSource(palette, true); + setPaletteSource(VDPDataStore::instance().getPalette(paletteVDP), true); } else { - if (palette != nullptr) memcpy(defaultPalette, palette, 32); - setPaletteSource(defaultPalette, false); + setPaletteSource(VDPDataStore::instance().getPalette(paletteSprites), false); } imageWidget->refresh(); imageWidgetSingle->refresh(); imageWidgetSpat->refresh(); imageWidgetColor->refresh(); - ui->editPaletteButton->setEnabled(state != Qt::Checked); } -void SpriteViewer::on_editPaletteButton_clicked(bool /*checked*/) -{ - auto* p = new PaletteDialog(); - p->setPalette(defaultPalette); - p->setAutoSync(true); - connect(p, &PaletteDialog::paletteSynced, imageWidget, &VramSpriteView::refresh); - connect(p, &PaletteDialog::paletteSynced, imageWidgetSingle, &VramSpriteView::refresh); - connect(p, &PaletteDialog::paletteSynced, imageWidgetSpat, &VramSpriteView::refresh); - connect(p, &PaletteDialog::paletteSynced, imageWidgetColor, &VramSpriteView::refresh); - p->show(); -} diff --git a/src/SpriteViewer.h b/src/SpriteViewer.h index 9280ce98..93e77f0e 100644 --- a/src/SpriteViewer.h +++ b/src/SpriteViewer.h @@ -7,6 +7,7 @@ #include class VramSpriteView; +class MSXPalette; class SpriteViewer : public QDialog { @@ -36,9 +37,8 @@ class SpriteViewer : public QDialog void on_cb_mag_currentIndexChanged(int index); void on_cb_alwaysShowColorTable_toggled(bool checked); void on_useVDPPalette_stateChanged(int state); - void on_editPaletteButton_clicked(bool checked); - void setPaletteSource(const uint8_t* palSource, bool useVDP); + void setPaletteSource(MSXPalette* palSource, bool useVDP); void decodeVDPregs(); void setCorrectEnabled(bool checked); void setCorrectVDPData(); diff --git a/src/SpriteViewer.ui b/src/SpriteViewer.ui index c631c874..fca68996 100644 --- a/src/SpriteViewer.ui +++ b/src/SpriteViewer.ui @@ -29,16 +29,6 @@
- - - - false - - - Edit palette.. - - - diff --git a/src/VramSpriteView.cpp b/src/VramSpriteView.cpp index 029a0aff..1f760f54 100644 --- a/src/VramSpriteView.cpp +++ b/src/VramSpriteView.cpp @@ -1,5 +1,6 @@ #include "VramSpriteView.h" #include "VDPDataStore.h" +#include "MSXPalette.h" #include #include #include @@ -13,6 +14,10 @@ VramSpriteView::VramSpriteView(QWidget* parent, mode drawer, bool singleSprite) // sprite size = 8x8, 16x16, 32x32 or 40x8, 48x16, 64x32 if EC bit respected calculateSizeOfSprites(); + msxPalette = nullptr; + setPaletteSource(VDPDataStore::instance().getPalette(paletteVDP), true); + + if (isSingleSpriteDrawer) { setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred)); zoomFactor = 4; @@ -49,8 +54,6 @@ int VramSpriteView::heightForWidth(int width) const // How many sprites do fit in this width? float x = int(width / (sizeOfSpritesHorizontal * zoomFactor)); // Does an int divided by an int gives an int that would be converted to float? int h = int(ceilf(float(nrOfSpritesToShow) / x)) * sizeOfSpritesVertical * zoomFactor; - //printf("\nheightForWidth sizeOfSpritesHorizontal %d sizeOfSpritesVertical %d zoomFactor %d \n", sizeOfSpritesHorizontal, sizeOfSpritesVertical, zoomFactor); - //printf("heightForWidth w=%d => total=%d x=%f => h=%d \n", width, nr_of_sprites_to_show, x, h); return h; } @@ -69,16 +72,16 @@ void VramSpriteView::setVramSource(const uint8_t* adr) { if (vramBase == adr) return; vramBase = adr; - decodePalette(); decode(); } -void VramSpriteView::setPaletteSource(const uint8_t* adr, bool useVDP) +void VramSpriteView::setPaletteSource(MSXPalette* pal, bool useVDP) { useVDPpalette = useVDP; - if (palette == adr) return; - palette = adr; - decodePalette(); + if (msxPalette == pal) return; + disconnect(msxPalette, &MSXPalette::paletteChanged, this, &VramSpriteView::decode); + msxPalette = pal; + connect(msxPalette, &MSXPalette::paletteChanged, this, &VramSpriteView::decode); decode(); } @@ -247,20 +250,6 @@ void VramSpriteView::drawGrid() } } -void VramSpriteView::decodePalette() -{ - if (!palette) return; - - for (int i = 0; i < 16; ++i) { - int r = (palette[2 * i + 0] & 0xf0) >> 4; - int b = (palette[2 * i + 0] & 0x0f); - int g = (palette[2 * i + 1] & 0x0f); - - auto scale = [](int x) { return (x >> 1) | (x << 2) | (x << 5); }; - msxPalette[i] = qRgb(scale(r), scale(g), scale(b)); - } -} - void VramSpriteView::decodePgt() { image.fill(QColor(Qt::lightGray)); @@ -330,7 +319,7 @@ void VramSpriteView::drawColSprite(int entry, QColor& /*bgcolor*/) int z = zoomFactor * ((useMagnification && useECbit) ? 2 : 1); if (spriteMode == 1) { bool ec = color & 128; - QRgb fgColor = msxPalette[color & 15]; // drop EC and unused bits + QRgb fgColor = msxPalette->color(color & 15); // drop EC and unused bits qp.fillRect(x, y, sizeOfSpritesHorizontal * z, sizeOfSpritesVertical * z, fgColor); qp.fillRect(x, y, z, sizeOfSpritesVertical * z, ec ? QRgb(Qt::white) : QRgb(Qt::black)); } else if (spriteMode == 2) { @@ -339,7 +328,7 @@ void VramSpriteView::drawColSprite(int entry, QColor& /*bgcolor*/) bool ec = colorbyte & 128; bool cc = colorbyte & 64; bool ic = colorbyte & 32; - QRgb fgColor = msxPalette[colorbyte & 15]; // drop EC, CC and IC bits + QRgb fgColor = msxPalette->color(colorbyte & 15); // drop EC, CC and IC bits qp.fillRect(x, y + charrow * z, sizeOfSpritesHorizontal * z, z, fgColor); // line with color qp.fillRect(x, y + charrow * z, z, z, (ec ? QColor(Qt::white) : QColor(Qt::black))); // EC bit set -> white qp.fillRect(x + z, y + charrow * z, z, z, (cc ? QColor(Qt::green) : QColor(Qt::black))); // CC bit set -> green @@ -367,7 +356,7 @@ void VramSpriteView::drawSpatSprite(int entry, QColor &bgColor) // Mode 0 already tested, we will not end up here with spritemode == 0 if (spriteMode == 1) { bool ec = color & 128; - QRgb fgColor = msxPalette[color & 15]; // drop EC and unused bits + QRgb fgColor = msxPalette->color(color & 15); // drop EC and unused bits if (attrY == 208) { // in spritemode 1 if Y is equal to 208 this and all lower priority sprites will not be displayed, so red bgcolor! bgColor = QColor(Qt::red); } @@ -405,12 +394,6 @@ void VramSpriteView::setSpritePixel(int x, int y, QRgb c) //image.setPixel(); } -QRgb VramSpriteView::getColor(int c) -{ - // TODO do we need to look at the TP bit??? - return msxPalette[c]; -} - void VramSpriteView::setAttributeTableAddress(int value) { attributeTableAddress = value; @@ -587,9 +570,8 @@ void VramSpriteView::refresh() // Reset pointers in case during boot these pointers weren't correctly set due to openMSX not having send over vram size... setVramSource(VDPDataStore::instance().getVramPointer()); if (useVDPpalette) { - setPaletteSource(VDPDataStore::instance().getPalettePointer(), true); + setPaletteSource(VDPDataStore::instance().getPalette(paletteVDP), true); } - decodePalette(); decode(); } @@ -695,7 +677,7 @@ void VramSpriteView::drawLineColoredSpriteAt(int character, int spriteBox, int x bool ec = colorByte & 128; int ec_offset = (useECbit && !ec) ? 32 : 0; // Draw more to the right if no ec but spritebox is extra wide to display ec effect - QRgb fg = msxPalette[colorByte & 15]; // Drop EC, CC and IC bits + QRgb fg = msxPalette->color(colorByte & 15); // Drop EC, CC and IC bits for (int charCol = 0; charCol < 8; ++charCol) { uint8_t mask = 1 << (7 - charCol); if (gridEnabled && zoomFactor > 4) { diff --git a/src/VramSpriteView.h b/src/VramSpriteView.h index adbfe2fb..888381f4 100644 --- a/src/VramSpriteView.h +++ b/src/VramSpriteView.h @@ -10,6 +10,8 @@ #include #include +#include "MSXPalette.h" + class VramSpriteView : public QWidget { Q_OBJECT @@ -27,7 +29,7 @@ class VramSpriteView : public QWidget [[nodiscard]] QSize sizeHint() const override; void setVramSource(const uint8_t* adr); - void setPaletteSource(const uint8_t* adr, bool useVDP); + void setPaletteSource(MSXPalette *pal, bool useVDP); void mousePressEvent(QMouseEvent* e) override; void mouseMoveEvent (QMouseEvent* e) override; @@ -71,13 +73,11 @@ class VramSpriteView : public QWidget void paintEvent(QPaintEvent* e) override; void decode(); - void decodePalette(); void decodePgt(); void decodeSpat(); void decodeCol(); void setSpritePixel(int x, int y, QRgb c); - QRgb getColor(int c); void drawMonochromeSpriteAt(int character, int spriteBox, int xOffset, int yOffset, QRgb fg, QRgb bg, bool ec = false); void drawLineColoredSpriteAt(int character, int spriteBox, int xOffset, int yOffset, int rowOffset, QRgb bg); @@ -94,10 +94,9 @@ class VramSpriteView : public QWidget [[nodiscard]] QString colorInfo(uint8_t color) const; private: - QRgb msxPalette[16]; + MSXPalette* msxPalette; QImage image; QPixmap pixImage; - const uint8_t* palette = nullptr; const uint8_t* vramBase = nullptr; int patternTableAddress = 0; int attributeTableAddress = 0; From 39a9d4296439f065034f26b158e8f313651e0627 Mon Sep 17 00:00:00 2001 From: David Heremans Date: Mon, 23 May 2022 18:59:28 +0200 Subject: [PATCH 50/63] .gitignore adaptions for qtcreator --- .gitignore | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.gitignore b/.gitignore index d0b8d3fe..8aec4c55 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,10 @@ moc_predefs.h qrc_resources.cpp Makefile .*.swp +*.orig +*.rej +*.pro +*.pro.user* +build-* +*.zip +*.rom From 157b3038c4600099bded7073ae9518b199fdae63 Mon Sep 17 00:00:00 2001 From: David Heremans Date: Mon, 23 May 2022 19:51:52 +0200 Subject: [PATCH 51/63] Have the BitMapViewer use MSXPalette --- src/BitMapViewer.cpp | 38 +---- src/BitMapViewer.h | 2 +- src/BitMapViewer.ui | 344 +++++++++++++++++++------------------- src/VramBitMappedView.cpp | 42 ++--- src/VramBitMappedView.h | 8 +- 5 files changed, 187 insertions(+), 247 deletions(-) diff --git a/src/BitMapViewer.cpp b/src/BitMapViewer.cpp index 22730295..9a181a75 100644 --- a/src/BitMapViewer.cpp +++ b/src/BitMapViewer.cpp @@ -4,26 +4,6 @@ #include "Convert.h" #include -static const uint8_t defaultPalette[32] = { -// RB G - 0x00, 0, - 0x00, 0, - 0x11, 6, - 0x33, 7, - 0x17, 1, - 0x27, 3, - 0x51, 1, - 0x27, 6, - 0x71, 1, - 0x73, 3, - 0x61, 6, - 0x64, 6, - 0x11, 4, - 0x65, 2, - 0x55, 5, - 0x77, 7, -}; - BitMapViewer::BitMapViewer(QWidget* parent) : QDialog(parent) , screenMod(0) // avoid UMR @@ -38,7 +18,6 @@ BitMapViewer::BitMapViewer(QWidget* parent) connect(useVDPRegisters, &QCheckBox::stateChanged,this, &BitMapViewer::on_useVDPRegisters_stateChanged); connect(saveImageButton, &QPushButton::clicked, this, &BitMapViewer::on_saveImageButton_clicked); - connect(editPaletteButton, &QPushButton::clicked, this, &BitMapViewer::on_editPaletteButton_clicked); connect(useVDPPalette, &QCheckBox::stateChanged, this, &BitMapViewer::on_useVDPPalette_stateChanged); connect(zoomLevel, qOverload(&QDoubleSpinBox::valueChanged), this, &BitMapViewer::on_zoomLevel_valueChanged); @@ -61,10 +40,9 @@ BitMapViewer::BitMapViewer(QWidget* parent) useVDP = useVDPRegisters->isChecked(); const uint8_t* vram = VDPDataStore::instance().getVramPointer(); - const uint8_t* palette = VDPDataStore::instance().getPalettePointer(); imageWidget->setVramSource(vram); imageWidget->setVramAddress(0); - imageWidget->setPaletteSource(palette); + imageWidget->setPaletteSource(VDPDataStore::instance().getPalette(paletteVDP)); //now hook up some signals and slots connect(&VDPDataStore::instance(), &VDPDataStore::dataRefreshed, @@ -246,23 +224,13 @@ void BitMapViewer::on_saveImageButton_clicked(bool /*checked*/) "Sorry, the save image dialog is not yet implemented"); } -void BitMapViewer::on_editPaletteButton_clicked(bool /*checked*/) -{ - useVDPPalette->setChecked(false); - QMessageBox::information( - this, - "Not yet implemented", - "Sorry, the palette editor is not yet implemented, " - "only disabling 'Use VDP palette registers' for now"); -} void BitMapViewer::on_useVDPPalette_stateChanged(int state) { if (state) { - const uint8_t* palette = VDPDataStore::instance().getPalettePointer(); - imageWidget->setPaletteSource(palette); + imageWidget->setPaletteSource(VDPDataStore::instance().getPalette(paletteVDP)); } else { - imageWidget->setPaletteSource(defaultPalette); + imageWidget->setPaletteSource(VDPDataStore::instance().getPalette(paletteBitmap)); } imageWidget->refresh(); } diff --git a/src/BitMapViewer.h b/src/BitMapViewer.h index e4ce81f5..00fff889 100644 --- a/src/BitMapViewer.h +++ b/src/BitMapViewer.h @@ -5,6 +5,7 @@ #include class VramBitMappedView; +class MSXPalette; class BitMapViewer : public QDialog, private Ui::BitMapViewer { @@ -25,7 +26,6 @@ class BitMapViewer : public QDialog, private Ui::BitMapViewer void on_useVDPRegisters_stateChanged(int state); void on_saveImageButton_clicked(bool checked); - void on_editPaletteButton_clicked(bool checked); void on_useVDPPalette_stateChanged(int state); void on_zoomLevel_valueChanged(double d); diff --git a/src/BitMapViewer.ui b/src/BitMapViewer.ui index 9fa0d68d..e4bde425 100644 --- a/src/BitMapViewer.ui +++ b/src/BitMapViewer.ui @@ -1,167 +1,168 @@ - + + BitMapViewer - - + + 0 0 - 604 + 703 619 - + Dialog - + - - + + 0 - - + + QFrame::StyledPanel - + QFrame::Raised - - + + 0 - + 2 - - - + + + Screen mode: - - - + + + false - + 5 - + 6 - + 7 - + 8 - + 10 - + 11 - + 12 - - - + + + false - + 0 - + 1 - + 2 - + 3 - - - + + + Lines visible - - - + + + false - + 192 - + 212 - + 256 - - - + + + Show page - - - + + + Replace color 0 by - - - + + + false - - - + + + Displayed as: @@ -170,16 +171,16 @@ - + - - + + Qt::Vertical - + QSizePolicy::Fixed - + 0 13 @@ -188,13 +189,13 @@ - + - - + + Qt::Horizontal - + 22 17 @@ -203,61 +204,61 @@ - + - - - - + + + + 0 - - - + + + Border color - - - + + + VDP mode: - - - + + + Vram address start: - - - + + + 5 - - - + + + Lines visible - - - + + + 0x00000 - - - + + + 212 @@ -265,11 +266,11 @@ - - + + Use current VDP settings - + true @@ -277,11 +278,11 @@ - - + + Qt::Horizontal - + 22 17 @@ -294,43 +295,36 @@ - - + + 1 - - + + Save image... - - - Edit palette.. - - - - - - + + Use VDP palette registers - + true - - + + Qt::Vertical - + QSizePolicy::Minimum - + 0 0 @@ -339,26 +333,26 @@ - + - - + + Zoom - - + + 2 - + 1.000000000000000 - + 16.000000000000000 - + 0.250000000000000 @@ -366,8 +360,8 @@ - - + + Take VRAM snapshot @@ -377,38 +371,38 @@ - - - + + + 0 0 - + 0 0 - + QFrame::Panel - + Qt::ScrollBarAsNeeded - + Qt::ScrollBarAsNeeded - + false - + Qt::AlignCenter - - + + - 38 + 80 0 508 420 @@ -418,91 +412,91 @@ - + - - + + X: - - - + + + 0 0 - + 18 0 - + 000 - - + + Y: - - - + + + 0 0 - + 18 0 - + 000 - - + + Color: - - - + + + 0 0 - + 18 0 - + 000 - - + + Qt::Horizontal - + 40 20 @@ -511,53 +505,53 @@ - - + + Vram address: - - - + + + 0 0 - + 42 0 - + 0x00000 - - + + byte value: - - - + + + 0 0 - + 24 0 - + 0x00 diff --git a/src/VramBitMappedView.cpp b/src/VramBitMappedView.cpp index 4ab32eea..a971c04f 100644 --- a/src/VramBitMappedView.cpp +++ b/src/VramBitMappedView.cpp @@ -1,5 +1,6 @@ #include "VramBitMappedView.h" #include "ranges.h" +#include "VDPDataStore.h" #include #include #include @@ -8,7 +9,7 @@ VramBitMappedView::VramBitMappedView(QWidget* parent) : QWidget(parent) , image(512, 512, QImage::Format_RGB32) { - ranges::fill(msxPalette, qRgb(80, 80, 80)); + palette = VDPDataStore::instance().getPalette(paletteVDP); setZoom(1.0f); // Mouse update events when mouse is moved over the image, Quibus likes this @@ -40,19 +41,6 @@ void VramBitMappedView::decode() update(); } -void VramBitMappedView::decodePallet() -{ - if (!palette) return; - - for (int i = 0; i < 16; ++i) { - int r = (palette[2 * i + 0] & 0xf0) >> 4; - int b = (palette[2 * i + 0] & 0x0f); - int g = (palette[2 * i + 1] & 0x0f); - auto scale = [](int x) { return (x >> 1) | (x << 2) | (x << 5); }; - msxPalette[i] = qRgb(scale(r), scale(g), scale(b)); - } -} - static unsigned interleave(unsigned x) { return (x >> 1) | ((x & 1) << 16); @@ -113,7 +101,7 @@ void VramBitMappedView::decodeSCR10() int j = (p[2] & 7) + ((p[3] & 3) << 3) - ((p[3] & 4) << 3); int k = (p[0] & 7) + ((p[1] & 3) << 3) - ((p[1] & 4) << 3); for (int n = 0; n < 4; ++n) { - QRgb c = (p[n] & 0x08) ? msxPalette[p[n] >> 4] // YAE + QRgb c = (p[n] & 0x08) ? palette->color(p[n] >> 4) // YAE : decodeYJK(p[n] >> 3, j, k); // YJK setPixel2x2(x + n, y, c); } @@ -143,7 +131,7 @@ void VramBitMappedView::decodeSCR8() QRgb VramBitMappedView::getColor(int c) { // TODO do we need to look at the TP bit??? - return msxPalette[c ? c : borderColor]; + return palette->color(c ? c : borderColor); } void VramBitMappedView::decodeSCR7() @@ -195,9 +183,7 @@ void VramBitMappedView::paintEvent(QPaintEvent* /*event*/) void VramBitMappedView::refresh() { - decodePallet(); decode(); - update(); } void VramBitMappedView::mouseMoveEvent(QMouseEvent* e) @@ -266,55 +252,47 @@ void VramBitMappedView::mousePressEvent(QMouseEvent* e) // since mouseMove only emits the correct signal we reuse/abuse that method mouseMoveEvent(e); - decodePallet(); decode(); - update(); } void VramBitMappedView::setBorderColor(int value) { borderColor = std::clamp(value, 0, 15); - decodePallet(); decode(); - update(); } void VramBitMappedView::setScreenMode(int mode) { screenMode = mode; decode(); - update(); } void VramBitMappedView::setLines(int nrLines) { lines = nrLines; - decode(); setFixedSize(int(512.0f * zoomFactor), int(float(lines) * 2.0f * zoomFactor)); - update(); + decode(); //setZoom(zoomFactor); } void VramBitMappedView::setVramAddress(int adr) { vramAddress = adr; - decodePallet(); decode(); - update(); } void VramBitMappedView::setVramSource(const uint8_t* adr) { vramBase = adr; - decodePallet(); decode(); - update(); } -void VramBitMappedView::setPaletteSource(const uint8_t* adr) +void VramBitMappedView::setPaletteSource(MSXPalette *adr) { + if (palette) { + disconnect(palette, &MSXPalette::paletteChanged, this, &VramBitMappedView::decode); + } palette = adr; - decodePallet(); + connect(palette, &MSXPalette::paletteChanged, this, &VramBitMappedView::decode); decode(); - update(); } diff --git a/src/VramBitMappedView.h b/src/VramBitMappedView.h index 037d0932..be4817a9 100644 --- a/src/VramBitMappedView.h +++ b/src/VramBitMappedView.h @@ -8,6 +8,8 @@ #include #include +class MSXPalette; + class VramBitMappedView : public QWidget { Q_OBJECT @@ -20,7 +22,7 @@ class VramBitMappedView : public QWidget void setLines(int nrLines); void setVramSource(const uint8_t* adr); void setVramAddress(int adr); - void setPaletteSource(const uint8_t* adr); + void setPaletteSource(MSXPalette* adr); void setBorderColor(int value); void mousePressEvent(QMouseEvent* e) override; @@ -39,7 +41,6 @@ class VramBitMappedView : public QWidget void paintEvent(QPaintEvent* e) override; void decode(); - void decodePallet(); void decodeSCR5(); void decodeSCR6(); void decodeSCR7(); @@ -51,10 +52,9 @@ class VramBitMappedView : public QWidget QRgb getColor(int c); private: - QRgb msxPalette[16]; QImage image; QPixmap pixImage; - const uint8_t* palette = nullptr; + MSXPalette* palette = nullptr; const uint8_t* vramBase = nullptr; float zoomFactor; unsigned vramAddress = 0; From 20a221af329a21c15595634bd3f48498f22d2a09 Mon Sep 17 00:00:00 2001 From: David Heremans Date: Mon, 23 May 2022 20:31:27 +0200 Subject: [PATCH 52/63] Have the TileViewer use MSXPalette --- src/PaletteView.ui | 3 +++ src/TileViewer.cpp | 48 ++++--------------------------------------- src/TileViewer.h | 2 -- src/TileViewer.ui | 16 +++------------ src/VramTiledView.cpp | 35 +++++++++---------------------- src/VramTiledView.h | 8 ++++---- 6 files changed, 24 insertions(+), 88 deletions(-) diff --git a/src/PaletteView.ui b/src/PaletteView.ui index 66f25583..f6b027f8 100644 --- a/src/PaletteView.ui +++ b/src/PaletteView.ui @@ -290,6 +290,9 @@ + + autosync to openMSX + Autosync diff --git a/src/TileViewer.cpp b/src/TileViewer.cpp index b2a57be5..b2df24a2 100644 --- a/src/TileViewer.cpp +++ b/src/TileViewer.cpp @@ -7,26 +7,6 @@ #include -// static to feed to PaletteDialog and be used when VDP colors aren't selected -uint8_t TileViewer::defaultPalette[32] = { -// RB G - 0x00, 0, - 0x00, 0, - 0x11, 6, - 0x33, 7, - 0x17, 1, - 0x27, 3, - 0x51, 1, - 0x27, 6, - 0x71, 1, - 0x73, 3, - 0x61, 6, - 0x64, 6, - 0x11, 4, - 0x65, 2, - 0x55, 5, - 0x77, 7, -}; TileViewer::TileViewer(QWidget* parent) @@ -43,7 +23,6 @@ TileViewer::TileViewer(QWidget* parent) connect(cb_color0, &QCheckBox::stateChanged, this, &TileViewer::on_cb_color0_stateChanged); connect(useVDPRegisters, &QCheckBox::stateChanged, this, &TileViewer::on_useVDPRegisters_stateChanged); - connect(editPaletteButton, &QPushButton::clicked, this, &TileViewer::on_editPaletteButton_clicked); connect(useVDPPalette, &QCheckBox::stateChanged, this, &TileViewer::on_useVDPPalette_stateChanged); connect(zoomLevel, qOverload(&QDoubleSpinBox::valueChanged), this, &TileViewer::on_zoomLevel_valueChanged); @@ -83,7 +62,7 @@ TileViewer::TileViewer(QWidget* parent) scrollArea->setWidget(imageWidget); const auto* vram = VDPDataStore::instance().getVramPointer(); - const auto* palette = VDPDataStore::instance().getPalettePointer(); + auto* palette = VDPDataStore::instance().getPalette(paletteVDP); //imageWidget->setNameTableAddress(0); //imageWidget->setPatternTableAddress(0); //imageWidget->setColorTableAddress(0); @@ -106,7 +85,7 @@ TileViewer::TileViewer(QWidget* parent) void TileViewer::VDPDataStoreDataRefreshed() { if (useVDPPalette->isChecked()) { - imageWidget->setPaletteSource(VDPDataStore::instance().getPalettePointer()); + imageWidget->setPaletteSource(VDPDataStore::instance().getPalette(paletteVDP)); } decodeVDPregs(); } @@ -336,33 +315,14 @@ void TileViewer::on_useVDPRegisters_stateChanged(int state) cb_color0->setEnabled(useManual); } -void TileViewer::on_editPaletteButton_clicked(bool /*checked*/) -{ - auto* p = new PaletteDialog(); - p->setPalette(defaultPalette); - p->setAutoSync(true); - connect(p, &PaletteDialog::paletteSynced, imageWidget, &VramTiledView::refresh); - connect(p, &PaletteDialog::paletteSynced, this, &TileViewer::update_label_characterimage); - p->show(); - //useVDPPalette->setChecked(false); - //QMessageBox::information( - // this, - // "Not yet implemented", - // "Sorry, the palette editor is not yet implemented, " - // "only disabling 'Use VDP palette registers' for now"); -} - void TileViewer::on_useVDPPalette_stateChanged(int state) { - const uint8_t* palette = VDPDataStore::instance().getPalettePointer(); if (state) { - imageWidget->setPaletteSource(palette); + imageWidget->setPaletteSource(VDPDataStore::instance().getPalette(paletteVDP)); } else { - if (palette) memcpy(defaultPalette, palette, 32); - imageWidget->setPaletteSource(defaultPalette); + imageWidget->setPaletteSource(VDPDataStore::instance().getPalette(paletteTiles)); } imageWidget->refresh(); - editPaletteButton->setEnabled(!state); } void TileViewer::on_zoomLevel_valueChanged(double d) diff --git a/src/TileViewer.h b/src/TileViewer.h index c5205306..de0ba474 100644 --- a/src/TileViewer.h +++ b/src/TileViewer.h @@ -28,7 +28,6 @@ class TileViewer : public QDialog, private Ui::TileViewer void on_cb_color0_stateChanged(int state); void on_useVDPRegisters_stateChanged(int state); - void on_editPaletteButton_clicked(bool checked); void on_useVDPPalette_stateChanged(int state); void on_zoomLevel_valueChanged(double d); @@ -53,7 +52,6 @@ class TileViewer : public QDialog, private Ui::TileViewer int mouseOverY = 0; int mouseOverChar = 0; - static uint8_t defaultPalette[32]; }; #endif // TILEVIEWER_H diff --git a/src/TileViewer.ui b/src/TileViewer.ui index 840ecdd3..c6e41c9e 100644 --- a/src/TileViewer.ui +++ b/src/TileViewer.ui @@ -6,7 +6,7 @@ 0 0 - 911 + 1070 756 @@ -50,8 +50,8 @@ 0 0 - 615 - 369 + 695 + 368 @@ -559,16 +559,6 @@ NT: $196E (base+$16E) - - - - false - - - Edit palette.. - - - diff --git a/src/VramTiledView.cpp b/src/VramTiledView.cpp index 5ff959d3..d9c45319 100644 --- a/src/VramTiledView.cpp +++ b/src/VramTiledView.cpp @@ -1,5 +1,6 @@ #include "VramTiledView.h" #include "VDPDataStore.h" +#include "MSXPalette.h" #include "Convert.h" #include "ranges.h" #include @@ -10,7 +11,8 @@ VramTiledView::VramTiledView(QWidget* parent) : QWidget(parent) , image(512, 512, QImage::Format_RGB32) { - ranges::fill(msxPalette, qRgb(80, 80, 80)); + palette = nullptr; + setPaletteSource(VDPDataStore::instance().getPalette(paletteVDP)); setZoom(1.0f); // Mouse update events when mouse is moved over the image, Quibus likes this @@ -80,21 +82,6 @@ void VramTiledView::decode() update(); } -void VramTiledView::decodePalette() -{ - if (!palette) return; - //printf("VramTiledView::decodePallet palletpointer %p \n", palette); - - for (int i = 0; i < 16; ++i) { - int r = (palette[2 * i + 0] & 0xf0) >> 4; - int b = (palette[2 * i + 0] & 0x0f); - int g = (palette[2 * i + 1] & 0x0f); - - auto scale = [](int x) { return (x >> 1) | (x << 2) | (x << 5); }; - msxPalette[i] = qRgb(scale(r), scale(g), scale(b)); - //printf("VramTiledView::decodePallet color %d => r %d g %d b %d \n", i, r, g, b); - } -} void VramTiledView::decodePatternTable() { @@ -211,12 +198,7 @@ void VramTiledView::setPixel2x2(int x, int y, QRgb c) QRgb VramTiledView::getColor(int c) { // TODO do we need to look at the TP bit??? - return msxPalette[c ? c : (tpBit ? 0 : borderColor)]; -} - -const uint8_t *VramTiledView::getPaletteSource() const -{ - return palette; + return palette->color(c ? c : (tpBit ? 0 : borderColor)); } int VramTiledView::getScreenMode() const @@ -434,8 +416,7 @@ void VramTiledView::paintEvent(QPaintEvent* /*event*/) void VramTiledView::refresh() { - decodePalette(); - decode(); + decode(); } QString VramTiledView::byteAsPattern(uint8_t byte) @@ -568,9 +549,13 @@ void VramTiledView::setColorTableAddress(int adr) decode(); } -void VramTiledView::setPaletteSource(const uint8_t* adr) +void VramTiledView::setPaletteSource(MSXPalette *adr) { if (palette == adr) return; + if (palette) { + disconnect(palette, &MSXPalette::paletteChanged, this, &VramTiledView::decode); + } palette = adr; + connect(palette, &MSXPalette::paletteChanged, this, &VramTiledView::decode); refresh(); } diff --git a/src/VramTiledView.h b/src/VramTiledView.h index 05e3f9ae..7e5e235e 100644 --- a/src/VramTiledView.h +++ b/src/VramTiledView.h @@ -10,6 +10,8 @@ #include #include +class MSXPalette; + class VramTiledView : public QWidget { Q_OBJECT @@ -23,7 +25,7 @@ class VramTiledView : public QWidget void setNameTableAddress(int adr); void setPatternTableAddress(int adr); void setColorTableAddress(int adr); - void setPaletteSource(const uint8_t *adr); + void setPaletteSource(MSXPalette *adr); void setBorderColor(int value); void setDrawGrid(bool value); void setTpBit(bool value); @@ -59,7 +61,6 @@ class VramTiledView : public QWidget void paintEvent(QPaintEvent* e) override; void decode(); - void decodePalette(); void decodePatternTable(); void decodeNameTable(); void overLayNameTable(); @@ -83,10 +84,9 @@ class VramTiledView : public QWidget QString byteAsPattern(uint8_t byte); private: - QRgb msxPalette[16]; QImage image; QPixmap pixImage; - const uint8_t* palette = nullptr; + MSXPalette* palette = nullptr; const uint8_t* vramBase = nullptr; float zoomFactor; bool drawGrid = true; From f903b4019c1b35cfd996aceb842cb27ee28a8c01 Mon Sep 17 00:00:00 2001 From: David Heremans Date: Mon, 23 May 2022 20:45:19 +0200 Subject: [PATCH 53/63] Removed the old PaletteDialog Now that the PaletteViewer has taken over all the functions of the PaletteDialog we remove all traces of this old dialog. --- src/PaletteDialog.cpp | 172 --------------------------------------- src/PaletteDialog.h | 59 -------------- src/PaletteDialog.ui | 185 ------------------------------------------ src/PalettePatch.cpp | 14 ---- src/PalettePatch.h | 1 - src/SpriteViewer.cpp | 22 ----- src/TileViewer.cpp | 4 - src/node.mk | 4 +- 8 files changed, 2 insertions(+), 459 deletions(-) delete mode 100644 src/PaletteDialog.cpp delete mode 100644 src/PaletteDialog.h delete mode 100644 src/PaletteDialog.ui diff --git a/src/PaletteDialog.cpp b/src/PaletteDialog.cpp deleted file mode 100644 index 014c6b15..00000000 --- a/src/PaletteDialog.cpp +++ /dev/null @@ -1,172 +0,0 @@ -#include -#include -#include -#include -#include "PaletteDialog.h" -#include "PalettePatch.h" -#include "Convert.h" -#include "ranges.h" - - -PaletteDialog::PaletteDialog(QWidget* parent) - : QDialog(parent), ui(std::make_unique()) -{ - ui->setupUi(this); - connect(ui->horizontalSlider_R, &QSlider::valueChanged, this, &PaletteDialog::on_horizontalSlider_R_valueChanged); - connect(ui->horizontalSlider_G, &QSlider::valueChanged, this, &PaletteDialog::on_horizontalSlider_G_valueChanged); - connect(ui->horizontalSlider_B, &QSlider::valueChanged, this, &PaletteDialog::on_horizontalSlider_B_valueChanged); - connect(ui->buttonBox, &QDialogButtonBox::clicked, this, &PaletteDialog::on_buttonBox_clicked); - connect(ui->cb_autosync, &QCheckBox::stateChanged, this, &PaletteDialog::on_cb_autosync_stateChanged); - - const QFont fixedFont = QFontDatabase::systemFont(QFontDatabase::FixedFont); - ui->plainTextEdit->setFont(fixedFont); - - setWindowTitle("Palette editor"); - ranges::fill(myPal, 0); - ranges::fill(myOriginalPal, 0); - // add colors to colorframe - - signalMapper = new QSignalMapper(this); - auto* gridLayout = new QGridLayout; - gridLayout->setSpacing(0); - for (int i = 0; i < 16; ++i) { - auto* button = new PalettePatch(nullptr, i); - connect(button, &PalettePatch::clicked, signalMapper, qOverload<>(&QSignalMapper::map)); - signalMapper->setMapping(button, i); - gridLayout->addWidget(button, i / 8, i % 8); - connect(this, &PaletteDialog::paletteChanged, - button, &PalettePatch::updatePaletteChanged); - connect(signalMapper, &QSignalMapper::mappedInt, - button, &PalettePatch::setHighlightTest); - } - - connect(signalMapper, &QSignalMapper::mappedInt, - this, &PaletteDialog::colorSelected); - - ui->colorsframe->setLayout(gridLayout); - connect(this, &PaletteDialog::paletteChanged, - this, &PaletteDialog::updateText); -} - -void PaletteDialog::updateText() -{ - ui->plainTextEdit->clear(); - for (int i = 0; i < 4; ++i) { - QString txt(" db "); - for (int j = 0; j < 4; ++j) { - txt.append(QString("%1,%2 ") - .arg(hexValue(myPal[2 * (j + 4 * i) + 0], 2)) - .arg(hexValue(myPal[2 * (j + 4 * i) + 1], 2))); - if (j < 3) txt.append(','); - } - ui->plainTextEdit->appendPlainText(txt); - } -} - -void PaletteDialog::restoreOpeningsPalette() -{ - memcpy(myPal, myOriginalPal, sizeof(myPal)); - emit paletteChanged(myPal); // Resets the PalettePatches - colorSelected(currentColor); // Resets the sliders - if (autoSync) { - syncToSource(); - } -} - -void PaletteDialog::colorSelected(int colorNumber) -{ - currentColor = colorNumber; - int r = (myPal[2 * currentColor + 0] & 0x70) >> 4; - int b = (myPal[2 * currentColor + 0] & 0x07); - int g = (myPal[2 * currentColor + 1] & 0x07); - ui->horizontalSlider_R->setValue(r); - ui->horizontalSlider_G->setValue(g); - ui->horizontalSlider_B->setValue(b); - ui->label_colornr->setText(QString("Color %1").arg(colorNumber)); -} - -void PaletteDialog::setPalette(uint8_t* pal) -{ - sourcePal = pal; - memcpy(myOriginalPal, pal, sizeof(myOriginalPal)); - memcpy(myPal, pal, sizeof(myPal)); - emit paletteChanged(myPal); -} - -//void PaletteDialog::decodepalette() -//{ -// for (int i = 0; i < 16; ++i) { -// int r = (myPal[2 * i + 0] & 0xf0) >> 4; -// int b = (myPal[2 * i + 0] & 0x0f); -// int g = (myPal[2 * i + 1] & 0x0f); -// -// auto scale = [](int x) { return (x >> 1) | (x << 2) | (x << 5); }; -// msxPalette[i] = qRgb(scale(r), scale(g), scale(b)); -// -// QGridLayout* l = dynamic_cast(ui->colorsframe->layout()); -// dynamic_cast(l->itemAtPosition(i % 8, i / 8)->widget())->setText(QString("%1(%2%3%4)").arg(i).arg(r).arg(g).arg(b)); -// } -//} - -void PaletteDialog::combineRGB() -{ - int r = ui->horizontalSlider_R->value(); - int g = ui->horizontalSlider_G->value(); - int b = ui->horizontalSlider_B->value(); - myPal[2 * currentColor + 0] = 16 * r + b; - myPal[2 * currentColor + 1] = g; - emit paletteChanged(myPal); - if (autoSync) { - syncToSource(); - } -} - -void PaletteDialog::syncToSource() -{ - memcpy(sourcePal, myPal, sizeof(myPal)); - emit paletteSynced(); -} - -void PaletteDialog::setAutoSync(bool value) -{ - if (autoSync == value) return; - autoSync = value; - ui->cb_autosync->setChecked(value); -} - -void PaletteDialog::on_horizontalSlider_R_valueChanged(int value) -{ - ui->label_R->setText(QString("R=%1").arg(value)); - combineRGB(); -} - -void PaletteDialog::on_horizontalSlider_G_valueChanged(int value) -{ - ui->label_G->setText(QString("G=%1").arg(value)); - combineRGB(); -} - -void PaletteDialog::on_horizontalSlider_B_valueChanged(int value) -{ - ui->label_B->setText(QString("B=%1").arg(value)); - combineRGB(); -} - -void PaletteDialog::on_buttonBox_clicked(QAbstractButton* button) -{ - if (button== ui->buttonBox->button(QDialogButtonBox::Apply) || - button== ui->buttonBox->button(QDialogButtonBox::Ok)) { - syncToSource(); - } else if (button== ui->buttonBox->button(QDialogButtonBox::Reset) || - button== ui->buttonBox->button(QDialogButtonBox::Cancel)) { - restoreOpeningsPalette(); - } -} - -void PaletteDialog::on_cb_autosync_stateChanged(int arg1) -{ - autoSync = arg1 != Qt::Unchecked; - if (autoSync) { - syncToSource(); - } -} diff --git a/src/PaletteDialog.h b/src/PaletteDialog.h deleted file mode 100644 index 1a2bc33c..00000000 --- a/src/PaletteDialog.h +++ /dev/null @@ -1,59 +0,0 @@ -#ifndef PALETTEDIALOG_H -#define PALETTEDIALOG_H - -#include "ui_PaletteDialog.h" -#include -#include -#include -#include -#include - -namespace Ui { - class PaletteDialog; -} - -class PaletteDialog : public QDialog -{ - Q_OBJECT -public: - explicit PaletteDialog(QWidget* parent = nullptr); - - void setPalette(uint8_t* pal); - void syncToSource(); - void setAutoSync(bool value); - -signals: - void paletteChanged(const uint8_t* pal); - void paletteSynced(); - -private: - void colorSelected(int colorNumber); - void on_horizontalSlider_R_valueChanged(int value); - void on_horizontalSlider_G_valueChanged(int value); - void on_horizontalSlider_B_valueChanged(int value); - void restoreOpeningsPalette(); - - void on_buttonBox_clicked(QAbstractButton* button); - - void on_cb_autosync_stateChanged(int arg1); - - void updateText(); - - void combineRGB(); - //void decodepalette(); - -private: - std::unique_ptr ui; - QSignalMapper* signalMapper; - - uint8_t* sourcePal = nullptr; - uint8_t myPal[32]; - uint8_t myOriginalPal[32]; - - int currentColor = 0; - QRgb msxPalette[16]; - - bool autoSync = false; -}; - -#endif // PALETTEDIALOG_H diff --git a/src/PaletteDialog.ui b/src/PaletteDialog.ui deleted file mode 100644 index 538acd53..00000000 --- a/src/PaletteDialog.ui +++ /dev/null @@ -1,185 +0,0 @@ - - - PaletteDialog - - - - 0 - 0 - 513 - 271 - - - - Dialog - - - - - - - - QFrame::StyledPanel - - - QFrame::Sunken - - - - - - - - - B=0 - - - - - - - G=0 - - - - - - - 7 - - - 1 - - - Qt::Horizontal - - - QSlider::TicksBothSides - - - - - - - R=0 - - - - - - - 7 - - - 1 - - - Qt::Horizontal - - - QSlider::TicksBothSides - - - - - - - 7 - - - 1 - - - Qt::Horizontal - - - QSlider::TicksBothSides - - - - - - - Color 0 - - - - - - - - - - - - 0 - 0 - - - - - 16777215 - 100 - - - - - - - - - - Autosync - - - - - - - Qt::Horizontal - - - QDialogButtonBox::Apply|QDialogButtonBox::Cancel|QDialogButtonBox::Ok|QDialogButtonBox::Reset - - - - - - - - - - - buttonBox - accepted() - PaletteDialog - accept() - - - 248 - 254 - - - 157 - 274 - - - - - buttonBox - rejected() - PaletteDialog - reject() - - - 316 - 260 - - - 286 - 274 - - - - - diff --git a/src/PalettePatch.cpp b/src/PalettePatch.cpp index d537a592..03e4d29e 100644 --- a/src/PalettePatch.cpp +++ b/src/PalettePatch.cpp @@ -18,20 +18,6 @@ void PalettePatch::setMSXPalette(MSXPalette* pal) paletteChanged(); } -//old method for PaletteDialog -void PalettePatch::updatePaletteChanged(const uint8_t* pal) -{ - int r = (pal[2 * msxPalNr + 0] & 0x70) >> 4; - int b = (pal[2 * msxPalNr + 0] & 0x07); - int g = (pal[2 * msxPalNr + 1] & 0x07); - auto scale = [](int x) { return (x >> 1) | (x << 2) | (x << 5); }; - myColor = qRgb(scale(r), scale(g), scale(b)); - //setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding)); - update(); - //printf("PalettePatch::updatePaletteChanged %i\n", msxPalNr); -} - -//new method for PaletteView void PalettePatch::paletteChanged() { myColor = myPal->color(msxPalNr); diff --git a/src/PalettePatch.h b/src/PalettePatch.h index 73373399..07e4c491 100644 --- a/src/PalettePatch.h +++ b/src/PalettePatch.h @@ -14,7 +14,6 @@ class PalettePatch : public QPushButton public slots: void setMSXPalette(MSXPalette* pal); - void updatePaletteChanged(const uint8_t* pal); void setHighlightTest(int colorNr); void paletteChanged(); diff --git a/src/SpriteViewer.cpp b/src/SpriteViewer.cpp index a96d9135..ed3393d2 100644 --- a/src/SpriteViewer.cpp +++ b/src/SpriteViewer.cpp @@ -1,31 +1,9 @@ #include "SpriteViewer.h" #include "VDPDataStore.h" #include "VramSpriteView.h" -//#include "PaletteDialog.h" #include "Convert.h" #include "MSXPalette.h" -// static to feed to PaletteDialog and be used when VDP colors aren't selected -uint8_t SpriteViewer::defaultPalette[32] = { -// RB G - 0x00, 0, - 0x00, 0, - 0x11, 6, - 0x33, 7, - 0x17, 1, - 0x27, 3, - 0x51, 1, - 0x27, 6, - 0x71, 1, - 0x73, 3, - 0x61, 6, - 0x64, 6, - 0x11, 4, - 0x65, 2, - 0x55, 5, - 0x77, 7, -}; - SpriteViewer::SpriteViewer(QWidget* parent) : QDialog(parent) , ui(std::make_unique()) diff --git a/src/TileViewer.cpp b/src/TileViewer.cpp index b2df24a2..126ac883 100644 --- a/src/TileViewer.cpp +++ b/src/TileViewer.cpp @@ -2,13 +2,9 @@ #include "ui_TileViewer.h" #include "VramTiledView.h" #include "VDPDataStore.h" -#include "PaletteDialog.h" #include "Convert.h" #include - - - TileViewer::TileViewer(QWidget* parent) : QDialog(parent), image4label(32, 32, QImage::Format_RGB32) { diff --git a/src/node.mk b/src/node.mk index 0650e56c..b71ae2b4 100644 --- a/src/node.mk +++ b/src/node.mk @@ -10,7 +10,7 @@ MOC_SRC_HDR:= \ DebugSession MainMemoryViewer BitMapViewer VramBitMappedView \ VDPDataStore VDPStatusRegViewer VDPRegViewer InteractiveLabel \ InteractiveButton VDPCommandRegViewer GotoDialog SymbolTable \ - TileViewer VramTiledView PaletteDialog VramSpriteView SpriteViewer \ + TileViewer VramTiledView VramSpriteView SpriteViewer \ BreakpointViewer SignalDispatcher \ blendsplitter/BlendSplitter blendsplitter/Expander \ blendsplitter/Overlay blendsplitter/SplitterDecorator \ @@ -33,7 +33,7 @@ SRC_ONLY:= \ UI:= \ ConnectDialog SymbolManager PreferencesDialog BreakpointDialog \ BitMapViewer VDPStatusRegisters VDPRegistersExplained VDPCommandRegisters \ - GotoDialog TileViewer PaletteDialog SpriteViewer BreakpointViewer \ + GotoDialog TileViewer SpriteViewer BreakpointViewer \ QuickGuide PaletteView include build/node-end.mk From 4d59b42a4075a3ab2cac797383e98e792cdad94b Mon Sep 17 00:00:00 2001 From: Manuel Bilderbeek Date: Tue, 24 May 2022 22:53:32 +0200 Subject: [PATCH 54/63] Fix two text issues/typos. --- src/QuickGuide.ui | 2 +- src/VDPRegistersExplained.ui | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/QuickGuide.ui b/src/QuickGuide.ui index df195d01..1c77d691 100644 --- a/src/QuickGuide.ui +++ b/src/QuickGuide.ui @@ -32,7 +32,7 @@ - <html><head/><body><h1 style=" margin-top:18px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:xx-large; font-weight:700; color:#000001;">Quickguide to the new blendsplitter way of working</span></h1><p><span style=" color:#000001;">Hi you may have accidentally stumbled upon the new way of working in the openMSX debugger. </span></p><p><span style=" color:#000001;">The old dockingwidgets has been abandoned in favor of a new layouting scheme that is inspired by the open source 3D package Blender. Here is a quick summary of how to work with the new layouts.</span></p><h2 style=" margin-top:16px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:x-large; font-weight:700; color:#000001;">Workspaces</span></h2><p><span style=" color:#000001;">Workspaces are essentially predefined window layouts.</span></p><p><span style=" color:#000001;">You can access the workspaces with the tabar at the top. Use the button at the rigth of the tabs to create a new workspace, you can create empty workspaces or pick an existent predefined workspace.</span></p><p><img src=":/quickguide/workspaces.png"/></p><h2 style=" margin-top:16px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:x-large; font-weight:700; color:#000001;">Areas</span></h2><p><span style=" color:#000001;">The debugger window is divided into a number of rectangles called Areas. An area has 4 corner handlers.</span></p><p><span style=" color:#000001;">Each area contains a switcher that contains a seperate debuggerview. You can change the debuggerview by selecting an alternative debuggerview in the dropdown list.</span></p><p><img src=":/quickguide/borders.png"/></p><h3 style=" margin-top:14px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:large; font-weight:700; color:#000001;">Resizing areas</span></h3><p><span style=" color:#000001;">You can resize areas by dragging their borders with </span><span style=" font-family:'monospace'; color:#000001;">LMB</span><span style=" color:#000001;">. Move your mouse cursor over the border between two areas, so that the cursor changes to a double-headed arrow, and then click and drag.</span></p><p><img src=":/quickguide/resize.png"/></p><h3 style=" margin-top:14px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:large; font-weight:700; color:#000001;">Splitting areas</span></h3><p><span style=" color:#000001;">Splitting an area will create a new area. Placing the mouse cursor in an area corner will change the cursor to a cross (+) to indicate that pressing down </span><span style=" font-family:'monospace'; color:#000001;">LMB</span><span style=" color:#000001;"> will activate splitting or joining operator. Dragging from area corner </span><span style=" font-weight:700; color:#000001;">inward</span><span style=" color:#000001;"> will </span><span style=" font-style:italic; color:#000001;">split</span><span style=" color:#000001;"> the area. You define the split direction by dragging either horizontally or vertically.</span></p><p><img src=":/quickguide/split.png"/></p><h3 style=" margin-top:14px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:large; font-weight:700; color:#000001;">Joining areas</span></h3><p><span style=" color:#000001;">Dragging from an area corner </span><span style=" font-weight:700; color:#000001;">outward</span><span style=" color:#000001;"> will </span><span style=" font-style:italic; color:#000001;">join</span><span style=" color:#000001;"> two areas. The area that will be closed shows a dark overlay. You can select which area will be closed by moving the mouse over areas. Release the </span><span style=" font-family:'monospace'; color:#000001;">LMB</span><span style=" color:#000001;"> to complete the join. If you press </span><span style=" font-family:'monospace'; color:#000001;">Esc</span><span style=" color:#000001;"> or </span><span style=" font-family:'monospace'; color:#000001;">RMB</span><span style=" color:#000001;"> before releasing the mouse, the operation will be canceled.</span></p><p><span style=" color:#000001;">You can only join areas if they share a common border.</span></p><p><img src=":/quickguide/join.png"/></p><h3 style=" margin-top:14px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:large; font-weight:700; color:#000001;">Switching the viewer in an area</span></h3><p><span style=" color:#000001;">Each area contains one viewer you can switch between viewers by selecting the desired viewer from the dropdown box at the top of each area.</span></p><p><img src=":/quickguide/switching.png"/></p><p><span style=" color:#000001;">There is no limitation to the amount of viewers per type that can be used.<br/></span></p><h2 style=" margin-top:16px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:x-large; font-weight:700; color:#000001;">Saving your current workspaces and area layout</span></h2><p><span style=" color:#000001;">You can save your current workspaces and layouts using the File menu.</span></p><p><span style=" color:#000001;">In the </span><span style=" font-weight:700; color:#000001;">&quot;System&quot; -&gt; &quot;Preferences...&quot;</span><span style=" color:#000001;"> menu you can select the </span><span style=" font-weight:700; color:#000001;">&quot;Workspace Layout&quot;</span><span style=" color:#000001;"> tab to select the layout that the debugger needs to use when starting.<br/>By default the selection is </span><span style=" font-style:italic; color:#000001;">&quot;First Time User&quot;</span><span style=" color:#000001;"> so that you will see this manual as first workspace when starting.<br/>Also for first time users each area split will by default show this manual, in regular usage an area split will create a duplicate of the area you started to split.</span></p><p><span style=" color:#000001;">Floating widgets aren't saved and need to be create manually each time.</span></p><p><span style=" color:#000001;"><br/></span></p><p><span style=" color:#000001;"><br/></span></p></body></html> + <html><head/><body><h1 style=" margin-top:18px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:xx-large; font-weight:700; color:#000001;">Quickguide to the new blendsplitter way of working</span></h1><p><span style=" color:#000001;">Hi you may have accidentally stumbled upon the new way of working in the openMSX debugger. </span></p><p><span style=" color:#000001;">The old dockingwidgets has been abandoned in favor of a new layouting scheme that is inspired by the open source 3D package Blender. Here is a quick summary of how to work with the new layouts.</span></p><h2 style=" margin-top:16px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:x-large; font-weight:700; color:#000001;">Workspaces</span></h2><p><span style=" color:#000001;">Workspaces are essentially predefined window layouts.</span></p><p><span style=" color:#000001;">You can access the workspaces with the tab bar at the top. Use the button at the rigth of the tabs to create a new workspace, you can create empty workspaces or pick an existent predefined workspace.</span></p><p><img src=":/quickguide/workspaces.png"/></p><h2 style=" margin-top:16px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:x-large; font-weight:700; color:#000001;">Areas</span></h2><p><span style=" color:#000001;">The debugger window is divided into a number of rectangles called Areas. An area has 4 corner handlers.</span></p><p><span style=" color:#000001;">Each area contains a switcher that contains a seperate debuggerview. You can change the debuggerview by selecting an alternative debuggerview in the dropdown list.</span></p><p><img src=":/quickguide/borders.png"/></p><h3 style=" margin-top:14px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:large; font-weight:700; color:#000001;">Resizing areas</span></h3><p><span style=" color:#000001;">You can resize areas by dragging their borders with </span><span style=" font-family:'monospace'; color:#000001;">LMB</span><span style=" color:#000001;">. Move your mouse cursor over the border between two areas, so that the cursor changes to a double-headed arrow, and then click and drag.</span></p><p><img src=":/quickguide/resize.png"/></p><h3 style=" margin-top:14px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:large; font-weight:700; color:#000001;">Splitting areas</span></h3><p><span style=" color:#000001;">Splitting an area will create a new area. Placing the mouse cursor in an area corner will change the cursor to a cross (+) to indicate that pressing down </span><span style=" font-family:'monospace'; color:#000001;">LMB</span><span style=" color:#000001;"> will activate splitting or joining operator. Dragging from area corner </span><span style=" font-weight:700; color:#000001;">inward</span><span style=" color:#000001;"> will </span><span style=" font-style:italic; color:#000001;">split</span><span style=" color:#000001;"> the area. You define the split direction by dragging either horizontally or vertically.</span></p><p><img src=":/quickguide/split.png"/></p><h3 style=" margin-top:14px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:large; font-weight:700; color:#000001;">Joining areas</span></h3><p><span style=" color:#000001;">Dragging from an area corner </span><span style=" font-weight:700; color:#000001;">outward</span><span style=" color:#000001;"> will </span><span style=" font-style:italic; color:#000001;">join</span><span style=" color:#000001;"> two areas. The area that will be closed shows a dark overlay. You can select which area will be closed by moving the mouse over areas. Release the </span><span style=" font-family:'monospace'; color:#000001;">LMB</span><span style=" color:#000001;"> to complete the join. If you press </span><span style=" font-family:'monospace'; color:#000001;">Esc</span><span style=" color:#000001;"> or </span><span style=" font-family:'monospace'; color:#000001;">RMB</span><span style=" color:#000001;"> before releasing the mouse, the operation will be canceled.</span></p><p><span style=" color:#000001;">You can only join areas if they share a common border.</span></p><p><img src=":/quickguide/join.png"/></p><h3 style=" margin-top:14px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:large; font-weight:700; color:#000001;">Switching the viewer in an area</span></h3><p><span style=" color:#000001;">Each area contains one viewer you can switch between viewers by selecting the desired viewer from the dropdown box at the top of each area.</span></p><p><img src=":/quickguide/switching.png"/></p><p><span style=" color:#000001;">There is no limitation to the amount of viewers per type that can be used.<br/></span></p><h2 style=" margin-top:16px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:x-large; font-weight:700; color:#000001;">Saving your current workspaces and area layout</span></h2><p><span style=" color:#000001;">You can save your current workspaces and layouts using the File menu.</span></p><p><span style=" color:#000001;">In the </span><span style=" font-weight:700; color:#000001;">&quot;System&quot; -&gt; &quot;Preferences...&quot;</span><span style=" color:#000001;"> menu you can select the </span><span style=" font-weight:700; color:#000001;">&quot;Workspace Layout&quot;</span><span style=" color:#000001;"> tab to select the layout that the debugger needs to use when starting.<br/>By default the selection is </span><span style=" font-style:italic; color:#000001;">&quot;First Time User&quot;</span><span style=" color:#000001;"> so that you will see this manual as first workspace when starting.<br/>Also for first time users each area split will by default show this manual, in regular usage an area split will create a duplicate of the area you started to split.</span></p><p><span style=" color:#000001;">Floating widgets aren't saved and need to be create manually each time.</span></p><p><span style=" color:#000001;"><br/></span></p><p><span style=" color:#000001;"><br/></span></p></body></html> Qt::RichText diff --git a/src/VDPRegistersExplained.ui b/src/VDPRegistersExplained.ui index 57900995..121f6e65 100644 --- a/src/VDPRegistersExplained.ui +++ b/src/VDPRegistersExplained.ui @@ -10301,7 +10301,7 @@ p, li { white-space: pre-wrap; } - Display enabeled + Display enabled From 5db0ee1dd0a877b424ada56351523cd93416664a Mon Sep 17 00:00:00 2001 From: David Heremans Date: Wed, 1 Jun 2022 20:14:44 +0200 Subject: [PATCH 55/63] PaletteView with better autosync indication The autosync is only meant for the VDP palette to sync to the current openMSX session, so make this more clear in the GUI. --- src/PaletteView.cpp | 6 ++++++ src/PaletteView.ui | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/PaletteView.cpp b/src/PaletteView.cpp index 3d9255e9..434793c8 100644 --- a/src/PaletteView.cpp +++ b/src/PaletteView.cpp @@ -165,6 +165,12 @@ void PaletteView::on_cbPalette_currentIndexChanged(int index) ui->pbCopyPaletteVDP->setEnabled(index != 0); ScopedAssign sa(isDisplayUpdating, true); setPalette(VDPDataStore::instance().getPalette(index)); + ui->cb_autosync->setEnabled(index==0); + if (index){ + ui->buttonBox->setDisabled(true); + } else { + ui->buttonBox->setDisabled(ui->cb_autosync->isChecked()); + } colorSelected(currentColor); } diff --git a/src/PaletteView.ui b/src/PaletteView.ui index f6b027f8..8e0d2d05 100644 --- a/src/PaletteView.ui +++ b/src/PaletteView.ui @@ -291,7 +291,7 @@ - autosync to openMSX + autosync VDP palette to openMSX Autosync From 39c7752968dce3d31bfe69e7844b1414fdf250c7 Mon Sep 17 00:00:00 2001 From: David Heremans Date: Sun, 26 Jun 2022 16:31:55 +0200 Subject: [PATCH 56/63] Improving HexViewer Now we can decode 8 bytes as a character. And since character definitions do not need to be aligned in memory the hexviewer address can now be unaligned as well. --- src/HexViewer.cpp | 160 +++++++++++++++++++++++++++++++++------------- src/HexViewer.h | 6 ++ 2 files changed, 121 insertions(+), 45 deletions(-) diff --git a/src/HexViewer.cpp b/src/HexViewer.cpp index e5fef8bb..1eaea858 100644 --- a/src/HexViewer.cpp +++ b/src/HexViewer.cpp @@ -66,7 +66,7 @@ HexViewer::HexViewer(QWidget* parent) void HexViewer::createActions() { - fillWidthAction = new QAction(tr("&Fill with"), this); + fillWidthAction = new QAction(tr("&Fill width"), this); fillWidthAction->setShortcut(tr("Ctrl+F")); fillWidthAction->setStatusTip(tr("Fill the width with as many bytes as possible.")); @@ -86,17 +86,39 @@ void HexViewer::createActions() setWith32Action->setShortcut(tr("Ctrl+3")); setWith32Action->setStatusTip(tr("Set width to 32 bytes.")); - connect(fillWidthAction, &QAction::triggered, this, &HexViewer::changeWidth); - connect(fillWidth2Action, &QAction::triggered, this, &HexViewer::changeWidth); - connect(setWith8Action, &QAction::triggered, this, &HexViewer::changeWidth); - connect(setWith16Action, &QAction::triggered, this, &HexViewer::changeWidth); - connect(setWith32Action, &QAction::triggered, this, &HexViewer::changeWidth); + decodeAsCharAction = new QAction(tr("&Show as char."), this); + decodeAsCharAction->setShortcut(tr("Ctrl+C")); + decodeAsCharAction->setCheckable(true); + decodeAsCharAction->setChecked(decodeAsChar); + decodeAsCharAction->setStatusTip(tr("decode 8 bytes as character.")); + + alignAddressAction = new QAction(tr("&Align addresses"), this); + alignAddressAction->setShortcut(tr("Ctrl+A")); + alignAddressAction->setCheckable(true); + alignAddressAction->setChecked(decodeAsChar); + alignAddressAction->setStatusTip(tr("Align adresses with width of line.")); + + + connect(fillWidthAction, &QAction::triggered, this, &HexViewer::changeWidth); + connect(fillWidth2Action, &QAction::triggered, this, &HexViewer::changeWidth); + connect(setWith8Action, &QAction::triggered, this, &HexViewer::changeWidth); + connect(setWith16Action, &QAction::triggered, this, &HexViewer::changeWidth); + connect(setWith32Action, &QAction::triggered, this, &HexViewer::changeWidth); + connect(decodeAsCharAction, &QAction::triggered, this, &HexViewer::changeWidth); + connect(alignAddressAction, &QAction::triggered, this, &HexViewer::changeWidth); //[=]() {alignAddress = alignAddressAction->isChecked();} ); addAction(fillWidthAction); addAction(fillWidth2Action); addAction(setWith8Action); addAction(setWith16Action); addAction(setWith32Action); + + QAction *sep = new QAction("", this); + sep->setSeparator(true); + addAction(sep); + + addAction(decodeAsCharAction); + addAction(alignAddressAction); setContextMenuPolicy(Qt::ActionsContextMenu); } @@ -107,12 +129,26 @@ void HexViewer::changeWidth() else if (sender() == setWith8Action) setDisplayWidth(8); else if (sender() == setWith16Action) setDisplayWidth(16); else if (sender() == setWith32Action) setDisplayWidth(32); + else if (sender() == decodeAsCharAction) setDisplayCharacters(decodeAsCharAction->isChecked()); + else if (sender() == alignAddressAction) setAlignAddress(alignAddressAction->isChecked()); +} + +void HexViewer::setAlignAddress(bool enabled) +{ + alignAddress = enabled; + setTopLocation(hexTopAddress); } void HexViewer::setIsEditable(bool enabled) { isEditable = enabled; - setUseMarker(true); + setUseMarker(true); +} + +void HexViewer::setDisplayCharacters(bool showchars) +{ + decodeAsChar = showchars; + setSizes(); } void HexViewer::setUseMarker(bool enabled) @@ -179,13 +215,18 @@ void HexViewer::setSizes() if (horBytes == 2 * hb2) hb2 = horBytes; w -= dataWidth + charWidth; if ((horBytes & 3) == 0) w -= EXTRA_SPACING; - if ((horBytes & 7) == 0) w -= EXTRA_SPACING; + if ((horBytes & 7) == 0) w -= EXTRA_SPACING; // remove scrollbar if (horBytes * visibleLines >= debuggableSize) sbw = 0; } // limit to power of two if needed if (displayMode == FILL_WIDTH_POWEROF2) horBytes = hb2; + + // if we want to show decoded chars then we limit ourself to multiples of 8 + if (decodeAsChar && horBytes >=8 ) { + horBytes=8*int(horBytes/8); + } } // check if a scrollbar is needed @@ -213,7 +254,7 @@ void HexViewer::setSizes() if (isEnabled()) { ///vertScrollBar->setValue(hexTopAddress / horBytes); - setTopLocation(horBytes * int(hexTopAddress / horBytes)); + setTopLocation(alignAddress ? horBytes * int(hexTopAddress / horBytes) : hexTopAddress); } else { update(); } @@ -332,42 +373,65 @@ void HexViewer::paintEvent(QPaintEvent* e) // print characters x += charWidth; for (int j = 0; j < horBytes; ++j) { - if (address + j >= debuggableSize) break; - uint8_t chr = hexData[address + j]; - if (chr < 32 || chr > 127) chr = '.'; - // draw marker if needed - if (useMarker || beingEdited) { - QRect b(x, y, charWidth, lineHeight); - if ((address + j) == hexMarkAddress) { - p.fillRect(b, hasFocus ? Qt::cyan - : Qt::lightGray); - } - // are we being edited ?? - if (hasFocus && isEditable && editedChars && - ((address + j) == hexMarkAddress)) { - if (beingEdited) { - p.fillRect(b, Qt::darkGreen); - } else { - p.drawRect(b); - } - } - } - // determine value colour - if (highlitChanges) { - QColor penClr = palette().color(QPalette::Text); - if (hexData[address + j] != previousHexData[address + j]) { - penClr = Qt::red; - } - if (((address + j) == hexMarkAddress) && beingEdited && - (cursorPosition == 0)) { - penClr = Qt::white; - } - p.setPen(penClr); - } - p.drawText(x, y + a, QString(chr)); + if (address + j < debuggableSize) { + uint8_t chr = hexData[address + j]; + if (chr < 32 || chr > 127) chr = '.'; + // draw marker if needed + if (useMarker || beingEdited) { + QRect b(x, y, charWidth, lineHeight); + if ((address + j) == hexMarkAddress) { + p.fillRect(b, hasFocus ? Qt::cyan + : Qt::lightGray); + } + // are we being edited ?? + if (hasFocus && isEditable && editedChars && + ((address + j) == hexMarkAddress)) { + if (beingEdited) { + p.fillRect(b, Qt::darkGreen); + } else { + p.drawRect(b); + } + } + } + // determine value colour + if (highlitChanges) { + QColor penClr = palette().color(QPalette::Text); + if (hexData[address + j] != previousHexData[address + j]) { + penClr = Qt::red; + } + if (((address + j) == hexMarkAddress) && beingEdited && + (cursorPosition == 0)) { + penClr = Qt::white; + } + p.setPen(penClr); + } + p.drawText(x, y + a, QString(chr)); + } x += charWidth; } + // if we are a multiple of 8 bytes we draw one or more decoded characters + if ((horBytes%8) == 0 ){ + x += EXTRA_SPACING; + int scale = int((lineHeight+1)/8); + + for (int j = 0; j < horBytes; ++j) { + if (address + j >= debuggableSize) break; + int yy = (j%8); + QColor penClr = Qt::lightGray; //Qt::white; +// if (hexData[address + j] != previousHexData[address + j]) { +// penClr = Qt::red; +// } + for (int k = 0; k < 8; ++k) { + QColor pcl= hexData[address + j]&(1 << (7 - k)) ? palette().color(QPalette::Text) : penClr ; + p.fillRect(x+k*scale,y+yy*scale, scale,scale, pcl); + } + if (yy == 7) { + x += 8*scale; + } + } + } + y += lineHeight; address += horBytes; if (address >= debuggableSize) break; @@ -397,7 +461,7 @@ void HexViewer::setDebuggable(const QString& name, int size) void HexViewer::scrollBarChanged(int addr) { int start = addr * horBytes; - if (start == hexTopAddress) { + if (start >= (hexTopAddress-horBytes) && start <= (hexTopAddress+horBytes)) { // nothing changed or a callback since we changed the value to // the current hexTopAddress return; @@ -444,7 +508,10 @@ void HexViewer::setTopLocation(int addr) if (debuggableName.isEmpty()) { return; } - int start = horBytes * int(addr / horBytes); + int start = addr; + if (alignAddress) { + start = horBytes * int(addr / horBytes); + } if (!waitingForData || (start != hexTopAddress)) { hexTopAddress = start; refresh(); @@ -606,7 +673,10 @@ void HexViewer::keyPressEvent(QKeyEvent* e) // Make scrolling downwards using cursors more "intuitive" int addr = hexTopAddress + horBytes * visibleLines; - if ((newAddress >= addr) && (newAddress <= (addr + horBytes))) { + if (!alignAddress && (newAddress == addr) && e->key() == Qt::Key_Right) { + ++hexTopAddress; + } else + if ((newAddress >= addr) && (newAddress <= (addr + horBytes))) { hexTopAddress += horBytes; } if (useMarker) { diff --git a/src/HexViewer.h b/src/HexViewer.h index d2ff0472..f2276170 100644 --- a/src/HexViewer.h +++ b/src/HexViewer.h @@ -22,6 +22,8 @@ class HexViewer : public QFrame void setUseMarker(bool enabled); void setIsEditable(bool enabled); + void setAlignAddress(bool enabled); + void setDisplayCharacters(bool showchars); void setDisplayMode(Mode mode); void setDisplayWidth(short width); @@ -62,6 +64,8 @@ class HexViewer : public QFrame QAction* setWith8Action; QAction* setWith16Action; QAction* setWith32Action; + QAction* decodeAsCharAction; + QAction* alignAddressAction; int wheelRemainder = 0; @@ -89,6 +93,8 @@ class HexViewer : public QFrame bool beingEdited = false; bool editedChars = false; bool hasFocus = false; + bool decodeAsChar= true; + bool alignAddress= true; int cursorPosition, editValue; friend class HexRequest; From ff9c79cf564a17c65a5aa73db0a567e8f17909af Mon Sep 17 00:00:00 2001 From: David Heremans Date: Thu, 18 Aug 2022 00:12:34 +0200 Subject: [PATCH 57/63] More HexViewer improvements Take decoded chars width into account. Cyan line in decoded char to indicate marker address. Allow shift+left/right when in unaligned mode to shift addresses in single byte steps. --- src/HexViewer.cpp | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/src/HexViewer.cpp b/src/HexViewer.cpp index 1eaea858..dedb24d4 100644 --- a/src/HexViewer.cpp +++ b/src/HexViewer.cpp @@ -95,7 +95,7 @@ void HexViewer::createActions() alignAddressAction = new QAction(tr("&Align addresses"), this); alignAddressAction->setShortcut(tr("Ctrl+A")); alignAddressAction->setCheckable(true); - alignAddressAction->setChecked(decodeAsChar); + alignAddressAction->setChecked(alignAddress); alignAddressAction->setStatusTip(tr("Align adresses with width of line.")); @@ -209,10 +209,19 @@ void HexViewer::setSizes() horBytes = 1; int hb2 = 1; w = width() - frameL - frameR - xData - dataWidth - 2 * charWidth - 8; - // calculate how many additional bytes can by displayed + // calculate how many additional bytes can be displayed while (w-sbw >= dataWidth + charWidth) { ++horBytes; - if (horBytes == 2 * hb2) hb2 = horBytes; + if (horBytes == 2 * hb2) { + hb2 = horBytes; + if (decodeAsChar){ + if (hb2 == 8 ) w -= EXTRA_SPACING; + if (hb2 >= 8 ){ + int scale = int((lineHeight+1)/8); + w -= scale*8; + } + } + }; w -= dataWidth + charWidth; if ((horBytes & 3) == 0) w -= EXTRA_SPACING; if ((horBytes & 7) == 0) w -= EXTRA_SPACING; @@ -411,14 +420,14 @@ void HexViewer::paintEvent(QPaintEvent* e) } // if we are a multiple of 8 bytes we draw one or more decoded characters - if ((horBytes%8) == 0 ){ + if ((horBytes%8) == 0 && decodeAsChar){ x += EXTRA_SPACING; int scale = int((lineHeight+1)/8); for (int j = 0; j < horBytes; ++j) { if (address + j >= debuggableSize) break; int yy = (j%8); - QColor penClr = Qt::lightGray; //Qt::white; + QColor penClr = (hasFocus && hexMarkAddress==(address + j) )? Qt::cyan : Qt::lightGray; //Qt::white; // if (hexData[address + j] != previousHexData[address + j]) { // penClr = Qt::red; // } @@ -580,11 +589,13 @@ void HexViewer::keyPressEvent(QKeyEvent* e) } else if (useMarker && e->key() == Qt::Key_Right) { setValue = beingEdited & !editedChars; ++newAddress; + if (!alignAddress && e->modifiers() == Qt::ShiftModifier) ++hexTopAddress; cursorPosition = 0; } else if (useMarker && e->key() == Qt::Key_Left) { setValue = beingEdited & !editedChars; --newAddress; - cursorPosition = 0; + if (!alignAddress && e->modifiers() == Qt::ShiftModifier) --hexTopAddress; + cursorPosition = 0; } else if (useMarker && e->key() == Qt::Key_Up) { setValue = beingEdited & !editedChars; newAddress -= horBytes; @@ -667,7 +678,7 @@ void HexViewer::keyPressEvent(QKeyEvent* e) if ((editedChars || useMarker) && (hexMarkAddress != newAddress)) { if (newAddress < 0) newAddress += debuggableSize; if (newAddress >= debuggableSize) newAddress -= debuggableSize; - // influencing hexTopAddress during Key_PageUp/Down might need following 2 lines. + // influencing hexTopAddress during Key_PageUp/Down or SHIFT+left/right might need following 2 lines. if (hexTopAddress < 0) hexTopAddress += debuggableSize; if (hexTopAddress >= debuggableSize) hexTopAddress -= debuggableSize; From 3592c7240e86dfcdb199be1c8b9363e462e6df09 Mon Sep 17 00:00:00 2001 From: David Heremans Date: Wed, 23 Nov 2022 12:20:41 +0100 Subject: [PATCH 58/63] Add minor tooltip --- src/TileViewer.ui | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/TileViewer.ui b/src/TileViewer.ui index c6e41c9e..c0b1eb98 100644 --- a/src/TileViewer.ui +++ b/src/TileViewer.ui @@ -50,8 +50,8 @@ 0 0 - 695 - 368 + 774 + 356 @@ -210,6 +210,9 @@ NT: $196E (base+$16E) + + visible when using 'Name Table + Overlay' as Tilemap Source + Highlight Tile From f7c064030b37ad40f96e8556465d69d32de16dd4 Mon Sep 17 00:00:00 2001 From: David Heremans Date: Wed, 23 Nov 2022 14:02:13 +0100 Subject: [PATCH 59/63] VDPRegViewer autodetects VDP in openMSX Since openMSX 18.0-106-ge55a4a904 (commit e55a4a9044b...) the TCL command 'machine_info device VDP' now also returns the version string from the machines XML config. This is now used to select the correct view for the VDPRegViewer when decoding the VDP registers. --- src/VDPDataStore.cpp | 33 +++++++++++++++++++ src/VDPDataStore.h | 6 +++- src/VDPRegViewer.cpp | 61 +++++++++++++++++++++++++++++++++--- src/VDPRegViewer.h | 10 ++++-- src/VDPRegistersExplained.ui | 30 ++++++++++++++++-- 5 files changed, 130 insertions(+), 10 deletions(-) diff --git a/src/VDPDataStore.cpp b/src/VDPDataStore.cpp index e1321034..bd55d259 100644 --- a/src/VDPDataStore.cpp +++ b/src/VDPDataStore.cpp @@ -54,6 +54,33 @@ class VDPDataStoreVRAMSizeCheck : public SimpleCommand }; +class VDPDataStoreVDPVersionCheck : public SimpleCommand +{ +public: + VDPDataStoreVDPVersionCheck(VDPDataStore& dataStore_) + : SimpleCommand("dict get [machine_info device VDP] version") + , dataStore(dataStore_) + { + } + + void replyOk(const QString& message) override + { + //printf("dataStore.vramSize %i\n", dataStore.vramSize); + dataStore.machineVDPVersionString = message.toStdString(); + emit dataStore.VDPVersionChanged(message); + delete this; + } + void replyNok(const QString& /*message*/) override + { + dataStore.machineVDPVersionString = "unknown"; + delete this; + } + +private: + VDPDataStore& dataStore; +}; + + static constexpr unsigned MAX_VRAM_SIZE = 0x30000; static constexpr unsigned MAX_TOTAL_SIZE = MAX_VRAM_SIZE + 32 + 16 + 64 + 2; @@ -83,6 +110,7 @@ void VDPDataStore::refresh() void VDPDataStore::refresh1() { + CommClient::instance().sendCommand(new VDPDataStoreVDPVersionCheck(*this)); CommClient::instance().sendCommand(new VDPDataStoreVRAMSizeCheck(*this)); } @@ -133,6 +161,11 @@ MSXPalette* VDPDataStore::getPalette(int index) return &palettes[index]; } +std::optional VDPDataStore::getVDPVersion() const +{ + return machineVDPVersionString; +} + size_t VDPDataStore::getVRAMSize() const { return vramSize; diff --git a/src/VDPDataStore.h b/src/VDPDataStore.h index 2f4ff004..c35a8a22 100644 --- a/src/VDPDataStore.h +++ b/src/VDPDataStore.h @@ -29,12 +29,14 @@ class VDPDataStore : public QObject, public SimpleHexRequestUser const uint8_t* getVdpVramPointer() const; MSXPalette* getPalette(int index); + std::optional getVDPVersion() const; size_t getVRAMSize() const; void refresh(); signals: - void dataRefreshed(); // The refresh got the new data + void dataRefreshed(); // The refresh got the new data + void VDPVersionChanged(QString VDPversion); // New VDP version received during refresh /** This might become handy later on, for now we only need the dataRefreshed * @@ -59,9 +61,11 @@ class VDPDataStore : public QObject, public SimpleHexRequestUser size_t vramSize; std::optional debuggableNameVRAM; // VRAM debuggable name + std::optional machineVDPVersionString; // VRAM debuggable name friend class VDPDataStoreVersionCheck; friend class VDPDataStoreVRAMSizeCheck; + friend class VDPDataStoreVDPVersionCheck; }; #endif // VDPDATASTORE_H diff --git a/src/VDPRegViewer.cpp b/src/VDPRegViewer.cpp index 615e2406..854be80b 100644 --- a/src/VDPRegViewer.cpp +++ b/src/VDPRegViewer.cpp @@ -38,7 +38,8 @@ VDPRegViewer::VDPRegViewer(QWidget *parent) { setupUi(this); connect(VDPcomboBox, qOverload(&QComboBox::currentIndexChanged), this, &VDPRegViewer::on_VDPcomboBox_currentIndexChanged); - + connect(cb_useOpenMSXVDP, &QCheckBox::stateChanged, this, &VDPRegViewer::on_cb_useOpenMSXVDP_stateChanged); + connect(&VDPDataStore::instance(),&VDPDataStore::VDPVersionChanged, this, &VDPRegViewer::on_VDPVersionChanged); vdpId = 99; // make sure that we parse the first time the status registers are read vdpId = VDP_V9958; //quick hack for now @@ -954,17 +955,67 @@ void VDPRegViewer::registerBitChanged(int reg, int bit, bool state) void VDPRegViewer::on_VDPcomboBox_currentIndexChanged(int index) { + int newVdpId = VDP_TMS99X8; switch (index) { case 0: - vdpId = VDP_V9958; + newVdpId = VDP_V9958; break; case 1: - vdpId = VDP_V9938; + newVdpId = VDP_V9938; break; case 2: - vdpId = VDP_TMS99X8; + newVdpId = VDP_TMS99X8; break; - } + }; + + // on_VDPVersionChanged might have changed vdpId already so avoid calling decode twice + if (newVdpId != vdpId){ + vdpId = newVdpId; + decodeStatusVDPRegs(); + decodeVDPRegs(); + }; + +} + +void VDPRegViewer::on_VDPVersionChanged(QString VDPversion) +{ + if (!cb_useOpenMSXVDP->isChecked()){ + label_VDPreported->setText(VDPversion); + return; + }; + + if (VDPversion == label_VDPreported->text()){ + return; + } else { + label_VDPreported->setText(VDPversion); + }; + VDPVersion_to_combobox(VDPversion); +} + +void VDPRegViewer::on_cb_useOpenMSXVDP_stateChanged(int arg1) +{ + if (arg1 == Qt::Checked){ + QString VDPversion = label_VDPreported->text(); + VDPVersion_to_combobox(VDPversion); + }; +} + +void VDPRegViewer::VDPVersion_to_combobox(QString VDPversion) +{ + if (VDPversion == "unknown"){ + return; + } else if (VDPversion == "V9958"){ + vdpId = VDP_V9958; + VDPcomboBox->setCurrentIndex(0); + } else if (VDPversion == "V9938"){ + vdpId = VDP_V9938; + VDPcomboBox->setCurrentIndex(1); + } else { + vdpId = VDP_TMS99X8; + VDPcomboBox->setCurrentIndex(2); + }; decodeStatusVDPRegs(); decodeVDPRegs(); } + + diff --git a/src/VDPRegViewer.h b/src/VDPRegViewer.h index 3920ae0c..edd44176 100644 --- a/src/VDPRegViewer.h +++ b/src/VDPRegViewer.h @@ -28,7 +28,7 @@ class buttonHighlightDispatcher : public QObject class VDPRegViewer : public QDialog, public SimpleHexRequestUser, - private Ui::VDPRegisters + private Ui::VDPRegisters { Q_OBJECT public: @@ -37,8 +37,12 @@ class VDPRegViewer : public QDialog, public SimpleHexRequestUser, void refresh(); void registerBitChanged(int reg, int bit, bool state); - //quick hack while no auto-detection... + //override auto-detection or in case of older openMSX... void on_VDPcomboBox_currentIndexChanged(int index); + void on_VDPVersionChanged(QString VDPversion); + +private slots: + void on_cb_useOpenMSXVDP_stateChanged(int arg1); private: void decodeVDPRegs(); @@ -59,6 +63,8 @@ class VDPRegViewer : public QDialog, public SimpleHexRequestUser, uint8_t regs[64 + 16 + 2]; buttonHighlightDispatcher* modeBitsDispat; int vdpId; + void VDPVersion_to_combobox(QString VDPversion); + }; #endif /* VDPSTATUSREGVIEWER_H */ diff --git a/src/VDPRegistersExplained.ui b/src/VDPRegistersExplained.ui index 121f6e65..db69a642 100644 --- a/src/VDPRegistersExplained.ui +++ b/src/VDPRegistersExplained.ui @@ -10951,6 +10951,31 @@ p, li { white-space: pre-wrap; } + + + + use VDP reported by openMSX: + + + true + + + + + + + + true + + + + older versions of openMSX do not expose this info + + + unknown + + + @@ -10968,10 +10993,11 @@ p, li { white-space: pre-wrap; } <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +<html><head><meta name="qrichtext" content="1" /><meta charset="utf-8" /><style type="text/css"> p, li { white-space: pre-wrap; } +hr { height: 1px; border-width: 0; } </style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600; font-style:italic;">Quick hack</span><span style=" font-size:10pt; font-style:italic;"> use this to switch between VDP chip, since no autodetection yet in the code</span></p></body></html> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-style:italic;">Decode VDP register for video chip</span></p></body></html> Qt::RichText From 594e192d017164313b08126d915026a9d3b39cf6 Mon Sep 17 00:00:00 2001 From: David Heremans Date: Wed, 23 Nov 2022 14:49:18 +0100 Subject: [PATCH 60/63] Avoid superfluous signals --- src/VDPDataStore.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/VDPDataStore.cpp b/src/VDPDataStore.cpp index bd55d259..f8c39966 100644 --- a/src/VDPDataStore.cpp +++ b/src/VDPDataStore.cpp @@ -38,9 +38,7 @@ class VDPDataStoreVRAMSizeCheck : public SimpleCommand void replyOk(const QString& message) override { - //printf("dataStore.vramSize %i\n", dataStore.vramSize); dataStore.vramSize = message.toInt(); - //printf("dataStore.vramSize %i\n", dataStore.vramSize); dataStore.refresh2(); delete this; } @@ -65,9 +63,10 @@ class VDPDataStoreVDPVersionCheck : public SimpleCommand void replyOk(const QString& message) override { - //printf("dataStore.vramSize %i\n", dataStore.vramSize); - dataStore.machineVDPVersionString = message.toStdString(); - emit dataStore.VDPVersionChanged(message); + if (!dataStore.machineVDPVersionString || message != QString::fromStdString(*dataStore.machineVDPVersionString)){ + dataStore.machineVDPVersionString = message.toStdString(); + emit dataStore.VDPVersionChanged(message); + }; delete this; } void replyNok(const QString& /*message*/) override From be840e922dc6a17a75fe7a23ec9df6f28fe0e030 Mon Sep 17 00:00:00 2001 From: David Heremans Date: Tue, 31 Jan 2023 15:50:08 +0100 Subject: [PATCH 61/63] Fix small display error in sprite info --- src/SpriteViewer.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/SpriteViewer.cpp b/src/SpriteViewer.cpp index ed3393d2..23da73bc 100644 --- a/src/SpriteViewer.cpp +++ b/src/SpriteViewer.cpp @@ -182,13 +182,13 @@ void SpriteViewer::spatwidget_mouseMoveEvent(int /*x*/, int /*y*/, int character const uint8_t* vramBase = VDPDataStore::instance().getVramPointer(); if (vramBase != nullptr && character < 32) { auto addr = spAtAddr + 4 * character; - ui->label_spat_posx->setText(QString::number(vramBase[addr + 0])); - ui->label_spat_posy->setText(QString::number(vramBase[addr + 1])); + ui->label_spat_posy->setText(QString::number(vramBase[addr + 0])); + ui->label_spat_posx->setText(QString::number(vramBase[addr + 1])); ui->label_spat_pattern->setText(QString::number(vramBase[addr + 2])); ui->label_spat_color->setText(QString::number(vramBase[addr + 3])); } else { - ui->label_spat_posx->setText(""); ui->label_spat_posy->setText(""); + ui->label_spat_posx->setText(""); ui->label_spat_pattern->setText(""); ui->label_spat_color->setText(""); } From 335a8d8641fb224407f22074c713a00467b1585d Mon Sep 17 00:00:00 2001 From: David Heremans Date: Tue, 31 Jan 2023 16:00:39 +0100 Subject: [PATCH 62/63] improve .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 8aec4c55..1e71796c 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ build/*.pyc derived/ build/msvc/.vs/* .vscode/ +.qtc_clangd/ __pycache__/ ui_*.h moc_*.cpp From dfb292e16cc2ec1f325d320a7a970b8a54cbbec0 Mon Sep 17 00:00:00 2001 From: David Heremans Date: Thu, 2 Feb 2023 01:39:30 +0100 Subject: [PATCH 63/63] Fix TileViewer layout --- src/TileViewer.ui | 48 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 34 insertions(+), 14 deletions(-) diff --git a/src/TileViewer.ui b/src/TileViewer.ui index c0b1eb98..04d1dd22 100644 --- a/src/TileViewer.ui +++ b/src/TileViewer.ui @@ -108,7 +108,7 @@ - TextLabel + col - row - @@ -164,6 +164,15 @@ + + QFormLayout::WrapLongRows + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + @@ -174,14 +183,20 @@ - TextLabel + - (-) + + + 0 + 0 + + - Address + Address: @@ -218,16 +233,6 @@ NT: $196E (base+$16E) - - - - 255 - - - 0 - - - @@ -241,6 +246,16 @@ NT: $196E (base+$16E) + + + + 255 + + + 0 + + + @@ -343,7 +358,7 @@ NT: $196E (base+$16E) - TextLabel + - @@ -646,6 +661,11 @@ NT: $196E (base+$16E) + + + Monospace + + Click on the tilemap to show character info