diff --git a/CMakeLists.txt b/CMakeLists.txt
index c95c842114..df73cdd9ae 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -63,6 +63,13 @@ file(GLOB UI_LIST *.ui)
set(PROJECT_SOURCES ${SRC_LIST} ${HEADER_LIST} ${UI_LIST})
+include(ScopyWhatsNew)
+set(FOLDER ${CMAKE_SOURCE_DIR}/resources/whatsnew/)
+set(RESOURCE_FILE ${CMAKE_SOURCE_DIR}/resources/whatsnew/whatsnew.qrc)
+generate_whats_new("${RESOURCE_FILE}" "${FOLDER}")
+file(GLOB WHATS_NEW_RESOURCES resources/whatsnew/whatsnew.qrc)
+qt_add_resources(SCOPY_RESOURCES ${WHATS_NEW_RESOURCES})
+
include(ScopyAbout)
configure_about(./resources/about)
file(GLOB SCOPY_RESOURCE_FILES gui/res/resources.qrc resources/aboutpage.qrc)
@@ -80,6 +87,16 @@ if(ENABLE_TRANSLATION)
qt_add_resources(SCOPY_RESOURCES ${CMAKE_BINARY_DIR}/translations.qrc)
endif()
+# file(GLOB WHATS_NEW_FILES ${CMAKE_CURRENT_SOURCE_DIR}/resources/whatsnew/*.html) set_source_files_properties(
+# ${WHATS_NEW_FILES} PROPERTIES OUTPUT_LOCATION ${CMAKE_BINARY_DIR}/whatsnew MACOSX_PACKAGE_LOCATION
+# ${CMAKE_BINARY_DIR}/whatsnew ) qt_add_translation(QM_FILES ${WHATS_NEW_FILES})
+
+# set(WHATSNEW) foreach(file ${WHATS_NEW_FILES}) get_filename_component(file_name ${file} NAME_WE) set(WHATSNEW
+# "${WHATSNEW}\n${CMAKE_BINARY_DIR}/whatsnew/${file_name}") endforeach()
+
+# configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/resources/whatsnew/whatsnew.qrc ${CMAKE_CURRENT_BINARY_DIR}/whatsnew.qrc
+# @ONLY )
+
if(DEFINED ENV{APPIMAGE})
add_compile_definitions(__appimage__)
endif()
diff --git a/cmake/Modules/ScopyWhatsNew.cmake b/cmake/Modules/ScopyWhatsNew.cmake
new file mode 100644
index 0000000000..4655369e81
--- /dev/null
+++ b/cmake/Modules/ScopyWhatsNew.cmake
@@ -0,0 +1,45 @@
+#
+# Copyright (c) 2024 Analog Devices Inc.
+#
+# This file is part of Scopy
+# (see https://www.github.com/analogdevicesinc/scopy).
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+#
+
+if(DEFINED __INCLUDED_SCOPY_WHATS_NEW_CMAKE)
+ return()
+endif()
+set(__INCLUDED_SCOPY_WHATS_NEW_CMAKE TRUE)
+
+function(generate_whats_new RESOURCE_FILE FOLDER)
+ # Specify the folder containing resources Create the list of HTML files recursively
+
+ file(GLOB_RECURSE HTML_FILES "${FOLDER}*.html")
+
+ # Start writing to the resource file
+ file(WRITE "${RESOURCE_FILE}" "\n \n")
+
+ # Loop through each HTML file and add it to the resource file
+ foreach(HTML_FILE ${HTML_FILES})
+ # Convert the file path to a resource path
+ file(RELATIVE_PATH relative ${FOLDER} ${HTML_FILE})
+
+ # Write the file to the resource file
+ file(APPEND "${RESOURCE_FILE}" " ${relative}\n")
+ endforeach()
+
+ # End the resource file
+ file(APPEND "${RESOURCE_FILE}" " \n\n")
+endfunction()
diff --git a/core/include/core/whatsnewoverlay.h b/core/include/core/whatsnewoverlay.h
new file mode 100644
index 0000000000..f649cde85e
--- /dev/null
+++ b/core/include/core/whatsnewoverlay.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2024 Analog Devices Inc.
+ *
+ * This file is part of Scopy
+ * (see https://www.github.com/analogdevicesinc/scopy).
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+
+#ifndef WHATSNEWOVERLAY_H
+#define WHATSNEWOVERLAY_H
+
+#include
+#include
+#include
+#include "scopy-core_export.h"
+#include
+#include
+
+namespace scopy {
+class SCOPY_CORE_EXPORT WhatsNewOverlay : public QWidget
+{
+ Q_OBJECT
+public:
+ explicit WhatsNewOverlay(QWidget *parent = nullptr);
+ ~WhatsNewOverlay();
+
+ void showOverlay();
+
+private:
+ PopupWidget *m_popupWidget;
+ QString getHtmlPageContent(QString fileName);
+ void initCarousel();
+ void generateVersionPage(QString filePath);
+
+ QStackedWidget *m_carouselWidget;
+ QComboBox *m_versionCb;
+};
+} // namespace scopy
+#endif // WHATSNEWOVERLAY_H
diff --git a/core/src/scopymainwindow.cpp b/core/src/scopymainwindow.cpp
index 69331fa1f2..e5ae9ac417 100644
--- a/core/src/scopymainwindow.cpp
+++ b/core/src/scopymainwindow.cpp
@@ -30,6 +30,7 @@
#include
#include
#include
+#include
#include "logging_categories.h"
#include "qmessagebox.h"
@@ -360,8 +361,12 @@ void ScopyMainWindow::setupPreferences()
QMetaObject::invokeMethod(license, &LicenseOverlay::showOverlay, Qt::QueuedConnection);
}
+ if(p->get("general_show_whats_new").toBool()) {
+ WhatsNewOverlay *whatsNew = new WhatsNewOverlay(this);
+ whatsNew->move(this->rect().center() - whatsNew->rect().center());
+ QMetaObject::invokeMethod(whatsNew, &WhatsNewOverlay::showOverlay, Qt::QueuedConnection);
+ }
}
-
void ScopyMainWindow::initPreferences()
{
QElapsedTimer timer;
@@ -375,6 +380,7 @@ void ScopyMainWindow::initPreferences()
p->init("general_save_session", true);
p->init("general_save_attached", true);
p->init("general_doubleclick_attach", true);
+ p->init("general_show_whats_new", true);
#if defined(__linux__) && (defined(__arm__) || defined(__aarch64__))
p->init("general_use_opengl", false);
#else
diff --git a/core/src/whatsnewoverlay.cpp b/core/src/whatsnewoverlay.cpp
new file mode 100644
index 0000000000..5d155187ed
--- /dev/null
+++ b/core/src/whatsnewoverlay.cpp
@@ -0,0 +1,201 @@
+/*
+ * Copyright (c) 2024 Analog Devices Inc.
+ *
+ * This file is part of Scopy
+ * (see https://www.github.com/analogdevicesinc/scopy).
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+
+#include "whatsnewoverlay.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+using namespace scopy;
+
+WhatsNewOverlay::WhatsNewOverlay(QWidget *parent)
+ : QWidget{parent}
+{
+ // main layout vertical
+ // main is popup widget ??
+ this->resize(500, 400);
+ QVBoxLayout *mainLayout = new QVBoxLayout();
+ this->setLayout(mainLayout);
+
+ m_carouselWidget = new QStackedWidget(this);
+
+ // bottom of main layout has controll widget
+
+ QWidget *overlayControllWidget = new QWidget(this);
+ QVBoxLayout *overlayControllWidgetLayout = new QVBoxLayout(overlayControllWidget);
+
+ QWidget *optionsoverlayControllWidget = new QWidget(overlayControllWidget);
+ overlayControllWidgetLayout->addWidget(optionsoverlayControllWidget);
+ QHBoxLayout *optionsControllLayout = new QHBoxLayout(optionsoverlayControllWidget);
+ optionsoverlayControllWidget->setLayout(optionsControllLayout);
+
+ // TODO implement preference
+ QCheckBox *showAgain = new QCheckBox("Show this again", optionsoverlayControllWidget);
+ showAgain->setChecked(true);
+ optionsControllLayout->addWidget(showAgain);
+
+ connect(showAgain, &QCheckBox::toggled, this, [=](bool en) {
+ Preferences *p = Preferences::GetInstance();
+ p->set("general_show_whats_new", en);
+ });
+
+ // version picker
+ m_versionCb = new QComboBox(optionsoverlayControllWidget);
+ optionsControllLayout->addWidget(m_versionCb);
+
+ connect(m_versionCb, qOverload(&QComboBox::currentIndexChanged), this,
+ [=](int idx) { m_carouselWidget->setCurrentIndex(idx); });
+
+ QPushButton *okButton = new QPushButton("Ok", optionsoverlayControllWidget);
+ connect(okButton, &QPushButton::clicked, this, [=]() { this->deleteLater(); });
+ Style::setStyle(okButton, style::properties::button::basicButton, true, true);
+ optionsControllLayout->addWidget(okButton);
+
+ mainLayout->addWidget(m_carouselWidget);
+ mainLayout->addWidget(overlayControllWidget);
+ Style::setBackgroundColor(this, json::theme::background_secondary);
+
+ initCarousel();
+}
+
+WhatsNewOverlay::~WhatsNewOverlay()
+{
+ // TODO
+}
+
+void WhatsNewOverlay::showOverlay()
+{
+ raise();
+ show();
+}
+
+void WhatsNewOverlay::initCarousel()
+{
+ QDir dir(":/whatsnew");
+
+ // Get a list of all entries in the directory
+ QFileInfoList entries = dir.entryInfoList(QDir::AllDirs | QDir::NoDotAndDotDot, QDir::Name);
+
+ // Iterate through the list and print the folder names
+
+ for(int i = entries.count() - 1; i >= 0; i--) {
+ QFileInfo fileInfo = entries.at(i);
+ if(fileInfo.isDir()) {
+ // add option to combo
+ m_versionCb->addItem(fileInfo.fileName());
+ // create page and button for page
+ generateVersionPage(fileInfo.absoluteFilePath());
+ }
+ }
+}
+
+void WhatsNewOverlay::generateVersionPage(QString filePath)
+{
+ QWidget *carouselContent = new QWidget(m_carouselWidget);
+ QVBoxLayout *carouselContentLayout = new QVBoxLayout(carouselContent);
+
+ // carousel control contains buttons for changeing info page
+ QWidget *carouselControllWidget = new QWidget(carouselContent);
+
+ QHBoxLayout *carouselControllLayout = new QHBoxLayout(carouselControllWidget);
+ carouselControllWidget->setLayout(carouselControllLayout);
+
+ QPushButton *previous = new QPushButton("<", carouselControllWidget);
+
+ QPushButton *next = new QPushButton(">", carouselControllWidget);
+
+ Style::setStyle(previous, style::properties::button::basicButton, true, true);
+ Style::setStyle(next, style::properties::button::basicButton, true, true);
+
+ carouselControllLayout->addWidget(previous);
+
+ QStackedWidget *versionCarouselWithControlls = new QStackedWidget(m_carouselWidget);
+
+ QDir versionDir(filePath);
+ QFileInfoList fileList = versionDir.entryInfoList(QDir::Files | QDir::NoDotAndDotDot);
+
+ int i = 0;
+ for(const QFileInfo &page : fileList) {
+
+ QWidget *scrollWidget = new QWidget();
+ scrollWidget->setLayout(new QVBoxLayout());
+ QScrollArea *scrollArea = new QScrollArea();
+ scrollArea->setWidgetResizable(true);
+ scrollArea->setWidget(scrollWidget);
+
+ QTextBrowser *htmlPage = new QTextBrowser(scrollWidget);
+ QString filePath(page.absoluteFilePath());
+ htmlPage->setHtml(getHtmlPageContent(filePath));
+ htmlPage->setProperty("openExternalLinks", true);
+
+ scrollWidget->layout()->addWidget(htmlPage);
+ versionCarouselWithControlls->addWidget(scrollArea);
+
+ QPushButton *htmlPageButton = new QPushButton("", carouselControllWidget);
+
+ connect(htmlPageButton, &QPushButton::clicked, this,
+ [=]() { versionCarouselWithControlls->setCurrentIndex(i); });
+
+ carouselControllLayout->addWidget(htmlPageButton);
+ Style::setStyle(htmlPageButton, style::properties::button::basicButton, true, true);
+ i++;
+ }
+
+ carouselControllLayout->addWidget(next);
+
+ connect(previous, &QPushButton::clicked, this, [=]() {
+ int currentIndex = versionCarouselWithControlls->currentIndex();
+ versionCarouselWithControlls->setCurrentIndex(
+ (currentIndex - 1 + versionCarouselWithControlls->count()) %
+ versionCarouselWithControlls->count());
+ });
+
+ connect(next, &QPushButton::clicked, this, [=]() {
+ int currentIndex = versionCarouselWithControlls->currentIndex();
+ versionCarouselWithControlls->setCurrentIndex((currentIndex + 1) %
+ versionCarouselWithControlls->count());
+ });
+
+ carouselContentLayout->addWidget(versionCarouselWithControlls);
+ carouselContentLayout->addWidget(carouselControllWidget);
+
+ m_carouselWidget->addWidget(carouselContent);
+}
+
+QString WhatsNewOverlay::getHtmlPageContent(QString fileName)
+{
+ QFile file(fileName);
+ file.open(QIODevice::ReadOnly);
+ QString text = QString(file.readAll());
+ file.close();
+
+ return text;
+}
+
+#include "moc_whatsnewoverlay.cpp"
+
+#include