From cbced5a6b21546b9ee2f83cd01746d3ca32760e8 Mon Sep 17 00:00:00 2001 From: Julien Marrec Date: Tue, 26 Mar 2024 14:18:25 +0100 Subject: [PATCH 1/5] Fix #672 - Add description, modelerDescription, UID and version UID to bcl results --- src/shared_gui_components/Component.cpp | 292 ++++++++++++++---------- src/shared_gui_components/Component.hpp | 2 + 2 files changed, 171 insertions(+), 123 deletions(-) diff --git a/src/shared_gui_components/Component.cpp b/src/shared_gui_components/Component.cpp index dc4318372..2fd83078b 100644 --- a/src/shared_gui_components/Component.cpp +++ b/src/shared_gui_components/Component.cpp @@ -39,6 +39,7 @@ #include #include #include +#include #include @@ -212,6 +213,8 @@ Component::Component(const Component& other) { m_uid = other.m_uid; m_versionId = other.m_versionId; m_description = other.m_description; + m_modelerDescription = other.m_modelerDescription; + m_versionModified = other.m_versionModified; m_fidelityLevel = other.m_fidelityLevel; m_error = other.m_error; m_attributes = other.m_attributes; @@ -245,6 +248,8 @@ Component& Component::operator=(const Component& other) { m_uid = other.m_uid; m_versionId = other.m_versionId; m_description = other.m_description; + m_modelerDescription = other.m_modelerDescription; + m_versionModified = other.m_versionModified; m_fidelityLevel = other.m_fidelityLevel; m_error = other.m_error; m_attributes = other.m_attributes; @@ -330,6 +335,13 @@ void Component::parseBCLMeasure(const BCLMeasure& bclMeasure) { m_uid = bclMeasure.uid().c_str(); m_versionId = bclMeasure.versionId().c_str(); m_description = bclMeasure.description().c_str(); + m_description = m_description.trimmed(); + m_modelerDescription = bclMeasure.modelerDescription().c_str(); + m_modelerDescription = m_modelerDescription.trimmed(); // alternative: .simplified, removes consecutive whitespaces inside the string as well + + if (auto dt_ = bclMeasure.versionModified()) { + m_versionModified = dt_->toXsdDateTime().c_str(); + } m_error = bclMeasure.error(); m_attributes = bclMeasure.attributes(); @@ -365,8 +377,13 @@ void Component::parseBCLSearchResult(const BCLSearchResult& bclSearchResult) { m_uid = bclSearchResult.uid().c_str(); m_versionId = bclSearchResult.versionId().c_str(); m_description = bclSearchResult.description().c_str(); + m_description = m_description.trimmed(); + m_modelerDescription = bclSearchResult.modelerDescription().c_str(); + m_modelerDescription = m_modelerDescription.trimmed(); m_fidelityLevel = bclSearchResult.fidelityLevel().c_str(); + // TODO: BCLSearchResult is missing version modified, cf https://github.com/NREL/OpenStudio/issues/5125 + // m_error m_attributes = bclSearchResult.attributes(); // TODO: arguments @@ -464,149 +481,162 @@ void Component::createAbridgedLayout() { } void Component::createCompleteLayout() { - QLabel* label = nullptr; - - QString string; auto* mainLayout = new QVBoxLayout(); - QTableWidget* tableWidget = nullptr; - ///! Error if (m_error) { - label = new QLabel("Errors"); + auto* label = new QLabel("Errors"); label->setObjectName("H1"); mainLayout->addWidget(label); label = new QLabel(m_error->c_str()); mainLayout->addWidget(label); + // TODO: why this empty label? label = new QLabel(); mainLayout->addWidget(label); } - ///! Attributes - ///! Class BCL only stores double (optional units), - ///! int (optional units), and string, with their names. - //if (!m_attributes.empty()){ - label = new QLabel("Attributes"); - label->setObjectName("H1"); - mainLayout->addWidget(label); - - tableWidget = new QTableWidget(0, 2, this); - // really don't want the user to select or give focus to any table cells - tableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers); - tableWidget->setSelectionMode(QAbstractItemView::NoSelection); - tableWidget->setAlternatingRowColors(true); - tableWidget->verticalHeader()->hide(); - tableWidget->horizontalHeader()->hide(); - tableWidget->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - tableWidget->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - tableWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); - tableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents); - tableWidget->horizontalHeader()->setStretchLastSection(true); - - mainLayout->addWidget(tableWidget); + // Description + if (!m_description.isEmpty()) { + { + auto* label = new QLabel("Description"); + label->setObjectName("H1"); + mainLayout->addWidget(label); + } + { + auto* content = new QLabel(m_description); + mainLayout->addWidget(content); + content->setWordWrap(true); + } + } - for (const Attribute& attribute : m_attributes) { + if (!m_modelerDescription.isEmpty()) { + { + auto* label = new QLabel("Modeler Description"); + label->setObjectName("H1"); + mainLayout->addWidget(label); + } + { + auto* content = new QLabel(m_modelerDescription); + mainLayout->addWidget(content); + content->setWordWrap(true); + } + } + + // Lambda Helpers for tables + + auto createAndRegisterTableWidgetWithTwoColums = [this, &mainLayout]() -> QTableWidget* { + auto* tableWidget = new QTableWidget(0, 2, this); + // really don't want the user to select or give focus to any table cells + tableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers); + tableWidget->setSelectionMode(QAbstractItemView::NoSelection); + tableWidget->setAlternatingRowColors(true); + tableWidget->verticalHeader()->hide(); + tableWidget->horizontalHeader()->hide(); + tableWidget->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + tableWidget->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + tableWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); + tableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents); + tableWidget->horizontalHeader()->setStretchLastSection(true); + mainLayout->addWidget(tableWidget); + return tableWidget; + }; + + auto addRowToTableWiget = [](QTableWidget* tableWidget, const QString& header, const QString& value) { tableWidget->insertRow(tableWidget->rowCount()); - auto* item = new QTableWidgetItem(attribute.name().c_str()); + auto* item = new QTableWidgetItem(header); tableWidget->setItem(tableWidget->rowCount() - 1, 0, item); - boost::optional optionalUnits = attribute.units(); + item = new QTableWidgetItem(value); + tableWidget->setItem(tableWidget->rowCount() - 1, 1, item); + }; + + auto makeTableShowCompletely = [](QTableWidget* tableWidget) { + // make the table show completely + const int rowHeight = tableWidget->rowHeight(0); + const int rowCount = tableWidget->rowCount(); + const int tableHeight = rowHeight * rowCount; + tableWidget->setFixedHeight(tableHeight); + }; - openstudio::AttributeValueType type = attribute.valueType(); + //if (!m_attributes.empty()){ + { + ///! Attributes + ///! Class BCL only stores double (optional units), + ///! int (optional units), and string, with their names. + auto* label = new QLabel("Attributes"); + label->setObjectName("H1"); + mainLayout->addWidget(label); - if (type == AttributeValueType::Boolean) { - bool success = attribute.valueAsBoolean(); - if (success) { - string = "true"; + auto* tableWidget = createAndRegisterTableWidgetWithTwoColums(); + for (const Attribute& attribute : m_attributes) { + + boost::optional optionalUnits = attribute.units(); + + const openstudio::AttributeValueType type = attribute.valueType(); + + QString display; + if (type == AttributeValueType::Boolean) { + display = attribute.valueAsBoolean() ? "true" : "false"; + } else if (type == AttributeValueType::Double) { + display.setNum(attribute.valueAsDouble()); + } else if (type == AttributeValueType::Integer) { + display.setNum(attribute.valueAsInteger()); + } else if (type == AttributeValueType::Unsigned) { + display.setNum(attribute.valueAsUnsigned()); + } else if (type == AttributeValueType::String) { + display = attribute.valueAsString().c_str(); + } else if (type == AttributeValueType::AttributeVector) { + AttributeVector attributeVector = attribute.valueAsAttributeVector(); + // TODO handle this case } else { - string = "false"; + // should never get here } - } else if (type == AttributeValueType::Double) { - string = string.setNum(attribute.valueAsDouble()); - } else if (type == AttributeValueType::Integer) { - string = string.setNum(attribute.valueAsInteger()); - } else if (type == AttributeValueType::Unsigned) { - string = string.setNum(attribute.valueAsUnsigned()); - } else if (type == AttributeValueType::String) { - string = attribute.valueAsString().c_str(); - } else if (type == AttributeValueType::AttributeVector) { - AttributeVector attributeVector = attribute.valueAsAttributeVector(); - // TODO handle this case - } else { - // should never get here - } - if (optionalUnits) { - string += " "; - std::string temp = optionalUnits.get(); - string += temp.c_str(); + if (optionalUnits) { + display += " "; + const std::string temp = optionalUnits.get(); + display += temp.c_str(); + } + + addRowToTableWiget(tableWidget, attribute.name().c_str(), display); } - item = new QTableWidgetItem(string); - tableWidget->setItem(tableWidget->rowCount() - 1, 1, item); - } - // make the table show completely - int rowHeight = tableWidget->rowHeight(0); - int rowCount = tableWidget->rowCount(); - int tableHeight = rowHeight * rowCount; - tableWidget->setFixedHeight(tableHeight); + makeTableShowCompletely(tableWidget); - label = new QLabel(); - mainLayout->addWidget(label); - //} + label = new QLabel(); + mainLayout->addWidget(label); + } /////! Arguments if (m_componentType != "component") { //if (!m_arguments.empty()){ - label = new QLabel("Arguments"); + auto* label = new QLabel("Arguments"); label->setObjectName("H1"); mainLayout->addWidget(label); - tableWidget = new QTableWidget(0, 2, this); - // really don't want the user to select or give focus to any table cells - tableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers); - tableWidget->setSelectionMode(QAbstractItemView::NoSelection); - tableWidget->setAlternatingRowColors(true); - tableWidget->verticalHeader()->hide(); - tableWidget->horizontalHeader()->hide(); - tableWidget->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - tableWidget->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - tableWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); - tableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents); - tableWidget->horizontalHeader()->setStretchLastSection(true); - - mainLayout->addWidget(tableWidget); + auto* tableWidget = createAndRegisterTableWidgetWithTwoColums(); for (const BCLMeasureArgument& argument : m_arguments) { - tableWidget->insertRow(tableWidget->rowCount()); std::string name = argument.displayName(); if (name.empty()) { name = argument.name(); } - auto* item = new QTableWidgetItem(name.c_str()); - tableWidget->setItem(tableWidget->rowCount() - 1, 0, item); - std::string type = argument.type(); boost::optional units = argument.units(); if (units) { type += " (" + units.get() + ")"; } - item = new QTableWidgetItem(type.c_str()); - tableWidget->setItem(tableWidget->rowCount() - 1, 1, item); + addRowToTableWiget(tableWidget, name.c_str(), type.c_str()); } - // make the table show completely - rowHeight = tableWidget->rowHeight(0); - rowCount = tableWidget->rowCount(); - tableHeight = rowHeight * rowCount; - tableWidget->setFixedHeight(tableHeight); + makeTableShowCompletely(tableWidget); label = new QLabel(); mainLayout->addWidget(label); @@ -614,7 +644,7 @@ void Component::createCompleteLayout() { /////! Files if (!m_files.empty()) { - label = new QLabel("Files"); + auto* label = new QLabel("Files"); label->setObjectName("H1"); mainLayout->addWidget(label); for (const BCLFile& file : m_files) { @@ -650,48 +680,64 @@ void Component::createCompleteLayout() { ///! Provenances //if (!m_provenances.empty()){ - label = new QLabel("Sources"); - label->setObjectName("H1"); - mainLayout->addWidget(label); - for (const BCLProvenance& provenance : m_provenances) { - string = "Author: "; - string += provenance.author().c_str(); - label = new QLabel(string); + { + auto* label = new QLabel("Sources"); + label->setObjectName("H1"); mainLayout->addWidget(label); + for (const BCLProvenance& provenance : m_provenances) { + QString display = "Author: "; + display += provenance.author().c_str(); + label = new QLabel(display); + mainLayout->addWidget(label); - string = "Comment: "; - string += provenance.comment().c_str(); - label = new QLabel(string); - mainLayout->addWidget(label); + display = "Comment: "; + display += provenance.comment().c_str(); + label = new QLabel(display); + mainLayout->addWidget(label); - string = "Date & time: "; - string += provenance.datetime().c_str(); - label = new QLabel(string); - mainLayout->addWidget(label); + display = "Date & time: "; + display += provenance.datetime().c_str(); + label = new QLabel(display); + mainLayout->addWidget(label); - label = new QLabel(); - mainLayout->addWidget(label); - } + label = new QLabel(); + mainLayout->addWidget(label); + } - if (m_provenances.empty()) { - label = new QLabel(); - mainLayout->addWidget(label); + if (m_provenances.empty()) { + label = new QLabel(); + mainLayout->addWidget(label); + } } - //} ///! Tags - //if (!m_tags.empty()){ - label = new QLabel("Tags"); - label->setObjectName("H1"); - mainLayout->addWidget(label); - for (const std::string& tag : m_tags) { - label = new QLabel(tag.c_str()); + //if (!m_tags.empty()) + { + auto* label = new QLabel("Tags"); + label->setObjectName("H1"); mainLayout->addWidget(label); + for (const std::string& tag : m_tags) { + label = new QLabel(tag.c_str()); + mainLayout->addWidget(label); - label = new QLabel(); + label = new QLabel(); + mainLayout->addWidget(label); + } + } + + { + auto* label = new QLabel("Version"); + label->setObjectName("H1"); mainLayout->addWidget(label); + + auto* tableWidget = createAndRegisterTableWidgetWithTwoColums(); + addRowToTableWiget(tableWidget, "UID", m_uid); + addRowToTableWiget(tableWidget, "Version ID", m_versionId); + if (!m_versionModified.isEmpty()) { + addRowToTableWiget(tableWidget, "Version Modified", m_versionModified); + } + makeTableShowCompletely(tableWidget); } - //} setLayout(mainLayout); } diff --git a/src/shared_gui_components/Component.hpp b/src/shared_gui_components/Component.hpp index e754ee329..7d6609cac 100644 --- a/src/shared_gui_components/Component.hpp +++ b/src/shared_gui_components/Component.hpp @@ -78,6 +78,8 @@ class Component : public QAbstractButton QString m_uid; QString m_versionId; QString m_description; + QString m_modelerDescription; + QString m_versionModified; QString m_fidelityLevel; boost::optional m_error; std::vector m_attributes; From ad32358e2f07c614d42721acb67639e69cd40e2a Mon Sep 17 00:00:00 2001 From: Julien Marrec Date: Tue, 26 Mar 2024 15:30:33 +0100 Subject: [PATCH 2/5] spelling mistake --- src/shared_gui_components/Component.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/shared_gui_components/Component.cpp b/src/shared_gui_components/Component.cpp index 2fd83078b..d64690297 100644 --- a/src/shared_gui_components/Component.cpp +++ b/src/shared_gui_components/Component.cpp @@ -544,7 +544,7 @@ void Component::createCompleteLayout() { return tableWidget; }; - auto addRowToTableWiget = [](QTableWidget* tableWidget, const QString& header, const QString& value) { + auto addRowToTableWidget = [](QTableWidget* tableWidget, const QString& header, const QString& value) { tableWidget->insertRow(tableWidget->rowCount()); auto* item = new QTableWidgetItem(header); @@ -601,7 +601,7 @@ void Component::createCompleteLayout() { display += temp.c_str(); } - addRowToTableWiget(tableWidget, attribute.name().c_str(), display); + addRowToTableWidget(tableWidget, attribute.name().c_str(), display); } makeTableShowCompletely(tableWidget); @@ -633,7 +633,7 @@ void Component::createCompleteLayout() { type += " (" + units.get() + ")"; } - addRowToTableWiget(tableWidget, name.c_str(), type.c_str()); + addRowToTableWidget(tableWidget, name.c_str(), type.c_str()); } makeTableShowCompletely(tableWidget); @@ -731,10 +731,10 @@ void Component::createCompleteLayout() { mainLayout->addWidget(label); auto* tableWidget = createAndRegisterTableWidgetWithTwoColums(); - addRowToTableWiget(tableWidget, "UID", m_uid); - addRowToTableWiget(tableWidget, "Version ID", m_versionId); + addRowToTableWidget(tableWidget, "UID", m_uid); + addRowToTableWidget(tableWidget, "Version ID", m_versionId); if (!m_versionModified.isEmpty()) { - addRowToTableWiget(tableWidget, "Version Modified", m_versionModified); + addRowToTableWidget(tableWidget, "Version Modified", m_versionModified); } makeTableShowCompletely(tableWidget); } From 986a5a48724c248d6df1a9ba1618e229cddb37a5 Mon Sep 17 00:00:00 2001 From: Julien Marrec Date: Tue, 26 Mar 2024 15:31:51 +0100 Subject: [PATCH 3/5] Allow clicking links in measure description/modeler description Similar to #639 that fixed #638 --- src/shared_gui_components/Component.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/shared_gui_components/Component.cpp b/src/shared_gui_components/Component.cpp index d64690297..efce31a65 100644 --- a/src/shared_gui_components/Component.cpp +++ b/src/shared_gui_components/Component.cpp @@ -507,8 +507,9 @@ void Component::createCompleteLayout() { } { auto* content = new QLabel(m_description); - mainLayout->addWidget(content); content->setWordWrap(true); + content->setOpenExternalLinks(true); + mainLayout->addWidget(content); } } @@ -520,8 +521,9 @@ void Component::createCompleteLayout() { } { auto* content = new QLabel(m_modelerDescription); - mainLayout->addWidget(content); content->setWordWrap(true); + content->setOpenExternalLinks(true); + mainLayout->addWidget(content); } } From cc43ab37565d093bd89fbc9b4b1177aacef7e915 Mon Sep 17 00:00:00 2001 From: Julien Marrec Date: Tue, 26 Mar 2024 15:50:31 +0100 Subject: [PATCH 4/5] Replace provenances with a table --- src/shared_gui_components/Component.cpp | 36 +++++++++++-------------- 1 file changed, 16 insertions(+), 20 deletions(-) diff --git a/src/shared_gui_components/Component.cpp b/src/shared_gui_components/Component.cpp index efce31a65..b44c6c3b9 100644 --- a/src/shared_gui_components/Component.cpp +++ b/src/shared_gui_components/Component.cpp @@ -686,29 +686,25 @@ void Component::createCompleteLayout() { auto* label = new QLabel("Sources"); label->setObjectName("H1"); mainLayout->addWidget(label); - for (const BCLProvenance& provenance : m_provenances) { - QString display = "Author: "; - display += provenance.author().c_str(); - label = new QLabel(display); - mainLayout->addWidget(label); - - display = "Comment: "; - display += provenance.comment().c_str(); - label = new QLabel(display); - mainLayout->addWidget(label); - - display = "Date & time: "; - display += provenance.datetime().c_str(); - label = new QLabel(display); - mainLayout->addWidget(label); - - label = new QLabel(); - mainLayout->addWidget(label); - } - if (m_provenances.empty()) { label = new QLabel(); mainLayout->addWidget(label); + } else { + auto* tableWidget = createAndRegisterTableWidgetWithTwoColums(); + for (const BCLProvenance& provenance : m_provenances) { + if (!provenance.author().empty()) { + addRowToTableWidget(tableWidget, "Author", provenance.author().c_str()); + } + if (!provenance.comment().empty()) { + addRowToTableWidget(tableWidget, "Comment", provenance.comment().c_str()); + } + if (!provenance.datetime().empty()) { + addRowToTableWidget(tableWidget, "Date & time", provenance.datetime().c_str()); + } + // TODO: add a separator? + // addRowToTableWidget(tableWidget, "", ""); + } + makeTableShowCompletely(tableWidget); } } From 44a4061fa8565113e985f97cfb7d020996d86291 Mon Sep 17 00:00:00 2001 From: Julien Marrec Date: Tue, 26 Mar 2024 16:22:52 +0100 Subject: [PATCH 5/5] Copy ctor and operator= are not copying some attributes? --- src/shared_gui_components/Component.cpp | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/shared_gui_components/Component.cpp b/src/shared_gui_components/Component.cpp index b44c6c3b9..3b36ef2e3 100644 --- a/src/shared_gui_components/Component.cpp +++ b/src/shared_gui_components/Component.cpp @@ -209,6 +209,7 @@ Component::Component(bool showAbridgedView, bool showCheckBox, QWidget* parent) Component::Component(const Component& other) { ///! no self-assignment if (this != &other) { + m_componentType = other.m_componentType; m_name = other.m_name; m_uid = other.m_uid; m_versionId = other.m_versionId; @@ -223,10 +224,8 @@ Component::Component(const Component& other) { m_fileReferences = other.m_fileReferences; m_provenances = other.m_provenances; m_tags = other.m_tags; - - // TODO: why were we assigning to other.xxx then overriding with false? - // m_showAbridgedView = other.m_showAbridgedView; - // m_showCheckBox = other.m_showCheckBox; + m_available = other.m_available; + m_updateAvailable = other.m_updateAvailable; m_showAbridgedView = false; m_showCheckBox = false; @@ -244,6 +243,7 @@ Component::Component(const Component& other) { Component& Component::operator=(const Component& other) { ///! no self-assignment if (this != &other) { + m_componentType = other.m_componentType; m_name = other.m_name; m_uid = other.m_uid; m_versionId = other.m_versionId; @@ -258,10 +258,8 @@ Component& Component::operator=(const Component& other) { m_fileReferences = other.m_fileReferences; m_provenances = other.m_provenances; m_tags = other.m_tags; - - // TODO: why were we assigning to other.xxx then overriding with false? - // m_showAbridgedView = other.m_showAbridgedView; - // m_showCheckBox = other.m_showCheckBox; + m_available = other.m_available; + m_updateAvailable = other.m_updateAvailable; m_showAbridgedView = false; m_showCheckBox = false;