Refactored InsightWindow class to inherit from QMainWindow, as opposed to a standard QObject

Replaced QWidget left panel with new PanelWidget instance
Also introduced a bottom panel (empty ATM)
Removed obsolete widgets
Added panel size adjustment on window resize
This commit is contained in:
Nav
2021-10-06 00:39:40 +01:00
parent 74b8e41e1b
commit 104f09f7c9
15 changed files with 561 additions and 449 deletions

View File

@@ -5,7 +5,6 @@
#include <utility>
#include "UiLoader.hpp"
#include "Widgets/SlidingHandleWidget.hpp"
#include "Widgets/RotatableLabel.hpp"
#include "Widgets/TargetWidgets/DIP/DualInlinePackageWidget.hpp"
@@ -29,10 +28,11 @@ using Bloom::Targets::TargetVariant;
using Bloom::Targets::TargetPackage;
using Bloom::Targets::TargetPinDescriptor;
InsightWindow::InsightWindow(
QApplication& application,
InsightWorker& insightWorker
): QObject(&application), insightWorker(insightWorker) {
InsightWindow::InsightWindow(InsightWorker& insightWorker): QMainWindow(nullptr), insightWorker(insightWorker) {
this->setObjectName("main-window");
this->setWindowTitle("Bloom Insight");
this->setMinimumSize(1000, 500);
auto mainWindowUiFile = QFile(
QString::fromStdString(Paths::compiledResourcesPath()
+ "/src/Insight/UserInterfaces/InsightWindow/UiFiles/InsightWindow.ui"
@@ -53,8 +53,8 @@ InsightWindow::InsightWindow(
}
auto uiLoader = UiLoader(this);
this->mainWindowWidget = uiLoader.load(&mainWindowUiFile);
this->mainWindowWidget->setStyleSheet(mainWindowStylesheet.readAll());
this->windowContainer = uiLoader.load(&mainWindowUiFile, this);
this->windowContainer->setStyleSheet(mainWindowStylesheet.readAll());
mainWindowUiFile.close();
mainWindowStylesheet.close();
@@ -64,11 +64,15 @@ InsightWindow::InsightWindow(
+ "/src/Insight/UserInterfaces/InsightWindow/Images/BloomIcon.svg"
)
));
this->ioContainerWidget = this->mainWindowWidget->findChild<InsightTargetWidgets::TargetPackageWidgetContainer*>(
this->layoutContainer = this->windowContainer->findChild<QWidget*>("layout-container");
this->mainMenuBar = this->windowContainer->findChild<QMenuBar*>("menu-bar");
this->layoutContainer->layout()->setMenuBar(this->mainMenuBar);
this->container = this->layoutContainer->findChild<QWidget*>("container");
this->ioContainerWidget = this->windowContainer->findChild<InsightTargetWidgets::TargetPackageWidgetContainer*>(
"io-container"
);
this->ioUnavailableWidget = this->mainWindowWidget->findChild<QLabel*>("io-inspection-unavailable");
this->mainMenuBar = this->mainWindowWidget->findChild<QMenuBar*>("menu-bar");
this->ioUnavailableWidget = this->windowContainer->findChild<QLabel*>("io-inspection-unavailable");
auto fileMenu = this->mainMenuBar->findChild<QMenu*>("file-menu");
auto helpMenu = this->mainMenuBar->findChild<QMenu*>("help-menu");
@@ -82,7 +86,7 @@ InsightWindow::InsightWindow(
connect(openGettingStartedUrlAction, &QAction::triggered, this, &InsightWindow::openGettingStartedUrl);
connect(openAboutWindowAction, &QAction::triggered, this, &InsightWindow::openAboutWindow);
this->header = this->mainWindowWidget->findChild<QWidget*>("header");
this->header = this->windowContainer->findChild<QWidget*>("header");
this->refreshIoInspectionButton = this->header->findChild<QToolButton*>("refresh-io-inspection-btn");
connect(this->refreshIoInspectionButton, &QToolButton::clicked, this, [this] {
@@ -110,13 +114,10 @@ InsightWindow::InsightWindow(
}
});
this->leftPanel = this->mainWindowWidget->findChild<QWidget*>("left-panel");
this->leftPanelLayoutContainer = this->leftPanel->findChild<QWidget*>("left-panel-layout-container");
this->leftMenuBar = this->container->findChild<QWidget*>("left-side-menu-bar");
this->leftPanel = this->container->findChild<PanelWidget*>("left-panel");
auto leftPanelSlider = this->mainWindowWidget->findChild<SlidingHandleWidget*>("left-panel-slider");
connect(leftPanelSlider, &SlidingHandleWidget::horizontalSlide, this, &InsightWindow::onLeftPanelHandleSlide);
this->targetRegistersButton = this->mainWindowWidget->findChild<QToolButton*>("target-registers-btn");
this->targetRegistersButton = this->container->findChild<QToolButton*>("target-registers-btn");
auto targetRegisterButtonLayout = this->targetRegistersButton->findChild<QVBoxLayout*>();
auto registersBtnLabel = new RotatableLabel(270, "Registers", this->targetRegistersButton);
registersBtnLabel->setObjectName("target-registers-btn-label");
@@ -125,9 +126,16 @@ InsightWindow::InsightWindow(
connect(this->targetRegistersButton, &QToolButton::clicked, this, &InsightWindow::toggleTargetRegistersPane);
this->footer = this->mainWindowWidget->findChild<QWidget*>("footer");
this->bottomMenuBar = this->container->findChild<QWidget*>("bottom-menu-bar");
this->bottomPanel = this->container->findChild<PanelWidget*>("bottom-panel");
this->footer = this->windowContainer->findChild<QWidget*>("footer");
this->targetStatusLabel = this->footer->findChild<QLabel*>("target-state");
this->programCounterValueLabel = this->footer->findChild<QLabel*>("target-program-counter-value");
const auto windowSize = this->size();
this->windowContainer->setFixedSize(windowSize);
this->layoutContainer->setFixedSize(windowSize);
}
void InsightWindow::init(TargetDescriptor targetDescriptor) {
@@ -135,171 +143,13 @@ void InsightWindow::init(TargetDescriptor targetDescriptor) {
this->activate();
}
void InsightWindow::activate() {
auto targetNameLabel = this->footer->findChild<QLabel*>("target-name");
auto targetIdLabel = this->footer->findChild<QLabel*>("target-id");
targetNameLabel->setText(QString::fromStdString(this->targetDescriptor.name));
targetIdLabel->setText("0x" + QString::fromStdString(this->targetDescriptor.id).remove("0x").toUpper());
this->variantMenu = this->footer->findChild<QMenu*>("target-variant-menu");
void InsightWindow::toggleUi(bool disable) {
this->uiDisabled = disable;
this->ioUnavailableWidget->hide();
std::optional<QString> previouslySelectedVariantName;
if (this->selectedVariant != nullptr) {
previouslySelectedVariantName = QString::fromStdString(this->selectedVariant->name).toLower();
this->selectedVariant = nullptr;
if (this->refreshIoInspectionButton != nullptr) {
this->refreshIoInspectionButton->setDisabled(disable);
this->refreshIoInspectionButton->repaint();
}
this->supportedVariantsByName.clear();
/*
* We don't want to present the user with duplicate target variants.
*
* In the context of Insight, a variant that doesn't differ in package type or pinout configuration is
* considered a duplicate.
*/
auto processedVariants = std::vector<TargetVariant>();
auto isDuplicateVariant = [&processedVariants](const TargetVariant& variantA) {
return std::ranges::any_of(
processedVariants.begin(),
processedVariants.end(),
[&variantA, &processedVariants](const TargetVariant& variantB) {
if (variantA.package != variantB.package) {
return false;
}
if (variantA.pinDescriptorsByNumber.size() != variantB.pinDescriptorsByNumber.size()) {
return false;
}
if (variantA.pinDescriptorsByNumber != variantB.pinDescriptorsByNumber) {
return false;
}
return true;
}
);
};
for (const auto& targetVariant: this->targetDescriptor.variants) {
if (isDuplicateVariant(targetVariant)) {
continue;
}
auto variantAction = new QAction(this->variantMenu);
variantAction->setText(
QString::fromStdString(targetVariant.name + " (" + targetVariant.packageName + ")")
);
if (InsightWindow::isVariantSupported(targetVariant)) {
auto supportedVariantPtr = &(this->supportedVariantsByName.insert(
std::pair(QString::fromStdString(targetVariant.name).toLower(), targetVariant)
).first->second);
connect(
variantAction,
&QAction::triggered,
this,
[this, supportedVariantPtr] {
this->selectVariant(supportedVariantPtr);
}
);
} else {
variantAction->setEnabled(false);
variantAction->setText(variantAction->text() + " (unsupported)");
}
this->variantMenu->addAction(variantAction);
processedVariants.push_back(targetVariant);
}
this->variantMenu->setEnabled(true);
Logger::debug("Number of target variants supported by Insight: " + std::to_string(supportedVariantsByName.size()));
if (!this->supportedVariantsByName.empty()) {
if (previouslySelectedVariantName.has_value()
&& this->supportedVariantsByName.contains(previouslySelectedVariantName.value())
) {
this->selectVariant(&(this->supportedVariantsByName.at(previouslySelectedVariantName.value())));
} else if (this->targetConfig.variantName.has_value()) {
auto selectedVariantName = QString::fromStdString(this->targetConfig.variantName.value());
if (this->supportedVariantsByName.contains(selectedVariantName)) {
// The user has specified a valid variant name in their config file, so use that as the default
this->selectVariant(&(this->supportedVariantsByName.at(selectedVariantName)));
} else {
Logger::error("Invalid target variant name \"" + this->targetConfig.variantName.value()
+ "\" - no such variant with the given name was found.");
}
}
if (this->selectedVariant == nullptr) {
/*
* Given that we haven't been able to select a variant at this point, we will just fallback to the first
* one that is available.
*/
this->selectVariant(&(this->supportedVariantsByName.begin()->second));
}
} else {
if (this->targetDescriptor.variants.empty()) {
this->variantMenu->parentWidget()->hide();
}
this->ioUnavailableWidget->setText(
"GPIO inspection is not available for this target. "
"Please report this to Bloom developers by clicking Help -> Report An Issue"
);
this->ioUnavailableWidget->show();
}
auto leftPanelLayout = this->leftPanelLayoutContainer->findChild<QVBoxLayout*>("left-panel-layout");
this->targetRegistersSidePane = new TargetRegistersPaneWidget(
this->targetDescriptor,
insightWorker,
this->leftPanelLayoutContainer
);
leftPanelLayout->addWidget(this->targetRegistersSidePane);
this->targetRegistersButton->setChecked(false);
this->targetRegistersButton->setDisabled(false);
this->toggleUi(this->targetState != TargetState::STOPPED);
this->activated = true;
}
void InsightWindow::deactivate() {
if (this->targetPackageWidget != nullptr) {
this->targetPackageWidget->hide();
this->targetPackageWidget->deleteLater();
this->targetPackageWidget = nullptr;
}
if (this->targetRegistersSidePane != nullptr) {
this->targetRegistersSidePane->deactivate();
this->targetRegistersSidePane->deleteLater();
this->leftPanel->setVisible(false);
this->targetRegistersButton->setChecked(false);
this->targetRegistersButton->setDisabled(true);
}
this->ioUnavailableWidget->setText(
"Insight deactivated - Bloom has been disconnected from the target.\n\n"
"Bloom will attempt to reconnect upon the start of a new debug session."
);
this->ioUnavailableWidget->show();
this->targetStatusLabel->setText("Unknown");
this->programCounterValueLabel->setText("-");
this->variantMenu->clear();
this->variantMenu->setEnabled(false);
this->toggleUi(true);
this->activated = false;
}
bool InsightWindow::isVariantSupported(const TargetVariant& variant) {
@@ -383,41 +233,219 @@ void InsightWindow::selectVariant(const TargetVariant* variant) {
});
}
this->mainWindowWidget->setMinimumSize(
this->targetPackageWidget->width() + 500,
this->targetPackageWidget->height() + 150
this->setMinimumSize(
this->targetPackageWidget->width() + 700,
this->targetPackageWidget->height() + 450
);
this->ioContainerWidget->resize(this->ioContainerWidget->size());
Logger::error("ressss");
this->adjustSize();
this->targetPackageWidget->show();
}
}
void InsightWindow::show() {
this->mainWindowWidget->activateWindow();
this->mainWindowWidget->show();
}
void InsightWindow::activate() {
auto targetNameLabel = this->footer->findChild<QLabel*>("target-name");
auto targetIdLabel = this->footer->findChild<QLabel*>("target-id");
targetNameLabel->setText(QString::fromStdString(this->targetDescriptor.name));
targetIdLabel->setText("0x" + QString::fromStdString(this->targetDescriptor.id).remove("0x").toUpper());
this->variantMenu = this->footer->findChild<QMenu*>("target-variant-menu");
void InsightWindow::close() {
if (this->mainWindowWidget != nullptr) {
this->mainWindowWidget->close();
this->ioUnavailableWidget->hide();
std::optional<QString> previouslySelectedVariantName;
if (this->selectedVariant != nullptr) {
previouslySelectedVariantName = QString::fromStdString(this->selectedVariant->name).toLower();
this->selectedVariant = nullptr;
}
}
void InsightWindow::toggleUi(bool disable) {
this->uiDisabled = disable;
this->supportedVariantsByName.clear();
if (this->refreshIoInspectionButton != nullptr) {
this->refreshIoInspectionButton->setDisabled(disable);
this->refreshIoInspectionButton->repaint();
/*
* We don't want to present the user with duplicate target variants.
*
* In the context of Insight, a variant that doesn't differ in package type or pinout configuration is
* considered a duplicate.
*/
auto processedVariants = std::vector<TargetVariant>();
auto isDuplicateVariant = [&processedVariants](const TargetVariant& variantA) {
return std::ranges::any_of(
processedVariants.begin(),
processedVariants.end(),
[&variantA, &processedVariants](const TargetVariant& variantB) {
if (variantA.package != variantB.package) {
return false;
}
if (variantA.pinDescriptorsByNumber.size() != variantB.pinDescriptorsByNumber.size()) {
return false;
}
if (variantA.pinDescriptorsByNumber != variantB.pinDescriptorsByNumber) {
return false;
}
return true;
}
);
};
for (const auto& targetVariant: this->targetDescriptor.variants) {
if (isDuplicateVariant(targetVariant)) {
continue;
}
auto variantAction = new QAction(this->variantMenu);
variantAction->setText(
QString::fromStdString(targetVariant.name + " (" + targetVariant.packageName + ")")
);
if (InsightWindow::isVariantSupported(targetVariant)) {
auto supportedVariantPtr = &(this->supportedVariantsByName.insert(
std::pair(QString::fromStdString(targetVariant.name).toLower(), targetVariant)
).first->second);
connect(
variantAction,
&QAction::triggered,
this,
[this, supportedVariantPtr] {
this->selectVariant(supportedVariantPtr);
}
);
} else {
variantAction->setEnabled(false);
variantAction->setText(variantAction->text() + " (unsupported)");
}
this->variantMenu->addAction(variantAction);
processedVariants.push_back(targetVariant);
}
this->variantMenu->setEnabled(true);
Logger::debug("Number of target variants supported by Insight: "
+ std::to_string(supportedVariantsByName.size()));
if (!this->supportedVariantsByName.empty()) {
if (previouslySelectedVariantName.has_value()
&& this->supportedVariantsByName.contains(previouslySelectedVariantName.value())
) {
this->selectVariant(&(this->supportedVariantsByName.at(previouslySelectedVariantName.value())));
} else if (this->targetConfig.variantName.has_value()) {
auto selectedVariantName = QString::fromStdString(this->targetConfig.variantName.value());
if (this->supportedVariantsByName.contains(selectedVariantName)) {
// The user has specified a valid variant name in their config file, so use that as the default
this->selectVariant(&(this->supportedVariantsByName.at(selectedVariantName)));
} else {
Logger::error("Invalid target variant name \"" + this->targetConfig.variantName.value()
+ "\" - no such variant with the given name was found.");
}
}
if (this->selectedVariant == nullptr) {
/*
* Given that we haven't been able to select a variant at this point, we will just fallback to the first
* one that is available.
*/
this->selectVariant(&(this->supportedVariantsByName.begin()->second));
}
} else {
if (this->targetDescriptor.variants.empty()) {
this->variantMenu->parentWidget()->hide();
}
this->ioUnavailableWidget->setText(
"GPIO inspection is not available for this target. "
"Please report this to Bloom developers by clicking Help -> Report An Issue"
);
this->ioUnavailableWidget->show();
}
auto leftPanelLayout = this->leftPanel->layout();
this->targetRegistersSidePane = new TargetRegistersPaneWidget(
this->targetDescriptor,
insightWorker,
this->leftPanel
);
leftPanelLayout->addWidget(this->targetRegistersSidePane);
this->targetRegistersButton->setChecked(false);
this->targetRegistersButton->setDisabled(false);
this->toggleUi(this->targetState != TargetState::STOPPED);
this->activated = true;
}
void InsightWindow::onLeftPanelHandleSlide(int horizontalPosition) {
auto width = std::max(this->leftPanelMinWidth, this->leftPanel->width() + horizontalPosition);
this->leftPanel->setMaximumWidth(width);
this->leftPanel->setFixedWidth(width);
void InsightWindow::deactivate() {
if (this->targetPackageWidget != nullptr) {
this->targetPackageWidget->hide();
this->targetPackageWidget->deleteLater();
this->targetPackageWidget = nullptr;
}
if (this->targetRegistersSidePane != nullptr) {
this->targetRegistersSidePane->deactivate();
this->targetRegistersSidePane->deleteLater();
this->leftPanel->setVisible(false);
this->targetRegistersButton->setChecked(false);
this->targetRegistersButton->setDisabled(true);
}
this->ioUnavailableWidget->setText(
"Insight deactivated - Bloom has been disconnected from the target.\n\n"
"Bloom will attempt to reconnect upon the start of a new debug session."
);
this->ioUnavailableWidget->show();
this->targetStatusLabel->setText("Unknown");
this->programCounterValueLabel->setText("-");
this->variantMenu->clear();
this->variantMenu->setEnabled(false);
this->toggleUi(true);
this->activated = false;
}
void InsightWindow::adjustPanels() {
const auto targetPackageWidgetSize = (this->targetPackageWidget != nullptr)
? this->targetPackageWidget->size() : QSize();
const auto containerSize = this->container->size();
/*
* The purpose of the -20 is to ensure there is some padding between the panel borders and the
* target package widget. Looks nicer with the padding.
*/
this->leftPanel->setMaximumResize(
std::max(
this->leftPanel->getMinimumResize(),
containerSize.width() - targetPackageWidgetSize.width() - this->leftMenuBar->width() - 20
)
);
this->bottomPanel->setMaximumResize(
std::max(
this->bottomPanel->getMinimumResize(),
containerSize.height() - targetPackageWidgetSize.height() - this->bottomMenuBar->height() - 20
)
);
}
void InsightWindow::resizeEvent(QResizeEvent* event) {
const auto windowSize = this->size();
this->windowContainer->setFixedSize(windowSize);
this->layoutContainer->setFixedSize(windowSize);
this->adjustPanels();
}
void InsightWindow::showEvent(QShowEvent* event) {
this->adjustPanels();
}
void InsightWindow::onTargetControllerSuspended() {
@@ -464,7 +492,7 @@ void InsightWindow::openGettingStartedUrl() {
void InsightWindow::openAboutWindow() {
if (this->aboutWindowWidget == nullptr) {
this->aboutWindowWidget = new AboutWindow(this->mainWindowWidget);
this->aboutWindowWidget = new AboutWindow(this->windowContainer);
}
this->aboutWindowWidget->show();