diff --git a/LicenseManager/keyGen/keygenWidget.cc b/LicenseManager/keyGen/keygenWidget.cc index 1b945b8aab83af4ec6643f3d9e8406b96ebb4ec1..980578535e7246afc36c0f98a1b205b1c8d8fede 100644 --- a/LicenseManager/keyGen/keygenWidget.cc +++ b/LicenseManager/keyGen/keygenWidget.cc @@ -45,6 +45,7 @@ #include <QtWidgets> #include <QMessageBox> +#include <QRegularExpression> #include "keygenWidget.hh" #include <iostream> @@ -137,10 +138,11 @@ QString KeyGen::Generate(QString expiryDate) const } QString KeyGen::filterString(QString in) { - const QRegExp validChar("[a-f0-9]"); - QString out; out.reserve(in.size()); + const QRegularExpression validChar("[a-f0-9]"); + QString out; + out.reserve(in.size()); for (QString::iterator it = in.begin(), it_end = in.end(); it != it_end; ++it) { - if (validChar.exactMatch(*it)) + if (validChar.match(*it).hasMatch()) out.append(*it); } return out; @@ -148,36 +150,38 @@ QString KeyGen::filterString(QString in) { std::vector<KeyGen> KeyGen::CreateFromMessyString(QString info) { - const QString dirt = "[\\s;>]*"; - const QRegExp rx("\\b([\\w-]+)" + dirt + "((?:(?:[a-f0-9]" + dirt + "){40}){6,})\\b"); - const QRegExp partRe("((?:[a-f0-9]" + dirt + "){40})"); + const QString dirt = "[\\s;>]*"; + const QRegularExpression rx("\\b([\\w-]+)" + dirt + "((?:(?:[a-f0-9]" + dirt + "){40}){6,})\\b"); + const QRegularExpression partRe("((?:[a-f0-9]" + dirt + "){40})"); std::vector<KeyGen> R; - int pos = 0; - while ((pos = rx.indexIn(info, pos)) != -1) { - QString hashesStr = rx.cap(2); + QRegularExpressionMatch rxMatch; + int pos = 0; + while ((pos = info.indexOf(rx, pos, &rxMatch)) != -1) { + QString hashesStr = rxMatch.captured(2); QStringList hashes; + QRegularExpressionMatch partReMatch; int hashPos = 0; - while ((hashPos = partRe.indexIn(hashesStr, hashPos)) != -1) { - hashes.append(filterString(partRe.cap(1))); - hashPos += partRe.matchedLength(); - } - - QStringList macList; - std::copy(hashes.begin() + 4, hashes.end() - 1, std::back_inserter(macList)); - - KeyGen K(rx.cap(1), - hashes[0], - hashes[1], - hashes[2], - hashes[3], - macList, - hashes[hashes.count()-1]); - R.push_back(K); - pos += rx.matchedLength(); - } + while ((hashPos = hashesStr.indexOf(partRe, hashPos, &partReMatch)) != -1) { + hashes.append(filterString(partReMatch.captured(1))); + hashPos += partReMatch.capturedLength(1); + } + + QStringList macList; + std::copy(hashes.begin() + 4, hashes.end() - 1, std::back_inserter(macList)); + + KeyGen K(rxMatch.captured(1), + hashes[0], + hashes[1], + hashes[2], + hashes[3], + macList, + hashes[hashes.count() - 1]); + R.push_back(K); + pos += rxMatch.capturedLength(0); + } - return R; + return R; } KeyGenWidget::KeyGenWidget(QMainWindow *parent) @@ -253,20 +257,19 @@ void KeyGenWidget::slotAnalyze() { keygens_ = KeyGen::CreateFromMessyString(inputData); keyList->clear(); - for (std::vector<KeyGen>::const_iterator it = keygens_.begin(), it_end = keygens_.end(); - it != it_end; ++it) { + for (const auto& keygen : keygens_) { QListWidgetItem *newItem = new QListWidgetItem( keyList); - newItem->setText(it->name); + newItem->setText(keygen.name); newItem->setHidden(false); - KeyGen::ValidationResult r = it->isValid(); + KeyGen::ValidationResult r = keygen.isValid(); if (!r) - newItem->setTextColor(QColor(255, 0, 0)); + newItem->setForeground(QColor(255, 0, 0)); else if (r == KeyGen::LATIN1) - newItem->setTextColor(QColor(128, 128, 0)); + newItem->setForeground(QColor(128, 128, 0)); } generateLocalButton->setVisible(false); - generateAllButton->setVisible(keygens_.size()); + generateAllButton->setVisible(!keygens_.empty()); } void KeyGenWidget::slotSplit() { @@ -274,7 +277,7 @@ void KeyGenWidget::slotSplit() { QString inputData = requestData->toPlainText(); // Split with ; - QStringList data = inputData.split(";",QString::SkipEmptyParts); + QStringList data = inputData.split(";",Qt::SkipEmptyParts); QString newText = data.join("\n"); diff --git a/PythonInterpreter/PythonInterpreter.cc b/PythonInterpreter/PythonInterpreter.cc index 2c6053d3d595adc090a6c8975125bcee88751f22..492c57acf07bb0e80b8a5e1ad9b80680f4a14395 100644 --- a/PythonInterpreter/PythonInterpreter.cc +++ b/PythonInterpreter/PythonInterpreter.cc @@ -166,8 +166,15 @@ void PythonInterpreter::initPython() { std::cerr << "Importing OpenFlipper core module ..."; #endif - py::module of_module(py::module::import("openflipper")); - main_namespace["openflipper"] = of_module; + try{ + py::module of_module(py::module::import("openflipper")); + main_namespace["openflipper"] = of_module; + } + catch (py::error_already_set &e) + { + pyError(e.what()); + return; + } #ifdef PYTHON_DEBUG std::cerr << " Done" << std::endl; @@ -185,8 +192,16 @@ void PythonInterpreter::initPython() { std::cerr << "Importing "+ pythonPlugins[i].toStdString() + " module ..."; #endif - py::module om_module(py::module::import(pythonPlugins[i].toStdString().c_str())); - main_namespace[pythonPlugins[i].toStdString().c_str()] = om_module; + //try catching an error here for debugging purposes + try{ + py::module om_module(py::module::import(pythonPlugins[i].toStdString().c_str())); + main_namespace[pythonPlugins[i].toStdString().c_str()] = om_module; + } + catch (py::error_already_set &e) + { + pyError(e.what()); + return; + } #ifdef PYTHON_DEBUG std::cerr << " Done" << std::endl; diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt index 2897728c4d77dc974c5ec02c185003ba3c0123ab..6dbab6e8d7adebb380127a079e99729c1b8b78b0 100644 --- a/cmake/CMakeLists.txt +++ b/cmake/CMakeLists.txt @@ -95,14 +95,15 @@ if (NOT DISABLE_OPENFLIPPER_PYTHON_SYSTEM) endif() if (NOT DISABLE_OPENFLIPPER_PYTHON_SYSTEM) - find_package(Python3 COMPONENTS Interpreter Development) - + if (NOT Python3_FOUND) + find_package(Python3 3.11 COMPONENTS Interpreter Development) + endif() if (NOT TARGET pybind11::module OR NOT TARGET pybind11::embed) include(FetchContent) FetchContent_Declare( pybind11 GIT_REPOSITORY https://github.com/pybind/pybind11 - GIT_TAG v2.10.4 + GIT_TAG v2.13.6 ) set(FETCHCONTENT_FULLY_DISCONNECTED OFF) FetchContent_MakeAvailable(pybind11) diff --git a/cmake/fixbundle.cmake.in b/cmake/fixbundle.cmake.in index 73698d927af4093b8416762dfa925fd8bcded8b1..cb4da4d149af606944ea8e2e48f2ddc67ffb8e81 100644 --- a/cmake/fixbundle.cmake.in +++ b/cmake/fixbundle.cmake.in @@ -58,3 +58,9 @@ fixup_bundle (@CMAKE_BINARY_DIR@/Build/@OPENFLIPPER_PRODUCT_STRING@.app "${_plug # create qt plugin configuration file file(WRITE "@CMAKE_BINARY_DIR@/Build/@OPENFLIPPER_PRODUCT_STRING@.app/Contents/Resources/qt.conf" "[Paths]\nPlugins = Resources/QtPlugins") +# Sign all Libraries (needed for Code Signing) +execute_process(COMMAND find "@CMAKE_BINARY_DIR@/Build/@OPENFLIPPER_PRODUCT_STRING@.app/Contents/Resources/QtPlugins/" -type f -name "*.dylib" -exec codesign --force --sign - --timestamp=none {} \;) +execute_process(COMMAND find "@CMAKE_BINARY_DIR@/Build/@OPENFLIPPER_PRODUCT_STRING@.app/Contents/Libraries/" -type f -name "*.dylib" -exec codesign --force --sign - --timestamp=none {} \;) + +# Sign all Frameworks (Also needed for Code Signing) +execute_process(COMMAND find "@CMAKE_BINARY_DIR@/Build/@OPENFLIPPER_PRODUCT_STRING@.app/Contents/Frameworks/" -type d -name "*.framework" -exec codesign --force --sign - --timestamp=none {} \;) diff --git a/libs_required/ACG/CMakeLists.txt b/libs_required/ACG/CMakeLists.txt index df8c5814c0a073e99d8bcc749bd384d600e49d80..4b16dbb4034e75015e1190f5b218bb8bca8884f7 100644 --- a/libs_required/ACG/CMakeLists.txt +++ b/libs_required/ACG/CMakeLists.txt @@ -93,6 +93,7 @@ set ( headers Math/QuaternionT.hh Math/VectorT.hh QtWidgets/QtApplication.hh + QtWidgets/QtChartHistogram.hh QtWidgets/QtClippingDialog.hh QtWidgets/QtColorChooserButton.hh QtWidgets/QtColorTranslator.hh @@ -209,6 +210,7 @@ set (sources GL/stipple_alpha.cc Math/BSplineBasis.cc QtWidgets/QtApplication.cc + QtWidgets/QtChartHistogram.cc QtWidgets/QtClippingDialog.cc QtWidgets/QtColorChooserButton.cc QtWidgets/QtColorTranslator.cc @@ -364,7 +366,7 @@ target_link_libraries ( ACG ${OPENMESH_LIBRARIES} ${GLEW_TARGET} ) if (QT6_FOUND) - target_link_libraries( ACG ${QT_TARGET}::OpenGLWidgets ) + target_link_libraries( ACG ${QT_TARGET}::OpenGLWidgets ${QT_TARGET}::Charts) endif() @@ -377,7 +379,7 @@ include(FetchContent) FetchContent_Declare( googletest GIT_REPOSITORY https://github.com/google/googletest.git - GIT_TAG f8d7d77c06936315286eb55f8de22cd23c188571 # v1.14.0 + GIT_TAG b514bdc898e2951020cbdca1304b75f5950d1f59 # v1.15.2 ) if(WIN32) # avoid linking errors, cf https://stackoverflow.com/questions/12540970/how-to-make-gtest-build-mdd-instead-of-mtd-by-default-using-cmake @@ -436,7 +438,7 @@ if ( ACG_BUILD_UNIT_TESTS ) ) target_link_libraries(ACG_tests - GTest::gtest GTest::gtest_main ${OPENMESH_LIBRARIES} ACG ${GLEW_TARGET} + GTest::gtest GTest::gtest_main ${OPENMESH_LIBRARIES} ACG ${GLEW_TARGET} Qt6::Charts ) add_test(NAME AllTestsIn_ACG_tests COMMAND ${OUT_DIR}/ACG_tests) diff --git a/libs_required/ACG/QtWidgets/QtChartHistogram.cc b/libs_required/ACG/QtWidgets/QtChartHistogram.cc new file mode 100644 index 0000000000000000000000000000000000000000..d0d987a6a6e7284df0b96b9cc50ae6c21faf0b0e --- /dev/null +++ b/libs_required/ACG/QtWidgets/QtChartHistogram.cc @@ -0,0 +1,293 @@ +/*===========================================================================*\ + * * + * OpenFlipper * + * Copyright (c) 2001-2024, RWTH-Aachen University * + * Department of Computer Graphics and Multimedia * + * All rights reserved. * + * www.openflipper.org * + * * + *---------------------------------------------------------------------------* + * This file is part of OpenFlipper. * + *---------------------------------------------------------------------------* + * * + * Redistribution and use in source and binary forms, with or without * + * modification, are permitted provided that the following conditions * + * are met: * + * * + * 1. Redistributions of source code must retain the above copyright notice, * + * this list of conditions and the following disclaimer. * + * * + * 2. Redistributions in binary form must reproduce the above copyright * + * notice, this list of conditions and the following disclaimer in the * + * documentation and/or other materials provided with the distribution. * + * * + * 3. Neither the name of the copyright holder nor the names of its * + * contributors may be used to endorse or promote products derived from * + * this software without specific prior written permission. * + * * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER * + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * + * * +\*===========================================================================*/ + + +//============================================================================= +// +// CLASS QtChart - IMPLEMENTATION +// +//============================================================================= + +//== INCLUDES ================================================================= + +#include "QtChartHistogram.hh" +#include <QChart> +#include <QValueAxis> +#include <QBarSeries> +#include <QLineSeries> +#include <QStackedBarSeries> +#include <QBarCategoryAxis> +#include <QBarSet> +#include <QChartView> +#include <QRubberBand> + +#include <cfloat> + +#include <Utils/ColorCoder.hh> +//== NAMESPACES =============================================================== + +namespace ACG { +namespace QtWidgets { + +//This class creates a Histogram in a QChartView. The Histogram can be zoomed in and out by using a rubberband. +//The x-axis values are updated when the rubberband is moved. The y-axis values are updated automatically. +//The Histogram can be color coded. +//!!!!!IMPORTANT!!!! This class allows for colored bars in the Histogram, which is not possible with QCharts alone. +//In order to achieve that we have to create a new QBarSet for each bar. And "stack" them on top of each other. +//This is not very efficient and should be avoided if possible. In addition to that, the x-axis is detached in order to allow +//a correct zoom behavior. (This is also very hacky and should be avoided but I didnt see any other way to make it work) +//However I think there is a bug in the QCharts library and as soon as it is fixed, the workaround is not needed anymore.. +QtChartHistogram::QtChartHistogram(QString title_X, QString title_Y, const std::vector<double>& _values, QWidget* _parent) : QChartView(_parent) +{ + //create chart + chart_ = new QChart(); + + //create x-axis + axisX = new QValueAxis(); + axisX->setTitleText(title_X); + axisX->setRange(0, 100); + chart_->addAxis(axisX, Qt::AlignBottom); + + // Create y-axis + axisY = new QValueAxis(); + axisY->setTitleText(title_Y); + axisY->setRange(0, 500); + chart_->addAxis(axisY, Qt::AlignLeft); + + // Set the chart to the chartView(this widget) + setChart(chart_); + setRubberBand(QChartView::RectangleRubberBand); + + // Create the series and attach it to the chart + series = new QStackedBarSeries(); + chart_->addSeries(series); + series->attachAxis(axisY); + + // Set the values + setValues(_values); + + // Get the rubberband from the chartView + rubberBand_ = findChild<QRubberBand *>(); + rubberBand_->installEventFilter(this); + + // Install eventfilter for the chartView, so we can update the cursor type if inside the chart + this->installEventFilter(this); + + // Connect the rubberband signal to the slot + connect(this, &QtChartHistogram::rubberBandChanged, this, &QtChartHistogram::rubberBandChangedSlot); + + // Set the render hint to antialiasing, so the chart looks nicer + setRenderHint(QPainter::Antialiasing); + + // Hide the legend + chart_->legend()->setVisible(false); + + replot(); + +} + +//destructor +QtChartHistogram::~QtChartHistogram() +{} + +//------------------------------------------------------------------------------ + +// Override the mouseReleaseEvent to emit a signal when the right mouse button is released +void QtChartHistogram::mouseReleaseEvent(QMouseEvent *event) +{ + if (event->button() == Qt::RightButton) { + // There might be a more elegant way to reset the zoom, but this is simple and works well + replot(); + } + else { + QChartView::mouseReleaseEvent(event); + } +} + +//------------------------------------------------------------------------------ + +// Event filter +bool QtChartHistogram::eventFilter(QObject *obj, QEvent *event) +{ + if (obj == this && event->type() == QEvent::Enter){ + // if we are inside the chart, we wanna change the cursor to a cross + setCursor(Qt::CrossCursor); + } + else if (obj == chart_ && event->type() == QEvent::Leave){ + // if we leave the chart, we wanna change the cursor back to the default + setCursor(Qt::ArrowCursor); + } + + // if we use rubberband on the chartView, we wanna update the x-axis values (as the x-axis is detached from the series) + if (obj == rubberBand_ && (event->type() == QEvent::HideToParent)){ + //transform the rubberband coordinates to the x-axis values + auto rubberminX = rubberBand_->geometry().x() - chart_->plotArea().x(); + auto rubbermaxX = rubberBand_->geometry().x() - chart_->plotArea().x() + rubberBand_->geometry().width(); + + emit rubberBandChanged(rubberminX, rubbermaxX); + } + return false; + +} + +//------------------------------------------------------------------------------ + +void QtChartHistogram::rubberBandChangedSlot(double rubberminX, double rubbermaxX) +{ + + //get the x values of the chart + qreal minX = static_cast<const QValueAxis*>(chart_->axes(Qt::Horizontal).back())->min(); + qreal maxX = static_cast<const QValueAxis*>(chart_->axes(Qt::Horizontal).back())->max(); + + //compute the new x-axis values + double newMin = minX + ((rubberminX)/ chart_->plotArea().width()) * (maxX - minX); + double newMax = minX + (rubbermaxX / chart_->plotArea().width()) * (maxX - minX); + + //set the new x-axis values + dynamic_cast<QValueAxis*>(chart_->axes(Qt::Horizontal).back())->setRange(newMin, newMax); + +} + +//------------------------------------------------------------------------------ + +// Set the values +void QtChartHistogram::setValues(const std::vector<double>& _values) +{ + values_ = _values; +} + +//------------------------------------------------------------------------------ + +// Replot the chart +void QtChartHistogram::replot() +{ + // Create intervals + const int intervalCount = 101; + + std::vector<int> intervals(intervalCount, 0); + + double realMin = FLT_MAX; + double realMax = -FLT_MAX; + + // Compute realMin and realMax + for (const auto& value : values_) { + if (!std::isnan(value)) { // Check for NaN + realMin = std::min(realMin, value); + realMax = std::max(realMax, value); + } + } + + // Check for the edge case where realMin equals realMax + // In this case we have only one value and we want to create some margins around the value + // In order to display the value correctly in the histogram + if (realMin == realMax) { + realMax = realMin + 50; + realMin = realMin - 50; + } + + float width = (realMax - realMin) / intervalCount; + + // Populate the intervals + for (const auto& value : values_) { + if (!std::isnan(value)) { // Check for NaN + int index = std::min(intervalCount - 1, static_cast<int>((value - realMin) / width)); + intervals[index]++; + } + } + + std::vector<QColor> colors; + + // If we want to color code the histogram + if (colorCoding_){ + // Create Colors for the intervals + ACG::ColorCoder cCoder(realMin,realMax); + for (int i = 0; i < intervalCount; i++) { + const double intervalCenter = realMin + (i + 0.5) * width; + colors.push_back(cCoder.color_qcolor(intervalCenter)); + } + } + else { + // Use just one color + for (int i = 0; i < intervalCount; i++) { + const double intervalCenter = realMin + (i + 0.5) * width; + colors.push_back(Qt::black); + } + } + + // Remove the old series and create a new one. For some reason you have to remove the series. Simply clearing the series and appending new values does not work. + chart_->removeSeries(series); + + // Clear the series + series = new QStackedBarSeries(); + + // Set the axes range + axisX->setRange(realMin, realMax); + axisY->setRange(0, *std::max_element(intervals.begin(), intervals.end())); + + // Create for each Bar a new set. This is needed to add different colors to each bar. + for (int i = 0; i < intervalCount; i++) { + QBarSet* set = new QBarSet("Values"); + for (int j = 0; j < intervalCount; j++){ + if (j == i){ + *set << intervals[j]; + set->setColor(colors[j]); + } + else{ + *set << 0; + } + } + set->setColor(colors[i]); + series->append(set); + } + chart_->addSeries(series); + series->attachAxis(axisY); +} + +void QtChartHistogram::setColorCoding(bool _colorCoding) +{ + colorCoding_ = _colorCoding; +} + +} // namespace QtWidgets + +} // namespace ACG + + diff --git a/libs_required/ACG/QtWidgets/QtChartHistogram.hh b/libs_required/ACG/QtWidgets/QtChartHistogram.hh new file mode 100644 index 0000000000000000000000000000000000000000..30a636c2a732b5c6fe78596f848fba94fd551ba2 --- /dev/null +++ b/libs_required/ACG/QtWidgets/QtChartHistogram.hh @@ -0,0 +1,125 @@ +/*===========================================================================*\ + * * + * OpenFlipper * + * Copyright (c) 2001-2024, RWTH-Aachen University * + * Department of Computer Graphics and Multimedia * + * All rights reserved. * + * www.openflipper.org * + * * + *---------------------------------------------------------------------------* + * This file is part of OpenFlipper. * + *---------------------------------------------------------------------------* + * * + * Redistribution and use in source and binary forms, with or without * + * modification, are permitted provided that the following conditions * + * are met: * + * * + * 1. Redistributions of source code must retain the above copyright notice, * + * this list of conditions and the following disclaimer. * + * * + * 2. Redistributions in binary form must reproduce the above copyright * + * notice, this list of conditions and the following disclaimer in the * + * documentation and/or other materials provided with the distribution. * + * * + * 3. Neither the name of the copyright holder nor the names of its * + * contributors may be used to endorse or promote products derived from * + * this software without specific prior written permission. * + * * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER * + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * + * * +\*===========================================================================*/ + + +//============================================================================= +// +// CLASS QtChart - IMPLEMENTATION +// +//============================================================================= + +//== INCLUDES ================================================================= +#include <QChart> +#include <QBarSeries> +#include <QLineSeries> +#include <QStackedBarSeries> +#include <QChartView> +#include <QRubberBand> +#include <cfloat> +#include <QValueAxis> + + +#include <QBarSet> + + + +//== NAMESPACES =============================================================== +namespace ACG { +namespace QtWidgets { + +//This class creates a Histogram in a QChartView. The Histogram can be zoomed in and out by using a rubberband. +//The x-axis values are updated when the rubberband is moved. The y-axis values are updated automatically. +//The Histogram can be color coded. +//!!!!!IMPORTANT!!!! This class allows for colored bars in the Histogram, which is not possible with QCharts alone. +//In order to achieve that we have to create a new QBarSet for each bar. And "stack" them on top of each other. +//This is not very efficient and should be avoided if possible. In addition to that, the x-axis is detached in order to allow +//a correct zoom behavior. (This is also very hacky and should be avoided but I didnt see any other way to make it work) +//However I think there is a bug in the QCharts library and as soon as it is fixed, the workaround is not needed anymore. +class QtChartHistogram : public QChartView { + Q_OBJECT + +public: + + /// Default constructor + explicit QtChartHistogram(QString title_X, QString title_Y, const std::vector<double>& _values, QWidget* _parent = 0); + + /// Destructor + ~QtChartHistogram(); + + void setColorCoding(bool _colorCoding); + + void setValues(const std::vector<double>& _values); + + void replot(); + +public slots: + + void rubberBandChangedSlot(double rubber_min, double rubber_max); + +signals: + + void rubberBandChanged(double rubber_min, double rubber_max); + +private: + + //variables + QChart* chart_; + QValueAxis* axisX; + QValueAxis* axisY; + QStackedBarSeries* series; + QRubberBand* rubberBand_; + bool colorCoding_; + std::vector<double> values_; + +protected: + + bool eventFilter(QObject *obj, QEvent *event) override; + void mouseReleaseEvent(QMouseEvent *event) override; + +}; + +} // namespace QtWidgets +} // namespace ACG + + + + + diff --git a/libs_required/ACG/QwtWidgets/QwtHistogramm.hh b/libs_required/ACG/QwtWidgets/QwtHistogramm.hh index 662d9b9e837c0240870dd8c5863f1ec502c0e3e4..a055b285b3df67730d3284a3da52454cad94991e 100644 --- a/libs_required/ACG/QwtWidgets/QwtHistogramm.hh +++ b/libs_required/ACG/QwtWidgets/QwtHistogramm.hh @@ -60,7 +60,7 @@ class QString; * via HistogramItem::setData(). Additionally you can set colors for each bar, * which are provided via HistogramItem::setColors() */ -class ACGDLLEXPORT Histogram: public QwtPlotItem +class [[deprecated("Use QCharts instead!")]] ACGDLLEXPORT Histogram: public QwtPlotItem { public: /// Constructor diff --git a/tests/run_tests.py b/tests/run_tests.py index d1c5f65d9b244c0a680016b1bdc44c7f19444fc1..f2444d19ae0ad04eb4a0eb76b11e6e01b9f83488 100644 --- a/tests/run_tests.py +++ b/tests/run_tests.py @@ -156,7 +156,7 @@ elif sys.platform == "win32": src_files = os.listdir("../Build") for file_name in src_files: - full_file_name = os.path.join("../Build", file_name) + full_file_name = os.path.join("..\Build", file_name) if os.path.isfile(full_file_name) and full_file_name.endswith(".dll"): print("Copyining" + full_file_name + " to testBinaries") shutil.copy(full_file_name, "testBinaries") @@ -184,7 +184,7 @@ print("Working directory for test execution: " + os.getcwd(), flush=True) # call ctest ctest = subprocess.run( - [ctest_executable, "-C", "Release", "--no-tests=error", "--no-compress-output", "--output-on-failure","--gtest_output=xml:report.xml"]) + [ctest_executable, "-C", "Debug", "--no-tests=error", "--no-compress-output", "--output-on-failure","--output-junit","report.xml"]) print("Return Code: ", ctest.returncode) diff --git a/widgets/glWidget/QtBaseViewer.cc b/widgets/glWidget/QtBaseViewer.cc index 89b70742e6dcde77ea273b281561de2b308ebfdd..601c3580323b7fa3f6c904845260e7e85bb447d7 100644 --- a/widgets/glWidget/QtBaseViewer.cc +++ b/widgets/glWidget/QtBaseViewer.cc @@ -1117,6 +1117,8 @@ void glViewer::paintGL(double _aspect) void glViewer::resizeEvent(QGraphicsSceneResizeEvent *) { const auto current_screen = QGuiApplication::screenAt(geometry().center().toPoint()); + if(!current_screen) + return; /// update device pixel ratio. getters in this class will make use of it /// so we only need to multiply scene information properties()->setDevicePixelRatio(current_screen->devicePixelRatio());