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