From c83cd3c45394b1645692e8e6dedbd7e1ac200285 Mon Sep 17 00:00:00 2001 From: dreamsourcelabTAI Date: Mon, 25 Mar 2024 11:19:23 +0800 Subject: [PATCH] Optimize the native window on window system --- DSView/pv/config/appconfig.cpp | 1066 ++++---- DSView/pv/config/appconfig.h | 329 +-- DSView/pv/interface/icallbacks.h | 256 +- DSView/pv/mainframe.cpp | 367 +-- DSView/pv/mainframe.h | 12 +- DSView/pv/mainwindow.cpp | 4397 +++++++++++++++--------------- DSView/pv/mainwindow.h | 497 ++-- DSView/pv/toolbars/titlebar.cpp | 671 +++-- DSView/pv/toolbars/titlebar.h | 218 +- DSView/pv/ui/popupdlglist.cpp | 151 +- DSView/pv/ui/popupdlglist.h | 79 +- DSView/pv/winnativewidget.cpp | 594 ++-- DSView/pv/winnativewidget.h | 60 +- DSView/pv/winshadow.cpp | 478 +--- DSView/pv/winshadow.h | 90 +- 15 files changed, 4611 insertions(+), 4654 deletions(-) diff --git a/DSView/pv/config/appconfig.cpp b/DSView/pv/config/appconfig.cpp index 142439e8..5ad2416e 100644 --- a/DSView/pv/config/appconfig.cpp +++ b/DSView/pv/config/appconfig.cpp @@ -1,533 +1,535 @@ -/* - * This file is part of the DSView project. - * DSView is based on PulseView. - * - * Copyright (C) 2021 DreamSourceLab - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "appconfig.h" -#include -#include -#include -#include -#include -#include -#include "../log.h" - -#define MAX_PROTOCOL_FORMAT_LIST 15 - -StringPair::StringPair(const std::string &key, const std::string &value) -{ - m_key = key; - m_value = value; -} - -//------------function -static QString FormatArrayToString(std::vector &protocolFormats) -{ - QString str; - - for (StringPair &o : protocolFormats){ - if (!str.isEmpty()){ - str += ";"; - } - str += o.m_key.c_str(); - str += "="; - str += o.m_value.c_str(); - } - - return str; -} - -static void StringToFormatArray(const QString &str, std::vector &protocolFormats) -{ - QStringList arr = str.split(";"); - for (int i=0; i maxSize) - { - o.fontSize = (maxSize + minSize) / 2; - } - - st.endGroup(); -} - -static void _saveApp(AppOptions &o, QSettings &st) -{ - st.beginGroup("Application"); - setFiled("quickScroll", st, o.quickScroll); - setFiled("warnofMultiTrig", st, o.warnofMultiTrig); - setFiled("originalData", st, o.originalData); - setFiled("ableSaveLog", st, o.ableSaveLog); - setFiled("appendLogMode", st, o.appendLogMode); - setFiled("logLevel", st, o.logLevel); - setFiled("transDecoderDlg", st, o.transDecoderDlg); - setFiled("trigPosDisplayInMid", st, o.trigPosDisplayInMid); - setFiled("displayProfileInBar", st, o.displayProfileInBar); - setFiled("swapBackBufferAlways", st, o.swapBackBufferAlways); - setFiled("fontSize", st, o.fontSize); - setFiled("autoScrollLatestData", st, o.autoScrollLatestData); - setFiled("version", st, APP_CONFIG_VERSION); - - QString fmt = FormatArrayToString(o.m_protocolFormats); - setFiled("protocalFormats", st, fmt); - st.endGroup(); -} - -//-----frame - -static void _loadDockOptions(DockOptions &o, QSettings &st, const char *group) -{ - st.beginGroup(group); - getFiled("decodeDoc", st, o.decodeDock, false); - getFiled("triggerDoc", st, o.triggerDock, false); - getFiled("measureDoc", st, o.measureDock, false); - getFiled("searchDoc", st, o.searchDock, false); - st.endGroup(); -} - -static void _saveDockOptions(DockOptions &o, QSettings &st, const char *group) -{ - st.beginGroup(group); - setFiled("decodeDoc", st, o.decodeDock); - setFiled("triggerDoc", st, o.triggerDock); - setFiled("measureDoc", st, o.measureDock); - setFiled("searchDoc", st, o.searchDock); - st.endGroup(); -} - -static void _loadFrame(FrameOptions &o, QSettings &st) -{ - st.beginGroup("MainFrame"); - getFiled("style", st, o.style, THEME_STYLE_DARK); - getFiled("language", st, o.language, -1); - getFiled("isMax", st, o.isMax, false); - getFiled("left", st, o.left, 0); - getFiled("top", st, o.top, 0); - getFiled("right", st, o.right, 0); - getFiled("bottom", st, o.bottom, 0); - getFiled("x", st, o.x, NO_POINT_VALUE); - getFiled("y", st, o.y, NO_POINT_VALUE); - getFiled("ox", st, o.ox, NO_POINT_VALUE); - getFiled("oy", st, o.oy, NO_POINT_VALUE); - - _loadDockOptions(o._logicDock, st, "LOGIC_DOCK"); - _loadDockOptions(o._analogDock, st, "ANALOG_DOCK"); - _loadDockOptions(o._dsoDock, st, "DSO_DOCK"); - - o.windowState = st.value("windowState", QByteArray()).toByteArray(); - st.endGroup(); - - if (o.language == -1 || (o.language != LAN_CN && o.language != LAN_EN)){ - //get local language - QLocale locale; - - if (QLocale::languageToString(locale.language()) == "Chinese") - o.language = LAN_CN; - else - o.language = LAN_EN; - } -} - -static void _saveFrame(FrameOptions &o, QSettings &st) -{ - st.beginGroup("MainFrame"); - setFiled("style", st, o.style); - setFiled("language", st, o.language); - setFiled("isMax", st, o.isMax); - setFiled("left", st, o.left); - setFiled("top", st, o.top); - setFiled("right", st, o.right); - setFiled("bottom", st, o.bottom); - setFiled("x", st, o.x); - setFiled("y", st, o.y); - setFiled("ox", st, o.ox); - setFiled("oy", st, o.oy); - - st.setValue("windowState", o.windowState); - - _saveDockOptions(o._logicDock, st, "LOGIC_DOCK"); - _saveDockOptions(o._analogDock, st, "ANALOG_DOCK"); - _saveDockOptions(o._dsoDock, st, "DSO_DOCK"); - - st.endGroup(); -} - -//------history -static void _loadHistory(UserHistory &o, QSettings &st) -{ - st.beginGroup("UserHistory"); - getFiled("exportDir", st, o.exportDir, ""); - getFiled("saveDir", st, o.saveDir, ""); - getFiled("showDocuments", st, o.showDocuments, true); - getFiled("screenShotPath", st, o.screenShotPath, ""); - getFiled("sessionDir", st, o.sessionDir, ""); - getFiled("openDir", st, o.openDir, ""); - getFiled("protocolExportPath", st, o.protocolExportPath, ""); - getFiled("exportFormat", st, o.exportFormat, ""); - st.endGroup(); -} - -static void _saveHistory(UserHistory &o, QSettings &st) -{ - st.beginGroup("UserHistory"); - setFiled("exportDir", st, o.exportDir); - setFiled("saveDir", st, o.saveDir); - setFiled("showDocuments", st, o.showDocuments); - setFiled("screenShotPath", st, o.screenShotPath); - setFiled("sessionDir", st, o.sessionDir); - setFiled("openDir", st, o.openDir); - setFiled("protocolExportPath", st, o.protocolExportPath); - setFiled("exportFormat", st, o.exportFormat); - st.endGroup(); -} - -/* -//------font -static void _loadFont(FontOptions &o, QSettings &st) -{ - st.beginGroup("FontSetting"); - getFiled("toolbarName", st, o.toolbar.name, ""); - getFiled("toolbarSize", st, o.toolbar.size, 9); - getFiled("channelLabelName", st, o.channelLabel.name, ""); - getFiled("channelLabelSize", st, o.channelLabel.size, 9); - getFiled("channelBodyName", st, o.channelBody.name, ""); - getFiled("channelBodySize", st, o.channelBody.size, 9); - getFiled("rulerName", st, o.ruler.name, ""); - getFiled("ruleSize", st, o.ruler.size, 9); - getFiled("titleName", st, o.title.name, ""); - getFiled("titleSize", st, o.title.size, 9); - getFiled("otherName", st, o.other.name, ""); - getFiled("otherSize", st, o.other.size, 9); - - st.endGroup(); -} - -static void _saveFont(FontOptions &o, QSettings &st) -{ - st.beginGroup("FontSetting"); - setFiled("toolbarName", st, o.toolbar.name); - setFiled("toolbarSize", st, o.toolbar.size); - setFiled("channelLabelName", st, o.channelLabel.name); - setFiled("channelLabelSize", st, o.channelLabel.size); - setFiled("channelBodyName", st, o.channelBody.name); - setFiled("channelBodySize", st, o.channelBody.size); - setFiled("rulerName", st, o.ruler.name); - setFiled("ruleSize", st, o.ruler.size); - setFiled("titleName", st, o.title.name); - setFiled("titleSize", st, o.title.size); - setFiled("otherName", st, o.other.name); - setFiled("otherSize", st, o.other.size); - - st.endGroup(); -} -*/ - -//------------AppConfig - -AppConfig::AppConfig() -{ -} - -AppConfig::AppConfig(AppConfig &o) -{ - (void)o; -} - -AppConfig::~AppConfig() -{ -} - - AppConfig& AppConfig::Instance() - { - static AppConfig *ins = NULL; - if (ins == NULL){ - ins = new AppConfig(); - } - return *ins; - } - -void AppConfig::LoadAll() -{ - QSettings st(QApplication::organizationName(), QApplication::applicationName()); - _loadApp(appOptions, st); - _loadHistory(userHistory, st); - _loadFrame(frameOptions, st); - - //dsv_dbg("Config file path:\"%s\"", st.fileName().toUtf8().data()); -} - -void AppConfig::SaveApp() -{ - QSettings st(QApplication::organizationName(), QApplication::applicationName()); - _saveApp(appOptions, st); -} - -void AppConfig::SaveHistory() -{ - QSettings st(QApplication::organizationName(), QApplication::applicationName()); - _saveHistory(userHistory, st); -} - -void AppConfig::SaveFrame() -{ - QSettings st(QApplication::organizationName(), QApplication::applicationName()); - _saveFrame(frameOptions, st); -} - -void AppConfig::SetProtocolFormat(const std::string &protocolName, const std::string &value) -{ - bool bChange = false; - for (StringPair &o : appOptions.m_protocolFormats){ - if (o.m_key == protocolName){ - o.m_value = value; - bChange = true; - break; - } - } - - if (!bChange) - { - if (appOptions.m_protocolFormats.size() > MAX_PROTOCOL_FORMAT_LIST) - { - while (appOptions.m_protocolFormats.size() < MAX_PROTOCOL_FORMAT_LIST) - { - appOptions.m_protocolFormats.erase(appOptions.m_protocolFormats.begin()); - } - } - appOptions.m_protocolFormats.push_back(StringPair(protocolName, value)); - bChange = true; - } - - if (bChange){ - SaveApp(); - } -} - -std::string AppConfig::GetProtocolFormat(const std::string &protocolName) -{ - for (StringPair &o : appOptions.m_protocolFormats){ - if (o.m_key == protocolName){ - return o.m_value; - } - } - return ""; -} - -void AppConfig::GetFontSizeRange(float *minSize, float *maxSize) -{ - assert(minSize); - assert(maxSize); - -#ifdef _WIN32 - *minSize = 7; - *maxSize = 12; -#endif - -#ifdef Q_OS_LINUX - *minSize = 8; - *maxSize = 14; -#endif - -#ifdef Q_OS_DARWIN - *minSize = 9; - *maxSize = 15; -#endif -} - - -//-------------api -QString GetIconPath() -{ - QString style = AppConfig::Instance().frameOptions.style; - if (style == ""){ - style = THEME_STYLE_DARK; - } - return ":/icons/" + style; -} - -QString GetAppDataDir() -{ -//applicationDirPath not end with '/' -#ifdef Q_OS_LINUX - QDir dir(QCoreApplication::applicationDirPath()); - if (dir.cd("..") && dir.cd("share") && dir.cd("DSView")) - { - return dir.absolutePath(); - } - QDir dir1("/usr/local/share/DSView"); - if (dir1.exists()){ - return dir1.absolutePath(); - } - - dsv_err("Data directory is not exists: ../share/DSView"); - assert(false); -#else - -#ifdef Q_OS_DARWIN - QDir dir1(QCoreApplication::applicationDirPath()); - //"./res" is not exists - if (dir1.cd("res") == false){ - QDir dir(QCoreApplication::applicationDirPath()); - // ../share/DSView - if (dir.cd("..") && dir.cd("share") && dir.cd("DSView")) - { - return dir.absolutePath(); - } - } -#endif - - // The bin location - return QCoreApplication::applicationDirPath(); -#endif -} - -QString GetFirmwareDir() -{ - QDir dir1 = GetAppDataDir() + "/res"; - // ./res - if (dir1.exists()){ - return dir1.absolutePath(); - } - - QDir dir(QCoreApplication::applicationDirPath()); - // ../share/DSView/res - if (dir.cd("..") && dir.cd("share") && dir.cd("DSView") && dir.cd("res")) - { - return dir.absolutePath(); - } - - dsv_err("%s%s", "Resource directory is not exists:", dir1.absolutePath().toUtf8().data()); - return dir1.absolutePath(); -} - -QString GetUserDataDir() -{ - #if QT_VERSION >= 0x050400 - return QStandardPaths::writableLocation(QStandardPaths::AppDataLocation); - #else - return QStandardPaths::writableLocation(QStandardPaths::DataLocation); - #endif -} - -QString GetDecodeScriptDir() -{ - QString path = GetAppDataDir() + "/decoders"; - - QDir dir1; - // ./decoders - if (dir1.exists(path)) - { - return path; - } - - QDir dir(QCoreApplication::applicationDirPath()); - // ../share/libsigrokdecode4DSL/decoders - if (dir.cd("..") && dir.cd("share") && dir.cd("libsigrokdecode4DSL") && dir.cd("decoders")) - { - return dir.absolutePath(); - } - return ""; -} - -QString GetProfileDir() -{ - #if QT_VERSION >= 0x050400 - return QStandardPaths::writableLocation(QStandardPaths::AppDataLocation); - #else - return QStandardPaths::writableLocation(QStandardPaths::DataLocation); - #endif +/* + * This file is part of the DSView project. + * DSView is based on PulseView. + * + * Copyright (C) 2021 DreamSourceLab + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "appconfig.h" +#include +#include +#include +#include +#include +#include +#include "../log.h" + +#define MAX_PROTOCOL_FORMAT_LIST 15 + +StringPair::StringPair(const std::string &key, const std::string &value) +{ + m_key = key; + m_value = value; +} + +//------------function +static QString FormatArrayToString(std::vector &protocolFormats) +{ + QString str; + + for (StringPair &o : protocolFormats){ + if (!str.isEmpty()){ + str += ";"; + } + str += o.m_key.c_str(); + str += "="; + str += o.m_value.c_str(); + } + + return str; +} + +static void StringToFormatArray(const QString &str, std::vector &protocolFormats) +{ + QStringList arr = str.split(";"); + for (int i=0; i maxSize) + { + o.fontSize = (maxSize + minSize) / 2; + } + + st.endGroup(); +} + +static void _saveApp(AppOptions &o, QSettings &st) +{ + st.beginGroup("Application"); + setFiled("quickScroll", st, o.quickScroll); + setFiled("warnofMultiTrig", st, o.warnofMultiTrig); + setFiled("originalData", st, o.originalData); + setFiled("ableSaveLog", st, o.ableSaveLog); + setFiled("appendLogMode", st, o.appendLogMode); + setFiled("logLevel", st, o.logLevel); + setFiled("transDecoderDlg", st, o.transDecoderDlg); + setFiled("trigPosDisplayInMid", st, o.trigPosDisplayInMid); + setFiled("displayProfileInBar", st, o.displayProfileInBar); + setFiled("swapBackBufferAlways", st, o.swapBackBufferAlways); + setFiled("fontSize", st, o.fontSize); + setFiled("autoScrollLatestData", st, o.autoScrollLatestData); + setFiled("version", st, APP_CONFIG_VERSION); + + QString fmt = FormatArrayToString(o.m_protocolFormats); + setFiled("protocalFormats", st, fmt); + st.endGroup(); +} + +//-----frame + +static void _loadDockOptions(DockOptions &o, QSettings &st, const char *group) +{ + st.beginGroup(group); + getFiled("decodeDoc", st, o.decodeDock, false); + getFiled("triggerDoc", st, o.triggerDock, false); + getFiled("measureDoc", st, o.measureDock, false); + getFiled("searchDoc", st, o.searchDock, false); + st.endGroup(); +} + +static void _saveDockOptions(DockOptions &o, QSettings &st, const char *group) +{ + st.beginGroup(group); + setFiled("decodeDoc", st, o.decodeDock); + setFiled("triggerDoc", st, o.triggerDock); + setFiled("measureDoc", st, o.measureDock); + setFiled("searchDoc", st, o.searchDock); + st.endGroup(); +} + +static void _loadFrame(FrameOptions &o, QSettings &st) +{ + st.beginGroup("MainFrame"); + getFiled("style", st, o.style, THEME_STYLE_DARK); + getFiled("language", st, o.language, -1); + getFiled("isMax", st, o.isMax, false); + getFiled("left", st, o.left, 0); + getFiled("top", st, o.top, 0); + getFiled("right", st, o.right, 0); + getFiled("bottom", st, o.bottom, 0); + getFiled("x", st, o.x, NO_POINT_VALUE); + getFiled("y", st, o.y, NO_POINT_VALUE); + getFiled("ox", st, o.ox, NO_POINT_VALUE); + getFiled("oy", st, o.oy, NO_POINT_VALUE); + getFiled("displayName", st, o.displayName, ""); + + _loadDockOptions(o._logicDock, st, "LOGIC_DOCK"); + _loadDockOptions(o._analogDock, st, "ANALOG_DOCK"); + _loadDockOptions(o._dsoDock, st, "DSO_DOCK"); + + o.windowState = st.value("windowState", QByteArray()).toByteArray(); + st.endGroup(); + + if (o.language == -1 || (o.language != LAN_CN && o.language != LAN_EN)){ + //get local language + QLocale locale; + + if (QLocale::languageToString(locale.language()) == "Chinese") + o.language = LAN_CN; + else + o.language = LAN_EN; + } +} + +static void _saveFrame(FrameOptions &o, QSettings &st) +{ + st.beginGroup("MainFrame"); + setFiled("style", st, o.style); + setFiled("language", st, o.language); + setFiled("isMax", st, o.isMax); + setFiled("left", st, o.left); + setFiled("top", st, o.top); + setFiled("right", st, o.right); + setFiled("bottom", st, o.bottom); + setFiled("x", st, o.x); + setFiled("y", st, o.y); + setFiled("ox", st, o.ox); + setFiled("oy", st, o.oy); + setFiled("displayName", st, o.displayName); + + st.setValue("windowState", o.windowState); + + _saveDockOptions(o._logicDock, st, "LOGIC_DOCK"); + _saveDockOptions(o._analogDock, st, "ANALOG_DOCK"); + _saveDockOptions(o._dsoDock, st, "DSO_DOCK"); + + st.endGroup(); +} + +//------history +static void _loadHistory(UserHistory &o, QSettings &st) +{ + st.beginGroup("UserHistory"); + getFiled("exportDir", st, o.exportDir, ""); + getFiled("saveDir", st, o.saveDir, ""); + getFiled("showDocuments", st, o.showDocuments, true); + getFiled("screenShotPath", st, o.screenShotPath, ""); + getFiled("sessionDir", st, o.sessionDir, ""); + getFiled("openDir", st, o.openDir, ""); + getFiled("protocolExportPath", st, o.protocolExportPath, ""); + getFiled("exportFormat", st, o.exportFormat, ""); + st.endGroup(); +} + +static void _saveHistory(UserHistory &o, QSettings &st) +{ + st.beginGroup("UserHistory"); + setFiled("exportDir", st, o.exportDir); + setFiled("saveDir", st, o.saveDir); + setFiled("showDocuments", st, o.showDocuments); + setFiled("screenShotPath", st, o.screenShotPath); + setFiled("sessionDir", st, o.sessionDir); + setFiled("openDir", st, o.openDir); + setFiled("protocolExportPath", st, o.protocolExportPath); + setFiled("exportFormat", st, o.exportFormat); + st.endGroup(); +} + +/* +//------font +static void _loadFont(FontOptions &o, QSettings &st) +{ + st.beginGroup("FontSetting"); + getFiled("toolbarName", st, o.toolbar.name, ""); + getFiled("toolbarSize", st, o.toolbar.size, 9); + getFiled("channelLabelName", st, o.channelLabel.name, ""); + getFiled("channelLabelSize", st, o.channelLabel.size, 9); + getFiled("channelBodyName", st, o.channelBody.name, ""); + getFiled("channelBodySize", st, o.channelBody.size, 9); + getFiled("rulerName", st, o.ruler.name, ""); + getFiled("ruleSize", st, o.ruler.size, 9); + getFiled("titleName", st, o.title.name, ""); + getFiled("titleSize", st, o.title.size, 9); + getFiled("otherName", st, o.other.name, ""); + getFiled("otherSize", st, o.other.size, 9); + + st.endGroup(); +} + +static void _saveFont(FontOptions &o, QSettings &st) +{ + st.beginGroup("FontSetting"); + setFiled("toolbarName", st, o.toolbar.name); + setFiled("toolbarSize", st, o.toolbar.size); + setFiled("channelLabelName", st, o.channelLabel.name); + setFiled("channelLabelSize", st, o.channelLabel.size); + setFiled("channelBodyName", st, o.channelBody.name); + setFiled("channelBodySize", st, o.channelBody.size); + setFiled("rulerName", st, o.ruler.name); + setFiled("ruleSize", st, o.ruler.size); + setFiled("titleName", st, o.title.name); + setFiled("titleSize", st, o.title.size); + setFiled("otherName", st, o.other.name); + setFiled("otherSize", st, o.other.size); + + st.endGroup(); +} +*/ + +//------------AppConfig + +AppConfig::AppConfig() +{ +} + +AppConfig::AppConfig(AppConfig &o) +{ + (void)o; +} + +AppConfig::~AppConfig() +{ +} + + AppConfig& AppConfig::Instance() + { + static AppConfig *ins = NULL; + if (ins == NULL){ + ins = new AppConfig(); + } + return *ins; + } + +void AppConfig::LoadAll() +{ + QSettings st(QApplication::organizationName(), QApplication::applicationName()); + _loadApp(appOptions, st); + _loadHistory(userHistory, st); + _loadFrame(frameOptions, st); + + //dsv_dbg("Config file path:\"%s\"", st.fileName().toUtf8().data()); +} + +void AppConfig::SaveApp() +{ + QSettings st(QApplication::organizationName(), QApplication::applicationName()); + _saveApp(appOptions, st); +} + +void AppConfig::SaveHistory() +{ + QSettings st(QApplication::organizationName(), QApplication::applicationName()); + _saveHistory(userHistory, st); +} + +void AppConfig::SaveFrame() +{ + QSettings st(QApplication::organizationName(), QApplication::applicationName()); + _saveFrame(frameOptions, st); +} + +void AppConfig::SetProtocolFormat(const std::string &protocolName, const std::string &value) +{ + bool bChange = false; + for (StringPair &o : appOptions.m_protocolFormats){ + if (o.m_key == protocolName){ + o.m_value = value; + bChange = true; + break; + } + } + + if (!bChange) + { + if (appOptions.m_protocolFormats.size() > MAX_PROTOCOL_FORMAT_LIST) + { + while (appOptions.m_protocolFormats.size() < MAX_PROTOCOL_FORMAT_LIST) + { + appOptions.m_protocolFormats.erase(appOptions.m_protocolFormats.begin()); + } + } + appOptions.m_protocolFormats.push_back(StringPair(protocolName, value)); + bChange = true; + } + + if (bChange){ + SaveApp(); + } +} + +std::string AppConfig::GetProtocolFormat(const std::string &protocolName) +{ + for (StringPair &o : appOptions.m_protocolFormats){ + if (o.m_key == protocolName){ + return o.m_value; + } + } + return ""; +} + +void AppConfig::GetFontSizeRange(float *minSize, float *maxSize) +{ + assert(minSize); + assert(maxSize); + +#ifdef _WIN32 + *minSize = 7; + *maxSize = 12; +#endif + +#ifdef Q_OS_LINUX + *minSize = 8; + *maxSize = 14; +#endif + +#ifdef Q_OS_DARWIN + *minSize = 9; + *maxSize = 15; +#endif +} + + +//-------------api +QString GetIconPath() +{ + QString style = AppConfig::Instance().frameOptions.style; + if (style == ""){ + style = THEME_STYLE_DARK; + } + return ":/icons/" + style; +} + +QString GetAppDataDir() +{ +//applicationDirPath not end with '/' +#ifdef Q_OS_LINUX + QDir dir(QCoreApplication::applicationDirPath()); + if (dir.cd("..") && dir.cd("share") && dir.cd("DSView")) + { + return dir.absolutePath(); + } + QDir dir1("/usr/local/share/DSView"); + if (dir1.exists()){ + return dir1.absolutePath(); + } + + dsv_err("Data directory is not exists: ../share/DSView"); + assert(false); +#else + +#ifdef Q_OS_DARWIN + QDir dir1(QCoreApplication::applicationDirPath()); + //"./res" is not exists + if (dir1.cd("res") == false){ + QDir dir(QCoreApplication::applicationDirPath()); + // ../share/DSView + if (dir.cd("..") && dir.cd("share") && dir.cd("DSView")) + { + return dir.absolutePath(); + } + } +#endif + + // The bin location + return QCoreApplication::applicationDirPath(); +#endif +} + +QString GetFirmwareDir() +{ + QDir dir1 = GetAppDataDir() + "/res"; + // ./res + if (dir1.exists()){ + return dir1.absolutePath(); + } + + QDir dir(QCoreApplication::applicationDirPath()); + // ../share/DSView/res + if (dir.cd("..") && dir.cd("share") && dir.cd("DSView") && dir.cd("res")) + { + return dir.absolutePath(); + } + + dsv_err("%s%s", "Resource directory is not exists:", dir1.absolutePath().toUtf8().data()); + return dir1.absolutePath(); +} + +QString GetUserDataDir() +{ + #if QT_VERSION >= 0x050400 + return QStandardPaths::writableLocation(QStandardPaths::AppDataLocation); + #else + return QStandardPaths::writableLocation(QStandardPaths::DataLocation); + #endif +} + +QString GetDecodeScriptDir() +{ + QString path = GetAppDataDir() + "/decoders"; + + QDir dir1; + // ./decoders + if (dir1.exists(path)) + { + return path; + } + + QDir dir(QCoreApplication::applicationDirPath()); + // ../share/libsigrokdecode4DSL/decoders + if (dir.cd("..") && dir.cd("share") && dir.cd("libsigrokdecode4DSL") && dir.cd("decoders")) + { + return dir.absolutePath(); + } + return ""; +} + +QString GetProfileDir() +{ + #if QT_VERSION >= 0x050400 + return QStandardPaths::writableLocation(QStandardPaths::AppDataLocation); + #else + return QStandardPaths::writableLocation(QStandardPaths::DataLocation); + #endif } \ No newline at end of file diff --git a/DSView/pv/config/appconfig.h b/DSView/pv/config/appconfig.h index 2e8ff817..0cccbebe 100644 --- a/DSView/pv/config/appconfig.h +++ b/DSView/pv/config/appconfig.h @@ -1,164 +1,165 @@ -/* - * This file is part of the DSView project. - * DSView is based on PulseView. - * - * Copyright (C) 2021 DreamSourceLab - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#pragma once - -#include -#include -#include -#include - -#define LAN_CN 25 -#define LAN_EN 31 - -#define THEME_STYLE_DARK "dark" -#define THEME_STYLE_LIGHT "light" - -#define APP_NAME "DSView" - -//--------------------api--- -QString GetIconPath(); -QString GetAppDataDir(); -QString GetFirmwareDir(); -QString GetUserDataDir(); -QString GetDecodeScriptDir(); -QString GetProfileDir(); - -//------------------class - -class StringPair -{ -public: - StringPair(const std::string &key, const std::string &value); - std::string m_key; - std::string m_value; -}; - - -#define APP_CONFIG_VERSION 3 -#define NO_POINT_VALUE -10000 - -struct AppOptions -{ - int version; - bool quickScroll; - bool warnofMultiTrig; - bool originalData; - bool ableSaveLog; - bool appendLogMode; - int logLevel; - bool transDecoderDlg; - bool trigPosDisplayInMid; - bool displayProfileInBar; - bool swapBackBufferAlways; - bool autoScrollLatestData; - float fontSize; - - std::vector m_protocolFormats; -}; - - // The dock pannel open status. - struct DockOptions - { - bool decodeDock; - bool triggerDock; - bool measureDock; - bool searchDock; -}; - -struct FrameOptions -{ - QString style; - int language; - int left; //frame region - int top; - int right; - int bottom; - int x; - int y; - int ox; - int oy; - bool isMax; - QByteArray windowState; - - DockOptions _logicDock; - DockOptions _analogDock; - DockOptions _dsoDock; -}; - -struct UserHistory -{ - QString exportDir; - QString saveDir; - bool showDocuments; - QString screenShotPath; - QString sessionDir; - QString openDir; - QString protocolExportPath; - QString exportFormat; -}; - -struct FontParam -{ - QString name; - float size; -}; - -struct FontOptions -{ - FontParam toolbar; - FontParam channelLabel; - FontParam channelBody; - FontParam ruler; - FontParam title; - FontParam other; -}; - -class AppConfig -{ -private: - AppConfig(); - ~AppConfig(); - AppConfig(AppConfig &o); - -public: - static AppConfig &Instance(); - - void LoadAll(); - void SaveApp(); - void SaveHistory(); - void SaveFrame(); - - void SetProtocolFormat(const std::string &protocolName, const std::string &value); - std::string GetProtocolFormat(const std::string &protocolName); - - inline bool IsLangCn() - { - return frameOptions.language == LAN_CN; - } - - static void GetFontSizeRange(float *minSize, float *maxSize); - -public: - AppOptions appOptions; - UserHistory userHistory; - FrameOptions frameOptions; -}; +/* + * This file is part of the DSView project. + * DSView is based on PulseView. + * + * Copyright (C) 2021 DreamSourceLab + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#pragma once + +#include +#include +#include +#include + +#define LAN_CN 25 +#define LAN_EN 31 + +#define THEME_STYLE_DARK "dark" +#define THEME_STYLE_LIGHT "light" + +#define APP_NAME "DSView" + +//--------------------api--- +QString GetIconPath(); +QString GetAppDataDir(); +QString GetFirmwareDir(); +QString GetUserDataDir(); +QString GetDecodeScriptDir(); +QString GetProfileDir(); + +//------------------class + +class StringPair +{ +public: + StringPair(const std::string &key, const std::string &value); + std::string m_key; + std::string m_value; +}; + + +#define APP_CONFIG_VERSION 3 +#define NO_POINT_VALUE -10000 + +struct AppOptions +{ + int version; + bool quickScroll; + bool warnofMultiTrig; + bool originalData; + bool ableSaveLog; + bool appendLogMode; + int logLevel; + bool transDecoderDlg; + bool trigPosDisplayInMid; + bool displayProfileInBar; + bool swapBackBufferAlways; + bool autoScrollLatestData; + float fontSize; + + std::vector m_protocolFormats; +}; + + // The dock pannel open status. + struct DockOptions + { + bool decodeDock; + bool triggerDock; + bool measureDock; + bool searchDock; +}; + +struct FrameOptions +{ + QString style; + int language; + int left; //frame region + int top; + int right; + int bottom; + int x; + int y; + int ox; + int oy; + bool isMax; + QString displayName; + QByteArray windowState; + + DockOptions _logicDock; + DockOptions _analogDock; + DockOptions _dsoDock; +}; + +struct UserHistory +{ + QString exportDir; + QString saveDir; + bool showDocuments; + QString screenShotPath; + QString sessionDir; + QString openDir; + QString protocolExportPath; + QString exportFormat; +}; + +struct FontParam +{ + QString name; + float size; +}; + +struct FontOptions +{ + FontParam toolbar; + FontParam channelLabel; + FontParam channelBody; + FontParam ruler; + FontParam title; + FontParam other; +}; + +class AppConfig +{ +private: + AppConfig(); + ~AppConfig(); + AppConfig(AppConfig &o); + +public: + static AppConfig &Instance(); + + void LoadAll(); + void SaveApp(); + void SaveHistory(); + void SaveFrame(); + + void SetProtocolFormat(const std::string &protocolName, const std::string &value); + std::string GetProtocolFormat(const std::string &protocolName); + + inline bool IsLangCn() + { + return frameOptions.language == LAN_CN; + } + + static void GetFontSizeRange(float *minSize, float *maxSize); + +public: + AppOptions appOptions; + UserHistory userHistory; + FrameOptions frameOptions; +}; diff --git a/DSView/pv/interface/icallbacks.h b/DSView/pv/interface/icallbacks.h index aa523d24..3a5a4b32 100644 --- a/DSView/pv/interface/icallbacks.h +++ b/DSView/pv/interface/icallbacks.h @@ -1,128 +1,128 @@ - -/* - * This file is part of the DSView project. - * DSView is based on PulseView. - * - * Copyright (C) 2021 DreamSourceLab - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef _I_CALLBACKS_ -#define _I_CALLBACKS_ - - -class ISessionCallback -{ -public: - virtual void session_error()=0; - virtual void session_save()=0; - virtual void data_updated()=0; - virtual void update_capture()=0; - virtual void cur_snap_samplerate_changed()=0; - virtual void signals_changed()=0; - virtual void receive_trigger(quint64 trigger_pos)=0; - virtual void frame_ended()=0; - virtual void frame_began()=0; - virtual void show_region(uint64_t start, uint64_t end, bool keep)=0; - virtual void show_wait_trigger()=0; - virtual void repeat_hold(int percent)=0; - virtual void decode_done()=0; - virtual void receive_data_len(quint64 len)=0; - virtual void receive_header()=0; - virtual void trigger_message(int msg)=0; - virtual void delay_prop_msg(QString strMsg)=0; -}; - -class ISessionDataGetter -{ -public: - virtual bool genSessionData(std::string &str) = 0; -}; - - -class IDlgCallback -{ -public: - virtual void OnDlgResult(bool bYes)=0; -}; - -class IMainForm{ -public: - virtual void switchLanguage(int language)=0; -}; - - -#define DSV_MSG_START_COLLECT_WORK_PREV 5001 -#define DSV_MSG_START_COLLECT_WORK 5002 -#define DSV_MSG_COLLECT_START 5003 -#define DSV_MSG_COLLECT_END 5004 -#define DSV_MSG_END_COLLECT_WORK_PREV 5005 -#define DSV_MSG_END_COLLECT_WORK 5006 -#define DSV_MSG_REV_END_PACKET 5007 - -#define DSV_MSG_DEVICE_LIST_UPDATED 6000 -#define DSV_MSG_BEGIN_DEVICE_OPTIONS 6001 //Begin show device options dialog. -#define DSV_MSG_END_DEVICE_OPTIONS 6002 -#define DSV_MSG_DEVICE_OPTIONS_UPDATED 6003 -#define DSV_MSG_DEVICE_DURATION_UPDATED 6004 -#define DSV_MSG_DEVICE_MODE_CHANGED 6005 -#define DSV_MSG_CURRENT_DEVICE_CHANGE_PREV 6006 -#define DSV_MSG_CURRENT_DEVICE_CHANGED 6007 -#define DSV_MSG_NEW_USB_DEVICE 6008 -#define DSV_MSG_CURRENT_DEVICE_DETACHED 6009 -#define DSV_MSG_DEVICE_CONFIG_UPDATED 6010 -#define DSV_MSG_DEMO_OPERATION_MODE_CHNAGED 6011 -#define DSV_MSG_COLLECT_MODE_CHANGED 6012 -#define DSV_MSG_DATA_POOL_CHANGED 6013 - -#define DSV_MSG_TRIG_NEXT_COLLECT 7001 -#define DSV_MSG_SAVE_COMPLETE 7002 -#define DSV_MSG_STORE_CONF_PREV 7003 - -#define DSV_MSG_CLEAR_DECODE_DATA 8001 - -#define DSV_MSG_APP_OPTIONS_CHANGED 9001 -#define DSV_MSG_FONT_OPTIONS_CHANGED 9002 - -class IMessageListener -{ -public: - virtual void OnMessage(int msg)=0; -}; - -class IDecoderPannel -{ -public: - virtual void update_deocder_item_name(void *trace_handel, const char *name)=0; -}; - -class IFontForm -{ -public: - virtual void update_font()=0; -}; - -enum ParentNativeEvent{ - PARENT_EVENT_DISPLAY_CHANGED = 0, -}; - -class IParentNativeEventCallback -{ -public: - virtual void OnParentNativeEvent(ParentNativeEvent msg)=0; -}; - -#endif + +/* + * This file is part of the DSView project. + * DSView is based on PulseView. + * + * Copyright (C) 2021 DreamSourceLab + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _I_CALLBACKS_ +#define _I_CALLBACKS_ + + +class ISessionCallback +{ +public: + virtual void session_error()=0; + virtual void session_save()=0; + virtual void data_updated()=0; + virtual void update_capture()=0; + virtual void cur_snap_samplerate_changed()=0; + virtual void signals_changed()=0; + virtual void receive_trigger(quint64 trigger_pos)=0; + virtual void frame_ended()=0; + virtual void frame_began()=0; + virtual void show_region(uint64_t start, uint64_t end, bool keep)=0; + virtual void show_wait_trigger()=0; + virtual void repeat_hold(int percent)=0; + virtual void decode_done()=0; + virtual void receive_data_len(quint64 len)=0; + virtual void receive_header()=0; + virtual void trigger_message(int msg)=0; + virtual void delay_prop_msg(QString strMsg)=0; +}; + +class ISessionDataGetter +{ +public: + virtual bool genSessionData(std::string &str) = 0; +}; + + +class IDlgCallback +{ +public: + virtual void OnDlgResult(bool bYes)=0; +}; + +class IMainForm{ +public: + virtual void switchLanguage(int language)=0; +}; + + +#define DSV_MSG_START_COLLECT_WORK_PREV 5001 +#define DSV_MSG_START_COLLECT_WORK 5002 +#define DSV_MSG_COLLECT_START 5003 +#define DSV_MSG_COLLECT_END 5004 +#define DSV_MSG_END_COLLECT_WORK_PREV 5005 +#define DSV_MSG_END_COLLECT_WORK 5006 +#define DSV_MSG_REV_END_PACKET 5007 + +#define DSV_MSG_DEVICE_LIST_UPDATED 6000 +#define DSV_MSG_BEGIN_DEVICE_OPTIONS 6001 //Begin show device options dialog. +#define DSV_MSG_END_DEVICE_OPTIONS 6002 +#define DSV_MSG_DEVICE_OPTIONS_UPDATED 6003 +#define DSV_MSG_DEVICE_DURATION_UPDATED 6004 +#define DSV_MSG_DEVICE_MODE_CHANGED 6005 +#define DSV_MSG_CURRENT_DEVICE_CHANGE_PREV 6006 +#define DSV_MSG_CURRENT_DEVICE_CHANGED 6007 +#define DSV_MSG_NEW_USB_DEVICE 6008 +#define DSV_MSG_CURRENT_DEVICE_DETACHED 6009 +#define DSV_MSG_DEVICE_CONFIG_UPDATED 6010 +#define DSV_MSG_DEMO_OPERATION_MODE_CHNAGED 6011 +#define DSV_MSG_COLLECT_MODE_CHANGED 6012 +#define DSV_MSG_DATA_POOL_CHANGED 6013 + +#define DSV_MSG_TRIG_NEXT_COLLECT 7001 +#define DSV_MSG_SAVE_COMPLETE 7002 +#define DSV_MSG_STORE_CONF_PREV 7003 + +#define DSV_MSG_CLEAR_DECODE_DATA 8001 + +#define DSV_MSG_APP_OPTIONS_CHANGED 9001 +#define DSV_MSG_FONT_OPTIONS_CHANGED 9002 + +class IMessageListener +{ +public: + virtual void OnMessage(int msg)=0; +}; + +class IDecoderPannel +{ +public: + virtual void update_deocder_item_name(void *trace_handel, const char *name)=0; +}; + +class IFontForm +{ +public: + virtual void update_font()=0; +}; + +enum ParentNativeEvent{ + PARENT_EVENT_DISPLAY_CHANGED = 0, +}; + +class IParentNativeEventCallback +{ +public: + virtual void OnParentNativeEvent(ParentNativeEvent msg)=0; +}; + +#endif diff --git a/DSView/pv/mainframe.cpp b/DSView/pv/mainframe.cpp index 94c05535..c58b13b2 100644 --- a/DSView/pv/mainframe.cpp +++ b/DSView/pv/mainframe.cpp @@ -75,7 +75,7 @@ MainFrame::MainFrame() _freezing = false; _titleBar = NULL; _mainWindow = NULL; - _is_native_title = false; + _is_win32_parent_window = false; _is_resize_ready = false; _parentNativeWidget = NULL; _mainWindow = NULL; @@ -95,18 +95,19 @@ MainFrame::MainFrame() bool isWin32 = false; #ifdef _WIN32 - setWindowFlags(Qt::Window | Qt::FramelessWindowHint | Qt::WindowSystemMenuHint | Qt::WindowMinMaxButtonsHint); - _is_native_title = true; + setWindowFlags(Qt::FramelessWindowHint); + _is_win32_parent_window = true; _taskBtn = NULL; isWin32 = true; #else setWindowFlags(Qt::Window | Qt::FramelessWindowHint | Qt::WindowSystemMenuHint); setAttribute(Qt::WA_TranslucentBackground); - _is_native_title = false; + _is_win32_parent_window = false; #endif - + #ifdef _WIN32 - if (!_is_native_title){ + if (!_is_win32_parent_window){ + setWindowFlags(Qt::Window | Qt::FramelessWindowHint | Qt::WindowSystemMenuHint | Qt::WindowMinMaxButtonsHint); setAttribute(Qt::WA_TranslucentBackground); } #endif @@ -134,7 +135,7 @@ MainFrame::MainFrame() _layout->setContentsMargins(0,0,0,0); - if (!isWin32 || !_is_native_title) + if (!isWin32 || !_is_win32_parent_window) { _top_left = new widgets::Border (TopLeft, this); _top_left->setFixedSize(Margin, Margin); @@ -230,8 +231,7 @@ bool MainFrame::ParentIsMaxsized() void MainFrame::MoveBegin() { #ifdef _WIN32 - if (_parentNativeWidget != NULL){ - _parentNativeWidget->SetMovingFlag(true); + if (_parentNativeWidget != NULL){ _move_start_screen = _parentNativeWidget->GetPointScreen(); } #endif @@ -247,19 +247,18 @@ void MainFrame::MoveEnd() SetFormRegion(rc.x(), rc.y(), rc.width(), rc.height()); } +#ifndef _WIN32 saveNormalRegion(); +#endif #ifdef _WIN32 if (_parentNativeWidget != NULL){ auto scr = _parentNativeWidget->GetPointScreen(); if (scr != _move_start_screen){ - _parentNativeWidget->UpdateChildDpi(); - _parentNativeWidget->ResizeSelf(); + _parentNativeWidget->UpdateChildDpi(); } - _parentNativeWidget->ResizeChild(); - _parentNativeWidget->MoveShadow(); - _parentNativeWidget->SetMovingFlag(false); + _parentNativeWidget->ResizeChild(); } #endif } @@ -272,22 +271,23 @@ void MainFrame::OnParentNativeEvent(ParentNativeEvent msg) void MainFrame::OnParentNaitveWindowEvent(int msg) { #ifdef _WIN32 - if (_parentNativeWidget != NULL){ - if (msg == PARENT_EVENT_DISPLAY_CHANGED){ - QTimer::singleShot(100, this, [this](){ - PopupDlgList::TryCloseAllByScreenChanged(); - _parentNativeWidget->OnDisplayChanged(); - }); - } - } -#endif -} + if (_parentNativeWidget != NULL + && msg == PARENT_EVENT_DISPLAY_CHANGED){ -void MainFrame::OnMoveWinShadow() -{ -#ifdef _WIN32 - if (_parentNativeWidget != NULL){ - _parentNativeWidget->MoveShadow(); + QTimer::singleShot(100, this, [this](){ + auto scr = _parentNativeWidget->GetPointScreen(); + if (scr == NULL){ + dsv_info("ERROR: failed to get point screen, will to get the primary."); + scr = QGuiApplication::primaryScreen(); + } + + PopupDlgList::TryCloseAllByScreenChanged(scr); + PopupDlgList::SetCurrentScreen(scr); + + _parentNativeWidget->UpdateChildDpi(); + _parentNativeWidget->ResizeChild(); + _parentNativeWidget->ReShowWindow(); + }); } #endif } @@ -320,7 +320,8 @@ void MainFrame::closeEvent(QCloseEvent *event) #ifdef _WIN32 if (_parentNativeWidget != NULL){ _parentNativeWidget->SetChildWidget(NULL); - _parentNativeWidget->Show(false); + setVisible(false); + _parentNativeWidget->Show(false); } #endif @@ -428,6 +429,12 @@ bool MainFrame::eventFilter(QObject *object, QEvent *event) int newLeft = 0; int newTop = 0; +#ifdef _WIN32 + if (_parentNativeWidget != NULL){ + return QFrame::eventFilter(object, event); + } +#endif + if (type != QEvent::MouseMove && type != QEvent::MouseButtonPress && type != QEvent::MouseButtonRelease @@ -477,21 +484,8 @@ bool MainFrame::eventFilter(QObject *object, QEvent *event) QPoint pt; int k = 1; - -#ifdef _WIN32 - POINT p; - GetCursorPos(&p); - pt.setX(p.x); - pt.setY(p.y); - - if (_parentNativeWidget != NULL){ - auto scr = _parentNativeWidget->GetPointScreen(); - assert(scr); - k = scr->devicePixelRatio(); - } -#else pt = mouse_event->globalPos(); -#endif + int datX = pt.x() - _clickPos.x(); int datY = pt.y() - _clickPos.y(); datX /= k; @@ -580,7 +574,9 @@ bool MainFrame::eventFilter(QObject *object, QEvent *event) if (r != l){ SetFormRegion(l, t, r-l, b-t); - saveNormalRegion(); + #ifndef _WIN32 + saveNormalRegion(); + #endif } return true; @@ -592,15 +588,7 @@ bool MainFrame::eventFilter(QObject *object, QEvent *event) _bDraging = true; _timer.start(50); -#ifdef _WIN32 - POINT p; - GetCursorPos(&p); - _clickPos.setX(p.x); - _clickPos.setY(p.y); -#else _clickPos = mouse_event->globalPos(); -#endif - _dragStartRegion = GetFormRegion(); } else if (type == QEvent::MouseButtonRelease) { @@ -630,10 +618,8 @@ void MainFrame::saveNormalRegion() #ifdef _WIN32 if (_parentNativeWidget != NULL){ - RECT rc; - auto scr = _parentNativeWidget->GetPointScreen(); - assert(scr); - int k = scr->devicePixelRatio(); + RECT rc; + int k = _parentNativeWidget->GetDevicePixelRatio(); GetWindowRect(_parentNativeWidget->Handle(), &rc); app.frameOptions.left = rc.left / k; @@ -661,6 +647,18 @@ void MainFrame::writeSettings() AppConfig &app = AppConfig::Instance(); app.frameOptions.isMax = IsMaxsized(); +#ifdef _WIN32 + if (_parentNativeWidget != NULL){ + auto scr = _parentNativeWidget->GetPointScreen(); + app.frameOptions.displayName = scr->name(); + } + else{ + app.frameOptions.displayName = windowHandle()->screen()->name(); + } +#else + app.frameOptions.displayName = windowHandle()->screen()->name(); +#endif + if (IsNormalsized() && isVisible()){ saveNormalRegion(); } @@ -698,24 +696,31 @@ void MainFrame::ShowFormInit() x, y, w, h, _initWndInfo.k); bool isWin32 = false; - #ifdef _WIN32 isWin32 = true; #endif if (_initWndInfo.isMaxSize){ move(x, y); - showMaximized(); + if (isWin32 &&_is_win32_parent_window){ + resize(w, h); + } + else{ + showMaximized(); + } } else{ move(x, y); resize(w, h); } - QFrame::show(); - - #ifdef _WIN32 - if (_is_native_title){ + if (!_is_win32_parent_window){ + QFrame::show(); + return; + } + +#ifdef _WIN32 + if (_is_win32_parent_window){ AttachNativeWindow(); } #endif @@ -727,19 +732,19 @@ void MainFrame::AttachNativeWindow() assert(_parentNativeWidget == NULL); - int k = _initWndInfo.k; - - int x = _normalRegion.x; - int y = _normalRegion.y; - int w = _normalRegion.w; - int h = _normalRegion.h; + int k = _initWndInfo.k; + int x = _normalRegion.x * k; + int y = _normalRegion.y * k; + int w = _normalRegion.w * k; + int h = _normalRegion.h * k; - x *= k; - y *= k; - w *= k; - h *= k; + bool isDrak = false; + + if (AppConfig::Instance().frameOptions.style == THEME_STYLE_DARK){ + isDrak = true; + } - WinNativeWidget *nativeWindow = new WinNativeWidget(x, y, w, h); + WinNativeWidget *nativeWindow = new WinNativeWidget(x, y, w, h, isDrak); nativeWindow->setGeometry(x, y, w, h); if (nativeWindow->Handle() == NULL){ @@ -751,6 +756,7 @@ void MainFrame::AttachNativeWindow() QScreen *scr = nativeWindow->GetPointScreen(); if (scr != NULL){ QRect full_rc = scr->availableGeometry(); + PopupDlgList::SetCurrentScreen(scr); if (full_rc.width() - _normalRegion.w < 100 && !_initWndInfo.isMaxSize) { @@ -769,6 +775,12 @@ void MainFrame::AttachNativeWindow() dsv_info("ERROR: get point screen error."); } + nativeWindow->SetChildWidget(this); + nativeWindow->SetNativeEventCallback(this); + nativeWindow->UpdateChildDpi(); + nativeWindow->SetTitleBarWidget(_titleBar); + _titleBar->EnableAbleDrag(false); + setWindowFlags(Qt::FramelessWindowHint); setProperty("_q_embedded_native_parent_handle", (WId)nativeWindow->Handle()); SetWindowLong((HWND)winId(), GWL_STYLE, WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS); @@ -776,6 +788,8 @@ void MainFrame::AttachNativeWindow() QEvent e(QEvent::EmbeddingControl); QApplication::sendEvent(this, &e); + + setVisible(true); if (_initWndInfo.isMaxSize){ nativeWindow->ShowMax(); @@ -783,25 +797,10 @@ void MainFrame::AttachNativeWindow() else{ nativeWindow->Show(true); } - - nativeWindow->SetChildWidget(this); - nativeWindow->SetNativeEventCallback(this); + + nativeWindow->SetBorderColor(QColor(0x80, 0x80, 0x80)); _parentNativeWidget = nativeWindow; - auto shandow = _parentNativeWidget->Shadow(); - if (shandow){ - shandow->SetFrame(this); - connect(shandow, SIGNAL(showSignal()), this, SLOT(OnMoveWinShadow())); - } - - QTimer::singleShot(50, this, [this](){ - move(0,0); - setVisible(true); - _parentNativeWidget->UpdateChildDpi(); - _parentNativeWidget->ResizeChild(); - _parentNativeWidget->BeginShowShadow(); - }); - #endif } @@ -810,9 +809,7 @@ void MainFrame::SetFormRegion(int x, int y, int w, int h) #ifdef _WIN32 if (_parentNativeWidget != NULL){ - auto scr = _parentNativeWidget->GetPointScreen(); - assert(scr); - int k = scr->devicePixelRatio(); + int k = _parentNativeWidget->GetDevicePixelRatio(); x *= k; y *= k; @@ -835,9 +832,7 @@ QRect MainFrame::GetFormRegion() #ifdef _WIN32 if (_parentNativeWidget != NULL){ - auto scr = _parentNativeWidget->GetPointScreen(); - assert(scr); - int k = scr->devicePixelRatio(); + int k = _parentNativeWidget->GetDevicePixelRatio(); RECT r; GetWindowRect(_parentNativeWidget->Handle(), &r); int x = r.left; @@ -886,33 +881,22 @@ bool MainFrame::IsMoving() return _titleBar->IsMoving(); } -int MainFrame::GetDevicePixelRatio() -{ -#ifdef _WIN32 - if (_parentNativeWidget != NULL){ - auto scr = _parentNativeWidget->GetPointScreen(); - assert(scr); - return scr->devicePixelRatio(); - } -#endif - - return windowHandle()->devicePixelRatio(); -} - void MainFrame::ReadSettings() { - AppConfig &app = AppConfig::Instance(); + AppConfig &app = AppConfig::Instance(); if (app.frameOptions.language > 0){ _mainWindow->switchLanguage(app.frameOptions.language); } + // The history scale region. int left = app.frameOptions.left; int top = app.frameOptions.top; int right = app.frameOptions.right; int bottom = app.frameOptions.bottom; int x = app.frameOptions.x; - int y = app.frameOptions.y; + int y = app.frameOptions.y; + QString lstDisplayName = app.frameOptions.displayName; if (x == NO_POINT_VALUE){ x = left; @@ -922,30 +906,52 @@ void MainFrame::ReadSettings() dsv_info("Read region info, x:%d, y:%d, w:%d, h:%d, isMax:%d", x, y, right-left, bottom-top, app.frameOptions.isMax); + if (lstDisplayName != ""){ + dsv_info("Last display:%s", lstDisplayName.toStdString().c_str()); + } + bool bReset = false; int scrIndex = -1; - - QRect winRc = {x, y, right-left, bottom-top}; - + int k = 1; + int zoomk = 1; + QString scrName = ""; + QRect full_rect = QRect(0,0,0,0); + QScreen *screen = NULL; + for (int i=0; iavailableGeometry(); - QRect inrc = rc.intersected(winRc); + QRect rc = QGuiApplication::screens().at(i)->availableGeometry(); QString name = QGuiApplication::screens().at(i)->name(); - dsv_info("Screen name:%s, region, left:%d, top:%d, right:%d, bottom:%d", - name.toStdString().c_str(), rc.left(), rc.top(), rc.right(), rc.bottom() ); - - if (scrIndex == -1 && (inrc.width() > 10 || inrc.height() > 10)){ + if (name == lstDisplayName){ scrIndex = i; } - } + dsv_info("Screen name:%s, region, left:%d, top:%d, width:%d, height:%d", + name.toStdString().c_str(), rc.left(), rc.top(), rc.width(), rc.height() ); + } + if (scrIndex == -1){ bReset = true; + screen = QGuiApplication::primaryScreen(); } - else{ - QRect rc = QGuiApplication::screens().at(scrIndex)->availableGeometry(); - QRect inrc = rc.intersected(winRc); + else{ + screen = QGuiApplication::screens().at(scrIndex); + } + + full_rect = screen->availableGeometry(); + k = screen->devicePixelRatio(); + scrName = screen->name(); + +#ifdef _WIN32 + if (_is_win32_parent_window){ + zoomk = k; + } +#endif + + QRect winRc = {x * zoomk, y * zoomk, right-left, bottom-top}; + + if (!bReset){ + QRect inrc = full_rect.intersected(winRc); if (inrc.width() < 70 || inrc.height() < 70 || winRc.width() < 300){ bReset = true; } @@ -956,28 +962,13 @@ void MainFrame::ReadSettings() _initWndInfo.r.w = 0; _initWndInfo.r.h = 0; _initWndInfo.isMaxSize = false; - int k = 1; - + if (app.frameOptions.isMax) { - QRect rc; - QString scrName; - - if (scrIndex == -1){ - rc = QGuiApplication::primaryScreen()->availableGeometry(); - scrName = QGuiApplication::primaryScreen()->name(); - k = QGuiApplication::primaryScreen()->devicePixelRatio(); - } - else{ - rc = QGuiApplication::screens().at(scrIndex)->availableGeometry(); - scrName = QGuiApplication::screens().at(scrIndex)->name(); - k = QGuiApplication::screens().at(scrIndex)->devicePixelRatio(); - } - - _initWndInfo.r.x = rc.left(); - _initWndInfo.r.y = rc.top(); - _initWndInfo.r.w = rc.width(); - _initWndInfo.r.h = rc.height(); + _initWndInfo.r.x = full_rect.left(); + _initWndInfo.r.y = full_rect.top(); + _initWndInfo.r.w = full_rect.width(); + _initWndInfo.r.h = full_rect.height(); _initWndInfo.isMaxSize = true; _normalRegion.x = x; @@ -985,44 +976,37 @@ void MainFrame::ReadSettings() _normalRegion.w = right-left; _normalRegion.h = bottom-top; - QRect inrc = rc.intersected(winRc); - if (inrc.width() < 70 || inrc.height() < 70 || winRc.width() < 300){ - _normalRegion.x = rc.left() + (rc.width() - _normalRegion.w) / 2; - _normalRegion.y = rc.top() + (rc.height() - _normalRegion.h) / 2; + QRect inrc = full_rect.intersected(winRc); + if (inrc.width() < 70 || inrc.height() < 70 || winRc.width() < 100){ + _normalRegion.x = full_rect.left() + + (full_rect.width() - _normalRegion.w) / 2 * zoomk; + _normalRegion.y = full_rect.top() + + (full_rect.height() - _normalRegion.h) / 2 * zoomk; + + _normalRegion.x /= zoomk; + _normalRegion.y /= zoomk; } dsv_info("Show as max, screen:%s, x:%d, y:%d, w:%d, h:%d", - scrName.toStdString().c_str(), rc.x(), rc.y(), rc.width(), rc.height()); + scrName.toStdString().c_str(), full_rect.x(), full_rect.y(), + full_rect.width(), full_rect.height()); } else if (bReset) - { - QRect rc; - QString scrName; - - if (scrIndex == -1){ - rc = QGuiApplication::primaryScreen()->availableGeometry(); - scrName = QGuiApplication::primaryScreen()->name(); - k = QGuiApplication::primaryScreen()->devicePixelRatio(); - } - else{ - rc = QGuiApplication::screens().at(scrIndex)->availableGeometry(); - scrName = QGuiApplication::screens().at(scrIndex)->name(); - k = QGuiApplication::screens().at(scrIndex)->devicePixelRatio(); - } - - int w = rc.width() / 1.5; - int h = rc.height() / 1.5; - const int x0 = rc.left() + (rc.width() - w) / 2; - const int y0 = rc.top() + (rc.height() - h) / 2; - - _initWndInfo.r.x = x0; - _initWndInfo.r.y = y0; + { + int w = full_rect.width() / 1.5; + int h = full_rect.height() / 1.5; + int x0 = full_rect.left() + (full_rect.width() - w) / 2 * zoomk; + int y0 = full_rect.top() + (full_rect.height() - h) / 2 * zoomk; + + _initWndInfo.r.x = x0 / zoomk; + _initWndInfo.r.y = y0 / zoomk; _initWndInfo.r.w = w; _initWndInfo.r.h = h; _normalRegion = _initWndInfo.r; dsv_info("Reset, screen:%s, x:%d, y:%d, w:%d, h:%d", - scrName.toStdString().c_str(), rc.left(), rc.top(), rc.width(), rc.height()); + scrName.toStdString().c_str(), full_rect.left(), full_rect.top(), + full_rect.width(), full_rect.height()); } else { @@ -1041,13 +1025,11 @@ void MainFrame::ReadSettings() #endif _initWndInfo.r.w = right - left; _initWndInfo.r.h = bottom - top; - _normalRegion = _initWndInfo.r; - QString scrName = QGuiApplication::screens().at(scrIndex)->name(); - QRect rc = QGuiApplication::screens().at(scrIndex)->availableGeometry(); - k = QGuiApplication::screens().at(scrIndex)->devicePixelRatio(); + _normalRegion = _initWndInfo.r; dsv_info("Restore, screen:%s, x:%d, y:%d, w:%d, h:%d", - scrName.toStdString().c_str() ,rc.left(), rc.top(), rc.width(), rc.height()); + scrName.toStdString().c_str() ,full_rect.left(), full_rect.top(), + full_rect.width(), full_rect.height()); } dsv_info("Normal region, x:%d, y:%d, w:%d, h:%d", @@ -1137,4 +1119,33 @@ void MainFrame::show_doc() } } +bool MainFrame::nativeEvent(const QByteArray &eventType, void *message, long *result) +{ +#ifdef _WIN32 + + if (_parentNativeWidget != NULL) + { + MSG *msg = static_cast(message); + HWND hwnd = _parentNativeWidget->Handle(); + + switch (msg->message) + { + case WM_NCMOUSEMOVE: + case WM_NCLBUTTONDOWN: + case WM_NCLBUTTONUP: + case WM_NCLBUTTONDBLCLK: + case WM_NCHITTEST: + { + *result = long(SendMessageW(hwnd, + msg->message, msg->wParam, msg->lParam)); + return true; + } + } + } + +#endif + + return QWidget::nativeEvent(eventType, message, result); +} + } // namespace pv diff --git a/DSView/pv/mainframe.h b/DSView/pv/mainframe.h index 726cafbe..00a336c8 100644 --- a/DSView/pv/mainframe.h +++ b/DSView/pv/mainframe.h @@ -98,7 +98,6 @@ public: bool IsMaxsized(); bool IsNormalsized(); bool IsMoving(); - int GetDevicePixelRatio(); void SetFormRegion(int x, int y, int w, int h); QRect GetFormRegion(); void saveNormalRegion(); @@ -112,6 +111,8 @@ protected: #endif void changeEvent(QEvent *event) override; + + bool nativeEvent(const QByteArray &eventType, void *message, long *result) override; signals: void sig_ParentNativeEvent(int msg); @@ -125,13 +126,11 @@ public slots: void showMaximized(); void showMinimized(); void OnParentNaitveWindowEvent(int msg); - void OnMoveWinShadow(); - + private: void hide_border(); void show_border(); void writeSettings(); - void ReadSettings(); void AttachNativeWindow(); @@ -170,9 +169,8 @@ private: QWinTaskbarProgress *_taskPrg; #endif - bool _is_native_title; - bool _is_resize_ready; - + bool _is_win32_parent_window; + bool _is_resize_ready; WinNativeWidget *_parentNativeWidget; FormInitInfo _initWndInfo; FormRegion _normalRegion; diff --git a/DSView/pv/mainwindow.cpp b/DSView/pv/mainwindow.cpp index c28b5ea8..b0ef2940 100644 --- a/DSView/pv/mainwindow.cpp +++ b/DSView/pv/mainwindow.cpp @@ -1,2198 +1,2199 @@ -/* - * This file is part of the DSView project. - * DSView is based on PulseView. - * - * Copyright (C) 2012 Joel Holdsworth - * Copyright (C) 2013 DreamSourceLab - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -//include with qt5 -#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) -#include -#endif - -#include "mainwindow.h" - -#include "data/logicsnapshot.h" -#include "data/dsosnapshot.h" -#include "data/analogsnapshot.h" - -#include "dialogs/about.h" -#include "dialogs/deviceoptions.h" -#include "dialogs/storeprogress.h" -#include "dialogs/waitingdialog.h" -#include "dialogs/regionoptions.h" - -#include "toolbars/samplingbar.h" -#include "toolbars/trigbar.h" -#include "toolbars/filebar.h" -#include "toolbars/logobar.h" -#include "toolbars/titlebar.h" - -#include "dock/triggerdock.h" -#include "dock/dsotriggerdock.h" -#include "dock/measuredock.h" -#include "dock/searchdock.h" -#include "dock/protocoldock.h" - -#include "view/view.h" -#include "view/trace.h" -#include "view/signal.h" -#include "view/dsosignal.h" -#include "view/logicsignal.h" -#include "view/analogsignal.h" - -/* __STDC_FORMAT_MACROS is required for PRIu64 and friends (in C++). */ -#include -#include -#include -#include -#include -#include "ui/msgbox.h" -#include "config/appconfig.h" -#include "appcontrol.h" -#include "dsvdef.h" -#include "appcontrol.h" -#include "utility/encoding.h" -#include "utility/path.h" -#include "log.h" -#include "sigsession.h" -#include "deviceagent.h" -#include -#include "ZipMaker.h" -#include "ui/langresource.h" -#include "mainframe.h" -#include "dsvdef.h" -#include - -namespace pv -{ - - namespace{ - QString tmp_file; - } - - MainWindow::MainWindow(toolbars::TitleBar *title_bar, QWidget *parent) - : QMainWindow(parent) - { - _msg = NULL; - _frame = parent; - - assert(title_bar); - assert(_frame); - - _title_bar = title_bar; - AppControl::Instance()->add_font_form(title_bar); - - _session = AppControl::Instance()->GetSession(); - _session->set_callback(this); - _device_agent = _session->get_device(); - _session->add_msg_listener(this); - - _is_auto_switch_device = false; - _is_save_confirm_msg = false; - - _pattern_mode = "random"; - - setup_ui(); - - setContextMenuPolicy(Qt::NoContextMenu); - - _key_vaild = false; - _last_key_press_time = high_resolution_clock::now(); - - update_title_bar_text(); - } - - void MainWindow::setup_ui() - { - setObjectName(QString::fromUtf8("MainWindow")); - setContentsMargins(0, 0, 0, 0); - layout()->setSpacing(0); - - // Setup the central widget - _central_widget = new QWidget(this); - _vertical_layout = new QVBoxLayout(_central_widget); - _vertical_layout->setSpacing(0); - _vertical_layout->setContentsMargins(0, 0, 0, 0); - setCentralWidget(_central_widget); - - // Setup the sampling bar - _sampling_bar = new toolbars::SamplingBar(_session, this); - _sampling_bar->setObjectName("sampling_bar"); - _trig_bar = new toolbars::TrigBar(_session, this); - _trig_bar->setObjectName("trig_bar"); - _file_bar = new toolbars::FileBar(_session, this); - _file_bar->setObjectName("file_bar"); - _logo_bar = new toolbars::LogoBar(_session, this); - _logo_bar->setObjectName("logo_bar"); - - // trigger dock - _trigger_dock = new QDockWidget(L_S(STR_PAGE_DLG, S_ID(IDS_DLG_TRIGGER_DOCK_TITLE), "Trigger Setting..."), this); - _trigger_dock->setObjectName("trigger_dock"); - _trigger_dock->setFeatures(QDockWidget::DockWidgetMovable); - _trigger_dock->setAllowedAreas(Qt::RightDockWidgetArea); - _trigger_dock->setVisible(false); - _trigger_widget = new dock::TriggerDock(_trigger_dock, _session); - _trigger_dock->setWidget(_trigger_widget); - - _dso_trigger_dock = new QDockWidget(L_S(STR_PAGE_DLG, S_ID(IDS_DLG_TRIGGER_DOCK_TITLE), "Trigger Setting..."), this); - _dso_trigger_dock->setObjectName("dso_trigger_dock"); - _dso_trigger_dock->setFeatures(QDockWidget::DockWidgetMovable); - _dso_trigger_dock->setAllowedAreas(Qt::RightDockWidgetArea); - _dso_trigger_dock->setVisible(false); - _dso_trigger_widget = new dock::DsoTriggerDock(_dso_trigger_dock, _session); - _dso_trigger_dock->setWidget(_dso_trigger_widget); - - // Setup _view widget - _view = new pv::view::View(_session, _sampling_bar, this); - _vertical_layout->addWidget(_view); - - - setIconSize(QSize(40, 40)); - addToolBar(_sampling_bar); - addToolBar(_trig_bar); - addToolBar(_file_bar); - addToolBar(_logo_bar); - - AppControl::Instance()->add_font_form(_sampling_bar); - AppControl::Instance()->add_font_form(_trig_bar); - AppControl::Instance()->add_font_form(_file_bar); - AppControl::Instance()->add_font_form(_logo_bar); - - // Setup the dockWidget - _protocol_dock = new QDockWidget(L_S(STR_PAGE_DLG, S_ID(IDS_DLG_PROTOCOL_DOCK_TITLE), "Decode Protocol"), this); - _protocol_dock->setObjectName("protocol_dock"); - _protocol_dock->setFeatures(QDockWidget::DockWidgetMovable); - _protocol_dock->setAllowedAreas(Qt::RightDockWidgetArea); - _protocol_dock->setVisible(false); - _protocol_widget = new dock::ProtocolDock(_protocol_dock, *_view, _session); - _protocol_dock->setWidget(_protocol_widget); - - _session->set_decoder_pannel(_protocol_widget); - - // measure dock - _measure_dock = new QDockWidget(L_S(STR_PAGE_DLG, S_ID(IDS_DLG_MEASURE_DOCK_TITLE), "Measurement"), this); - _measure_dock->setObjectName("measure_dock"); - _measure_dock->setFeatures(QDockWidget::DockWidgetMovable); - _measure_dock->setAllowedAreas(Qt::RightDockWidgetArea); - _measure_dock->setVisible(false); - _measure_widget = new dock::MeasureDock(_measure_dock, *_view, _session); - _measure_dock->setWidget(_measure_widget); - - // search dock - _search_dock = new QDockWidget(L_S(STR_PAGE_DLG, S_ID(IDS_DLG_SEARCH_DOCK_TITLE), "Search..."), this); - _search_dock->setObjectName("search_dock"); - _search_dock->setFeatures(QDockWidget::NoDockWidgetFeatures); - _search_dock->setTitleBarWidget(new QWidget(_search_dock)); - _search_dock->setAllowedAreas(Qt::BottomDockWidgetArea); - _search_dock->setVisible(false); - - _search_widget = new dock::SearchDock(_search_dock, *_view, _session); - _search_dock->setWidget(_search_widget); - - addDockWidget(Qt::RightDockWidgetArea, _protocol_dock); - addDockWidget(Qt::RightDockWidgetArea, _trigger_dock); - addDockWidget(Qt::RightDockWidgetArea, _dso_trigger_dock); - addDockWidget(Qt::RightDockWidgetArea, _measure_dock); - addDockWidget(Qt::BottomDockWidgetArea, _search_dock); - - // event filter - _view->installEventFilter(this); - _sampling_bar->installEventFilter(this); - _trig_bar->installEventFilter(this); - _file_bar->installEventFilter(this); - _logo_bar->installEventFilter(this); - _dso_trigger_dock->installEventFilter(this); - _trigger_dock->installEventFilter(this); - _protocol_dock->installEventFilter(this); - _measure_dock->installEventFilter(this); - _search_dock->installEventFilter(this); - - // defaut language - AppConfig &app = AppConfig::Instance(); - switchLanguage(app.frameOptions.language); - switchTheme(app.frameOptions.style); - - retranslateUi(); - - _sampling_bar->set_view(_view); - - - // Add the font form - AppControl::Instance()->add_font_form(_protocol_widget); - AppControl::Instance()->add_font_form(_dso_trigger_widget); - AppControl::Instance()->add_font_form(_measure_widget); - AppControl::Instance()->add_font_form(_search_widget); - AppControl::Instance()->add_font_form(_trigger_widget); - AppControl::Instance()->add_font_form(_view->get_time_view()); - AppControl::Instance()->add_font_form(_view); - - // event - connect(&_event, SIGNAL(session_error()), this, SLOT(on_session_error())); - connect(&_event, SIGNAL(signals_changed()), this, SLOT(on_signals_changed())); - connect(&_event, SIGNAL(receive_trigger(quint64)), this, SLOT(on_receive_trigger(quint64))); - connect(&_event, SIGNAL(frame_ended()), this, SLOT(on_frame_ended()), Qt::DirectConnection); - connect(&_event, SIGNAL(frame_began()), this, SLOT(on_frame_began()), Qt::DirectConnection); - connect(&_event, SIGNAL(decode_done()), this, SLOT(on_decode_done())); - connect(&_event, SIGNAL(data_updated()), this, SLOT(on_data_updated())); - connect(&_event, SIGNAL(cur_snap_samplerate_changed()), this, SLOT(on_cur_snap_samplerate_changed())); - connect(&_event, SIGNAL(receive_data_len(quint64)), this, SLOT(on_receive_data_len(quint64))); - connect(&_event, SIGNAL(trigger_message(int)), this, SLOT(on_trigger_message(int))); - - // view - connect(_view, SIGNAL(cursor_update()), _measure_widget, SLOT(cursor_update())); - connect(_view, SIGNAL(cursor_moving()), _measure_widget, SLOT(cursor_moving())); - connect(_view, SIGNAL(cursor_moved()), _measure_widget, SLOT(reCalc())); - connect(_view, SIGNAL(prgRate(int)), this, SIGNAL(prgRate(int))); - connect(_view, SIGNAL(auto_trig(int)), _dso_trigger_widget, SLOT(auto_trig(int))); - - // trig_bar - connect(_trig_bar, SIGNAL(sig_protocol(bool)), this, SLOT(on_protocol(bool))); - connect(_trig_bar, SIGNAL(sig_trigger(bool)), this, SLOT(on_trigger(bool))); - connect(_trig_bar, SIGNAL(sig_measure(bool)), this, SLOT(on_measure(bool))); - connect(_trig_bar, SIGNAL(sig_search(bool)), this, SLOT(on_search(bool))); - connect(_trig_bar, SIGNAL(sig_setTheme(QString)), this, SLOT(switchTheme(QString))); - connect(_trig_bar, SIGNAL(sig_show_lissajous(bool)), _view, SLOT(show_lissajous(bool))); - - // file toolbar - connect(_file_bar, SIGNAL(sig_load_file(QString)), this, SLOT(on_load_file(QString))); - connect(_file_bar, SIGNAL(sig_save()), this, SLOT(on_save())); - connect(_file_bar, SIGNAL(sig_export()), this, SLOT(on_export())); - connect(_file_bar, SIGNAL(sig_screenShot()), this, SLOT(on_screenShot()), Qt::QueuedConnection); - connect(_file_bar, SIGNAL(sig_load_session(QString)), this, SLOT(on_load_session(QString))); - connect(_file_bar, SIGNAL(sig_store_session(QString)), this, SLOT(on_store_session(QString))); - - // logobar - connect(_logo_bar, SIGNAL(sig_open_doc()), this, SLOT(on_open_doc())); - - connect(_protocol_widget, SIGNAL(protocol_updated()), this, SLOT(on_signals_changed())); - - // SamplingBar - connect(_sampling_bar, SIGNAL(sig_store_session_data()), this, SLOT(on_save())); - - // - connect(_dso_trigger_widget, SIGNAL(set_trig_pos(int)), _view, SLOT(set_trig_pos(int))); - - _delay_prop_msg_timer.SetCallback(std::bind(&MainWindow::on_delay_prop_msg, this)); - - _logo_bar->set_mainform_callback(this); - - bool bLoadFile = false; - - // Try load from file. - QString ldFileName(AppControl::Instance()->_open_file_name.c_str()); - if (ldFileName != "") - { - std::string file_name = pv::path::ToUnicodePath(ldFileName); - - if (QFile::exists(ldFileName)) - { - dsv_info("Auto load file:%s", file_name.c_str()); - tmp_file = ldFileName; - bLoadFile = true; - - QTimer::singleShot(300, this, [this](){ - on_load_file(tmp_file); - tmp_file = ""; - }); - } - else - { - dsv_err("file is not exists:%s", file_name.c_str()); - MsgBox::Show(L_S(STR_PAGE_MSG, S_ID(IDS_MSG_OPEN_FILE_ERROR), "Open file error!"), ldFileName, NULL); - } - } - - if (!bLoadFile){ - _session->set_default_device(); - } - } - - //* - void MainWindow::retranslateUi() - { - _trigger_dock->setWindowTitle(L_S(STR_PAGE_DLG, S_ID(IDS_DLG_TRIGGER_DOCK_TITLE), "Trigger Setting...")); - _dso_trigger_dock->setWindowTitle(L_S(STR_PAGE_DLG, S_ID(IDS_DLG_TRIGGER_DOCK_TITLE), "Trigger Setting...")); - _protocol_dock->setWindowTitle(L_S(STR_PAGE_DLG, S_ID(IDS_DLG_PROTOCOL_DOCK_TITLE), "Decode Protocol")); - _measure_dock->setWindowTitle(L_S(STR_PAGE_DLG, S_ID(IDS_DLG_MEASURE_DOCK_TITLE), "Measurement")); - _search_dock->setWindowTitle(L_S(STR_PAGE_DLG, S_ID(IDS_DLG_SEARCH_DOCK_TITLE), "Search...")); - _view->get_time_view()->update_lang(); - } - - void MainWindow::on_load_file(QString file_name) - { - try - { - if (_device_agent->is_hardware()){ - save_config(); - } - - _session->set_file(file_name); - } - catch (QString e) - { - QString strMsg(L_S(STR_PAGE_MSG, S_ID(IDS_MSG_FAIL_TO_LOAD), "Failed to load ")); - strMsg += file_name; - MsgBox::Show(strMsg); - _session->set_default_device(); - } - } - - void MainWindow::session_error() - { - _event.session_error(); - } - - void MainWindow::session_save() - { - save_config(); - } - - void MainWindow::on_session_error() - { - QString title; - QString details; - QString ch_status = ""; - - switch (_session->get_error()) - { - case SigSession::Hw_err: - dsv_info("MainWindow::on_session_error(),Hw_err, stop capture"); - _session->stop_capture(); - title = L_S(STR_PAGE_MSG, S_ID(IDS_MSG_HARDWARE_ERROR), "Hardware Operation Failed"); - details = L_S(STR_PAGE_MSG, S_ID(IDS_MSG_HARDWARE_ERROR_DET), - "Please replug device to refresh hardware configuration!"); - break; - case SigSession::Malloc_err: - dsv_info("MainWindow::on_session_error(),Malloc_err, stop capture"); - _session->stop_capture(); - title = L_S(STR_PAGE_MSG, S_ID(IDS_MSG_MALLOC_ERROR), "Malloc Error"); - details = L_S(STR_PAGE_MSG, S_ID(IDS_MSG_MALLOC_ERROR_DET), - "Memory is not enough for this sample!\nPlease reduce the sample depth!"); - break; - case SigSession::Pkt_data_err: - title = L_S(STR_PAGE_MSG, S_ID(IDS_MSG_PACKET_ERROR), "Packet Error"); - details = L_S(STR_PAGE_MSG, S_ID(IDS_MSG_PACKET_ERROR_DET), - "the content of received packet are not expected!"); - _session->refresh(0); - break; - case SigSession::Data_overflow: - dsv_info("MainWindow::on_session_error(),Data_overflow, stop capture"); - _session->stop_capture(); - title = L_S(STR_PAGE_MSG, S_ID(IDS_MSG_DATA_OVERFLOW), "Data Overflow"); - details = L_S(STR_PAGE_MSG, S_ID(IDS_MSG_DATA_OVERFLOW_DET), - "USB bandwidth can not support current sample rate! \nPlease reduce the sample rate!"); - break; - default: - title = L_S(STR_PAGE_MSG, S_ID(IDS_MSG_UNDEFINED_ERROR), "Undefined Error"); - details = L_S(STR_PAGE_MSG, S_ID(IDS_MSG_UNDEFINED_ERROR_DET), "Not expected error!"); - break; - } - - pv::dialogs::DSMessageBox msg(this, title); - msg.mBox()->setText(details); - msg.mBox()->setStandardButtons(QMessageBox::Ok); - msg.mBox()->setIcon(QMessageBox::Warning); - connect(_session->device_event_object(), SIGNAL(device_updated()), &msg, SLOT(accept())); - _msg = &msg; - msg.exec(); - _msg = NULL; - - _session->clear_error(); - } - - void MainWindow::save_config() - { - if (_device_agent->have_instance() == false) - { - dsv_info("There is no need to save the configuration"); - return; - } - - AppConfig &app = AppConfig::Instance(); - - if (_device_agent->is_hardware()){ - QString sessionFile = gen_config_file_path(true); - save_config_to_file(sessionFile); - } - - app.frameOptions.windowState = saveState(); - app.SaveFrame(); - } - - QString MainWindow::gen_config_file_path(bool isNewFormat) - { - AppConfig &app = AppConfig::Instance(); - - QString file = GetProfileDir(); - QDir dir(file); - if (dir.exists() == false){ - dir.mkpath(file); - } - - QString driver_name = _device_agent->driver_name(); - QString mode_name = QString::number(_device_agent->get_work_mode()); - QString lang_name; - QString base_path = dir.absolutePath() + "/" + driver_name + mode_name; - - if (!isNewFormat){ - lang_name = QString::number(app.frameOptions.language); - } - - return base_path + ".ses" + lang_name + ".dsc"; - } - - bool MainWindow::able_to_close() - { - if (_device_agent->is_hardware() && _session->have_hardware_data() == false){ - _sampling_bar->commit_settings(); - } - // not used, refer to closeEvent of mainFrame - save_config(); - - if (confirm_to_store_data()){ - on_save(); - return false; - } - return true; - } - - void MainWindow::on_protocol(bool visible) - { - _protocol_dock->setVisible(visible); - - if (!visible) - _view->setFocus(); - } - - void MainWindow::on_trigger(bool visible) - { - if (_device_agent->get_work_mode() != DSO) - { - _trigger_widget->update_view(); - _trigger_dock->setVisible(visible); - _dso_trigger_dock->setVisible(false); - } - else - { - _dso_trigger_widget->update_view(); - _trigger_dock->setVisible(false); - _dso_trigger_dock->setVisible(visible); - } - - if (!visible) - _view->setFocus(); - } - - void MainWindow::on_measure(bool visible) - { - _measure_dock->setVisible(visible); - - if (!visible) - _view->setFocus(); - } - - void MainWindow::on_search(bool visible) - { - _search_dock->setVisible(visible); - _view->show_search_cursor(visible); - - if (!visible) - _view->setFocus(); - } - - void MainWindow::on_screenShot() - { - AppConfig &app = AppConfig::Instance(); - QString default_name = app.userHistory.screenShotPath + "/" + APP_NAME + QDateTime::currentDateTime().toString("-yyMMdd-hhmmss"); - - int x = parentWidget()->pos().x(); - int y = parentWidget()->pos().y(); - int w = parentWidget()->frameGeometry().width(); - int h = parentWidget()->frameGeometry().height(); - - (void)h; - (void)w; - (void)x; - (void)y; - -#ifdef _WIN32 - #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) - QPixmap pixmap = QGuiApplication::primaryScreen()->grabWindow(QApplication::desktop->winId(), x, y, w, h); - #else - QPixmap pixmap = QPixmap::grabWidget(parentWidget()); - #endif -#elif __APPLE__ - x += MainFrame::Margin; - y += MainFrame::Margin; - w -= MainFrame::Margin * 2; - h -= MainFrame::Margin * 2; - - #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) - QPixmap pixmap = QGuiApplication::primaryScreen()->grabWindow(winId(), x, y, w, h); - #else - QDesktopWidget *desktop = QApplication::desktop(); - int curMonitor = desktop->screenNumber(this); - QPixmap pixmap = QGuiApplication::screens().at(curMonitor)->grabWindow(winId(), x, y, w, h); - #endif -#else - QPixmap pixmap = QGuiApplication::primaryScreen()->grabWindow(winId()); -#endif - - QString format = "png"; - QString fileName = QFileDialog::getSaveFileName( - this, - L_S(STR_PAGE_DLG, S_ID(IDS_DLG_SAVE_AS), "Save As"), - default_name, - "png file(*.png);;jpeg file(*.jpeg)", - &format); - - if (!fileName.isEmpty()) - { - QStringList list = format.split('.').last().split(')'); - QString suffix = list.first(); - - QFileInfo f(fileName); - if (f.suffix().compare(suffix)) - { - //tr - fileName += "." + suffix; - } - - pixmap.save(fileName, suffix.toLatin1()); - - fileName = path::GetDirectoryName(fileName); - - if (app.userHistory.screenShotPath != fileName) - { - app.userHistory.screenShotPath = fileName; - app.SaveHistory(); - } - } - } - - // save file - void MainWindow::on_save() - { - using pv::dialogs::StoreProgress; - - if (_device_agent->have_instance() == false) - { - dsv_info("Have no device, can't to save data."); - return; - } - - if (_session->is_working()){ - dsv_info("Save data: stop the current device."); - _session->stop_capture(); - } - - _session->set_saving(true); - - StoreProgress *dlg = new StoreProgress(_session, this); - dlg->SetView(_view); - dlg->save_run(this); - } - - void MainWindow::on_export() - { - using pv::dialogs::StoreProgress; - - if (_session->is_working()){ - dsv_info("Export data: stop the current device."); - _session->stop_capture(); - } - - StoreProgress *dlg = new StoreProgress(_session, this); - dlg->SetView(_view); - dlg->export_run(); - } - - bool MainWindow::on_load_session(QString name) - { - return load_config_from_file(name); - } - - bool MainWindow::load_config_from_file(QString file) - { - if (file == ""){ - dsv_err("File name is empty."); - assert(false); - } - - _protocol_widget->del_all_protocol(); - - std::string file_name = pv::path::ToUnicodePath(file); - dsv_info("Load device profile: \"%s\"", file_name.c_str()); - - QFile sf(file); - - if (!sf.exists()){ - dsv_warn("Warning: device profile is not exists: \"%s\"", file_name.c_str()); - return false; - } - - if (!sf.open(QIODevice::ReadOnly)) - { - dsv_warn("Warning: Couldn't open device profile to load!"); - return false; - } - - QString data = QString::fromUtf8(sf.readAll()); - QJsonDocument doc = QJsonDocument::fromJson(data.toUtf8()); - sf.close(); - - bool bDecoder = false; - int ret = load_config_from_json(doc, bDecoder); - - if (ret && _device_agent->get_work_mode() == DSO) - { - _dso_trigger_widget->update_view(); - } - - if (_device_agent->is_hardware()){ - _title_ext_string = file; - update_title_bar_text(); - } - - return ret; - } - - bool MainWindow::gen_config_json(QJsonObject &sessionVar) - { - AppConfig &app = AppConfig::Instance(); - - GVariant *gvar_opts; - GVariant *gvar; - gsize num_opts; - - QString title = QApplication::applicationName() + " v" + QApplication::applicationVersion(); - - QJsonArray channelVar; - sessionVar["Version"] = QJsonValue::fromVariant(SESSION_FORMAT_VERSION); - sessionVar["Device"] = QJsonValue::fromVariant(_device_agent->driver_name()); - sessionVar["DeviceMode"] = QJsonValue::fromVariant(_device_agent->get_work_mode()); - sessionVar["Language"] = QJsonValue::fromVariant(app.frameOptions.language); - sessionVar["Title"] = QJsonValue::fromVariant(title); - - if (_device_agent->is_hardware() && _device_agent->get_work_mode() == LOGIC) - { - sessionVar["CollectMode"] = _session->get_collect_mode(); - } - - gvar_opts = _device_agent->get_config_list(NULL, SR_CONF_DEVICE_SESSIONS); - if (gvar_opts == NULL) - { - dsv_warn("Device config list is empty. id:SR_CONF_DEVICE_SESSIONS"); - /* Driver supports no device instance sessions. */ - return false; - } - - const int *const options = (const int32_t *)g_variant_get_fixed_array( - gvar_opts, &num_opts, sizeof(int32_t)); - - for (unsigned int i = 0; i < num_opts; i++) - { - const struct sr_config_info *const info = _device_agent->get_config_info(options[i]); - gvar = _device_agent->get_config(info->key); - if (gvar != NULL) - { - if (info->datatype == SR_T_BOOL) - sessionVar[info->name] = QJsonValue::fromVariant(g_variant_get_boolean(gvar)); - else if (info->datatype == SR_T_UINT64) - sessionVar[info->name] = QJsonValue::fromVariant(QString::number(g_variant_get_uint64(gvar))); - else if (info->datatype == SR_T_UINT8) - sessionVar[info->name] = QJsonValue::fromVariant(g_variant_get_byte(gvar)); - else if (info->datatype == SR_T_INT16) - sessionVar[info->name] = QJsonValue::fromVariant(g_variant_get_int16(gvar)); - else if (info->datatype == SR_T_FLOAT) //save as string format - sessionVar[info->name] = QJsonValue::fromVariant(QString::number(g_variant_get_double(gvar))); - else if (info->datatype == SR_T_CHAR) - sessionVar[info->name] = QJsonValue::fromVariant(g_variant_get_string(gvar, NULL)); - else if (info->datatype == SR_T_LIST) - sessionVar[info->name] = QJsonValue::fromVariant(g_variant_get_int16(gvar)); - else{ - dsv_err("Unkown config info type:%d", info->datatype); - assert(false); - } - g_variant_unref(gvar); - } - } - - for (auto s : _session->get_signals()) - { - QJsonObject s_obj; - s_obj["index"] = s->get_index(); - s_obj["view_index"] = s->get_view_index(); - s_obj["type"] = s->get_type(); - s_obj["enabled"] = s->enabled(); - s_obj["name"] = s->get_name(); - - if (s->get_colour().isValid()) - s_obj["colour"] = QJsonValue::fromVariant(s->get_colour()); - else - s_obj["colour"] = QJsonValue::fromVariant("default"); - - view::LogicSignal *logicSig = NULL; - if ((logicSig = dynamic_cast(s))) - { - s_obj["strigger"] = logicSig->get_trig(); - } - - if (s->signal_type() == SR_CHANNEL_DSO) - { - view::DsoSignal *dsoSig = (view::DsoSignal*)s; - s_obj["vdiv"] = QJsonValue::fromVariant(static_cast(dsoSig->get_vDialValue())); - s_obj["vfactor"] = QJsonValue::fromVariant(static_cast(dsoSig->get_factor())); - s_obj["coupling"] = dsoSig->get_acCoupling(); - s_obj["trigValue"] = dsoSig->get_trig_vrate(); - s_obj["zeroPos"] = dsoSig->get_zero_ratio(); - } - - if (s->signal_type() == SR_CHANNEL_ANALOG) - { - view::AnalogSignal *analogSig = (view::AnalogSignal*)s; - s_obj["vdiv"] = QJsonValue::fromVariant(static_cast(analogSig->get_vdiv())); - s_obj["vfactor"] = QJsonValue::fromVariant(static_cast(analogSig->get_factor())); - s_obj["coupling"] = analogSig->get_acCoupling(); - s_obj["zeroPos"] = analogSig->get_zero_ratio(); - s_obj["mapUnit"] = analogSig->get_mapUnit(); - s_obj["mapMin"] = analogSig->get_mapMin(); - s_obj["mapMax"] = analogSig->get_mapMax(); - s_obj["mapDefault"] = analogSig->get_mapDefault(); - } - channelVar.append(s_obj); - } - sessionVar["channel"] = channelVar; - - if (_device_agent->get_work_mode() == LOGIC) - { - sessionVar["trigger"] = _trigger_widget->get_session(); - } - - StoreSession ss(_session); - QJsonArray decodeJson; - ss.gen_decoders_json(decodeJson); - sessionVar["decoder"] = decodeJson; - - if (_device_agent->get_work_mode() == DSO) - { - sessionVar["measure"] = _view->get_viewstatus()->get_session(); - } - - if (gvar_opts != NULL) - g_variant_unref(gvar_opts); - - return true; - } - - bool MainWindow::load_config_from_json(QJsonDocument &doc, bool &haveDecoder) - { - haveDecoder = false; - - QJsonObject sessionObj = doc.object(); - - int mode = _device_agent->get_work_mode(); - - // check config file version - if (!sessionObj.contains("Version")) - { - dsv_dbg("Profile version is not exists!"); - return false; - } - - int format_ver = sessionObj["Version"].toInt(); - - if (format_ver < 2) - { - dsv_err("Profile version is error!"); - return false; - } - - if (sessionObj.contains("CollectMode") && _device_agent->is_hardware()){ - int collect_mode = sessionObj["CollectMode"].toInt(); - _session->set_collect_mode((DEVICE_COLLECT_MODE)collect_mode); - } - - int conf_dev_mode = sessionObj["DeviceMode"].toInt(); - - if (_device_agent->is_hardware()) - { - QString driverName = _device_agent->driver_name(); - QString sessionDevice = sessionObj["Device"].toString(); - // check device and mode - if (driverName != sessionDevice || mode != conf_dev_mode) - { - MsgBox::Show(NULL, L_S(STR_PAGE_MSG, S_ID(IDS_MSG_PROFILE_NOT_COMPATIBLE), "Profile is not compatible with current device or mode!"), this); - return false; - } - } - - // load device settings - GVariant *gvar_opts = _device_agent->get_config_list(NULL, SR_CONF_DEVICE_SESSIONS); - gsize num_opts; - - if (gvar_opts != NULL) - { - const int *const options = (const int32_t *)g_variant_get_fixed_array( - gvar_opts, &num_opts, sizeof(int32_t)); - - for (unsigned int i = 0; i < num_opts; i++) - { - const struct sr_config_info *info = _device_agent->get_config_info(options[i]); - - if (!sessionObj.contains(info->name)) - continue; - - GVariant *gvar = NULL; - int id = 0; - - if (info->datatype == SR_T_BOOL){ - gvar = g_variant_new_boolean(sessionObj[info->name].toInt()); - } - else if (info->datatype == SR_T_UINT64){ - //from string text. - gvar = g_variant_new_uint64(sessionObj[info->name].toString().toULongLong()); - } - else if (info->datatype == SR_T_UINT8){ - if (sessionObj[info->name].toString() != "") - gvar = g_variant_new_byte(sessionObj[info->name].toString().toUInt()); - else - gvar = g_variant_new_byte(sessionObj[info->name].toInt()); - } - else if (info->datatype == SR_T_INT16){ - gvar = g_variant_new_int16(sessionObj[info->name].toInt()); - } - else if (info->datatype == SR_T_FLOAT){ - if (sessionObj[info->name].toString() != "") - gvar = g_variant_new_double(sessionObj[info->name].toString().toDouble()); - else - gvar = g_variant_new_double(sessionObj[info->name].toDouble()); - } - else if (info->datatype == SR_T_CHAR){ - gvar = g_variant_new_string(sessionObj[info->name].toString().toLocal8Bit().data()); - } - else if (info->datatype == SR_T_LIST) - { - id = 0; - - if (format_ver > 2){ - // Is new version format. - id = sessionObj[info->name].toInt(); - } - else{ - const char *fd_key = sessionObj[info->name].toString().toLocal8Bit().data(); - id = ds_dsl_option_value_to_code(conf_dev_mode, info->key, fd_key); - if (id == -1){ - dsv_err("Convert failed, key:\"%s\", value:\"%s\"" - ,info->name, fd_key); - id = 0; //set default value. - } - else{ - dsv_info("Convert success, key:\"%s\", value:\"%s\", get code:%d" - ,info->name, fd_key, id); - } - } - gvar = g_variant_new_int16(id); - } - - if (gvar == NULL) - { - dsv_warn("Warning: Profile failed to parse key:'%s'", info->name); - continue; - } - - bool bFlag = _device_agent->set_config(info->key, gvar); - if (!bFlag){ - dsv_err("Set device config option failed, id:%d, code:%d", info->key, id); - } - } - } - - // load channel settings - if (mode == DSO) - { - for (const GSList *l = _device_agent->get_channels(); l; l = l->next) - { - sr_channel *const probe = (sr_channel *)l->data; - assert(probe); - - for (const QJsonValue &value : sessionObj["channel"].toArray()) - { - QJsonObject obj = value.toObject(); - if (QString(probe->name) == obj["name"].toString() && - probe->type == obj["type"].toDouble()) - { - probe->vdiv = obj["vdiv"].toDouble(); - probe->coupling = obj["coupling"].toDouble(); - probe->vfactor = obj["vfactor"].toDouble(); - probe->trig_value = obj["trigValue"].toDouble(); - probe->map_unit = g_strdup(obj["mapUnit"].toString().toStdString().c_str()); - probe->map_min = obj["mapMin"].toDouble(); - probe->map_max = obj["mapMax"].toDouble(); - probe->enabled = obj["enabled"].toBool(); - break; - } - } - } - } - else - { - for (const GSList *l = _device_agent->get_channels(); l; l = l->next) - { - sr_channel *const probe = (sr_channel *)l->data; - assert(probe); - bool isEnabled = false; - - for (const QJsonValue &value : sessionObj["channel"].toArray()) - { - QJsonObject obj = value.toObject(); - - if ((probe->index == obj["index"].toInt()) && - (probe->type == obj["type"].toInt())) - { - isEnabled = true; - QString chan_name = obj["name"].toString().trimmed(); - if (chan_name == ""){ - chan_name = QString::number(probe->index); - } - - probe->enabled = obj["enabled"].toBool(); - probe->name = g_strdup(chan_name.toStdString().c_str()); - probe->vdiv = obj["vdiv"].toDouble(); - probe->coupling = obj["coupling"].toDouble(); - probe->vfactor = obj["vfactor"].toDouble(); - probe->trig_value = obj["trigValue"].toDouble(); - probe->map_unit = g_strdup(obj["mapUnit"].toString().toStdString().c_str()); - probe->map_min = obj["mapMin"].toDouble(); - probe->map_max = obj["mapMax"].toDouble(); - - if (obj.contains("mapDefault")) - { - probe->map_default = obj["mapDefault"].toBool(); - } - - break; - } - } - if (!isEnabled) - probe->enabled = false; - } - } - - _session->reload(); - - // load signal setting - if (mode == DSO) - { - for (auto s : _session->get_signals()) - { - for (const QJsonValue &value : sessionObj["channel"].toArray()) - { - QJsonObject obj = value.toObject(); - - if (s->get_name() == obj["name"].toString() && - s->get_type() == obj["type"].toDouble()) - { - s->set_colour(QColor(obj["colour"].toString())); - - if (s->signal_type() == SR_CHANNEL_DSO) - { - view::DsoSignal *dsoSig = (view::DsoSignal*)s; - dsoSig->load_settings(); - dsoSig->set_zero_ratio(obj["zeroPos"].toDouble()); - dsoSig->set_trig_ratio(obj["trigValue"].toDouble()); - dsoSig->commit_settings(); - } - break; - } - } - } - } - else - { - for (auto s : _session->get_signals()) - { - for (const QJsonValue &value : sessionObj["channel"].toArray()) - { - QJsonObject obj = value.toObject(); - if ((s->get_index() == obj["index"].toInt()) && - (s->get_type() == obj["type"].toInt())) - { - QString chan_name = obj["name"].toString().trimmed(); - if (chan_name == ""){ - chan_name = QString::number(s->get_index()); - } - - s->set_colour(QColor(obj["colour"].toString())); - s->set_name(chan_name); - - view::LogicSignal *logicSig = NULL; - if ((logicSig = dynamic_cast(s))) - { - logicSig->set_trig(obj["strigger"].toDouble()); - } - - if (s->signal_type() == SR_CHANNEL_DSO) - { - view::DsoSignal *dsoSig = (view::DsoSignal*)s; - dsoSig->load_settings(); - dsoSig->set_zero_ratio(obj["zeroPos"].toDouble()); - dsoSig->set_trig_ratio(obj["trigValue"].toDouble()); - dsoSig->commit_settings(); - } - - if (s->signal_type() == SR_CHANNEL_ANALOG) - { - view::AnalogSignal *analogSig = (view::AnalogSignal*)s; - analogSig->set_zero_ratio(obj["zeroPos"].toDouble()); - analogSig->commit_settings(); - } - - break; - } - } - } - } - - // update UI settings - _sampling_bar->update_sample_rate_list(); - _trigger_widget->device_updated(); - _view->header_updated(); - - // load trigger settings - if (sessionObj.contains("trigger")) - { - _trigger_widget->set_session(sessionObj["trigger"].toObject()); - } - - // load decoders - if (sessionObj.contains("decoder")) - { - QJsonArray deArray = sessionObj["decoder"].toArray(); - if (deArray.empty() == false) - { - haveDecoder = true; - StoreSession ss(_session); - ss.load_decoders(_protocol_widget, deArray); - _view->update_all_trace_postion(); - } - } - - // load measure - if (sessionObj.contains("measure")) - { - auto *bottom_bar = _view->get_viewstatus(); - bottom_bar->load_session(sessionObj["measure"].toArray(), format_ver); - } - - if (gvar_opts != NULL) - g_variant_unref(gvar_opts); - - load_channel_view_indexs(doc); - - return true; - } - - void MainWindow::load_channel_view_indexs(QJsonDocument &doc) - { - QJsonObject sessionObj = doc.object(); - - int mode = _device_agent->get_work_mode(); - if (mode != LOGIC) - return; - - std::vector view_indexs; - - for (const QJsonValue &value : sessionObj["channel"].toArray()){ - QJsonObject obj = value.toObject(); - - if (obj.contains("view_index")){ - view_indexs.push_back(obj["view_index"].toInt()); - } - } - - if (view_indexs.size()){ - int i = 0; - - for (auto s : _session->get_signals()){ - s->set_view_index(view_indexs[i]); - i++; - } - - _view->update_all_trace_postion(); - } - } - - bool MainWindow::on_store_session(QString name) - { - return save_config_to_file(name); - } - - bool MainWindow::save_config_to_file(QString name) - { - if (name == ""){ - dsv_err("Session file name is empty."); - assert(false); - } - - std::string file_name = pv::path::ToUnicodePath(name); - dsv_info("Store session to file: \"%s\"", file_name.c_str()); - - QFile sf(name); - if (!sf.open(QIODevice::WriteOnly | QIODevice::Text)) - { - dsv_warn("Warning: Couldn't open profile to write!"); - return false; - } - - QTextStream outStream(&sf); - encoding::set_utf8(outStream); - - QJsonObject sessionVar; - if (!gen_config_json(sessionVar)){ - return false; - } - - QJsonDocument sessionDoc(sessionVar); - outStream << QString::fromUtf8(sessionDoc.toJson()); - sf.close(); - return true; - } - - bool MainWindow::genSessionData(std::string &str) - { - QJsonObject sessionVar; - if (!gen_config_json(sessionVar)) - { - return false; - } - - QJsonDocument sessionDoc(sessionVar); - QString data = QString::fromUtf8(sessionDoc.toJson()); - str.append(data.toLocal8Bit().data()); - return true; - } - - void MainWindow::restore_dock() - { - // default dockwidget size - AppConfig &app = AppConfig::Instance(); - QByteArray st = app.frameOptions.windowState; - if (!st.isEmpty()) - { - try - { - restoreState(st); - } - catch (...) - { - MsgBox::Show(NULL, L_S(STR_PAGE_MSG, S_ID(IDS_MSG_RESTORE_WINDOW_ERROR), "restore window status error!")); - } - } - - // Resotre the dock pannel. - if (_device_agent->have_instance()) - _trig_bar->reload(); - } - - bool MainWindow::eventFilter(QObject *object, QEvent *event) - { - (void)object; - - if (event->type() == QEvent::KeyPress) - { - const auto &sigs = _session->get_signals(); - QKeyEvent *ke = (QKeyEvent *)event; - - int modifier = ke->modifiers(); - if(modifier & Qt::ControlModifier || - modifier & Qt::ShiftModifier || - modifier & Qt::AltModifier) - { - return true; - } - - high_resolution_clock::time_point key_press_time = high_resolution_clock::now(); - milliseconds timeInterval = std::chrono::duration_cast(key_press_time - _last_key_press_time); - int64_t time_keep = timeInterval.count(); - if (time_keep < 200){ - return true; - } - _last_key_press_time = key_press_time; - - switch (ke->key()) - { - case Qt::Key_S: - _sampling_bar->run_or_stop(); - break; - - case Qt::Key_I: - _sampling_bar->run_or_stop_instant(); - break; - - case Qt::Key_T: - _trig_bar->trigger_clicked(); - break; - - case Qt::Key_D: - _trig_bar->protocol_clicked(); - break; - - case Qt::Key_M: - _trig_bar->measure_clicked(); - break; - - case Qt::Key_R: - _trig_bar->search_clicked(); - break; - - case Qt::Key_O: - _sampling_bar->config_device(); - break; - - case Qt::Key_PageUp: - _view->set_scale_offset(_view->scale(), - _view->offset() - _view->get_view_width()); - break; - case Qt::Key_PageDown: - _view->set_scale_offset(_view->scale(), - _view->offset() + _view->get_view_width()); - - break; - - case Qt::Key_Left: - _view->zoom(1); - break; - - case Qt::Key_Right: - _view->zoom(-1); - break; - - case Qt::Key_0: - for (auto s : sigs) - { - if (s->signal_type() == SR_CHANNEL_DSO) - { - view::DsoSignal *dsoSig = (view::DsoSignal*)s; - if (dsoSig->get_index() == 0) - dsoSig->set_vDialActive(!dsoSig->get_vDialActive()); - else - dsoSig->set_vDialActive(false); - } - } - _view->setFocus(); - update(); - break; - - case Qt::Key_1: - for (auto s : sigs) - { - if (s->signal_type() == SR_CHANNEL_DSO) - { - view::DsoSignal *dsoSig = (view::DsoSignal*)s; - if (dsoSig->get_index() == 1) - dsoSig->set_vDialActive(!dsoSig->get_vDialActive()); - else - dsoSig->set_vDialActive(false); - } - } - _view->setFocus(); - update(); - break; - - case Qt::Key_Up: - for (auto s : sigs) - { - if (s->signal_type() == SR_CHANNEL_DSO){ - view::DsoSignal *dsoSig = (view::DsoSignal*)s; - if (dsoSig->get_vDialActive()) - { - dsoSig->go_vDialNext(true); - update(); - break; - } - } - } - break; - - case Qt::Key_Down: - for (auto s : sigs) - { - if (s->signal_type() == SR_CHANNEL_DSO){ - view::DsoSignal *dsoSig = (view::DsoSignal*)s; - if (dsoSig->get_vDialActive()) - { - dsoSig->go_vDialPre(true); - update(); - break; - } - } - } - break; - - default: - QWidget::keyPressEvent((QKeyEvent *)event); - } - return true; - } - return false; - } - - void MainWindow::switchLanguage(int language) - { - if (language == 0) - return; - - AppConfig &app = AppConfig::Instance(); - - if (app.frameOptions.language != language && language > 0) - { - app.frameOptions.language = language; - app.SaveFrame(); - LangResource::Instance()->Load(language); - } - - if (language == LAN_CN) - { - _qtTrans.load(":/qt_" + QString::number(language)); - qApp->installTranslator(&_qtTrans); - _myTrans.load(":/my_" + QString::number(language)); - qApp->installTranslator(&_myTrans); - retranslateUi(); - } - else if (language == LAN_EN) - { - qApp->removeTranslator(&_qtTrans); - qApp->removeTranslator(&_myTrans); - retranslateUi(); - } - else - { - dsv_err("%s%d", "Unknown language code:", language); - } - } - - void MainWindow::switchTheme(QString style) - { - AppConfig &app = AppConfig::Instance(); - - if (app.frameOptions.style != style) - { - app.frameOptions.style = style; - app.SaveFrame(); - } - - QString qssRes = ":/" + style + ".qss"; - QFile qss(qssRes); - qss.open(QFile::ReadOnly | QFile::Text); - qApp->setStyleSheet(qss.readAll()); - qss.close(); - - - data_updated(); - } - - void MainWindow::data_updated() - { - _event.data_updated(); // safe call - } - - void MainWindow::on_data_updated() - { - _measure_widget->reCalc(); - _view->data_updated(); - } - - void MainWindow::on_open_doc() - { - openDoc(); - } - - void MainWindow::openDoc() - { - QDir dir(GetAppDataDir()); - AppConfig &app = AppConfig::Instance(); - int lan = app.frameOptions.language; - QDesktopServices::openUrl( - QUrl("file:///" + dir.absolutePath() + "/ug" + QString::number(lan) + ".pdf")); - } - - void MainWindow::update_capture() - { - _view->update_hori_res(); - } - - void MainWindow::cur_snap_samplerate_changed() - { - _event.cur_snap_samplerate_changed(); // safe call - } - - void MainWindow::on_cur_snap_samplerate_changed() - { - _measure_widget->cursor_update(); - } - - /*------------------on event end-------*/ - - void MainWindow::signals_changed() - { - _event.signals_changed(); // safe call - } - - void MainWindow::on_signals_changed() - { - _view->signals_changed(NULL); - } - - void MainWindow::receive_trigger(quint64 trigger_pos) - { - _event.receive_trigger(trigger_pos); // save call - } - - void MainWindow::on_receive_trigger(quint64 trigger_pos) - { - _view->receive_trigger(trigger_pos); - } - - void MainWindow::frame_ended() - { - _event.frame_ended(); // save call - } - - void MainWindow::on_frame_ended() - { - _view->receive_end(); - } - - void MainWindow::frame_began() - { - _event.frame_began(); // save call - } - - void MainWindow::on_frame_began() - { - _view->frame_began(); - } - - void MainWindow::show_region(uint64_t start, uint64_t end, bool keep) - { - _view->show_region(start, end, keep); - } - - void MainWindow::show_wait_trigger() - { - _view->show_wait_trigger(); - } - - void MainWindow::repeat_hold(int percent) - { - (void)percent; - _view->repeat_show(); - } - - void MainWindow::decode_done() - { - _event.decode_done(); // safe call - } - - void MainWindow::on_decode_done() - { - _protocol_widget->update_model(); - } - - void MainWindow::receive_data_len(quint64 len) - { - _event.receive_data_len(len); // safe call - } - - void MainWindow::on_receive_data_len(quint64 len) - { - _view->set_receive_len(len); - } - - void MainWindow::receive_header() - { - } - - void MainWindow::check_usb_device_speed() - { - // USB device speed check - if (_device_agent->is_hardware()) - { - int usb_speed = LIBUSB_SPEED_HIGH; - _device_agent->get_config_int32(SR_CONF_USB_SPEED, usb_speed); - - bool usb30_support = false; - - if (_device_agent->get_config_bool(SR_CONF_USB30_SUPPORT, usb30_support)) - { - dsv_info("The device's USB module version: %d.0", usb30_support ? 3 : 2); - - int cable_ver = 1; - if (usb_speed == LIBUSB_SPEED_HIGH) - cable_ver = 2; - else if (usb_speed == LIBUSB_SPEED_SUPER) - cable_ver = 3; - - dsv_info("The cable's USB port version: %d.0", cable_ver); - - if (usb30_support && usb_speed == LIBUSB_SPEED_HIGH){ - QString str_err(L_S(STR_PAGE_DLG, S_ID(IDS_DLG_CHECK_USB_SPEED_ERROR), - "Plug the device into a USB 2.0 port will seriously affect its performance.\nPlease replug it into a USB 3.0 port.")); - delay_prop_msg(str_err); - } - } - } - } - - void MainWindow::trigger_message(int msg) - { - _event.trigger_message(msg); - } - - void MainWindow::on_trigger_message(int msg) - { - _session->broadcast_msg(msg); - } - - void MainWindow::reset_all_view() - { - _sampling_bar->reload(); - _view->status_clear(); - _view->reload(); - _view->set_device(); - _trigger_widget->update_view(); - _trigger_widget->device_updated(); - _trig_bar->reload(); - _dso_trigger_widget->update_view(); - _measure_widget->reload(); - - if (_device_agent->get_work_mode() == ANALOG) - _view->get_viewstatus()->setVisible(false); - else - _view->get_viewstatus()->setVisible(true); - } - - bool MainWindow::confirm_to_store_data() - { - bool ret = false; - _is_save_confirm_msg = true; - - if (_session->have_hardware_data() && _session->is_first_store_confirm()) - { - // Only popup one time. - ret = MsgBox::Confirm(L_S(STR_PAGE_MSG, S_ID(IDS_MSG_SAVE_CAPDATE), "Save captured data?")); - - if (!ret && _is_auto_switch_device) - { - dsv_info("The data save confirm end, auto switch to the new device."); - _is_auto_switch_device = false; - - if (_session->is_working()) - _session->stop_capture(); - - _session->set_default_device(); - } - } - - _is_save_confirm_msg = false; - return ret; - } - - void MainWindow::check_config_file_version() - { - auto device_agent = _session->get_device(); - if (device_agent->is_file() && device_agent->is_new_device()) - { - if (device_agent->get_work_mode() == LOGIC) - { - int version = -1; - if (device_agent->get_config_int16(SR_CONF_FILE_VERSION, version)) - { - if (version == 1) - { - QString strMsg(L_S(STR_PAGE_DLG, S_ID(IDS_DLG_CHECK_SESSION_FILE_VERSION_ERROR), - "Current loading file has an old format. \nThis will lead to a slow loading speed. \nPlease resave it after loaded.")); - MsgBox::Show(strMsg); - } - } - } - } - } - - void MainWindow::load_device_config() - { - _title_ext_string = ""; - int mode = _device_agent->get_work_mode(); - QString file; - - if (_device_agent->is_hardware()) - { - QString ses_name = gen_config_file_path(true); - - bool bExist = false; - - QFile sf(ses_name); - if (!sf.exists()){ - dsv_info("Try to load the low version profile."); - ses_name = gen_config_file_path(false); - } - else{ - bExist = true; - } - - if (!bExist) - { - QFile sf2(ses_name); - if (!sf2.exists()){ - dsv_info("Try to load the default profile."); - ses_name = _file_bar->genDefaultSessionFile(); - } - } - - file = ses_name; - } - else if (_device_agent->is_demo()) - { - QDir dir(GetFirmwareDir()); - if (dir.exists()) - { - QString ses_name = dir.absolutePath() + "/" - + _device_agent->driver_name() + QString::number(mode) + ".dsc"; - - QFile sf(ses_name); - if (sf.exists()){ - file = ses_name; - } - } - } - - if (file != ""){ - bool ret = load_config_from_file(file); - if (ret && _device_agent->is_hardware()){ - _title_ext_string = file; - } - } - } - - QJsonDocument MainWindow::get_config_json_from_data_file(QString file, bool &bSucesss) - { - QJsonDocument sessionDoc; - QJsonParseError error; - bSucesss = false; - - if (file == ""){ - dsv_err("File name is empty."); - assert(false); - } - - auto f_name = pv::path::ConvertPath(file); - ZipReader rd(f_name.c_str()); - auto *data = rd.GetInnterFileData("session"); - - if (data != NULL) - { - QByteArray raw_bytes = QByteArray::fromRawData(data->data(), data->size()); - QString jsonStr(raw_bytes.data()); - QByteArray qbs = jsonStr.toUtf8(); - sessionDoc = QJsonDocument::fromJson(qbs, &error); - - if (error.error != QJsonParseError::NoError) - { - QString estr = error.errorString(); - dsv_err("File::get_session(), parse json error:\"%s\"!", estr.toUtf8().data()); - } - else{ - bSucesss = true; - } - - rd.ReleaseInnerFileData(data); - } - - return sessionDoc; - } - - QJsonArray MainWindow::get_decoder_json_from_data_file(QString file, bool &bSucesss) - { - QJsonArray dec_array; - QJsonParseError error; - - bSucesss = false; - - if (file == ""){ - dsv_err("File name is empty."); - assert(false); - } - - /* read "decoders" */ - auto f_name = path::ConvertPath(file); - ZipReader rd(f_name.c_str()); - auto *data = rd.GetInnterFileData("decoders"); - - if (data != NULL) - { - QByteArray raw_bytes = QByteArray::fromRawData(data->data(), data->size()); - QString jsonStr(raw_bytes.data()); - QByteArray qbs = jsonStr.toUtf8(); - QJsonDocument sessionDoc = QJsonDocument::fromJson(qbs, &error); - - if (error.error != QJsonParseError::NoError) - { - QString estr = error.errorString(); - dsv_err("MainWindow::get_decoder_json_from_file(), parse json error:\"%s\"!", estr.toUtf8().data()); - } - else{ - bSucesss = true; - } - - dec_array = sessionDoc.array(); - rd.ReleaseInnerFileData(data); - } - - return dec_array; - } - - void MainWindow::update_toolbar_view_status() - { - _sampling_bar->update_view_status(); - _file_bar->update_view_status(); - _trig_bar->update_view_status(); - } - - void MainWindow::OnMessage(int msg) - { - switch (msg) - { - case DSV_MSG_DEVICE_LIST_UPDATED: - _sampling_bar->update_device_list(); - break; - - case DSV_MSG_START_COLLECT_WORK_PREV: - if (_device_agent->get_work_mode() == LOGIC) - _trigger_widget->try_commit_trigger(); - else if (_device_agent->get_work_mode() == DSO) - _dso_trigger_widget->check_setting(); - - _view->capture_init(); - _view->on_state_changed(false); - break; - - case DSV_MSG_START_COLLECT_WORK: - update_toolbar_view_status(); - _view->on_state_changed(false); - _protocol_widget->update_view_status(); - break; - - case DSV_MSG_COLLECT_END: - prgRate(0); - _view->repeat_unshow(); - _view->on_state_changed(true); - _protocol_widget->update_view_status(); - break; - - case DSV_MSG_END_COLLECT_WORK: - update_toolbar_view_status(); - break; - - case DSV_MSG_CURRENT_DEVICE_CHANGE_PREV: - if (_msg != NULL){ - _msg->close(); - _msg = NULL; - } - _view->hide_calibration(); - - _protocol_widget->del_all_protocol(); - _view->reload(); - break; - - case DSV_MSG_CURRENT_DEVICE_CHANGED: - { - reset_all_view(); - load_device_config(); - update_title_bar_text(); - _sampling_bar->update_device_list(); - - _logo_bar->dsl_connected(_session->get_device()->is_hardware()); - update_toolbar_view_status(); - _session->device_event_object()->device_updated(); - - if (_device_agent->is_hardware()) - { - _session->on_load_config_end(); - } - - if (_device_agent->get_work_mode() == LOGIC && _device_agent->is_file() == false) - _view->auto_set_max_scale(); - - if (_device_agent->is_file()) - { - check_config_file_version(); - - bool bDoneDecoder = false; - bool bLoadSuccess = false; - QJsonDocument doc = get_config_json_from_data_file(_device_agent->path(), bLoadSuccess); - - if (bLoadSuccess){ - load_config_from_json(doc, bDoneDecoder); - } - - if (!bDoneDecoder && _device_agent->get_work_mode() == LOGIC) - { - QJsonArray deArray = get_decoder_json_from_data_file(_device_agent->path(), bLoadSuccess); - - if (bLoadSuccess){ - StoreSession ss(_session); - ss.load_decoders(_protocol_widget, deArray); - } - } - - _view->update_all_trace_postion(); - QTimer::singleShot(100, this, [this](){ - _session->start_capture(true); - }); - } - else if (_device_agent->is_demo()) - { - if(_device_agent->get_work_mode() == LOGIC) - { - _pattern_mode = _device_agent->get_demo_operation_mode(); - _protocol_widget->del_all_protocol(); - _view->auto_set_max_scale(); - - if(_pattern_mode != "random"){ - load_demo_decoder_config(_pattern_mode); - } - } - } - - calc_min_height(); - - if (_device_agent->is_hardware() && _device_agent->is_new_device()){ - check_usb_device_speed(); - } - } - break; - - case DSV_MSG_DEVICE_OPTIONS_UPDATED: - _trigger_widget->device_updated(); - _measure_widget->reload(); - _view->check_calibration(); - break; - - case DSV_MSG_DEVICE_DURATION_UPDATED: - _trigger_widget->device_updated(); - _view->timebase_changed(); - break; - - case DSV_MSG_DEVICE_MODE_CHANGED: - _view->mode_changed(); - reset_all_view(); - load_device_config(); - update_title_bar_text(); - _view->hide_calibration(); - - update_toolbar_view_status(); - _sampling_bar->update_sample_rate_list(); - - if (_device_agent->is_hardware()) - _session->on_load_config_end(); - - if (_device_agent->get_work_mode() == LOGIC) - _view->auto_set_max_scale(); - - if(_device_agent->is_demo()) - { - _pattern_mode = _device_agent->get_demo_operation_mode(); - _protocol_widget->del_all_protocol(); - - if(_device_agent->get_work_mode() == LOGIC) - { - if(_pattern_mode != "random"){ - _device_agent->update(); - load_demo_decoder_config(_pattern_mode); - } - } - } - - calc_min_height(); - break; - - case DSV_MSG_NEW_USB_DEVICE: - { - if (_msg != NULL){ - _msg->close(); - _msg = NULL; - } - - _sampling_bar->update_device_list(); - - if (_session->get_device()->is_demo() == false) - { - QString msgText = L_S(STR_PAGE_MSG, S_ID(IDS_MSG_TO_SWITCH_DEVICE), "To switch the new device?"); - - if (MsgBox::Confirm(msgText, "", &_msg, NULL) == false){ - _msg = NULL; - return; - } - _msg = NULL; - } - - // The store confirm is not processed. - if (_is_save_confirm_msg){ - dsv_info("New device attached:Waitting for the confirm box be closed."); - _is_auto_switch_device = true; - return; - } - - if (_session->is_saving()){ - dsv_info("New device attached:Waitting for store the data. and will switch to new device."); - _is_auto_switch_device = true; - return; - } - - int mode = _device_agent->get_work_mode(); - - if (mode != DSO && confirm_to_store_data()) - { - _is_auto_switch_device = true; - - if (_session->is_working()) - _session->stop_capture(); - - on_save(); - } - else - { - if (_session->is_working()) - _session->stop_capture(); - - _session->set_default_device(); - } - } - break; - - case DSV_MSG_CURRENT_DEVICE_DETACHED: - if (_msg != NULL){ - _msg->close(); - _msg = NULL; - } - - // Save current config, and switch to the last device. - _session->device_event_object()->device_updated(); - save_config(); - _view->hide_calibration(); - - if (_session->is_saving()){ - dsv_info("Device detached:Waitting for store the data. and will switch to new device."); - _is_auto_switch_device = true; - return; - } - - if (confirm_to_store_data()){ - _is_auto_switch_device = true; - on_save(); - } - else{ - _session->set_default_device(); - } - break; - - case DSV_MSG_SAVE_COMPLETE: - _session->clear_store_confirm_flag(); - - if (_is_auto_switch_device) - { - _is_auto_switch_device = false; - _session->set_default_device(); - } - else - { - ds_device_handle devh = _sampling_bar->get_next_device_handle(); - if (devh != NULL_HANDLE) - { - dsv_info("Auto switch to the selected device."); - _session->set_device(devh); - } - } - break; - - case DSV_MSG_CLEAR_DECODE_DATA: - if (_device_agent->get_work_mode() == LOGIC) - _protocol_widget->reset_view(); - break; - - case DSV_MSG_STORE_CONF_PREV: - if (_device_agent->is_hardware() && _session->have_hardware_data() == false){ - _sampling_bar->commit_settings(); - } - break; - - case DSV_MSG_BEGIN_DEVICE_OPTIONS: - case DSV_MSG_COLLECT_MODE_CHANGED: - if(_device_agent->is_demo()){ - _pattern_mode = _device_agent->get_demo_operation_mode(); - } - if (msg == DSV_MSG_COLLECT_MODE_CHANGED){ - _trigger_widget->device_updated(); - _view->update(); - } - break; - - case DSV_MSG_END_DEVICE_OPTIONS: - case DSV_MSG_DEMO_OPERATION_MODE_CHNAGED: - if(_device_agent->is_demo() &&_device_agent->get_work_mode() == LOGIC){ - QString pattern_mode = _device_agent->get_demo_operation_mode(); - - if(pattern_mode != _pattern_mode) - { - _pattern_mode = pattern_mode; - - _device_agent->update(); - _session->clear_view_data(); - _session->init_signals(); - update_toolbar_view_status(); - _sampling_bar->update_sample_rate_list(); - _protocol_widget->del_all_protocol(); - - if(_pattern_mode != "random"){ - _session->set_collect_mode(COLLECT_SINGLE); - load_demo_decoder_config(_pattern_mode); - - if (msg == DSV_MSG_END_DEVICE_OPTIONS) - _session->start_capture(false); // Auto load data. - } - } - } - calc_min_height(); - break; - - case DSV_MSG_APP_OPTIONS_CHANGED: - update_title_bar_text(); - break; - - case DSV_MSG_FONT_OPTIONS_CHANGED: - AppControl::Instance()->update_font_forms(); - break; - case DSV_MSG_DATA_POOL_CHANGED: - _view->check_measure(); - break; - } - } - - void MainWindow::calc_min_height() - { - if (_frame != NULL) - { - if (_device_agent->get_work_mode() == LOGIC) - { - int ch_num = _session->get_ch_num(-1); - int win_height = Base_Height + Per_Chan_Height * ch_num; - - if (win_height < Min_Height) - _frame->setMinimumHeight(win_height); - else - _frame->setMinimumHeight(Min_Height); - } - else{ - _frame->setMinimumHeight(Min_Height); - } - } - } - - void MainWindow::delay_prop_msg(QString strMsg) - { - _strMsg = strMsg; - if (_strMsg != ""){ - _delay_prop_msg_timer.Start(500); - } - } - - void MainWindow::on_delay_prop_msg() - { - _delay_prop_msg_timer.Stop(); - - if (_strMsg != ""){ - MsgBox::Show("", _strMsg, this, &_msg); - _msg = NULL; - } - } - - void MainWindow::update_title_bar_text() - { - // Set the title - QString title = QApplication::applicationName() + " v" + QApplication::applicationVersion(); - AppConfig &app = AppConfig::Instance(); - - if (_title_ext_string != "" && app.appOptions.displayProfileInBar){ - title += " [" + _title_ext_string + "]"; - } - - if (_lst_title_string != title){ - _lst_title_string = title; - - setWindowTitle(QApplication::translate("MainWindow", title.toLocal8Bit().data(), 0)); - _title_bar->setTitle(this->windowTitle()); - } - } - - void MainWindow::load_demo_decoder_config(QString optname) - { - QString file = GetAppDataDir() + "/demo/logic/" + optname + ".demo"; - bool bLoadSurccess = false; - - QJsonArray deArray = get_decoder_json_from_data_file(file, bLoadSurccess); - - if (bLoadSurccess){ - StoreSession ss(_session); - ss.load_decoders(_protocol_widget, deArray); - } - - QJsonDocument doc = get_config_json_from_data_file(file, bLoadSurccess); - if (bLoadSurccess){ - load_channel_view_indexs(doc); - } - - _view->update_all_trace_postion(); - } - -} // namespace pv +/* + * This file is part of the DSView project. + * DSView is based on PulseView. + * + * Copyright (C) 2012 Joel Holdsworth + * Copyright (C) 2013 DreamSourceLab + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//include with qt5 +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) +#include +#endif + +#include "mainwindow.h" + +#include "data/logicsnapshot.h" +#include "data/dsosnapshot.h" +#include "data/analogsnapshot.h" + +#include "dialogs/about.h" +#include "dialogs/deviceoptions.h" +#include "dialogs/storeprogress.h" +#include "dialogs/waitingdialog.h" +#include "dialogs/regionoptions.h" + +#include "toolbars/samplingbar.h" +#include "toolbars/trigbar.h" +#include "toolbars/filebar.h" +#include "toolbars/logobar.h" +#include "toolbars/titlebar.h" + +#include "dock/triggerdock.h" +#include "dock/dsotriggerdock.h" +#include "dock/measuredock.h" +#include "dock/searchdock.h" +#include "dock/protocoldock.h" + +#include "view/view.h" +#include "view/trace.h" +#include "view/signal.h" +#include "view/dsosignal.h" +#include "view/logicsignal.h" +#include "view/analogsignal.h" + +/* __STDC_FORMAT_MACROS is required for PRIu64 and friends (in C++). */ +#include +#include +#include +#include +#include +#include "ui/msgbox.h" +#include "config/appconfig.h" +#include "appcontrol.h" +#include "dsvdef.h" +#include "appcontrol.h" +#include "utility/encoding.h" +#include "utility/path.h" +#include "log.h" +#include "sigsession.h" +#include "deviceagent.h" +#include +#include "ZipMaker.h" +#include "ui/langresource.h" +#include "mainframe.h" +#include "dsvdef.h" +#include + +namespace pv +{ + + namespace{ + QString tmp_file; + } + + MainWindow::MainWindow(toolbars::TitleBar *title_bar, QWidget *parent) + : QMainWindow(parent) + { + _msg = NULL; + _frame = parent; + + assert(title_bar); + assert(_frame); + + _title_bar = title_bar; + AppControl::Instance()->add_font_form(title_bar); + + _session = AppControl::Instance()->GetSession(); + _session->set_callback(this); + _device_agent = _session->get_device(); + _session->add_msg_listener(this); + + _is_auto_switch_device = false; + _is_save_confirm_msg = false; + + _pattern_mode = "random"; + + setup_ui(); + + setContextMenuPolicy(Qt::NoContextMenu); + + _key_vaild = false; + _last_key_press_time = high_resolution_clock::now(); + + update_title_bar_text(); + } + + void MainWindow::setup_ui() + { + setObjectName(QString::fromUtf8("MainWindow")); + setContentsMargins(0, 0, 0, 0); + layout()->setSpacing(0); + + // Setup the central widget + _central_widget = new QWidget(this); + _vertical_layout = new QVBoxLayout(_central_widget); + _vertical_layout->setSpacing(0); + _vertical_layout->setContentsMargins(0, 0, 0, 0); + setCentralWidget(_central_widget); + + // Setup the sampling bar + _sampling_bar = new toolbars::SamplingBar(_session, this); + _sampling_bar->setObjectName("sampling_bar"); + _trig_bar = new toolbars::TrigBar(_session, this); + _trig_bar->setObjectName("trig_bar"); + _file_bar = new toolbars::FileBar(_session, this); + _file_bar->setObjectName("file_bar"); + _logo_bar = new toolbars::LogoBar(_session, this); + _logo_bar->setObjectName("logo_bar"); + + // trigger dock + _trigger_dock = new QDockWidget(L_S(STR_PAGE_DLG, S_ID(IDS_DLG_TRIGGER_DOCK_TITLE), "Trigger Setting..."), this); + _trigger_dock->setObjectName("trigger_dock"); + _trigger_dock->setFeatures(QDockWidget::DockWidgetMovable); + _trigger_dock->setAllowedAreas(Qt::RightDockWidgetArea); + _trigger_dock->setVisible(false); + _trigger_widget = new dock::TriggerDock(_trigger_dock, _session); + _trigger_dock->setWidget(_trigger_widget); + + _dso_trigger_dock = new QDockWidget(L_S(STR_PAGE_DLG, S_ID(IDS_DLG_TRIGGER_DOCK_TITLE), "Trigger Setting..."), this); + _dso_trigger_dock->setObjectName("dso_trigger_dock"); + _dso_trigger_dock->setFeatures(QDockWidget::DockWidgetMovable); + _dso_trigger_dock->setAllowedAreas(Qt::RightDockWidgetArea); + _dso_trigger_dock->setVisible(false); + _dso_trigger_widget = new dock::DsoTriggerDock(_dso_trigger_dock, _session); + _dso_trigger_dock->setWidget(_dso_trigger_widget); + + // Setup _view widget + _view = new pv::view::View(_session, _sampling_bar, this); + _vertical_layout->addWidget(_view); + + + setIconSize(QSize(40, 40)); + addToolBar(_sampling_bar); + addToolBar(_trig_bar); + addToolBar(_file_bar); + addToolBar(_logo_bar); + + AppControl::Instance()->add_font_form(_sampling_bar); + AppControl::Instance()->add_font_form(_trig_bar); + AppControl::Instance()->add_font_form(_file_bar); + AppControl::Instance()->add_font_form(_logo_bar); + + // Setup the dockWidget + _protocol_dock = new QDockWidget(L_S(STR_PAGE_DLG, S_ID(IDS_DLG_PROTOCOL_DOCK_TITLE), "Decode Protocol"), this); + _protocol_dock->setObjectName("protocol_dock"); + _protocol_dock->setFeatures(QDockWidget::DockWidgetMovable); + _protocol_dock->setAllowedAreas(Qt::RightDockWidgetArea); + _protocol_dock->setVisible(false); + _protocol_widget = new dock::ProtocolDock(_protocol_dock, *_view, _session); + _protocol_dock->setWidget(_protocol_widget); + + _session->set_decoder_pannel(_protocol_widget); + + // measure dock + _measure_dock = new QDockWidget(L_S(STR_PAGE_DLG, S_ID(IDS_DLG_MEASURE_DOCK_TITLE), "Measurement"), this); + _measure_dock->setObjectName("measure_dock"); + _measure_dock->setFeatures(QDockWidget::DockWidgetMovable); + _measure_dock->setAllowedAreas(Qt::RightDockWidgetArea); + _measure_dock->setVisible(false); + _measure_widget = new dock::MeasureDock(_measure_dock, *_view, _session); + _measure_dock->setWidget(_measure_widget); + + // search dock + _search_dock = new QDockWidget(L_S(STR_PAGE_DLG, S_ID(IDS_DLG_SEARCH_DOCK_TITLE), "Search..."), this); + _search_dock->setObjectName("search_dock"); + _search_dock->setFeatures(QDockWidget::NoDockWidgetFeatures); + _search_dock->setTitleBarWidget(new QWidget(_search_dock)); + _search_dock->setAllowedAreas(Qt::BottomDockWidgetArea); + _search_dock->setVisible(false); + + _search_widget = new dock::SearchDock(_search_dock, *_view, _session); + _search_dock->setWidget(_search_widget); + + addDockWidget(Qt::RightDockWidgetArea, _protocol_dock); + addDockWidget(Qt::RightDockWidgetArea, _trigger_dock); + addDockWidget(Qt::RightDockWidgetArea, _dso_trigger_dock); + addDockWidget(Qt::RightDockWidgetArea, _measure_dock); + addDockWidget(Qt::BottomDockWidgetArea, _search_dock); + + // event filter + _view->installEventFilter(this); + _sampling_bar->installEventFilter(this); + _trig_bar->installEventFilter(this); + _file_bar->installEventFilter(this); + _logo_bar->installEventFilter(this); + _dso_trigger_dock->installEventFilter(this); + _trigger_dock->installEventFilter(this); + _protocol_dock->installEventFilter(this); + _measure_dock->installEventFilter(this); + _search_dock->installEventFilter(this); + + // defaut language + AppConfig &app = AppConfig::Instance(); + switchLanguage(app.frameOptions.language); + switchTheme(app.frameOptions.style); + + retranslateUi(); + + _sampling_bar->set_view(_view); + + + // Add the font form + AppControl::Instance()->add_font_form(_protocol_widget); + AppControl::Instance()->add_font_form(_dso_trigger_widget); + AppControl::Instance()->add_font_form(_measure_widget); + AppControl::Instance()->add_font_form(_search_widget); + AppControl::Instance()->add_font_form(_trigger_widget); + AppControl::Instance()->add_font_form(_view->get_time_view()); + AppControl::Instance()->add_font_form(_view); + + // event + connect(&_event, SIGNAL(session_error()), this, SLOT(on_session_error())); + connect(&_event, SIGNAL(signals_changed()), this, SLOT(on_signals_changed())); + connect(&_event, SIGNAL(receive_trigger(quint64)), this, SLOT(on_receive_trigger(quint64))); + connect(&_event, SIGNAL(frame_ended()), this, SLOT(on_frame_ended()), Qt::DirectConnection); + connect(&_event, SIGNAL(frame_began()), this, SLOT(on_frame_began()), Qt::DirectConnection); + connect(&_event, SIGNAL(decode_done()), this, SLOT(on_decode_done())); + connect(&_event, SIGNAL(data_updated()), this, SLOT(on_data_updated())); + connect(&_event, SIGNAL(cur_snap_samplerate_changed()), this, SLOT(on_cur_snap_samplerate_changed())); + connect(&_event, SIGNAL(receive_data_len(quint64)), this, SLOT(on_receive_data_len(quint64))); + connect(&_event, SIGNAL(trigger_message(int)), this, SLOT(on_trigger_message(int))); + + // view + connect(_view, SIGNAL(cursor_update()), _measure_widget, SLOT(cursor_update())); + connect(_view, SIGNAL(cursor_moving()), _measure_widget, SLOT(cursor_moving())); + connect(_view, SIGNAL(cursor_moved()), _measure_widget, SLOT(reCalc())); + connect(_view, SIGNAL(prgRate(int)), this, SIGNAL(prgRate(int))); + connect(_view, SIGNAL(auto_trig(int)), _dso_trigger_widget, SLOT(auto_trig(int))); + + // trig_bar + connect(_trig_bar, SIGNAL(sig_protocol(bool)), this, SLOT(on_protocol(bool))); + connect(_trig_bar, SIGNAL(sig_trigger(bool)), this, SLOT(on_trigger(bool))); + connect(_trig_bar, SIGNAL(sig_measure(bool)), this, SLOT(on_measure(bool))); + connect(_trig_bar, SIGNAL(sig_search(bool)), this, SLOT(on_search(bool))); + connect(_trig_bar, SIGNAL(sig_setTheme(QString)), this, SLOT(switchTheme(QString))); + connect(_trig_bar, SIGNAL(sig_show_lissajous(bool)), _view, SLOT(show_lissajous(bool))); + + // file toolbar + connect(_file_bar, SIGNAL(sig_load_file(QString)), this, SLOT(on_load_file(QString))); + connect(_file_bar, SIGNAL(sig_save()), this, SLOT(on_save())); + connect(_file_bar, SIGNAL(sig_export()), this, SLOT(on_export())); + connect(_file_bar, SIGNAL(sig_screenShot()), this, SLOT(on_screenShot()), Qt::QueuedConnection); + connect(_file_bar, SIGNAL(sig_load_session(QString)), this, SLOT(on_load_session(QString))); + connect(_file_bar, SIGNAL(sig_store_session(QString)), this, SLOT(on_store_session(QString))); + + // logobar + connect(_logo_bar, SIGNAL(sig_open_doc()), this, SLOT(on_open_doc())); + + connect(_protocol_widget, SIGNAL(protocol_updated()), this, SLOT(on_signals_changed())); + + // SamplingBar + connect(_sampling_bar, SIGNAL(sig_store_session_data()), this, SLOT(on_save())); + + // + connect(_dso_trigger_widget, SIGNAL(set_trig_pos(int)), _view, SLOT(set_trig_pos(int))); + + _delay_prop_msg_timer.SetCallback(std::bind(&MainWindow::on_delay_prop_msg, this)); + + _logo_bar->set_mainform_callback(this); + + bool bLoadFile = false; + + // Try load from file. + QString ldFileName(AppControl::Instance()->_open_file_name.c_str()); + if (ldFileName != "") + { + std::string file_name = pv::path::ToUnicodePath(ldFileName); + + if (QFile::exists(ldFileName)) + { + dsv_info("Auto load file:%s", file_name.c_str()); + tmp_file = ldFileName; + bLoadFile = true; + + QTimer::singleShot(300, this, [this](){ + on_load_file(tmp_file); + tmp_file = ""; + }); + } + else + { + dsv_err("file is not exists:%s", file_name.c_str()); + MsgBox::Show(L_S(STR_PAGE_MSG, S_ID(IDS_MSG_OPEN_FILE_ERROR), "Open file error!"), ldFileName, NULL); + } + } + + if (!bLoadFile){ + _session->set_default_device(); + } + } + + //* + void MainWindow::retranslateUi() + { + _trigger_dock->setWindowTitle(L_S(STR_PAGE_DLG, S_ID(IDS_DLG_TRIGGER_DOCK_TITLE), "Trigger Setting...")); + _dso_trigger_dock->setWindowTitle(L_S(STR_PAGE_DLG, S_ID(IDS_DLG_TRIGGER_DOCK_TITLE), "Trigger Setting...")); + _protocol_dock->setWindowTitle(L_S(STR_PAGE_DLG, S_ID(IDS_DLG_PROTOCOL_DOCK_TITLE), "Decode Protocol")); + _measure_dock->setWindowTitle(L_S(STR_PAGE_DLG, S_ID(IDS_DLG_MEASURE_DOCK_TITLE), "Measurement")); + _search_dock->setWindowTitle(L_S(STR_PAGE_DLG, S_ID(IDS_DLG_SEARCH_DOCK_TITLE), "Search...")); + _view->get_time_view()->update_lang(); + } + + void MainWindow::on_load_file(QString file_name) + { + try + { + if (_device_agent->is_hardware()){ + save_config(); + } + + _session->set_file(file_name); + } + catch (QString e) + { + QString strMsg(L_S(STR_PAGE_MSG, S_ID(IDS_MSG_FAIL_TO_LOAD), "Failed to load ")); + strMsg += file_name; + MsgBox::Show(strMsg); + _session->set_default_device(); + } + } + + void MainWindow::session_error() + { + _event.session_error(); + } + + void MainWindow::session_save() + { + save_config(); + } + + void MainWindow::on_session_error() + { + QString title; + QString details; + QString ch_status = ""; + + switch (_session->get_error()) + { + case SigSession::Hw_err: + dsv_info("MainWindow::on_session_error(),Hw_err, stop capture"); + _session->stop_capture(); + title = L_S(STR_PAGE_MSG, S_ID(IDS_MSG_HARDWARE_ERROR), "Hardware Operation Failed"); + details = L_S(STR_PAGE_MSG, S_ID(IDS_MSG_HARDWARE_ERROR_DET), + "Please replug device to refresh hardware configuration!"); + break; + case SigSession::Malloc_err: + dsv_info("MainWindow::on_session_error(),Malloc_err, stop capture"); + _session->stop_capture(); + title = L_S(STR_PAGE_MSG, S_ID(IDS_MSG_MALLOC_ERROR), "Malloc Error"); + details = L_S(STR_PAGE_MSG, S_ID(IDS_MSG_MALLOC_ERROR_DET), + "Memory is not enough for this sample!\nPlease reduce the sample depth!"); + break; + case SigSession::Pkt_data_err: + title = L_S(STR_PAGE_MSG, S_ID(IDS_MSG_PACKET_ERROR), "Packet Error"); + details = L_S(STR_PAGE_MSG, S_ID(IDS_MSG_PACKET_ERROR_DET), + "the content of received packet are not expected!"); + _session->refresh(0); + break; + case SigSession::Data_overflow: + dsv_info("MainWindow::on_session_error(),Data_overflow, stop capture"); + _session->stop_capture(); + title = L_S(STR_PAGE_MSG, S_ID(IDS_MSG_DATA_OVERFLOW), "Data Overflow"); + details = L_S(STR_PAGE_MSG, S_ID(IDS_MSG_DATA_OVERFLOW_DET), + "USB bandwidth can not support current sample rate! \nPlease reduce the sample rate!"); + break; + default: + title = L_S(STR_PAGE_MSG, S_ID(IDS_MSG_UNDEFINED_ERROR), "Undefined Error"); + details = L_S(STR_PAGE_MSG, S_ID(IDS_MSG_UNDEFINED_ERROR_DET), "Not expected error!"); + break; + } + + pv::dialogs::DSMessageBox msg(this, title); + msg.mBox()->setText(details); + msg.mBox()->setStandardButtons(QMessageBox::Ok); + msg.mBox()->setIcon(QMessageBox::Warning); + connect(_session->device_event_object(), SIGNAL(device_updated()), &msg, SLOT(accept())); + _msg = &msg; + msg.exec(); + _msg = NULL; + + _session->clear_error(); + } + + void MainWindow::save_config() + { + if (_device_agent->have_instance() == false) + { + dsv_info("There is no need to save the configuration"); + return; + } + + AppConfig &app = AppConfig::Instance(); + + if (_device_agent->is_hardware()){ + QString sessionFile = gen_config_file_path(true); + save_config_to_file(sessionFile); + } + + app.frameOptions.windowState = saveState(); + app.SaveFrame(); + } + + QString MainWindow::gen_config_file_path(bool isNewFormat) + { + AppConfig &app = AppConfig::Instance(); + + QString file = GetProfileDir(); + QDir dir(file); + if (dir.exists() == false){ + dir.mkpath(file); + } + + QString driver_name = _device_agent->driver_name(); + QString mode_name = QString::number(_device_agent->get_work_mode()); + QString lang_name; + QString base_path = dir.absolutePath() + "/" + driver_name + mode_name; + + if (!isNewFormat){ + lang_name = QString::number(app.frameOptions.language); + } + + return base_path + ".ses" + lang_name + ".dsc"; + } + + bool MainWindow::able_to_close() + { + if (_device_agent->is_hardware() && _session->have_hardware_data() == false){ + _sampling_bar->commit_settings(); + } + // not used, refer to closeEvent of mainFrame + save_config(); + + if (confirm_to_store_data()){ + on_save(); + return false; + } + return true; + } + + void MainWindow::on_protocol(bool visible) + { + _protocol_dock->setVisible(visible); + + if (!visible) + _view->setFocus(); + } + + void MainWindow::on_trigger(bool visible) + { + if (_device_agent->get_work_mode() != DSO) + { + _trigger_widget->update_view(); + _trigger_dock->setVisible(visible); + _dso_trigger_dock->setVisible(false); + } + else + { + _dso_trigger_widget->update_view(); + _trigger_dock->setVisible(false); + _dso_trigger_dock->setVisible(visible); + } + + if (!visible) + _view->setFocus(); + } + + void MainWindow::on_measure(bool visible) + { + _measure_dock->setVisible(visible); + + if (!visible) + _view->setFocus(); + } + + void MainWindow::on_search(bool visible) + { + _search_dock->setVisible(visible); + _view->show_search_cursor(visible); + + if (!visible) + _view->setFocus(); + } + + void MainWindow::on_screenShot() + { + AppConfig &app = AppConfig::Instance(); + QString default_name = app.userHistory.screenShotPath + "/" + APP_NAME + QDateTime::currentDateTime().toString("-yyMMdd-hhmmss"); + + int x = parentWidget()->pos().x(); + int y = parentWidget()->pos().y(); + int w = parentWidget()->frameGeometry().width(); + int h = parentWidget()->frameGeometry().height(); + + (void)h; + (void)w; + (void)x; + (void)y; + +#ifdef _WIN32 + #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + QPixmap pixmap = QGuiApplication::primaryScreen()->grabWindow(QApplication::desktop->winId(), x, y, w, h); + #else + QPixmap pixmap = QPixmap::grabWidget(parentWidget()); + #endif +#elif __APPLE__ + x += MainFrame::Margin; + y += MainFrame::Margin; + w -= MainFrame::Margin * 2; + h -= MainFrame::Margin * 2; + + #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + QPixmap pixmap = QGuiApplication::primaryScreen()->grabWindow(winId(), x, y, w, h); + #else + QDesktopWidget *desktop = QApplication::desktop(); + int curMonitor = desktop->screenNumber(this); + QPixmap pixmap = QGuiApplication::screens().at(curMonitor)->grabWindow(winId(), x, y, w, h); + #endif +#else + QPixmap pixmap = QGuiApplication::primaryScreen()->grabWindow(winId()); +#endif + + QString format = "png"; + QString fileName = QFileDialog::getSaveFileName( + this, + L_S(STR_PAGE_DLG, S_ID(IDS_DLG_SAVE_AS), "Save As"), + default_name, + "png file(*.png);;jpeg file(*.jpeg)", + &format); + + if (!fileName.isEmpty()) + { + QStringList list = format.split('.').last().split(')'); + QString suffix = list.first(); + + QFileInfo f(fileName); + if (f.suffix().compare(suffix)) + { + //tr + fileName += "." + suffix; + } + + pixmap.save(fileName, suffix.toLatin1()); + + fileName = path::GetDirectoryName(fileName); + + if (app.userHistory.screenShotPath != fileName) + { + app.userHistory.screenShotPath = fileName; + app.SaveHistory(); + } + } + } + + // save file + void MainWindow::on_save() + { + using pv::dialogs::StoreProgress; + + if (_device_agent->have_instance() == false) + { + dsv_info("Have no device, can't to save data."); + return; + } + + if (_session->is_working()){ + dsv_info("Save data: stop the current device."); + _session->stop_capture(); + } + + _session->set_saving(true); + + StoreProgress *dlg = new StoreProgress(_session, this); + dlg->SetView(_view); + dlg->save_run(this); + } + + void MainWindow::on_export() + { + using pv::dialogs::StoreProgress; + + if (_session->is_working()){ + dsv_info("Export data: stop the current device."); + _session->stop_capture(); + } + + StoreProgress *dlg = new StoreProgress(_session, this); + dlg->SetView(_view); + dlg->export_run(); + } + + bool MainWindow::on_load_session(QString name) + { + return load_config_from_file(name); + } + + bool MainWindow::load_config_from_file(QString file) + { + if (file == ""){ + dsv_err("File name is empty."); + assert(false); + } + + _protocol_widget->del_all_protocol(); + + std::string file_name = pv::path::ToUnicodePath(file); + dsv_info("Load device profile: \"%s\"", file_name.c_str()); + + QFile sf(file); + + if (!sf.exists()){ + dsv_warn("Warning: device profile is not exists: \"%s\"", file_name.c_str()); + return false; + } + + if (!sf.open(QIODevice::ReadOnly)) + { + dsv_warn("Warning: Couldn't open device profile to load!"); + return false; + } + + QString data = QString::fromUtf8(sf.readAll()); + QJsonDocument doc = QJsonDocument::fromJson(data.toUtf8()); + sf.close(); + + bool bDecoder = false; + int ret = load_config_from_json(doc, bDecoder); + + if (ret && _device_agent->get_work_mode() == DSO) + { + _dso_trigger_widget->update_view(); + } + + if (_device_agent->is_hardware()){ + _title_ext_string = file; + update_title_bar_text(); + } + + return ret; + } + + bool MainWindow::gen_config_json(QJsonObject &sessionVar) + { + AppConfig &app = AppConfig::Instance(); + + GVariant *gvar_opts; + GVariant *gvar; + gsize num_opts; + + QString title = QApplication::applicationName() + " v" + QApplication::applicationVersion(); + + QJsonArray channelVar; + sessionVar["Version"] = QJsonValue::fromVariant(SESSION_FORMAT_VERSION); + sessionVar["Device"] = QJsonValue::fromVariant(_device_agent->driver_name()); + sessionVar["DeviceMode"] = QJsonValue::fromVariant(_device_agent->get_work_mode()); + sessionVar["Language"] = QJsonValue::fromVariant(app.frameOptions.language); + sessionVar["Title"] = QJsonValue::fromVariant(title); + + if (_device_agent->is_hardware() && _device_agent->get_work_mode() == LOGIC) + { + sessionVar["CollectMode"] = _session->get_collect_mode(); + } + + gvar_opts = _device_agent->get_config_list(NULL, SR_CONF_DEVICE_SESSIONS); + if (gvar_opts == NULL) + { + dsv_warn("Device config list is empty. id:SR_CONF_DEVICE_SESSIONS"); + /* Driver supports no device instance sessions. */ + return false; + } + + const int *const options = (const int32_t *)g_variant_get_fixed_array( + gvar_opts, &num_opts, sizeof(int32_t)); + + for (unsigned int i = 0; i < num_opts; i++) + { + const struct sr_config_info *const info = _device_agent->get_config_info(options[i]); + gvar = _device_agent->get_config(info->key); + if (gvar != NULL) + { + if (info->datatype == SR_T_BOOL) + sessionVar[info->name] = QJsonValue::fromVariant(g_variant_get_boolean(gvar)); + else if (info->datatype == SR_T_UINT64) + sessionVar[info->name] = QJsonValue::fromVariant(QString::number(g_variant_get_uint64(gvar))); + else if (info->datatype == SR_T_UINT8) + sessionVar[info->name] = QJsonValue::fromVariant(g_variant_get_byte(gvar)); + else if (info->datatype == SR_T_INT16) + sessionVar[info->name] = QJsonValue::fromVariant(g_variant_get_int16(gvar)); + else if (info->datatype == SR_T_FLOAT) //save as string format + sessionVar[info->name] = QJsonValue::fromVariant(QString::number(g_variant_get_double(gvar))); + else if (info->datatype == SR_T_CHAR) + sessionVar[info->name] = QJsonValue::fromVariant(g_variant_get_string(gvar, NULL)); + else if (info->datatype == SR_T_LIST) + sessionVar[info->name] = QJsonValue::fromVariant(g_variant_get_int16(gvar)); + else{ + dsv_err("Unkown config info type:%d", info->datatype); + assert(false); + } + g_variant_unref(gvar); + } + } + + for (auto s : _session->get_signals()) + { + QJsonObject s_obj; + s_obj["index"] = s->get_index(); + s_obj["view_index"] = s->get_view_index(); + s_obj["type"] = s->get_type(); + s_obj["enabled"] = s->enabled(); + s_obj["name"] = s->get_name(); + + if (s->get_colour().isValid()) + s_obj["colour"] = QJsonValue::fromVariant(s->get_colour()); + else + s_obj["colour"] = QJsonValue::fromVariant("default"); + + view::LogicSignal *logicSig = NULL; + if ((logicSig = dynamic_cast(s))) + { + s_obj["strigger"] = logicSig->get_trig(); + } + + if (s->signal_type() == SR_CHANNEL_DSO) + { + view::DsoSignal *dsoSig = (view::DsoSignal*)s; + s_obj["vdiv"] = QJsonValue::fromVariant(static_cast(dsoSig->get_vDialValue())); + s_obj["vfactor"] = QJsonValue::fromVariant(static_cast(dsoSig->get_factor())); + s_obj["coupling"] = dsoSig->get_acCoupling(); + s_obj["trigValue"] = dsoSig->get_trig_vrate(); + s_obj["zeroPos"] = dsoSig->get_zero_ratio(); + } + + if (s->signal_type() == SR_CHANNEL_ANALOG) + { + view::AnalogSignal *analogSig = (view::AnalogSignal*)s; + s_obj["vdiv"] = QJsonValue::fromVariant(static_cast(analogSig->get_vdiv())); + s_obj["vfactor"] = QJsonValue::fromVariant(static_cast(analogSig->get_factor())); + s_obj["coupling"] = analogSig->get_acCoupling(); + s_obj["zeroPos"] = analogSig->get_zero_ratio(); + s_obj["mapUnit"] = analogSig->get_mapUnit(); + s_obj["mapMin"] = analogSig->get_mapMin(); + s_obj["mapMax"] = analogSig->get_mapMax(); + s_obj["mapDefault"] = analogSig->get_mapDefault(); + } + channelVar.append(s_obj); + } + sessionVar["channel"] = channelVar; + + if (_device_agent->get_work_mode() == LOGIC) + { + sessionVar["trigger"] = _trigger_widget->get_session(); + } + + StoreSession ss(_session); + QJsonArray decodeJson; + ss.gen_decoders_json(decodeJson); + sessionVar["decoder"] = decodeJson; + + if (_device_agent->get_work_mode() == DSO) + { + sessionVar["measure"] = _view->get_viewstatus()->get_session(); + } + + if (gvar_opts != NULL) + g_variant_unref(gvar_opts); + + return true; + } + + bool MainWindow::load_config_from_json(QJsonDocument &doc, bool &haveDecoder) + { + haveDecoder = false; + + QJsonObject sessionObj = doc.object(); + + int mode = _device_agent->get_work_mode(); + + // check config file version + if (!sessionObj.contains("Version")) + { + dsv_dbg("Profile version is not exists!"); + return false; + } + + int format_ver = sessionObj["Version"].toInt(); + + if (format_ver < 2) + { + dsv_err("Profile version is error!"); + return false; + } + + if (sessionObj.contains("CollectMode") && _device_agent->is_hardware()){ + int collect_mode = sessionObj["CollectMode"].toInt(); + _session->set_collect_mode((DEVICE_COLLECT_MODE)collect_mode); + } + + int conf_dev_mode = sessionObj["DeviceMode"].toInt(); + + if (_device_agent->is_hardware()) + { + QString driverName = _device_agent->driver_name(); + QString sessionDevice = sessionObj["Device"].toString(); + // check device and mode + if (driverName != sessionDevice || mode != conf_dev_mode) + { + MsgBox::Show(NULL, L_S(STR_PAGE_MSG, S_ID(IDS_MSG_PROFILE_NOT_COMPATIBLE), "Profile is not compatible with current device or mode!"), this); + return false; + } + } + + // load device settings + GVariant *gvar_opts = _device_agent->get_config_list(NULL, SR_CONF_DEVICE_SESSIONS); + gsize num_opts; + + if (gvar_opts != NULL) + { + const int *const options = (const int32_t *)g_variant_get_fixed_array( + gvar_opts, &num_opts, sizeof(int32_t)); + + for (unsigned int i = 0; i < num_opts; i++) + { + const struct sr_config_info *info = _device_agent->get_config_info(options[i]); + + if (!sessionObj.contains(info->name)) + continue; + + GVariant *gvar = NULL; + int id = 0; + + if (info->datatype == SR_T_BOOL){ + gvar = g_variant_new_boolean(sessionObj[info->name].toInt()); + } + else if (info->datatype == SR_T_UINT64){ + //from string text. + gvar = g_variant_new_uint64(sessionObj[info->name].toString().toULongLong()); + } + else if (info->datatype == SR_T_UINT8){ + if (sessionObj[info->name].toString() != "") + gvar = g_variant_new_byte(sessionObj[info->name].toString().toUInt()); + else + gvar = g_variant_new_byte(sessionObj[info->name].toInt()); + } + else if (info->datatype == SR_T_INT16){ + gvar = g_variant_new_int16(sessionObj[info->name].toInt()); + } + else if (info->datatype == SR_T_FLOAT){ + if (sessionObj[info->name].toString() != "") + gvar = g_variant_new_double(sessionObj[info->name].toString().toDouble()); + else + gvar = g_variant_new_double(sessionObj[info->name].toDouble()); + } + else if (info->datatype == SR_T_CHAR){ + gvar = g_variant_new_string(sessionObj[info->name].toString().toLocal8Bit().data()); + } + else if (info->datatype == SR_T_LIST) + { + id = 0; + + if (format_ver > 2){ + // Is new version format. + id = sessionObj[info->name].toInt(); + } + else{ + const char *fd_key = sessionObj[info->name].toString().toLocal8Bit().data(); + id = ds_dsl_option_value_to_code(conf_dev_mode, info->key, fd_key); + if (id == -1){ + dsv_err("Convert failed, key:\"%s\", value:\"%s\"" + ,info->name, fd_key); + id = 0; //set default value. + } + else{ + dsv_info("Convert success, key:\"%s\", value:\"%s\", get code:%d" + ,info->name, fd_key, id); + } + } + gvar = g_variant_new_int16(id); + } + + if (gvar == NULL) + { + dsv_warn("Warning: Profile failed to parse key:'%s'", info->name); + continue; + } + + bool bFlag = _device_agent->set_config(info->key, gvar); + if (!bFlag){ + dsv_err("Set device config option failed, id:%d, code:%d", info->key, id); + } + } + } + + // load channel settings + if (mode == DSO) + { + for (const GSList *l = _device_agent->get_channels(); l; l = l->next) + { + sr_channel *const probe = (sr_channel *)l->data; + assert(probe); + + for (const QJsonValue &value : sessionObj["channel"].toArray()) + { + QJsonObject obj = value.toObject(); + if (QString(probe->name) == obj["name"].toString() && + probe->type == obj["type"].toDouble()) + { + probe->vdiv = obj["vdiv"].toDouble(); + probe->coupling = obj["coupling"].toDouble(); + probe->vfactor = obj["vfactor"].toDouble(); + probe->trig_value = obj["trigValue"].toDouble(); + probe->map_unit = g_strdup(obj["mapUnit"].toString().toStdString().c_str()); + probe->map_min = obj["mapMin"].toDouble(); + probe->map_max = obj["mapMax"].toDouble(); + probe->enabled = obj["enabled"].toBool(); + break; + } + } + } + } + else + { + for (const GSList *l = _device_agent->get_channels(); l; l = l->next) + { + sr_channel *const probe = (sr_channel *)l->data; + assert(probe); + bool isEnabled = false; + + for (const QJsonValue &value : sessionObj["channel"].toArray()) + { + QJsonObject obj = value.toObject(); + + if ((probe->index == obj["index"].toInt()) && + (probe->type == obj["type"].toInt())) + { + isEnabled = true; + QString chan_name = obj["name"].toString().trimmed(); + if (chan_name == ""){ + chan_name = QString::number(probe->index); + } + + probe->enabled = obj["enabled"].toBool(); + probe->name = g_strdup(chan_name.toStdString().c_str()); + probe->vdiv = obj["vdiv"].toDouble(); + probe->coupling = obj["coupling"].toDouble(); + probe->vfactor = obj["vfactor"].toDouble(); + probe->trig_value = obj["trigValue"].toDouble(); + probe->map_unit = g_strdup(obj["mapUnit"].toString().toStdString().c_str()); + probe->map_min = obj["mapMin"].toDouble(); + probe->map_max = obj["mapMax"].toDouble(); + + if (obj.contains("mapDefault")) + { + probe->map_default = obj["mapDefault"].toBool(); + } + + break; + } + } + if (!isEnabled) + probe->enabled = false; + } + } + + _session->reload(); + + // load signal setting + if (mode == DSO) + { + for (auto s : _session->get_signals()) + { + for (const QJsonValue &value : sessionObj["channel"].toArray()) + { + QJsonObject obj = value.toObject(); + + if (s->get_name() == obj["name"].toString() && + s->get_type() == obj["type"].toDouble()) + { + s->set_colour(QColor(obj["colour"].toString())); + + if (s->signal_type() == SR_CHANNEL_DSO) + { + view::DsoSignal *dsoSig = (view::DsoSignal*)s; + dsoSig->load_settings(); + dsoSig->set_zero_ratio(obj["zeroPos"].toDouble()); + dsoSig->set_trig_ratio(obj["trigValue"].toDouble()); + dsoSig->commit_settings(); + } + break; + } + } + } + } + else + { + for (auto s : _session->get_signals()) + { + for (const QJsonValue &value : sessionObj["channel"].toArray()) + { + QJsonObject obj = value.toObject(); + if ((s->get_index() == obj["index"].toInt()) && + (s->get_type() == obj["type"].toInt())) + { + QString chan_name = obj["name"].toString().trimmed(); + if (chan_name == ""){ + chan_name = QString::number(s->get_index()); + } + + s->set_colour(QColor(obj["colour"].toString())); + s->set_name(chan_name); + + view::LogicSignal *logicSig = NULL; + if ((logicSig = dynamic_cast(s))) + { + logicSig->set_trig(obj["strigger"].toDouble()); + } + + if (s->signal_type() == SR_CHANNEL_DSO) + { + view::DsoSignal *dsoSig = (view::DsoSignal*)s; + dsoSig->load_settings(); + dsoSig->set_zero_ratio(obj["zeroPos"].toDouble()); + dsoSig->set_trig_ratio(obj["trigValue"].toDouble()); + dsoSig->commit_settings(); + } + + if (s->signal_type() == SR_CHANNEL_ANALOG) + { + view::AnalogSignal *analogSig = (view::AnalogSignal*)s; + analogSig->set_zero_ratio(obj["zeroPos"].toDouble()); + analogSig->commit_settings(); + } + + break; + } + } + } + } + + // update UI settings + _sampling_bar->update_sample_rate_list(); + _trigger_widget->device_updated(); + _view->header_updated(); + + // load trigger settings + if (sessionObj.contains("trigger")) + { + _trigger_widget->set_session(sessionObj["trigger"].toObject()); + } + + // load decoders + if (sessionObj.contains("decoder")) + { + QJsonArray deArray = sessionObj["decoder"].toArray(); + if (deArray.empty() == false) + { + haveDecoder = true; + StoreSession ss(_session); + ss.load_decoders(_protocol_widget, deArray); + _view->update_all_trace_postion(); + } + } + + // load measure + if (sessionObj.contains("measure")) + { + auto *bottom_bar = _view->get_viewstatus(); + bottom_bar->load_session(sessionObj["measure"].toArray(), format_ver); + } + + if (gvar_opts != NULL) + g_variant_unref(gvar_opts); + + load_channel_view_indexs(doc); + + return true; + } + + void MainWindow::load_channel_view_indexs(QJsonDocument &doc) + { + QJsonObject sessionObj = doc.object(); + + int mode = _device_agent->get_work_mode(); + if (mode != LOGIC) + return; + + std::vector view_indexs; + + for (const QJsonValue &value : sessionObj["channel"].toArray()){ + QJsonObject obj = value.toObject(); + + if (obj.contains("view_index")){ + view_indexs.push_back(obj["view_index"].toInt()); + } + } + + if (view_indexs.size()){ + int i = 0; + + for (auto s : _session->get_signals()){ + s->set_view_index(view_indexs[i]); + i++; + } + + _view->update_all_trace_postion(); + } + } + + bool MainWindow::on_store_session(QString name) + { + return save_config_to_file(name); + } + + bool MainWindow::save_config_to_file(QString name) + { + if (name == ""){ + dsv_err("Session file name is empty."); + assert(false); + } + + std::string file_name = pv::path::ToUnicodePath(name); + dsv_info("Store session to file: \"%s\"", file_name.c_str()); + + QFile sf(name); + if (!sf.open(QIODevice::WriteOnly | QIODevice::Text)) + { + dsv_warn("Warning: Couldn't open profile to write!"); + return false; + } + + QTextStream outStream(&sf); + encoding::set_utf8(outStream); + + QJsonObject sessionVar; + if (!gen_config_json(sessionVar)){ + return false; + } + + QJsonDocument sessionDoc(sessionVar); + outStream << QString::fromUtf8(sessionDoc.toJson()); + sf.close(); + return true; + } + + bool MainWindow::genSessionData(std::string &str) + { + QJsonObject sessionVar; + if (!gen_config_json(sessionVar)) + { + return false; + } + + QJsonDocument sessionDoc(sessionVar); + QString data = QString::fromUtf8(sessionDoc.toJson()); + str.append(data.toLocal8Bit().data()); + return true; + } + + void MainWindow::restore_dock() + { + // default dockwidget size + AppConfig &app = AppConfig::Instance(); + QByteArray st = app.frameOptions.windowState; + if (!st.isEmpty()) + { + try + { + restoreState(st); + } + catch (...) + { + MsgBox::Show(NULL, L_S(STR_PAGE_MSG, S_ID(IDS_MSG_RESTORE_WINDOW_ERROR), "restore window status error!")); + } + } + + // Resotre the dock pannel. + if (_device_agent->have_instance()) + _trig_bar->reload(); + } + + bool MainWindow::eventFilter(QObject *object, QEvent *event) + { + (void)object; + + if (event->type() == QEvent::KeyPress) + { + const auto &sigs = _session->get_signals(); + QKeyEvent *ke = (QKeyEvent *)event; + + int modifier = ke->modifiers(); + + if(modifier & Qt::ControlModifier || + modifier & Qt::ShiftModifier || + modifier & Qt::AltModifier) + { + return true; + } + + high_resolution_clock::time_point key_press_time = high_resolution_clock::now(); + milliseconds timeInterval = std::chrono::duration_cast(key_press_time - _last_key_press_time); + int64_t time_keep = timeInterval.count(); + if (time_keep < 200){ + return true; + } + _last_key_press_time = key_press_time; + + switch (ke->key()) + { + case Qt::Key_S: + _sampling_bar->run_or_stop(); + break; + + case Qt::Key_I: + _sampling_bar->run_or_stop_instant(); + break; + + case Qt::Key_T: + _trig_bar->trigger_clicked(); + break; + + case Qt::Key_D: + _trig_bar->protocol_clicked(); + break; + + case Qt::Key_M: + _trig_bar->measure_clicked(); + break; + + case Qt::Key_R: + _trig_bar->search_clicked(); + break; + + case Qt::Key_O: + _sampling_bar->config_device(); + break; + + case Qt::Key_PageUp: + _view->set_scale_offset(_view->scale(), + _view->offset() - _view->get_view_width()); + break; + case Qt::Key_PageDown: + _view->set_scale_offset(_view->scale(), + _view->offset() + _view->get_view_width()); + + break; + + case Qt::Key_Left: + _view->zoom(1); + break; + + case Qt::Key_Right: + _view->zoom(-1); + break; + + case Qt::Key_0: + for (auto s : sigs) + { + if (s->signal_type() == SR_CHANNEL_DSO) + { + view::DsoSignal *dsoSig = (view::DsoSignal*)s; + if (dsoSig->get_index() == 0) + dsoSig->set_vDialActive(!dsoSig->get_vDialActive()); + else + dsoSig->set_vDialActive(false); + } + } + _view->setFocus(); + update(); + break; + + case Qt::Key_1: + for (auto s : sigs) + { + if (s->signal_type() == SR_CHANNEL_DSO) + { + view::DsoSignal *dsoSig = (view::DsoSignal*)s; + if (dsoSig->get_index() == 1) + dsoSig->set_vDialActive(!dsoSig->get_vDialActive()); + else + dsoSig->set_vDialActive(false); + } + } + _view->setFocus(); + update(); + break; + + case Qt::Key_Up: + for (auto s : sigs) + { + if (s->signal_type() == SR_CHANNEL_DSO){ + view::DsoSignal *dsoSig = (view::DsoSignal*)s; + if (dsoSig->get_vDialActive()) + { + dsoSig->go_vDialNext(true); + update(); + break; + } + } + } + break; + + case Qt::Key_Down: + for (auto s : sigs) + { + if (s->signal_type() == SR_CHANNEL_DSO){ + view::DsoSignal *dsoSig = (view::DsoSignal*)s; + if (dsoSig->get_vDialActive()) + { + dsoSig->go_vDialPre(true); + update(); + break; + } + } + } + break; + + default: + QWidget::keyPressEvent((QKeyEvent *)event); + } + return true; + } + return false; + } + + void MainWindow::switchLanguage(int language) + { + if (language == 0) + return; + + AppConfig &app = AppConfig::Instance(); + + if (app.frameOptions.language != language && language > 0) + { + app.frameOptions.language = language; + app.SaveFrame(); + LangResource::Instance()->Load(language); + } + + if (language == LAN_CN) + { + _qtTrans.load(":/qt_" + QString::number(language)); + qApp->installTranslator(&_qtTrans); + _myTrans.load(":/my_" + QString::number(language)); + qApp->installTranslator(&_myTrans); + retranslateUi(); + } + else if (language == LAN_EN) + { + qApp->removeTranslator(&_qtTrans); + qApp->removeTranslator(&_myTrans); + retranslateUi(); + } + else + { + dsv_err("%s%d", "Unknown language code:", language); + } + } + + void MainWindow::switchTheme(QString style) + { + AppConfig &app = AppConfig::Instance(); + + if (app.frameOptions.style != style) + { + app.frameOptions.style = style; + app.SaveFrame(); + } + + QString qssRes = ":/" + style + ".qss"; + QFile qss(qssRes); + qss.open(QFile::ReadOnly | QFile::Text); + qApp->setStyleSheet(qss.readAll()); + qss.close(); + + + data_updated(); + } + + void MainWindow::data_updated() + { + _event.data_updated(); // safe call + } + + void MainWindow::on_data_updated() + { + _measure_widget->reCalc(); + _view->data_updated(); + } + + void MainWindow::on_open_doc() + { + openDoc(); + } + + void MainWindow::openDoc() + { + QDir dir(GetAppDataDir()); + AppConfig &app = AppConfig::Instance(); + int lan = app.frameOptions.language; + QDesktopServices::openUrl( + QUrl("file:///" + dir.absolutePath() + "/ug" + QString::number(lan) + ".pdf")); + } + + void MainWindow::update_capture() + { + _view->update_hori_res(); + } + + void MainWindow::cur_snap_samplerate_changed() + { + _event.cur_snap_samplerate_changed(); // safe call + } + + void MainWindow::on_cur_snap_samplerate_changed() + { + _measure_widget->cursor_update(); + } + + /*------------------on event end-------*/ + + void MainWindow::signals_changed() + { + _event.signals_changed(); // safe call + } + + void MainWindow::on_signals_changed() + { + _view->signals_changed(NULL); + } + + void MainWindow::receive_trigger(quint64 trigger_pos) + { + _event.receive_trigger(trigger_pos); // save call + } + + void MainWindow::on_receive_trigger(quint64 trigger_pos) + { + _view->receive_trigger(trigger_pos); + } + + void MainWindow::frame_ended() + { + _event.frame_ended(); // save call + } + + void MainWindow::on_frame_ended() + { + _view->receive_end(); + } + + void MainWindow::frame_began() + { + _event.frame_began(); // save call + } + + void MainWindow::on_frame_began() + { + _view->frame_began(); + } + + void MainWindow::show_region(uint64_t start, uint64_t end, bool keep) + { + _view->show_region(start, end, keep); + } + + void MainWindow::show_wait_trigger() + { + _view->show_wait_trigger(); + } + + void MainWindow::repeat_hold(int percent) + { + (void)percent; + _view->repeat_show(); + } + + void MainWindow::decode_done() + { + _event.decode_done(); // safe call + } + + void MainWindow::on_decode_done() + { + _protocol_widget->update_model(); + } + + void MainWindow::receive_data_len(quint64 len) + { + _event.receive_data_len(len); // safe call + } + + void MainWindow::on_receive_data_len(quint64 len) + { + _view->set_receive_len(len); + } + + void MainWindow::receive_header() + { + } + + void MainWindow::check_usb_device_speed() + { + // USB device speed check + if (_device_agent->is_hardware()) + { + int usb_speed = LIBUSB_SPEED_HIGH; + _device_agent->get_config_int32(SR_CONF_USB_SPEED, usb_speed); + + bool usb30_support = false; + + if (_device_agent->get_config_bool(SR_CONF_USB30_SUPPORT, usb30_support)) + { + dsv_info("The device's USB module version: %d.0", usb30_support ? 3 : 2); + + int cable_ver = 1; + if (usb_speed == LIBUSB_SPEED_HIGH) + cable_ver = 2; + else if (usb_speed == LIBUSB_SPEED_SUPER) + cable_ver = 3; + + dsv_info("The cable's USB port version: %d.0", cable_ver); + + if (usb30_support && usb_speed == LIBUSB_SPEED_HIGH){ + QString str_err(L_S(STR_PAGE_DLG, S_ID(IDS_DLG_CHECK_USB_SPEED_ERROR), + "Plug the device into a USB 2.0 port will seriously affect its performance.\nPlease replug it into a USB 3.0 port.")); + delay_prop_msg(str_err); + } + } + } + } + + void MainWindow::trigger_message(int msg) + { + _event.trigger_message(msg); + } + + void MainWindow::on_trigger_message(int msg) + { + _session->broadcast_msg(msg); + } + + void MainWindow::reset_all_view() + { + _sampling_bar->reload(); + _view->status_clear(); + _view->reload(); + _view->set_device(); + _trigger_widget->update_view(); + _trigger_widget->device_updated(); + _trig_bar->reload(); + _dso_trigger_widget->update_view(); + _measure_widget->reload(); + + if (_device_agent->get_work_mode() == ANALOG) + _view->get_viewstatus()->setVisible(false); + else + _view->get_viewstatus()->setVisible(true); + } + + bool MainWindow::confirm_to_store_data() + { + bool ret = false; + _is_save_confirm_msg = true; + + if (_session->have_hardware_data() && _session->is_first_store_confirm()) + { + // Only popup one time. + ret = MsgBox::Confirm(L_S(STR_PAGE_MSG, S_ID(IDS_MSG_SAVE_CAPDATE), "Save captured data?")); + + if (!ret && _is_auto_switch_device) + { + dsv_info("The data save confirm end, auto switch to the new device."); + _is_auto_switch_device = false; + + if (_session->is_working()) + _session->stop_capture(); + + _session->set_default_device(); + } + } + + _is_save_confirm_msg = false; + return ret; + } + + void MainWindow::check_config_file_version() + { + auto device_agent = _session->get_device(); + if (device_agent->is_file() && device_agent->is_new_device()) + { + if (device_agent->get_work_mode() == LOGIC) + { + int version = -1; + if (device_agent->get_config_int16(SR_CONF_FILE_VERSION, version)) + { + if (version == 1) + { + QString strMsg(L_S(STR_PAGE_DLG, S_ID(IDS_DLG_CHECK_SESSION_FILE_VERSION_ERROR), + "Current loading file has an old format. \nThis will lead to a slow loading speed. \nPlease resave it after loaded.")); + MsgBox::Show(strMsg); + } + } + } + } + } + + void MainWindow::load_device_config() + { + _title_ext_string = ""; + int mode = _device_agent->get_work_mode(); + QString file; + + if (_device_agent->is_hardware()) + { + QString ses_name = gen_config_file_path(true); + + bool bExist = false; + + QFile sf(ses_name); + if (!sf.exists()){ + dsv_info("Try to load the low version profile."); + ses_name = gen_config_file_path(false); + } + else{ + bExist = true; + } + + if (!bExist) + { + QFile sf2(ses_name); + if (!sf2.exists()){ + dsv_info("Try to load the default profile."); + ses_name = _file_bar->genDefaultSessionFile(); + } + } + + file = ses_name; + } + else if (_device_agent->is_demo()) + { + QDir dir(GetFirmwareDir()); + if (dir.exists()) + { + QString ses_name = dir.absolutePath() + "/" + + _device_agent->driver_name() + QString::number(mode) + ".dsc"; + + QFile sf(ses_name); + if (sf.exists()){ + file = ses_name; + } + } + } + + if (file != ""){ + bool ret = load_config_from_file(file); + if (ret && _device_agent->is_hardware()){ + _title_ext_string = file; + } + } + } + + QJsonDocument MainWindow::get_config_json_from_data_file(QString file, bool &bSucesss) + { + QJsonDocument sessionDoc; + QJsonParseError error; + bSucesss = false; + + if (file == ""){ + dsv_err("File name is empty."); + assert(false); + } + + auto f_name = pv::path::ConvertPath(file); + ZipReader rd(f_name.c_str()); + auto *data = rd.GetInnterFileData("session"); + + if (data != NULL) + { + QByteArray raw_bytes = QByteArray::fromRawData(data->data(), data->size()); + QString jsonStr(raw_bytes.data()); + QByteArray qbs = jsonStr.toUtf8(); + sessionDoc = QJsonDocument::fromJson(qbs, &error); + + if (error.error != QJsonParseError::NoError) + { + QString estr = error.errorString(); + dsv_err("File::get_session(), parse json error:\"%s\"!", estr.toUtf8().data()); + } + else{ + bSucesss = true; + } + + rd.ReleaseInnerFileData(data); + } + + return sessionDoc; + } + + QJsonArray MainWindow::get_decoder_json_from_data_file(QString file, bool &bSucesss) + { + QJsonArray dec_array; + QJsonParseError error; + + bSucesss = false; + + if (file == ""){ + dsv_err("File name is empty."); + assert(false); + } + + /* read "decoders" */ + auto f_name = path::ConvertPath(file); + ZipReader rd(f_name.c_str()); + auto *data = rd.GetInnterFileData("decoders"); + + if (data != NULL) + { + QByteArray raw_bytes = QByteArray::fromRawData(data->data(), data->size()); + QString jsonStr(raw_bytes.data()); + QByteArray qbs = jsonStr.toUtf8(); + QJsonDocument sessionDoc = QJsonDocument::fromJson(qbs, &error); + + if (error.error != QJsonParseError::NoError) + { + QString estr = error.errorString(); + dsv_err("MainWindow::get_decoder_json_from_file(), parse json error:\"%s\"!", estr.toUtf8().data()); + } + else{ + bSucesss = true; + } + + dec_array = sessionDoc.array(); + rd.ReleaseInnerFileData(data); + } + + return dec_array; + } + + void MainWindow::update_toolbar_view_status() + { + _sampling_bar->update_view_status(); + _file_bar->update_view_status(); + _trig_bar->update_view_status(); + } + + void MainWindow::OnMessage(int msg) + { + switch (msg) + { + case DSV_MSG_DEVICE_LIST_UPDATED: + _sampling_bar->update_device_list(); + break; + + case DSV_MSG_START_COLLECT_WORK_PREV: + if (_device_agent->get_work_mode() == LOGIC) + _trigger_widget->try_commit_trigger(); + else if (_device_agent->get_work_mode() == DSO) + _dso_trigger_widget->check_setting(); + + _view->capture_init(); + _view->on_state_changed(false); + break; + + case DSV_MSG_START_COLLECT_WORK: + update_toolbar_view_status(); + _view->on_state_changed(false); + _protocol_widget->update_view_status(); + break; + + case DSV_MSG_COLLECT_END: + prgRate(0); + _view->repeat_unshow(); + _view->on_state_changed(true); + _protocol_widget->update_view_status(); + break; + + case DSV_MSG_END_COLLECT_WORK: + update_toolbar_view_status(); + break; + + case DSV_MSG_CURRENT_DEVICE_CHANGE_PREV: + if (_msg != NULL){ + _msg->close(); + _msg = NULL; + } + _view->hide_calibration(); + + _protocol_widget->del_all_protocol(); + _view->reload(); + break; + + case DSV_MSG_CURRENT_DEVICE_CHANGED: + { + reset_all_view(); + load_device_config(); + update_title_bar_text(); + _sampling_bar->update_device_list(); + + _logo_bar->dsl_connected(_session->get_device()->is_hardware()); + update_toolbar_view_status(); + _session->device_event_object()->device_updated(); + + if (_device_agent->is_hardware()) + { + _session->on_load_config_end(); + } + + if (_device_agent->get_work_mode() == LOGIC && _device_agent->is_file() == false) + _view->auto_set_max_scale(); + + if (_device_agent->is_file()) + { + check_config_file_version(); + + bool bDoneDecoder = false; + bool bLoadSuccess = false; + QJsonDocument doc = get_config_json_from_data_file(_device_agent->path(), bLoadSuccess); + + if (bLoadSuccess){ + load_config_from_json(doc, bDoneDecoder); + } + + if (!bDoneDecoder && _device_agent->get_work_mode() == LOGIC) + { + QJsonArray deArray = get_decoder_json_from_data_file(_device_agent->path(), bLoadSuccess); + + if (bLoadSuccess){ + StoreSession ss(_session); + ss.load_decoders(_protocol_widget, deArray); + } + } + + _view->update_all_trace_postion(); + QTimer::singleShot(100, this, [this](){ + _session->start_capture(true); + }); + } + else if (_device_agent->is_demo()) + { + if(_device_agent->get_work_mode() == LOGIC) + { + _pattern_mode = _device_agent->get_demo_operation_mode(); + _protocol_widget->del_all_protocol(); + _view->auto_set_max_scale(); + + if(_pattern_mode != "random"){ + load_demo_decoder_config(_pattern_mode); + } + } + } + + calc_min_height(); + + if (_device_agent->is_hardware() && _device_agent->is_new_device()){ + check_usb_device_speed(); + } + } + break; + + case DSV_MSG_DEVICE_OPTIONS_UPDATED: + _trigger_widget->device_updated(); + _measure_widget->reload(); + _view->check_calibration(); + break; + + case DSV_MSG_DEVICE_DURATION_UPDATED: + _trigger_widget->device_updated(); + _view->timebase_changed(); + break; + + case DSV_MSG_DEVICE_MODE_CHANGED: + _view->mode_changed(); + reset_all_view(); + load_device_config(); + update_title_bar_text(); + _view->hide_calibration(); + + update_toolbar_view_status(); + _sampling_bar->update_sample_rate_list(); + + if (_device_agent->is_hardware()) + _session->on_load_config_end(); + + if (_device_agent->get_work_mode() == LOGIC) + _view->auto_set_max_scale(); + + if(_device_agent->is_demo()) + { + _pattern_mode = _device_agent->get_demo_operation_mode(); + _protocol_widget->del_all_protocol(); + + if(_device_agent->get_work_mode() == LOGIC) + { + if(_pattern_mode != "random"){ + _device_agent->update(); + load_demo_decoder_config(_pattern_mode); + } + } + } + + calc_min_height(); + break; + + case DSV_MSG_NEW_USB_DEVICE: + { + if (_msg != NULL){ + _msg->close(); + _msg = NULL; + } + + _sampling_bar->update_device_list(); + + if (_session->get_device()->is_demo() == false) + { + QString msgText = L_S(STR_PAGE_MSG, S_ID(IDS_MSG_TO_SWITCH_DEVICE), "To switch the new device?"); + + if (MsgBox::Confirm(msgText, "", &_msg, NULL) == false){ + _msg = NULL; + return; + } + _msg = NULL; + } + + // The store confirm is not processed. + if (_is_save_confirm_msg){ + dsv_info("New device attached:Waitting for the confirm box be closed."); + _is_auto_switch_device = true; + return; + } + + if (_session->is_saving()){ + dsv_info("New device attached:Waitting for store the data. and will switch to new device."); + _is_auto_switch_device = true; + return; + } + + int mode = _device_agent->get_work_mode(); + + if (mode != DSO && confirm_to_store_data()) + { + _is_auto_switch_device = true; + + if (_session->is_working()) + _session->stop_capture(); + + on_save(); + } + else + { + if (_session->is_working()) + _session->stop_capture(); + + _session->set_default_device(); + } + } + break; + + case DSV_MSG_CURRENT_DEVICE_DETACHED: + if (_msg != NULL){ + _msg->close(); + _msg = NULL; + } + + // Save current config, and switch to the last device. + _session->device_event_object()->device_updated(); + save_config(); + _view->hide_calibration(); + + if (_session->is_saving()){ + dsv_info("Device detached:Waitting for store the data. and will switch to new device."); + _is_auto_switch_device = true; + return; + } + + if (confirm_to_store_data()){ + _is_auto_switch_device = true; + on_save(); + } + else{ + _session->set_default_device(); + } + break; + + case DSV_MSG_SAVE_COMPLETE: + _session->clear_store_confirm_flag(); + + if (_is_auto_switch_device) + { + _is_auto_switch_device = false; + _session->set_default_device(); + } + else + { + ds_device_handle devh = _sampling_bar->get_next_device_handle(); + if (devh != NULL_HANDLE) + { + dsv_info("Auto switch to the selected device."); + _session->set_device(devh); + } + } + break; + + case DSV_MSG_CLEAR_DECODE_DATA: + if (_device_agent->get_work_mode() == LOGIC) + _protocol_widget->reset_view(); + break; + + case DSV_MSG_STORE_CONF_PREV: + if (_device_agent->is_hardware() && _session->have_hardware_data() == false){ + _sampling_bar->commit_settings(); + } + break; + + case DSV_MSG_BEGIN_DEVICE_OPTIONS: + case DSV_MSG_COLLECT_MODE_CHANGED: + if(_device_agent->is_demo()){ + _pattern_mode = _device_agent->get_demo_operation_mode(); + } + if (msg == DSV_MSG_COLLECT_MODE_CHANGED){ + _trigger_widget->device_updated(); + _view->update(); + } + break; + + case DSV_MSG_END_DEVICE_OPTIONS: + case DSV_MSG_DEMO_OPERATION_MODE_CHNAGED: + if(_device_agent->is_demo() &&_device_agent->get_work_mode() == LOGIC){ + QString pattern_mode = _device_agent->get_demo_operation_mode(); + + if(pattern_mode != _pattern_mode) + { + _pattern_mode = pattern_mode; + + _device_agent->update(); + _session->clear_view_data(); + _session->init_signals(); + update_toolbar_view_status(); + _sampling_bar->update_sample_rate_list(); + _protocol_widget->del_all_protocol(); + + if(_pattern_mode != "random"){ + _session->set_collect_mode(COLLECT_SINGLE); + load_demo_decoder_config(_pattern_mode); + + if (msg == DSV_MSG_END_DEVICE_OPTIONS) + _session->start_capture(false); // Auto load data. + } + } + } + calc_min_height(); + break; + + case DSV_MSG_APP_OPTIONS_CHANGED: + update_title_bar_text(); + break; + + case DSV_MSG_FONT_OPTIONS_CHANGED: + AppControl::Instance()->update_font_forms(); + break; + case DSV_MSG_DATA_POOL_CHANGED: + _view->check_measure(); + break; + } + } + + void MainWindow::calc_min_height() + { + if (_frame != NULL) + { + if (_device_agent->get_work_mode() == LOGIC) + { + int ch_num = _session->get_ch_num(-1); + int win_height = Base_Height + Per_Chan_Height * ch_num; + + if (win_height < Min_Height) + _frame->setMinimumHeight(win_height); + else + _frame->setMinimumHeight(Min_Height); + } + else{ + _frame->setMinimumHeight(Min_Height); + } + } + } + + void MainWindow::delay_prop_msg(QString strMsg) + { + _strMsg = strMsg; + if (_strMsg != ""){ + _delay_prop_msg_timer.Start(500); + } + } + + void MainWindow::on_delay_prop_msg() + { + _delay_prop_msg_timer.Stop(); + + if (_strMsg != ""){ + MsgBox::Show("", _strMsg, this, &_msg); + _msg = NULL; + } + } + + void MainWindow::update_title_bar_text() + { + // Set the title + QString title = QApplication::applicationName() + " v" + QApplication::applicationVersion(); + AppConfig &app = AppConfig::Instance(); + + if (_title_ext_string != "" && app.appOptions.displayProfileInBar){ + title += " [" + _title_ext_string + "]"; + } + + if (_lst_title_string != title){ + _lst_title_string = title; + + setWindowTitle(QApplication::translate("MainWindow", title.toLocal8Bit().data(), 0)); + _title_bar->setTitle(this->windowTitle()); + } + } + + void MainWindow::load_demo_decoder_config(QString optname) + { + QString file = GetAppDataDir() + "/demo/logic/" + optname + ".demo"; + bool bLoadSurccess = false; + + QJsonArray deArray = get_decoder_json_from_data_file(file, bLoadSurccess); + + if (bLoadSurccess){ + StoreSession ss(_session); + ss.load_decoders(_protocol_widget, deArray); + } + + QJsonDocument doc = get_config_json_from_data_file(file, bLoadSurccess); + if (bLoadSurccess){ + load_channel_view_indexs(doc); + } + + _view->update_all_trace_postion(); + } + +} // namespace pv diff --git a/DSView/pv/mainwindow.h b/DSView/pv/mainwindow.h index f5e82d74..78e08cf3 100644 --- a/DSView/pv/mainwindow.h +++ b/DSView/pv/mainwindow.h @@ -1,248 +1,249 @@ -/* - * This file is part of the DSView project. - * DSView is based on PulseView. - * - * Copyright (C) 2012 Joel Holdsworth - * Copyright (C) 2013 DreamSourceLab - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - - -#ifndef DSVIEW_PV_MAINWINDOW_H -#define DSVIEW_PV_MAINWINDOW_H - -#include -#include -#include -#include "dialogs/dsmessagebox.h" -#include "interface/icallbacks.h" -#include "eventobject.h" -#include -#include -#include "dstimer.h" - -class QAction; -class QMenuBar; -class QMenu; -class QVBoxLayout; -class QStatusBar; -class QToolBar; -class QWidget; -class QDockWidget; -class AppControl; -class DeviceAgent; - -using std::chrono::high_resolution_clock; -using std::chrono::milliseconds; - -namespace pv { - -class SigSession; - -namespace toolbars { -class SamplingBar; -class TrigBar; -class FileBar; -class LogoBar; -class TitleBar; -} - -namespace dock{ -class ProtocolDock; -class TriggerDock; -class DsoTriggerDock; -class MeasureDock; -class SearchDock; -} - -namespace view { -class View; -} - -//The mainwindow,referenced by MainFrame -//TODO: create graph view,toolbar,and show device list -class MainWindow : - public QMainWindow, - public ISessionCallback, - public IMainForm, - public ISessionDataGetter, - public IMessageListener -{ - Q_OBJECT - -public: - static const int Min_Width = 350; - static const int Min_Height = 300; - static const int Base_Height = 150; - static const int Per_Chan_Height = 35; - -public: - explicit MainWindow(toolbars::TitleBar *title_bar, QWidget *parent = 0); - - void openDoc(); - -public slots: - void switchTheme(QString style); - void restore_dock(); - -private slots: - void on_load_file(QString file_name); - void on_open_doc(); - void on_protocol(bool visible); - void on_trigger(bool visible); - void on_measure(bool visible); - void on_search(bool visible); - void on_screenShot(); - void on_save(); - - void on_export(); - bool on_load_session(QString name); - bool on_store_session(QString name); - void on_data_updated(); - - void on_session_error(); - void on_signals_changed(); - void on_receive_trigger(quint64 trigger_pos); - void on_frame_ended(); - void on_frame_began(); - void on_decode_done(); - void on_receive_data_len(quint64 len); - void on_cur_snap_samplerate_changed(); - void on_trigger_message(int msg); - void on_delay_prop_msg(); - -signals: - void prgRate(int progress); - -public: - //IMainForm - void switchLanguage(int language) override; - bool able_to_close(); - -private: - void setup_ui(); - void retranslateUi(); - bool eventFilter(QObject *object, QEvent *event); - void check_usb_device_speed(); - void reset_all_view(); - bool confirm_to_store_data(); - void update_toolbar_view_status(); - void calc_min_height(); - void update_title_bar_text(); - - //json operation -private: - QString gen_config_file_path(bool isNewFormat); - bool load_config_from_file(QString file); - bool load_config_from_json(QJsonDocument &doc, bool &haveDecoder); - void load_device_config(); - bool gen_config_json(QJsonObject &sessionVar); - void save_config(); - bool save_config_to_file(QString file); - void load_channel_view_indexs(QJsonDocument &doc); - QJsonDocument get_config_json_from_data_file(QString file, bool &bSucesss); - QJsonArray get_decoder_json_from_data_file(QString file, bool &bSucesss); - void check_config_file_version(); - void load_demo_decoder_config(QString optname); - - -private: - //ISessionCallback - void session_error() override; - void session_save() override; - void data_updated() override; - void update_capture() override; - void cur_snap_samplerate_changed() override; - void signals_changed() override; - void receive_trigger(quint64 trigger_pos) override; - void frame_ended() override; - void frame_began() override; - void show_region(uint64_t start, uint64_t end, bool keep) override; - void show_wait_trigger() override; - void repeat_hold(int percent) override; - void decode_done() override; - void receive_data_len(quint64 len) override; - void receive_header() override; - void trigger_message(int msg) override; - void delay_prop_msg(QString strMsg) override; - - //ISessionDataGetter - bool genSessionData(std::string &str) override; - - //IMessageListener - void OnMessage(int msg) override; - -private: - pv::view::View *_view; - dialogs::DSMessageBox *_msg; - - QMenuBar *_menu_bar; - QMenu *_menu_file; - QAction *_action_open; - QAction *_action_connect; - QAction *_action_quit; - - QMenu *_menu_view; - QAction *_action_view_zoom_in; - QAction *_action_view_zoom_out; - QAction *_action_view_show_cursors; - - QMenu *_menu_help; - QAction *_action_about; - - QWidget *_central_widget; - QVBoxLayout *_vertical_layout; - - toolbars::SamplingBar *_sampling_bar; - toolbars::TrigBar *_trig_bar; - toolbars::FileBar *_file_bar; - toolbars::LogoBar *_logo_bar; //help button, on top right - toolbars::TitleBar *_title_bar; - - - QDockWidget *_protocol_dock; - dock::ProtocolDock *_protocol_widget; - QDockWidget *_trigger_dock; - QDockWidget *_dso_trigger_dock; - dock::TriggerDock *_trigger_widget; - dock::DsoTriggerDock *_dso_trigger_widget; - QDockWidget *_measure_dock; - dock::MeasureDock *_measure_widget; - QDockWidget *_search_dock; - dock::SearchDock *_search_widget; - - QTranslator _qtTrans; - QTranslator _myTrans; - EventObject _event; - SigSession *_session; - DeviceAgent *_device_agent; - bool _is_auto_switch_device; - high_resolution_clock::time_point _last_key_press_time; - bool _is_save_confirm_msg; - QString _pattern_mode; - QWidget *_frame; - DsTimer _delay_prop_msg_timer; - QString _strMsg; - QString _lst_title_string; - QString _title_ext_string; - - int _key_value; - bool _key_vaild; -}; - -} // namespace pv - -#endif // DSVIEW_PV_MAINWINDOW_H +/* + * This file is part of the DSView project. + * DSView is based on PulseView. + * + * Copyright (C) 2012 Joel Holdsworth + * Copyright (C) 2013 DreamSourceLab + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +#ifndef DSVIEW_PV_MAINWINDOW_H +#define DSVIEW_PV_MAINWINDOW_H + +#include +#include +#include +#include "dialogs/dsmessagebox.h" +#include "interface/icallbacks.h" +#include "eventobject.h" +#include +#include +#include "dstimer.h" + +class QAction; +class QMenuBar; +class QMenu; +class QVBoxLayout; +class QStatusBar; +class QToolBar; +class QWidget; +class QDockWidget; +class AppControl; +class DeviceAgent; + +using std::chrono::high_resolution_clock; +using std::chrono::milliseconds; + +namespace pv { + +class SigSession; + +namespace toolbars { +class SamplingBar; +class TrigBar; +class FileBar; +class LogoBar; +class TitleBar; +} + +namespace dock{ +class ProtocolDock; +class TriggerDock; +class DsoTriggerDock; +class MeasureDock; +class SearchDock; +} + +namespace view { +class View; +} + +//The mainwindow,referenced by MainFrame +//TODO: create graph view,toolbar,and show device list +class MainWindow : + public QMainWindow, + public ISessionCallback, + public IMainForm, + public ISessionDataGetter, + public IMessageListener +{ + Q_OBJECT + +public: + static const int Min_Width = 350; + static const int Min_Height = 300; + static const int Base_Height = 150; + static const int Per_Chan_Height = 35; + +public: + explicit MainWindow(toolbars::TitleBar *title_bar, QWidget *parent = 0); + + void openDoc(); + +public slots: + void switchTheme(QString style); + void restore_dock(); + +private slots: + void on_load_file(QString file_name); + void on_open_doc(); + void on_protocol(bool visible); + void on_trigger(bool visible); + void on_measure(bool visible); + void on_search(bool visible); + void on_screenShot(); + void on_save(); + + void on_export(); + bool on_load_session(QString name); + bool on_store_session(QString name); + void on_data_updated(); + + void on_session_error(); + void on_signals_changed(); + void on_receive_trigger(quint64 trigger_pos); + void on_frame_ended(); + void on_frame_began(); + void on_decode_done(); + void on_receive_data_len(quint64 len); + void on_cur_snap_samplerate_changed(); + void on_trigger_message(int msg); + void on_delay_prop_msg(); + +signals: + void prgRate(int progress); + +public: + //IMainForm + void switchLanguage(int language) override; + bool able_to_close(); + + +private: + void setup_ui(); + void retranslateUi(); + bool eventFilter(QObject *object, QEvent *event); + void check_usb_device_speed(); + void reset_all_view(); + bool confirm_to_store_data(); + void update_toolbar_view_status(); + void calc_min_height(); + void update_title_bar_text(); + + //json operation +private: + QString gen_config_file_path(bool isNewFormat); + bool load_config_from_file(QString file); + bool load_config_from_json(QJsonDocument &doc, bool &haveDecoder); + void load_device_config(); + bool gen_config_json(QJsonObject &sessionVar); + void save_config(); + bool save_config_to_file(QString file); + void load_channel_view_indexs(QJsonDocument &doc); + QJsonDocument get_config_json_from_data_file(QString file, bool &bSucesss); + QJsonArray get_decoder_json_from_data_file(QString file, bool &bSucesss); + void check_config_file_version(); + void load_demo_decoder_config(QString optname); + + +private: + //ISessionCallback + void session_error() override; + void session_save() override; + void data_updated() override; + void update_capture() override; + void cur_snap_samplerate_changed() override; + void signals_changed() override; + void receive_trigger(quint64 trigger_pos) override; + void frame_ended() override; + void frame_began() override; + void show_region(uint64_t start, uint64_t end, bool keep) override; + void show_wait_trigger() override; + void repeat_hold(int percent) override; + void decode_done() override; + void receive_data_len(quint64 len) override; + void receive_header() override; + void trigger_message(int msg) override; + void delay_prop_msg(QString strMsg) override; + + //ISessionDataGetter + bool genSessionData(std::string &str) override; + + //IMessageListener + void OnMessage(int msg) override; + +private: + pv::view::View *_view; + dialogs::DSMessageBox *_msg; + + QMenuBar *_menu_bar; + QMenu *_menu_file; + QAction *_action_open; + QAction *_action_connect; + QAction *_action_quit; + + QMenu *_menu_view; + QAction *_action_view_zoom_in; + QAction *_action_view_zoom_out; + QAction *_action_view_show_cursors; + + QMenu *_menu_help; + QAction *_action_about; + + QWidget *_central_widget; + QVBoxLayout *_vertical_layout; + + toolbars::SamplingBar *_sampling_bar; + toolbars::TrigBar *_trig_bar; + toolbars::FileBar *_file_bar; + toolbars::LogoBar *_logo_bar; //help button, on top right + toolbars::TitleBar *_title_bar; + + + QDockWidget *_protocol_dock; + dock::ProtocolDock *_protocol_widget; + QDockWidget *_trigger_dock; + QDockWidget *_dso_trigger_dock; + dock::TriggerDock *_trigger_widget; + dock::DsoTriggerDock *_dso_trigger_widget; + QDockWidget *_measure_dock; + dock::MeasureDock *_measure_widget; + QDockWidget *_search_dock; + dock::SearchDock *_search_widget; + + QTranslator _qtTrans; + QTranslator _myTrans; + EventObject _event; + SigSession *_session; + DeviceAgent *_device_agent; + bool _is_auto_switch_device; + high_resolution_clock::time_point _last_key_press_time; + bool _is_save_confirm_msg; + QString _pattern_mode; + QWidget *_frame; + DsTimer _delay_prop_msg_timer; + QString _strMsg; + QString _lst_title_string; + QString _title_ext_string; + + int _key_value; + bool _key_vaild; +}; + +} // namespace pv + +#endif // DSVIEW_PV_MAINWINDOW_H diff --git a/DSView/pv/toolbars/titlebar.cpp b/DSView/pv/toolbars/titlebar.cpp index 8e9a80ec..9478c053 100644 --- a/DSView/pv/toolbars/titlebar.cpp +++ b/DSView/pv/toolbars/titlebar.cpp @@ -1,341 +1,330 @@ -/* - * This file is part of the DSView project. - * DSView is based on PulseView. - * - * Copyright (C) 2016 DreamSourceLab - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "titlebar.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -#ifdef _WIN32 -#include -#endif - -#include "../config/appconfig.h" -#include "../appcontrol.h" -#include "../dsvdef.h" -#include "../ui/fn.h" - -namespace pv { -namespace toolbars { - -TitleBar::TitleBar(bool top, QWidget *parent, ITitleParent *titleParent, bool hasClose) : - QWidget(parent) -{ - _minimizeButton = NULL; - _maximizeButton = NULL; - _closeButton = NULL; - _moving = false; - _is_draging = false; - _parent = parent; - _isTop = top; - _hasClose = hasClose; - _title = NULL; - _is_native = false; - _titleParent = titleParent; - _is_done_moved = false; - - assert(parent); - - setObjectName("TitleBar"); - setContentsMargins(0,0,0,0); - setFixedHeight(32); - - QHBoxLayout *lay1 = new QHBoxLayout(this); - - _title = new QLabel(this); - lay1->addWidget(_title); - - if (_isTop) { - _minimizeButton = new XToolButton(this); - _minimizeButton->setObjectName("MinimizeButton"); - _maximizeButton = new XToolButton(this); - _maximizeButton->setObjectName("MaximizeButton"); - - lay1->addWidget(_minimizeButton); - lay1->addWidget(_maximizeButton); - - connect(this, SIGNAL(normalShow()), parent, SLOT(showNormal())); - connect(this, SIGNAL( maximizedShow()), parent, SLOT(showMaximized())); - connect(_minimizeButton, SIGNAL( clicked()), parent, SLOT(showMinimized())); - connect(_maximizeButton, SIGNAL( clicked()), this, SLOT(showMaxRestore())); - } - - if (_isTop || _hasClose) { - _closeButton= new XToolButton(this); - _closeButton->setObjectName("CloseButton"); - lay1->addWidget(_closeButton); - connect(_closeButton, SIGNAL( clicked()), parent, SLOT(close())); - } - - lay1->insertStretch(0, 500); - lay1->insertStretch(2, 500); - lay1->setContentsMargins(0,0,0,0); - lay1->setSpacing(0); - - setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); - - update_font(); -} - -TitleBar::~TitleBar(){ - DESTROY_QT_OBJECT(_minimizeButton); - DESTROY_QT_OBJECT(_maximizeButton); - DESTROY_QT_OBJECT(_closeButton); -} - -void TitleBar::changeEvent(QEvent *event) -{ - if (event->type() == QEvent::StyleChange) - reStyle(); - QWidget::changeEvent(event); -} - -void TitleBar::reStyle() -{ - QString iconPath = GetIconPath(); - - if (_isTop) { - _minimizeButton->setIcon(QIcon(iconPath+"/minimize.svg")); - if (ParentIsMaxsized()) - _maximizeButton->setIcon(QIcon(iconPath+"/restore.svg")); - else - _maximizeButton->setIcon(QIcon(iconPath+"/maximize.svg")); - } - if (_isTop || _hasClose) - _closeButton->setIcon(QIcon(iconPath+"/close.svg")); -} - -bool TitleBar::ParentIsMaxsized() -{ - if (_titleParent != NULL){ - return _titleParent->ParentIsMaxsized(); - } - else{ - return parentWidget()->isMaximized(); - } -} - -void TitleBar::paintEvent(QPaintEvent *event) -{ - //draw logo icon - QStyleOption o; - o.initFrom(this); - QPainter p(this); - style()->drawPrimitive(QStyle::PE_Widget, &o, &p, this); - - p.setRenderHint(QPainter::Antialiasing, true); - - const int xgap = 2; - const int xstart = 10; - p.setPen(QPen(QColor(213, 15, 37, 255), 2, Qt::SolidLine)); - p.drawLine(xstart + xgap*0, height()*0.50, xstart + xgap*0, height()*0.66); - p.drawLine(xstart + xgap*18, height()*0.34, xstart + xgap*18, height()*0.50); - - p.setPen(QPen(QColor(238, 178, 17, 255), 2, Qt::SolidLine)); - p.drawLine(xstart + xgap*2, height()*0.50, xstart + xgap*2, height()*0.83); - p.drawLine(xstart + xgap*16, height()*0.17, xstart + xgap*16, height()*0.50); - - p.setPen(QPen(QColor(17, 133, 209, 255), 2, Qt::SolidLine)); - p.drawLine(xstart + xgap*4, height()*0.50, xstart + xgap*4, height()*1.00); - p.drawLine(xstart + xgap*14, height()*0.00, xstart + xgap*14, height()*0.50); - - p.setPen(QPen(QColor(0, 153, 37, 200), 2, Qt::SolidLine)); - p.drawLine(xstart + xgap*6, height()*0.50, xstart + xgap*6, height()*0.83); - p.drawLine(xstart + xgap*12, height()*0.17, xstart + xgap*12, height()*0.50); - - p.setPen(QPen(QColor(109, 50, 156, 255), 2, Qt::SolidLine)); - p.drawLine(xstart + xgap*8, height()*0.50, xstart + xgap*8, height()*0.66); - p.drawLine(xstart + xgap*10, height()*0.34, xstart + xgap*10, height()*0.50); - - QWidget::paintEvent(event); -} - -void TitleBar::setTitle(QString title) -{ - if (!_is_native){ - _title->setText(title); - } - else if (_parent != NULL){ - _parent->setWindowTitle(title); - } -} - -QString TitleBar::title() -{ - if (!_is_native){ - return _title->text(); - } - else if (_parent != NULL){ - return _parent->windowTitle(); - } - return ""; -} - -void TitleBar::showMaxRestore() -{ - QString iconPath = GetIconPath(); - if (ParentIsMaxsized()) { - _maximizeButton->setIcon(QIcon(iconPath+"/maximize.svg")); - normalShow(); - } else { - _maximizeButton->setIcon(QIcon(iconPath+"/restore.svg")); - maximizedShow(); - } -} - -void TitleBar::setRestoreButton(bool max) -{ - QString iconPath = GetIconPath(); - if (!max) { - _maximizeButton->setIcon(QIcon(iconPath+"/maximize.svg")); - } else { - _maximizeButton->setIcon(QIcon(iconPath+"/restore.svg")); - } -} - -void TitleBar::mousePressEvent(QMouseEvent* event) -{ - bool ableMove = !ParentIsMaxsized(); - - if(event->button() == Qt::LeftButton && ableMove) - { - int x = event->pos().x(); - int y = event->pos().y(); - - bool bTopWidow = AppControl::Instance()->GetTopWindow() == _parent; - bool bClick = (x >= 6 && y >= 5 && x <= width() - 6); //top window need resize hit check - - if (!bTopWidow || bClick ){ - _is_draging = true; - -#ifdef _WIN32 - POINT p; - GetCursorPos(&p); - _clickPos.setX(p.x); - _clickPos.setY(p.y); -#else - _clickPos = event->globalPos(); -#endif - if (_titleParent != NULL){ - _oldPos = _titleParent->GetParentPos(); - } - else{ - _oldPos = _parent->pos(); - } - - _is_done_moved = false; - - event->accept(); - return; - } - } - QWidget::mousePressEvent(event); -} - -void TitleBar::mouseMoveEvent(QMouseEvent *event) -{ - if(_is_draging){ - - int datX = 0; - int datY = 0; - -#ifdef _WIN32 - POINT p; - GetCursorPos(&p); - int k = window()->devicePixelRatio(); - datX = (p.x - _clickPos.x()) / k; - datY = (p.y - _clickPos.y()) / k; - -#else - datX = (event->globalPos().x() - _clickPos.x()); - datY = (event->globalPos().y() - _clickPos.y()); -#endif - - int x = _oldPos.x() + datX; - int y = _oldPos.y() + datY; - - if (!_moving){ - if (ABS_VAL(datX) >= 2 || ABS_VAL(datY) >= 2){ - _moving = true; - } - else{ - return; - } - } - - if (_titleParent != NULL){ - - if (!_is_done_moved){ - _is_done_moved = true; - _titleParent->MoveBegin(); - } - - _titleParent->MoveWindow(x, y); - } - else{ - _parent->move(x, y); - } - - event->accept(); - return; - } - QWidget::mouseMoveEvent(event); -} - -void TitleBar::mouseReleaseEvent(QMouseEvent* event) -{ - if (_moving && _titleParent != NULL){ - _titleParent->MoveEnd(); - } - _moving = false; - _is_draging = false; - QWidget::mouseReleaseEvent(event); -} - -void TitleBar::mouseDoubleClickEvent(QMouseEvent *event) -{ - QWidget::mouseDoubleClickEvent(event); - - if (_isTop){ - - QTimer::singleShot(200, this, [this](){ - showMaxRestore(); - }); - } -} - -void TitleBar::update_font() -{ - QFont font = this->font(); - font.setPointSizeF(AppConfig::Instance().appOptions.fontSize+1); - _title->setFont(font); -} - -} // namespace toolbars -} // namespace pv +/* + * This file is part of the DSView project. + * DSView is based on PulseView. + * + * Copyright (C) 2016 DreamSourceLab + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "titlebar.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../config/appconfig.h" +#include "../appcontrol.h" +#include "../dsvdef.h" +#include "../ui/fn.h" + +namespace pv { +namespace toolbars { + +namespace{ + static bool _is_able_drag = true; +} + +TitleBar::TitleBar(bool top, QWidget *parent, ITitleParent *titleParent, bool hasClose) : + QWidget(parent) +{ + _minimizeButton = NULL; + _maximizeButton = NULL; + _closeButton = NULL; + _moving = false; + _is_draging = false; + _parent = parent; + _isTop = top; + _hasClose = hasClose; + _title = NULL; + _is_native = false; + _titleParent = titleParent; + _is_done_moved = false; + + assert(parent); + + setObjectName("TitleBar"); + setContentsMargins(0,0,0,0); + setFixedHeight(32); + + QHBoxLayout *lay1 = new QHBoxLayout(this); + + _title = new QLabel(this); + lay1->addWidget(_title); + + if (_isTop) { + _minimizeButton = new XToolButton(this); + _minimizeButton->setObjectName("MinimizeButton"); + _maximizeButton = new XToolButton(this); + _maximizeButton->setObjectName("MaximizeButton"); + + lay1->addWidget(_minimizeButton); + lay1->addWidget(_maximizeButton); + + connect(this, SIGNAL(normalShow()), parent, SLOT(showNormal())); + connect(this, SIGNAL( maximizedShow()), parent, SLOT(showMaximized())); + connect(_minimizeButton, SIGNAL( clicked()), parent, SLOT(showMinimized())); + connect(_maximizeButton, SIGNAL( clicked()), this, SLOT(showMaxRestore())); + } + + if (_isTop || _hasClose) { + _closeButton= new XToolButton(this); + _closeButton->setObjectName("CloseButton"); + lay1->addWidget(_closeButton); + connect(_closeButton, SIGNAL( clicked()), parent, SLOT(close())); + } + + lay1->insertStretch(0, 500); + lay1->insertStretch(2, 500); + lay1->setContentsMargins(0,0,0,0); + lay1->setSpacing(0); + + setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); + + update_font(); +} + +TitleBar::~TitleBar(){ + DESTROY_QT_OBJECT(_minimizeButton); + DESTROY_QT_OBJECT(_maximizeButton); + DESTROY_QT_OBJECT(_closeButton); +} + +void TitleBar::changeEvent(QEvent *event) +{ + if (event->type() == QEvent::StyleChange) + reStyle(); + QWidget::changeEvent(event); +} + +void TitleBar::reStyle() +{ + QString iconPath = GetIconPath(); + + if (_isTop) { + _minimizeButton->setIcon(QIcon(iconPath+"/minimize.svg")); + if (ParentIsMaxsized()) + _maximizeButton->setIcon(QIcon(iconPath+"/restore.svg")); + else + _maximizeButton->setIcon(QIcon(iconPath+"/maximize.svg")); + } + if (_isTop || _hasClose) + _closeButton->setIcon(QIcon(iconPath+"/close.svg")); +} + +bool TitleBar::ParentIsMaxsized() +{ + if (_titleParent != NULL){ + return _titleParent->ParentIsMaxsized(); + } + else{ + return parentWidget()->isMaximized(); + } +} + +void TitleBar::paintEvent(QPaintEvent *event) +{ + //draw logo icon + QStyleOption o; + o.initFrom(this); + QPainter p(this); + style()->drawPrimitive(QStyle::PE_Widget, &o, &p, this); + + p.setRenderHint(QPainter::Antialiasing, true); + + const int xgap = 2; + const int xstart = 10; + p.setPen(QPen(QColor(213, 15, 37, 255), 2, Qt::SolidLine)); + p.drawLine(xstart + xgap*0, height()*0.50, xstart + xgap*0, height()*0.66); + p.drawLine(xstart + xgap*18, height()*0.34, xstart + xgap*18, height()*0.50); + + p.setPen(QPen(QColor(238, 178, 17, 255), 2, Qt::SolidLine)); + p.drawLine(xstart + xgap*2, height()*0.50, xstart + xgap*2, height()*0.83); + p.drawLine(xstart + xgap*16, height()*0.17, xstart + xgap*16, height()*0.50); + + p.setPen(QPen(QColor(17, 133, 209, 255), 2, Qt::SolidLine)); + p.drawLine(xstart + xgap*4, height()*0.50, xstart + xgap*4, height()*1.00); + p.drawLine(xstart + xgap*14, height()*0.00, xstart + xgap*14, height()*0.50); + + p.setPen(QPen(QColor(0, 153, 37, 200), 2, Qt::SolidLine)); + p.drawLine(xstart + xgap*6, height()*0.50, xstart + xgap*6, height()*0.83); + p.drawLine(xstart + xgap*12, height()*0.17, xstart + xgap*12, height()*0.50); + + p.setPen(QPen(QColor(109, 50, 156, 255), 2, Qt::SolidLine)); + p.drawLine(xstart + xgap*8, height()*0.50, xstart + xgap*8, height()*0.66); + p.drawLine(xstart + xgap*10, height()*0.34, xstart + xgap*10, height()*0.50); + + QWidget::paintEvent(event); +} + +void TitleBar::setTitle(QString title) +{ + if (!_is_native){ + _title->setText(title); + } + else if (_parent != NULL){ + _parent->setWindowTitle(title); + } +} + +QString TitleBar::title() +{ + if (!_is_native){ + return _title->text(); + } + else if (_parent != NULL){ + return _parent->windowTitle(); + } + return ""; +} + +void TitleBar::showMaxRestore() +{ + QString iconPath = GetIconPath(); + if (ParentIsMaxsized()) { + _maximizeButton->setIcon(QIcon(iconPath+"/maximize.svg")); + normalShow(); + } else { + _maximizeButton->setIcon(QIcon(iconPath+"/restore.svg")); + maximizedShow(); + } +} + +void TitleBar::setRestoreButton(bool max) +{ + QString iconPath = GetIconPath(); + if (!max) { + _maximizeButton->setIcon(QIcon(iconPath+"/maximize.svg")); + } else { + _maximizeButton->setIcon(QIcon(iconPath+"/restore.svg")); + } +} + +void TitleBar::mousePressEvent(QMouseEvent* event) +{ + bool ableMove = !ParentIsMaxsized(); + + if(event->button() == Qt::LeftButton && ableMove && _is_able_drag) + { + int x = event->pos().x(); + int y = event->pos().y(); + + bool bTopWidow = AppControl::Instance()->GetTopWindow() == _parent; + bool bClick = (x >= 6 && y >= 5 && x <= width() - 6); //top window need resize hit check + + if (!bTopWidow || bClick ){ + _is_draging = true; + + _clickPos = event->globalPos(); + + if (_titleParent != NULL){ + _oldPos = _titleParent->GetParentPos(); + } + else{ + _oldPos = _parent->pos(); + } + + _is_done_moved = false; + + event->accept(); + return; + } + } + QWidget::mousePressEvent(event); +} + +void TitleBar::mouseMoveEvent(QMouseEvent *event) +{ + if(_is_draging){ + + int datX = 0; + int datY = 0; + + datX = (event->globalPos().x() - _clickPos.x()); + datY = (event->globalPos().y() - _clickPos.y()); + + int x = _oldPos.x() + datX; + int y = _oldPos.y() + datY; + + if (!_moving){ + if (ABS_VAL(datX) >= 2 || ABS_VAL(datY) >= 2){ + _moving = true; + } + else{ + return; + } + } + + if (_titleParent != NULL){ + + if (!_is_done_moved){ + _is_done_moved = true; + _titleParent->MoveBegin(); + } + + _titleParent->MoveWindow(x, y); + } + else{ + _parent->move(x, y); + } + + event->accept(); + return; + } + QWidget::mouseMoveEvent(event); +} + +void TitleBar::mouseReleaseEvent(QMouseEvent* event) +{ + if (_moving && _titleParent != NULL){ + _titleParent->MoveEnd(); + } + _moving = false; + _is_draging = false; + QWidget::mouseReleaseEvent(event); +} + +void TitleBar::mouseDoubleClickEvent(QMouseEvent *event) +{ + QWidget::mouseDoubleClickEvent(event); + + if (_isTop){ + + QTimer::singleShot(200, this, [this](){ + showMaxRestore(); + }); + } +} + +void TitleBar::update_font() +{ + QFont font = this->font(); + font.setPointSizeF(AppConfig::Instance().appOptions.fontSize+1); + _title->setFont(font); +} + +void TitleBar::EnableAbleDrag(bool bEnabled) +{ + _is_able_drag = bEnabled; +} + +} // namespace toolbars +} // namespace pv diff --git a/DSView/pv/toolbars/titlebar.h b/DSView/pv/toolbars/titlebar.h index fac30af4..b3f61b04 100644 --- a/DSView/pv/toolbars/titlebar.h +++ b/DSView/pv/toolbars/titlebar.h @@ -1,108 +1,110 @@ -/* - * This file is part of the DSView project. - * DSView is based on PulseView. - * - * Copyright (C) 2016 DreamSourceLab - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef DSVIEW_PV_TOOLBARS_TITLEBAR_H -#define DSVIEW_PV_TOOLBARS_TITLEBAR_H - -#include -#include "../interface/icallbacks.h" -#include "../ui/xtoolbutton.h" - - -class QHBoxLayout; -class QLabel; - -namespace pv { - -class ITitleParent -{ -public: - virtual void MoveWindow(int x, int y)=0; - virtual QPoint GetParentPos()=0; - virtual bool ParentIsMaxsized()=0; - virtual void MoveBegin()=0; - virtual void MoveEnd()=0; -}; - -namespace toolbars { - -class TitleBar : public QWidget, public IFontForm -{ - Q_OBJECT - -public: - TitleBar(bool top, QWidget *parent, ITitleParent *titleParent, bool hasClose); - ~TitleBar(); - - void setTitle(QString title); - QString title(); - - //IFontForm - void update_font() override; - - inline void set_native(){ - _is_native = true; - } - -private: - void changeEvent(QEvent *event); - void reStyle(); - - bool ParentIsMaxsized(); - -signals: - void normalShow(); - void maximizedShow(); - -public slots: - void showMaxRestore(); - void setRestoreButton(bool max); - inline bool IsMoving(){return _moving;} - -protected: - void paintEvent(QPaintEvent *event); - void mousePressEvent(QMouseEvent *event); - void mouseMoveEvent(QMouseEvent *event); - void mouseReleaseEvent(QMouseEvent *event); - void mouseDoubleClickEvent(QMouseEvent *event); - - - XToolButton *_minimizeButton; - XToolButton *_maximizeButton; - XToolButton *_closeButton; - QLabel *_title; - - bool _moving; - bool _is_draging; - bool _isTop; - bool _hasClose; - QPoint _clickPos; - QPoint _oldPos; - QWidget *_parent; - bool _is_native; - ITitleParent *_titleParent; - bool _is_done_moved; -}; - -} // namespace toolbars -} // namespace pv - -#endif // DSVIEW_PV_TOOLBARS_TITLEBAR_H +/* + * This file is part of the DSView project. + * DSView is based on PulseView. + * + * Copyright (C) 2016 DreamSourceLab + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef DSVIEW_PV_TOOLBARS_TITLEBAR_H +#define DSVIEW_PV_TOOLBARS_TITLEBAR_H + +#include +#include "../interface/icallbacks.h" +#include "../ui/xtoolbutton.h" + + +class QHBoxLayout; +class QLabel; + +namespace pv { + +class ITitleParent +{ +public: + virtual void MoveWindow(int x, int y)=0; + virtual QPoint GetParentPos()=0; + virtual bool ParentIsMaxsized()=0; + virtual void MoveBegin()=0; + virtual void MoveEnd()=0; +}; + +namespace toolbars { + +class TitleBar : public QWidget, public IFontForm +{ + Q_OBJECT + +public: + TitleBar(bool top, QWidget *parent, ITitleParent *titleParent, bool hasClose); + ~TitleBar(); + + void setTitle(QString title); + QString title(); + + //IFontForm + void update_font() override; + + inline void set_native(){ + _is_native = true; + } + + void EnableAbleDrag(bool bEnabled); + +private: + void changeEvent(QEvent *event); + void reStyle(); + + bool ParentIsMaxsized(); + +signals: + void normalShow(); + void maximizedShow(); + +public slots: + void showMaxRestore(); + void setRestoreButton(bool max); + inline bool IsMoving(){return _moving;} + +protected: + void paintEvent(QPaintEvent *event); + void mousePressEvent(QMouseEvent *event); + void mouseMoveEvent(QMouseEvent *event); + void mouseReleaseEvent(QMouseEvent *event); + void mouseDoubleClickEvent(QMouseEvent *event); + + + XToolButton *_minimizeButton; + XToolButton *_maximizeButton; + XToolButton *_closeButton; + QLabel *_title; + + bool _moving; + bool _is_draging; + bool _isTop; + bool _hasClose; + QPoint _clickPos; + QPoint _oldPos; + QWidget *_parent; + bool _is_native; + ITitleParent *_titleParent; + bool _is_done_moved; +}; + +} // namespace toolbars +} // namespace pv + +#endif // DSVIEW_PV_TOOLBARS_TITLEBAR_H diff --git a/DSView/pv/ui/popupdlglist.cpp b/DSView/pv/ui/popupdlglist.cpp index 5779b6fd..0ae612a3 100644 --- a/DSView/pv/ui/popupdlglist.cpp +++ b/DSView/pv/ui/popupdlglist.cpp @@ -1,70 +1,81 @@ -/* - * This file is part of the DSView project. - * DSView is based on PulseView. - * - * Copyright (C) 2024 DreamSourceLab - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "popupdlglist.h" -#include - -namespace{ - std::vector g_popup_dlg_list; - int g_screen_count = 1; -} - -void PopupDlgList::AddDlgTolist(QWidget *w) -{ - if (w != nullptr){ - g_popup_dlg_list.push_back(w); - } - g_screen_count = QGuiApplication::screens().size(); -} - -void PopupDlgList::RemoveDlgFromList(QWidget *w) -{ - if (w != nullptr){ - for (auto it = g_popup_dlg_list.begin(); it != g_popup_dlg_list.end(); ++it) - { - if ((*it) == w){ - g_popup_dlg_list.erase(it); - break; - } - } - } -} - -void PopupDlgList::TryCloseAllByScreenChanged() -{ - int screen_count = QGuiApplication::screens().size(); - - if (screen_count != g_screen_count) - { - int num = g_popup_dlg_list.size(); - - for (int i=0; iisVisible()){ - (*it)->close(); //Close the dialog. - g_popup_dlg_list.erase(it); - --num; - --i; - } - } - } -} \ No newline at end of file +/* + * This file is part of the DSView project. + * DSView is based on PulseView. + * + * Copyright (C) 2024 DreamSourceLab + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "popupdlglist.h" +#include +#include +#include +#include + +#include "../log.h" + +namespace{ + std::vector g_popup_dlg_list; + QScreen *currentScreen = NULL; +} + +void PopupDlgList::AddDlgTolist(QWidget *w) +{ + if (w != nullptr){ + PopuDlgItem item; + item.screen = currentScreen; + item.widget = w; + g_popup_dlg_list.push_back(item); + } +} + +void PopupDlgList::RemoveDlgFromList(QWidget *w) +{ + if (w != nullptr){ + for (auto it = g_popup_dlg_list.begin(); it != g_popup_dlg_list.end(); ++it) + { + if ((*it).widget == w){ + g_popup_dlg_list.erase(it); + break; + } + } + } +} + +void PopupDlgList::TryCloseAllByScreenChanged(QScreen *windowScreen) +{ + int num = g_popup_dlg_list.size(); + + for (int i=0; iisVisible()){ + if ((*it).screen != windowScreen){ + w->close(); //Close the dialog. + g_popup_dlg_list.erase(it); + --num; + --i; + } + } + } +} + +void PopupDlgList::SetCurrentScreen(QScreen *screen) +{ + currentScreen = screen; +} diff --git a/DSView/pv/ui/popupdlglist.h b/DSView/pv/ui/popupdlglist.h index 33cf390e..a8ffd2c7 100644 --- a/DSView/pv/ui/popupdlglist.h +++ b/DSView/pv/ui/popupdlglist.h @@ -1,36 +1,45 @@ -/* - * This file is part of the DSView project. - * DSView is based on PulseView. - * - * Copyright (C) 2024 DreamSourceLab - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef POPUP_DLG_LIST_H -#define POPUP_DLG_LIST_H - -#include -#include - -class PopupDlgList -{ -public: - static void AddDlgTolist(QWidget *w); - static void RemoveDlgFromList(QWidget *w); - static void TryCloseAllByScreenChanged(); -}; - +/* + * This file is part of the DSView project. + * DSView is based on PulseView. + * + * Copyright (C) 2024 DreamSourceLab + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef POPUP_DLG_LIST_H +#define POPUP_DLG_LIST_H + +#include +#include + +class QScreen; + +struct PopuDlgItem +{ + QScreen *screen; + QWidget *widget; +}; + +class PopupDlgList +{ +public: + static void AddDlgTolist(QWidget *w); + static void RemoveDlgFromList(QWidget *w); + static void TryCloseAllByScreenChanged(QScreen *windowScreen); + static void SetCurrentScreen(QScreen *screen); +}; + #endif \ No newline at end of file diff --git a/DSView/pv/winnativewidget.cpp b/DSView/pv/winnativewidget.cpp index 099d9154..51890741 100644 --- a/DSView/pv/winnativewidget.cpp +++ b/DSView/pv/winnativewidget.cpp @@ -21,7 +21,7 @@ */ -#include "WinNativeWidget.h" +#include "winnativewidget.h" #include #include #include @@ -34,9 +34,11 @@ #include #include #include +#include #include "log.h" #include "../config.h" +#include "winshadow.h" #define FIXED_WIDTH(widget) (widget->minimumWidth() >= widget->maximumWidth()) #define FIXED_HEIGHT(widget) (widget->minimumHeight() >= widget->maximumHeight()) @@ -45,19 +47,24 @@ namespace pv { //-----------------------------WinNativeWidget -WinNativeWidget::WinNativeWidget(const int x, const int y, const int width, const int height) +WinNativeWidget::WinNativeWidget(const int x, const int y, const int width, + const int height, bool isDark) { _childWindow = nullptr; childWidget = nullptr; _hWnd = NULL; _event_callback = NULL; - _is_moving = false; - _shadow = NULL; - _cur_screen = NULL; + + _titleBarWidget = NULL; + _is_native_border = IsWin11OrGreater(); + _hCurrentMonitor = NULL; + _shadow = NULL; + _border_color = QColor(0x80,0x80,0x80); - HBRUSH windowBackground = CreateSolidBrush(RGB(0, 0, 0)); HINSTANCE hInstance = GetModuleHandle(nullptr); - WNDCLASSEX wcx = { 0 }; + WNDCLASSEX wcx; + + memset(&wcx, 0, sizeof(WNDCLASSEXW)); wcx.cbSize = sizeof(WNDCLASSEX); wcx.style = CS_HREDRAW | CS_VREDRAW; @@ -66,10 +73,15 @@ WinNativeWidget::WinNativeWidget(const int x, const int y, const int width, cons wcx.cbClsExtra = 0; wcx.cbWndExtra = 0; wcx.lpszClassName = L"DSViewWindowClass"; - wcx.hbrBackground = windowBackground; wcx.hCursor = LoadCursor(hInstance, IDC_ARROW); - + if (isDark){ + wcx.hbrBackground = CreateSolidBrush(RGB(38, 38, 38)); + } + else{ + wcx.hbrBackground = CreateSolidBrush(RGB(248, 248, 248)); + } + RegisterClassEx(&wcx); if (FAILED(RegisterClassEx(&wcx))) { @@ -78,7 +90,7 @@ WinNativeWidget::WinNativeWidget(const int x, const int y, const int width, cons } _hWnd = CreateWindow(L"DSViewWindowClass", L"DSView", - // WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_THICKFRAME | WS_CLIPCHILDREN, + //WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_THICKFRAME | WS_CLIPCHILDREN, WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, x, y, width, height, NULL, NULL, hInstance, NULL); @@ -88,19 +100,20 @@ WinNativeWidget::WinNativeWidget(const int x, const int y, const int width, cons dsv_info("ERROR: can't create naitive window"); assert(false); } - + + SetWindowLongW(_hWnd, GWL_STYLE, GetWindowLongW(_hWnd, GWL_STYLE) & ~WS_CAPTION); SetWindowLongPtr(_hWnd, GWLP_USERDATA, reinterpret_cast(this)); - SetWindowPos(_hWnd, NULL, x, y, 0, 0, SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE); + SetWindowPos(_hWnd, NULL, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE); + + if (!_is_native_border){ + _shadow = new WinShadow(_hWnd, NULL); + _shadow->createWinId(); + } } WinNativeWidget::~WinNativeWidget() { if (_hWnd){ - if (_shadow){ - _shadow->hide(); - delete _shadow; - _shadow = NULL; - } Show(false); DestroyWindow(_hWnd); } @@ -113,38 +126,34 @@ void WinNativeWidget::SetChildWidget(QWidget *w) if (w != NULL){ _childWindow = (HWND)w->winId(); - _shadow = new WinShadow(_hWnd, w); - _shadow->createWinId(); - } + } + else if (_shadow != NULL){ + _shadow->hideShadow(); + _shadow->close(); //Set null, the applictoin will exit. + } +} + +void WinNativeWidget::ReShowWindow() +{ + if (IsMaxsized()){ + ShowMax(); + } + else{ + ShowNormal(); + } + Show(true); } LRESULT CALLBACK WinNativeWidget::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { WinNativeWidget *self = reinterpret_cast(GetWindowLongPtr(hWnd, GWLP_USERDATA)); - if (self == NULL) - { + if (self == NULL){ return DefWindowProc(hWnd, message, wParam, lParam); } switch (message) { - case WM_ACTIVATE: - { - switch (wParam) - { - case WA_ACTIVE: - case WA_CLICKACTIVE: - { - self->BeginShowShadow(); - break; - } - case WA_INACTIVE: - { - break; - } - } - } case WM_SYSCOMMAND: { if (wParam == SC_KEYMENU) @@ -153,101 +162,223 @@ LRESULT CALLBACK WinNativeWidget::WndProc(HWND hWnd, UINT message, WPARAM wParam GetWindowRect(hWnd, &winrect); TrackPopupMenu(GetSystemMenu(hWnd, false), TPM_TOPALIGN | TPM_LEFTALIGN, winrect.left + 5, winrect.top + 5, 0, hWnd, NULL); } - else - { - return DefWindowProc(hWnd, message, wParam, lParam); - } break;; - } + } case WM_NCCALCSIZE: { - return 0; - } + if (!wParam || self->IsMaxsized()){ + return 0; + } + if (!self->_is_native_border){ + return 0; + } + + int k = self->GetDevicePixelRatio(); + NCCALCSIZE_PARAMS* params = reinterpret_cast(lParam); + RECT* rect = ¶ms->rgrc[0]; + + int borderSize = 1 * k; + rect->left += borderSize; + rect->top += 1; + rect->right -= borderSize; + rect->bottom -= borderSize; + + return WVR_VALIDRECTS; + } + case WM_NCACTIVATE: + { + // Is activing. + if (wParam){ + return 0; + } + + HWND hForegWnd = GetForegroundWindow(); + HWND hActiveWnd = GetActiveWindow(); + + // Is not the foreground window. + if (hForegWnd != hActiveWnd){ + return 0; + } + + //Is the foreground window, but is not actived, maybe opening a child dialog. + SetWindowRedraw(hWnd, FALSE); + LRESULT result = DefWindowProc(hWnd, message, wParam, lParam); + SetWindowRedraw(hWnd, TRUE); + return result; + } case WM_CLOSE: { - if (self->childWidget != NULL) - { + if (self->childWidget != NULL) { self->childWidget->close(); return 0; } break; } - case WM_DESTROY: + case WM_MOVE: { - // PostQuitMessage(0); + if (IsIconic(hWnd) == FALSE) { + self->_hCurrentMonitor = MonitorFromWindow(hWnd, MONITOR_DEFAULTTONEAREST); + self->ResizeChild(); + } + break; + } + case WM_DPICHANGED: + case WM_DISPLAYCHANGE: + { + if (self->_event_callback != NULL){ + self->_event_callback->OnParentNativeEvent(PARENT_EVENT_DISPLAY_CHANGED); + } + else{ + self->UpdateChildDpi(); + self->ResizeChild(); + } break; } case WM_SIZE: - { - if (self->_childWindow != NULL){ - self->ResizeChild(); - - if (self->_shadow){ - if (self->IsNormalsized()){ - self->_shadow->tryToShow(); - } - else{ - self->_shadow->hide(); - } - } - - self->MoveShadow(); + { + if (wParam != SIZE_MINIMIZED && self->_childWindow != NULL){ + self->ResizeChild(); } - - break; - } - case WM_GETMINMAXINFO: - { - if (self->childWidget) - { - auto gw = self->childWidget; - int k = gw->windowHandle()->devicePixelRatio(); - MINMAXINFO *mmi = reinterpret_cast(lParam); - - int border_width = 0; - QSize minimum = gw->minimumSize(); - QSize sizeHint = gw->minimumSizeHint(); - - mmi->ptMinTrackSize.x = qFloor(qMax(minimum.width(), sizeHint.width()) * - k) + border_width * 2; - mmi->ptMinTrackSize.y = qFloor(qMax(minimum.height(), sizeHint.height()) * - k) + border_width; - - QSize maximum = gw->maximumSize(); - - mmi->ptMaxTrackSize.x = qFloor(maximum.width() * k) + border_width * 2; - mmi->ptMaxTrackSize.y = qFloor(maximum.height() * k) + border_width; - } - break; - } - case WM_DISPLAYCHANGE: - { - dsv_info("Display changed."); - - if (self->_event_callback != NULL){ - self->_event_callback->OnParentNativeEvent(PARENT_EVENT_DISPLAY_CHANGED); - } - break; } case WM_WINDOWPOSCHANGING: { + static int lst_state = -1; int st = 3; if (self->IsMaxsized()) st = 1; else if (self->IsNormalsized()) st = 2; - - if (self->childWidget != NULL && self->_shadow){ + + if (self->childWidget != NULL && self->_shadow && lst_state != st){ if (st == 2){ - if (self->childWidget->isVisible() && !self->_is_moving){ + if (self->childWidget->isVisible()){ self->_shadow->showLater(); + self->showBorder(); } } else { - self->_shadow->hide(); + self->_shadow->hide(); + self->hideBorder(); + } + + lst_state = st; + } + break; + } + case WM_GETMINMAXINFO: + { + if (self->childWidget && self->_hCurrentMonitor) + { + int maxWidth = 0; + int maxHeight = 0; + bool bError = false; + + if (!self->getMonitorWorkArea(self->_hCurrentMonitor, &maxWidth, &maxHeight)) + { + HMONITOR hCurrentMonitor = MonitorFromWindow(self->_hWnd, MONITOR_DEFAULTTONEAREST); + + if (!self->getMonitorWorkArea(hCurrentMonitor, &maxWidth, &maxHeight)){ + dsv_info("ERROR: failed to get work area from window handle."); + bError = true; + } + } + + if (!bError) + { + auto gw = self->childWidget; + int k = self->GetDevicePixelRatio(); + QSize minimum = gw->minimumSize(); + QSize sizeHint = gw->minimumSizeHint(); + + MINMAXINFO *mmi = reinterpret_cast(lParam); + mmi->ptMinTrackSize.x = qFloor(qMax(minimum.width(), sizeHint.width()) * k); + mmi->ptMinTrackSize.y = qFloor(qMax(minimum.height(), sizeHint.height()) * k); + mmi->ptMaxTrackSize.x = maxWidth; + mmi->ptMaxTrackSize.y = maxHeight; + } + } + break; + } + case WM_NCHITTEST: + { + auto childWidget = self->childWidget; + if (childWidget == NULL) + break; + + + int k = self->GetDevicePixelRatio(); + const LONG borderWidth = 8 * k; + RECT winrect; + GetWindowRect(hWnd, &winrect); + long x = GET_X_LPARAM(lParam); + long y = GET_Y_LPARAM(lParam); + + // Check if the size can to resize. + if (!self->IsMaxsized()) + { + //bottom left corner + if (x >= winrect.left && x < winrect.left + borderWidth && + y < winrect.bottom && y >= winrect.bottom - borderWidth) + { + return HTBOTTOMLEFT; + } + //bottom right corner + if (x < winrect.right && x >= winrect.right - borderWidth && + y < winrect.bottom && y >= winrect.bottom - borderWidth) + { + return HTBOTTOMRIGHT; + } + //top left corner + if (x >= winrect.left && x < winrect.left + borderWidth && + y >= winrect.top && y < winrect.top + borderWidth) + { + return HTTOPLEFT; + } + //top right corner + if (x < winrect.right && x >= winrect.right - borderWidth && + y >= winrect.top && y < winrect.top + borderWidth) + { + return HTTOPRIGHT; + } + //left border + if (x >= winrect.left && x < winrect.left + borderWidth) + { + return HTLEFT; + } + //right border + if (x < winrect.right && x >= winrect.right - borderWidth) + { + return HTRIGHT; + } + //bottom border + if (y < winrect.bottom && y >= winrect.bottom - borderWidth) + { + return HTBOTTOM; + } + //top border + if (y >= winrect.top && y < winrect.top + borderWidth) + { + return HTTOP; + } + } + + // Check unble move. + if (self->_titleBarWidget) + { + QRect titleRect = self->_titleBarWidget->geometry(); + + int titleWidth = titleRect.width() * k - 55 * k; + int titleHeight = titleRect.height() * k; + + if (x > winrect.left + 2 * k && x < winrect.left + titleWidth) + { + if (y > winrect.top + 2 * k && y < winrect.top + titleHeight){ + return HTCAPTION; + } } } + break; } } @@ -255,90 +386,66 @@ LRESULT CALLBACK WinNativeWidget::WndProc(HWND hWnd, UINT message, WPARAM wParam return DefWindowProc(hWnd, message, wParam, lParam); } +bool WinNativeWidget::getMonitorWorkArea(HMONITOR hCurrentMonitor, int *outWidth, int *outHeight) +{ + assert(outWidth); + assert(outHeight); + + MONITORINFO monitorInfo; + memset(&monitorInfo, 0, sizeof(MONITORINFO)); + monitorInfo.cbSize = sizeof(MONITORINFO); + GetMonitorInfo(hCurrentMonitor, &monitorInfo); + + int borderSizeX = GetSystemMetrics(SM_CXSIZEFRAME); + int borderSizeY = GetSystemMetrics(SM_CYSIZEFRAME); + int workAreaWidth = monitorInfo.rcWork.right - monitorInfo.rcWork.left; + int workAreaHeight = monitorInfo.rcWork.bottom - monitorInfo.rcWork.top; + int maxWidth = workAreaWidth + borderSizeX * 2; + int maxHeight = workAreaHeight + borderSizeY * 2; + + if (workAreaWidth > 0){ + *outWidth = maxWidth; + *outHeight = maxHeight; + return true; + } + + return false; +} + void WinNativeWidget::ResizeChild() { if (_childWindow != NULL){ - RECT rc; - GetWindowRect(_hWnd, &rc); - int sp = 0; - int x = sp; - int y = sp; - int w = rc.right - rc.left - sp * 2; - int h = rc.bottom - rc.top - sp * 2; - - if (IsMaxsized()) { - w -= 8; - h -= 8; + int k = GetDevicePixelRatio(); + + if (_shadow != NULL){ + _shadow->setScale(k); + _shadow->moveShadow(); } - - MoveWindow(_childWindow, x, y, w - 1 , h - 1 , 1); - MoveWindow(_childWindow, x, y, w , h , 1); - childWidget->updateGeometry(); - } -} -void WinNativeWidget::ResizeSelf() -{ - if (_hWnd) - { RECT rc; - GetWindowRect(_hWnd, &rc); + GetClientRect(_hWnd, &rc); - int x = rc.left; - int y = rc.top; + int x = 0; + int y = 0; int w = rc.right - rc.left; int h = rc.bottom - rc.top; - - static int times = 0; - times++; - - if (times % 2 == 0){ - w += 2; - h += 2; + + if (IsMaxsized()){ + w -= 4 * k; + h -= 4 * k; } else{ - w -= 2; - h -= 2; + int border = 0 * k; + x += border; + y += border; + w -= border * 2; + h -= border * 2; } - - MoveWindow(_hWnd, x, y, w , h , 1); - } -} -void WinNativeWidget::MoveShadow() -{ - if (!_shadow || !childWidget){ - return; - } - - if (IsNormalsized()) - { - - RECT rc; - GetWindowRect(_hWnd, &rc); - - int bw = SHADOW_BORDER_WIDTH; - - // bw = 20; - - int x = rc.left; - int y = rc.top; - int w = rc.right - rc.left; - int h = rc.bottom - rc.top; - - x -= bw; - y -= bw; - w += bw * 2; - h += bw * 2; - - MoveWindow((HWND)_shadow->winId(), x, y, w , h , 1); - _shadow->setActive(isActiveWindow()); - } - else{ - _shadow->hide(); - _shadow->setActive(false); - _shadow->update(); + MoveWindow(_childWindow, x, y, w + 1 , h + 1 , 1); + MoveWindow(_childWindow, x, y, w , h , 1); + childWidget->updateGeometry(); } } @@ -349,21 +456,16 @@ bool WinNativeWidget::isActiveWindow() } void WinNativeWidget::setGeometry(const int x, const int y, const int width, const int height) -{ - // dsv_info("set parent window, x:%d, y:%d, w:%d, h:%d", x, y, width, height); +{ if (_hWnd != NULL){ MoveWindow(_hWnd, x, y, width, height, 1); - } + } } void WinNativeWidget::Show(bool bShow) { if (_hWnd){ - ShowWindow(_hWnd, bShow ? SW_SHOW : SW_HIDE); - - if (!bShow && _shadow){ - _shadow->hide(); - } + ShowWindow(_hWnd, bShow ? SW_SHOW : SW_HIDE); } } @@ -373,18 +475,7 @@ void WinNativeWidget::Show(bool bShow) GetClientRect(_hWnd, &rc); int w = rc.right; int h = rc.bottom; - MoveWindow(_hWnd, x, y, w, h, 1); - - if (_shadow != NULL){ - auto scr = GetPointScreen(); - - if (_cur_screen && scr && scr != _cur_screen){ - _shadow->windowHandle()->setScreen(scr); - } - _cur_screen = scr; - - MoveShadow(); - } + MoveWindow(_hWnd, x, y, w, h, 1); } void WinNativeWidget::ShowNormal() @@ -413,11 +504,11 @@ void WinNativeWidget::UpdateChildDpi() QScreen *scr = screenFromWindow(_hWnd); if (scr != NULL && childWidget != NULL){ childWidget->windowHandle()->setScreen(scr); - if (_shadow){ + if (_shadow != NULL){ _shadow->windowHandle()->setScreen(scr); } } - else{ + else{ dsv_info("ERROR: failed to update child's screen."); } } @@ -427,7 +518,11 @@ QScreen* WinNativeWidget::screenFromWindow(HWND hwnd) if (hwnd == NULL) return NULL; - HMONITOR monitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST); + HMONITOR monitor = _hCurrentMonitor; + + if (monitor == NULL){ + monitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST); + } MONITORINFO monitor_info; memset(&monitor_info, 0, sizeof(MONITORINFO)); @@ -455,18 +550,6 @@ QScreen* WinNativeWidget::GetPointScreen() return screenFromWindow(_hWnd); } -void WinNativeWidget::OnDisplayChanged() -{ - UpdateChildDpi(); - ResizeChild(); - - RECT rc; - GetWindowRect(_hWnd, &rc); - int w = rc.right - rc.left; - int h = rc.bottom - rc.top; - MoveWindow(_hWnd, rc.left, rc.top, w + 1, h + 1, 1); -} - bool WinNativeWidget::IsMaxsized() { WINDOWPLACEMENT wp; @@ -491,12 +574,101 @@ bool WinNativeWidget::IsNormalsized() return wp.showCmd == SW_SHOWNORMAL; } -void WinNativeWidget::BeginShowShadow() +void WinNativeWidget::SetBorderColor(QColor color) { - if (_shadow){ - _shadow->show(); - _shadow->showLater(); + _border_color = color; + + if (_hWnd) + { + if (_is_native_border) + { + const DWORD DWMWINDOWATTRIBUTE_DWMWA_BORDER_COLOR = 34; + COLORREF COLOR = RGB(color.red(), color.green(), color.blue()); + typedef HRESULT(WINAPI *tDwmSetWindowAttribute)(HWND, DWORD, LPCVOID, DWORD); + tDwmSetWindowAttribute pDwmSetWindowAttribute = + tDwmSetWindowAttribute(QLibrary::resolve("dwmapi", "DwmSetWindowAttribute")); + if (pDwmSetWindowAttribute){ + pDwmSetWindowAttribute(_hWnd, DWMWINDOWATTRIBUTE_DWMWA_BORDER_COLOR, &COLOR, sizeof(COLOR)); + } + } + else if (childWidget != NULL){ + if (IsMaxsized()){ + hideBorder(); + } + else{ + showBorder(); + } + } } } +void WinNativeWidget::showBorder() +{ + if (childWidget != NULL && !_is_native_border){ + childWidget->setObjectName("DSViewFrame"); + QString borderCss = "#DSViewFrame {border-radius:0px; border:1px solid %1;}"; + QString borderStyle = borderCss.arg(_border_color.name()); + childWidget->setStyleSheet(borderStyle); + } +} + +void WinNativeWidget::hideBorder() +{ + if (childWidget != NULL && !_is_native_border){ + childWidget->setObjectName("DSViewFrame"); + QString borderCss = "#DSViewFrame {border-radius:0px; border:0px solid %1;}"; + QString borderStyle = borderCss.arg(_border_color.name()); + childWidget->setStyleSheet(borderStyle); + } +} + +bool WinNativeWidget::isWinXOrGreater(DWORD major_version, DWORD minor_version, DWORD build_number) +{ + bool is_win_x_or_greater = false; + + typedef NTSTATUS(WINAPI *tRtlGetVersion)(LPOSVERSIONINFOEXW); + tRtlGetVersion pRtlGetVersion = tRtlGetVersion(QLibrary::resolve("ntdll", "RtlGetVersion")); + + if (pRtlGetVersion) + { + OSVERSIONINFOEXW os_info; + memset(&os_info, 0, sizeof(OSVERSIONINFOEXW)); + os_info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXW); + NTSTATUS status = pRtlGetVersion(&os_info); + if (status == 0) + { + is_win_x_or_greater = (os_info.dwMajorVersion >= major_version && + os_info.dwMinorVersion >= minor_version && + os_info.dwBuildNumber >= build_number); + } + } + + return is_win_x_or_greater; +} + +bool WinNativeWidget::IsWin11OrGreater() +{ + return isWinXOrGreater(10, 0, 22000); +} + +int WinNativeWidget::GetDevicePixelRatio() +{ + auto scr = GetPointScreen(); + if (scr != NULL){ + return scr->devicePixelRatio(); + } + else if (childWidget != NULL){ + return childWidget->windowHandle()->devicePixelRatio(); + } + return 1; +} + +bool WinNativeWidget::IsVisible() +{ + if (_hWnd){ + return IsWindowVisible(_hWnd); + } + return false; +} + } diff --git a/DSView/pv/winnativewidget.h b/DSView/pv/winnativewidget.h index 692b9c11..f2ac1ea4 100644 --- a/DSView/pv/winnativewidget.h +++ b/DSView/pv/winnativewidget.h @@ -31,22 +31,27 @@ #include #include "interface/icallbacks.h" -#include "winshadow.h" #ifndef WM_DPICHANGED #define WM_DPICHANGED 0x02E0 #endif +#ifndef SM_CXPADDEDBORDER +#define SM_CXPADDEDBORDER 105 +#endif + + namespace pv { - + +class WinShadow; class WinNativeWidget { public: - WinNativeWidget(const int x, const int y, const int width, const int heigh); + WinNativeWidget(const int x, const int y, const int width, const int heigh, bool isDark); ~WinNativeWidget(); - + static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); void SetChildWidget(QWidget *w); @@ -65,46 +70,49 @@ public: void ShowMin(); void UpdateChildDpi(); - void ResizeChild(); - void ResizeSelf(); - - inline void SetMovingFlag(bool bMoving){ - _is_moving = bMoving; - _cur_screen = NULL; - } - + void ResizeChild(); + QScreen* GetPointScreen(); inline void SetNativeEventCallback(IParentNativeEventCallback *callback){ _event_callback = callback; } - - void OnDisplayChanged(); + bool IsMaxsized(); bool IsMinsized(); - bool IsNormalsized(); - - void MoveShadow(); - - inline WinShadow* Shadow(){ - return _shadow; - } - + bool IsNormalsized(); bool isActiveWindow(); - void BeginShowShadow(); + void SetBorderColor(QColor color); + bool IsWin11OrGreater(); + + inline void SetTitleBarWidget(QWidget *w){ + _titleBarWidget = w; + } + + int GetDevicePixelRatio(); + bool IsVisible(); + + void ReShowWindow(); private: QScreen* screenFromWindow(HWND hwnd); - + bool isWinXOrGreater(DWORD major_version, DWORD minor_version, DWORD build_number); + void showBorder(); + void hideBorder(); + bool getMonitorWorkArea(HMONITOR hCurrentMonitor, int *outWidth, int *outHeight); + private: QWidget* childWidget; HWND _childWindow; HWND _hWnd; + QWidget *_titleBarWidget; IParentNativeEventCallback *_event_callback; - bool _is_moving; + + bool _is_native_border; + HMONITOR _hCurrentMonitor; WinShadow *_shadow; - QScreen *_cur_screen; + QColor _border_color; }; } diff --git a/DSView/pv/winshadow.cpp b/DSView/pv/winshadow.cpp index c8487e28..c14e859b 100644 --- a/DSView/pv/winshadow.cpp +++ b/DSView/pv/winshadow.cpp @@ -18,117 +18,51 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ - #include "winshadow.h" -#include "log.h" -#include "config/appconfig.h" -#include "mainframe.h" -#include "mainwindow.h" - +#define COLOR1 QColor(0, 0, 0, 75) +#define COLOR2 QColor(0, 0, 0, 30) +#define COLOR3 QColor(0, 0, 0, 1) + namespace pv { -namespace - { - const QColor dark_border0 = QColor(80, 80, 80, 255); - const QColor dark_border1 = QColor(48, 47, 47, 200); - const QColor dark_border2 = QColor(48, 47, 47, 150); - const QColor dark_border3 = QColor(48, 47, 47, 100); - const QColor dark_border4 = QColor(48, 47, 47, 10); - - const QColor light_border0 = QColor(100, 100, 100, 255); - const QColor light_border1 = QColor(150, 150, 150, 150); - const QColor light_border2 = QColor(150, 150, 150, 100); - const QColor light_border3 = QColor(150, 150, 150, 50); - const QColor light_border4 = QColor(150, 150, 150, 0); - - const int Margin = 4; - } - -WinShadow::WinShadow(HWND hwnd, QWidget *parent) : QWidget(parent) -{ +WinShadow::WinShadow(HWND hwnd, QWidget *parent) + : QWidget(parent) +{ + m_hwnd = HWND(hwnd); m_active = true; - m_timer = NULL; - m_bClean = false; - _frame = NULL; - _hit_border = None; - _bDraging = false; - _freezing = false; - - setWindowFlags(Qt::Window | Qt::FramelessWindowHint); + m_parent = parent; + m_scale = 1; + + setWindowFlags(Qt::Window | Qt::FramelessWindowHint | + (!m_parent ? Qt::Tool : Qt::WindowFlags(0))); + setAttribute(Qt::WA_NoSystemBackground); setAttribute(Qt::WA_TranslucentBackground); - + m_timer = new QTimer(this); - connect(m_timer, &QTimer::timeout, this, &WinShadow::show); + connect(m_timer, &QTimer::timeout, this, &WinShadow::showShadow); + connect(this, &WinShadow::showSignal, this, &WinShadow::onMoveSelf); m_timer->setInterval(500); - m_timer->setSingleShot(true); - - _layout = new QGridLayout(this); - _layout->setSpacing(0); - _layout->setContentsMargins(0,0,0,0); - - setLayout(_layout); - - if (true) - { - _top_left = new widgets::Border (TopLeft, this); - _top_left->setFixedSize(Margin, Margin); - _top_left->installEventFilter(this); - _top = new widgets::Border (Top, this); - _top->setFixedHeight(Margin); - _top->installEventFilter(this); - _top_right = new widgets::Border (TopRight, this); - _top_right->setFixedSize(Margin, Margin); - _top_right->installEventFilter(this); - - _left = new widgets::Border (Left, this); - _left->setFixedWidth(Margin); - _left->installEventFilter(this); - _right = new widgets::Border (Right, this); - _right->setFixedWidth(Margin); - _right->installEventFilter(this); - - _bottom_left = new widgets::Border (BottomLeft, this); - _bottom_left->setFixedSize(Margin, Margin); - _bottom_left->installEventFilter(this); - _bottom = new widgets::Border (Bottom, this); - _bottom->setFixedHeight(Margin); - _bottom->installEventFilter(this); - _bottom_right = new widgets::Border (BottomRight, this); - _bottom_right->setFixedSize(Margin, Margin); - _bottom_right->installEventFilter(this); - - _layout->addWidget(_top_left, 0, 0); - _layout->addWidget(_top, 0, 1); - _layout->addWidget(_top_right, 0, 2); - _layout->addWidget(_left, 1, 0); - - _layout->addWidget(_right, 1, 2); - _layout->addWidget(_bottom_left, 2, 0); - _layout->addWidget(_bottom, 2, 1); - _layout->addWidget(_bottom_right, 2, 2); - } + m_timer->setSingleShot(true); } -int WinShadow::shadowWidth() -{ - return SHADOW_BORDER_WIDTH; +void WinShadow::onMoveSelf() +{ + moveShadow(); } void WinShadow::showLater() { m_timer->stop(); - m_timer->start(); + m_timer->start(); } -void WinShadow::show() +void WinShadow::showShadow() { - m_bClean = false; - if (m_timer->isActive()) return; @@ -144,283 +78,145 @@ void WinShadow::show() QWidget::raise(); SetWindowPos(m_hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE); - } -bool WinShadow::tryToShow() +void WinShadow::hideShadow() { - if (!isVisible()){ - show(); - - if (!m_timer->isActive()){ - showLater(); - } - return true; - } - return false; -} - -void WinShadow::SetClean(bool bClean) -{ - m_bClean = bClean; - if (isVisible()){ - repaint(); - } -} - -void WinShadow::hide() -{ - SetClean(true); m_timer->stop(); - + if (!isVisible()) return; - + QWidget::hide(); } void WinShadow::setActive(bool active) -{ +{ m_active = active; - repaint(); + repaint(); } bool WinShadow::nativeEvent(const QByteArray &eventType, void *message, long *result) -{ +{ MSG *msg = static_cast(message); switch (msg->message) { - case WM_ACTIVATE: - { - switch (msg->wParam) + case WM_ACTIVATE: { - case WA_ACTIVE: - case WA_CLICKACTIVE: + switch (msg->wParam) + { + case WA_ACTIVE: + case WA_CLICKACTIVE: + { + SetForegroundWindow(m_hwnd); + + break; + } + } + break; + } + case WM_MOUSEACTIVATE: { - SetForegroundWindow(m_hwnd); - break; + SetForegroundWindow(m_hwnd); + *result = MA_NOACTIVATE; + + return true; } - default: - break; - } - - break; - } - case WM_MOUSEACTIVATE: - { - SetForegroundWindow(m_hwnd); - *result = MA_NOACTIVATE; - return true; - } - /* - case WM_NCMOUSEMOVE: - case WM_NCLBUTTONDOWN: - case WM_NCLBUTTONUP: - case WM_NCLBUTTONDBLCLK: - case WM_NCHITTEST: - { - *result = long(SendMessageW(m_hwnd, msg->message, msg->wParam, msg->lParam)); - return true; - } - */ - default: - break; - } - - return QWidget::nativeEvent(eventType, message, result); -} - -bool WinShadow::eventFilter(QObject *object, QEvent *event) -{ - const QEvent::Type type = event->type(); - const QMouseEvent *const mouse_event = (QMouseEvent*)event; - int newWidth = 0; - int newHeight = 0; - int newLeft = 0; - int newTop = 0; - - if (_frame == NULL){ - return QWidget::eventFilter(object, event); - } - - if (type != QEvent::MouseMove - && type != QEvent::MouseButtonPress - && type != QEvent::MouseButtonRelease - && type != QEvent::Leave){ - return QWidget::eventFilter(object, event); - } - - //when window is maximized, or is moving, call return - if (_frame->IsMaxsized() || _frame->IsMoving()){ - return QWidget::eventFilter(object, event); - } - - if (!_bDraging && type == QEvent::MouseMove && (!(mouse_event->buttons() | Qt::NoButton))){ - if (object == _top_left) { - _hit_border = TopLeft; - setCursor(Qt::SizeFDiagCursor); - } else if (object == _bottom_right) { - _hit_border = BottomRight; - setCursor(Qt::SizeFDiagCursor); - } else if (object == _top_right) { - _hit_border = TopRight; - setCursor(Qt::SizeBDiagCursor); - } else if (object == _bottom_left) { - _hit_border = BottomLeft; - setCursor(Qt::SizeBDiagCursor); - } else if (object == _left) { - _hit_border = Left; - setCursor(Qt::SizeHorCursor); - } else if (object == _right) { - _hit_border = Right; - setCursor(Qt::SizeHorCursor); - } else if (object == _bottom) { - _hit_border = Bottom; - setCursor(Qt::SizeVerCursor); - } else if (object == _top) { - _hit_border = Top; - setCursor(Qt::SizeVerCursor); - } else { - _hit_border = None; - setCursor(Qt::ArrowCursor); - } - - return QWidget::eventFilter(object, event); - } - - if (type == QEvent::MouseMove) { - - QPoint pt; - int k = _frame->GetDevicePixelRatio(); - - POINT p; - GetCursorPos(&p); - pt.setX(p.x); - pt.setY(p.y); - - - int datX = pt.x() - _clickPos.x(); - int datY = pt.y() - _clickPos.y(); - datX /= k; - datY /= k; - - int l = _dragStartRegion.left(); - int t = _dragStartRegion.top(); - int r = _dragStartRegion.right(); - int b = _dragStartRegion.bottom(); - - if(mouse_event->buttons().testFlag(Qt::LeftButton)) { - - // Do nothing this time. - if (_freezing){ - return QWidget::eventFilter(object, event); - } - - int minW = MainWindow::Min_Width; - int minH = MainWindow::Min_Height; - - switch (_hit_border) { - case TopLeft: - l += datX; - t += datY; - if (r - l < minW) - l = r - minW; - if (b - t < minH) - t = b - minH; - break; - - case BottomLeft: - l += datX; - b += datY; - if (r - l < minW) - l = r - minW; - if (b - t < minH) - b = t + minH; - break; - - case TopRight: - r += datX; - t += datY; - if (r - l < minW) - r = l + minW; - if (b - t < minH) - t = b - minH; - break; - - case BottomRight: - r += datX; - b += datY; - if (r - l < minW) - r = l + minW; - if (b - t < minH) - b = t + minH; - break; - - case Left: - l += datX; - if (r - l < minW) - l = r - minW; - break; - - case Right: - r += datX; - if (r - l < minW) - r = l + minW; - break; - - case Top: - t += datY; - if (b - t < minH) - t = b - minH; - break; - - case Bottom: - b += datY; - if (b - t < minH) - b = t + minH; - break; - - default: - r = l; - break; - } - - if (r != l){ - _frame->SetFormRegion(l, t, r-l, b-t); - _frame->saveNormalRegion(); - } - + case WM_NCMOUSEMOVE: + case WM_NCLBUTTONDOWN: + case WM_NCLBUTTONUP: + case WM_NCLBUTTONDBLCLK: + case WM_NCHITTEST: + { + *result = long(SendMessageW(m_hwnd, msg->message, msg->wParam, msg->lParam)); return true; } } - else if (type == QEvent::MouseButtonPress) { - if (mouse_event->button() == Qt::LeftButton) - if (_hit_border != None) - _bDraging = true; - _timer.start(50); - - - POINT p; - GetCursorPos(&p); - _clickPos.setX(p.x); - _clickPos.setY(p.y); - - - _dragStartRegion = _frame->GetFormRegion(); - } - else if (type == QEvent::MouseButtonRelease) { - if (mouse_event->button() == Qt::LeftButton) { - _bDraging = false; - _timer.stop(); - } - } - else if (!_bDraging && type == QEvent::Leave) { - _hit_border = None; - setCursor(Qt::ArrowCursor); - } - return QWidget::eventFilter(object, event); + return QWidget::nativeEvent(eventType, message, result); +} + +void WinShadow::moveShadow() +{ + WINDOWPLACEMENT wp; + wp.length = sizeof(WINDOWPLACEMENT); + GetWindowPlacement(m_hwnd, &wp); + + if (wp.showCmd == SW_SHOWNORMAL){ + + RECT rc; + GetWindowRect(m_hwnd, &rc); + + int bw = (SHADOW_BORDER_WIDTH - 1) * m_scale; + + int x = rc.left; + int y = rc.top; + int w = rc.right - rc.left; + int h = rc.bottom - rc.top; + + x -= bw; + y -= bw; + w += bw * 2; + h += bw * 2; + + const HWND active_window = GetActiveWindow(); + bool isActiveWindow = ((active_window == m_hwnd) + || IsChild(m_hwnd, active_window)); + + MoveWindow((HWND)winId(), x, y, w , h , 1); + setActive(isActiveWindow); + } } +void WinShadow::paintEvent(QPaintEvent *event) +{ + const int shadow_width = SHADOW_BORDER_WIDTH; + QPainter painter(this); + painter.setCompositionMode(QPainter::CompositionMode_Source); + + if (!m_active) + { + painter.fillRect(rect(), QColor(0, 0, 0, 1)); + + QRect rect1 = rect().adjusted(shadow_width, shadow_width, -shadow_width, -shadow_width); + + painter.fillRect(rect1, Qt::transparent); + + return; + } + + QPixmap radial_gradient = QPixmap(shadow_width * 2, shadow_width * 2); + + { + radial_gradient.fill(QColor(0, 0, 0, 1)); + + QPainter painter(&radial_gradient); + painter.setRenderHint(QPainter::Antialiasing); + painter.setCompositionMode(QPainter::CompositionMode_Source); + + QRadialGradient gradient(shadow_width, shadow_width, shadow_width); + gradient.setColorAt(0.0, COLOR1); + gradient.setColorAt(0.2, COLOR2); + gradient.setColorAt(0.5, COLOR3); + + QPen pen(Qt::transparent, 0); + painter.setPen(pen); + painter.setBrush(gradient); + painter.drawEllipse(0, 0, shadow_width * 2, shadow_width * 2); + } + + QRect rect1 = rect().adjusted(shadow_width, shadow_width, -shadow_width, -shadow_width); + + painter.drawPixmap(0, 0, shadow_width, shadow_width, radial_gradient, 0, 0, shadow_width, shadow_width); + painter.drawPixmap(rect().width() - shadow_width, 0, radial_gradient, shadow_width, 0, shadow_width, shadow_width); //Top-right corner + painter.drawPixmap(0, rect().height() - shadow_width, radial_gradient, 0, shadow_width, shadow_width, shadow_width); //Bottom-left corner + painter.drawPixmap(rect().width() - shadow_width, rect().height() - shadow_width, radial_gradient, shadow_width, shadow_width, shadow_width, shadow_width); //Bottom-right corner + + painter.drawPixmap(shadow_width, 0, rect1.width(), shadow_width, radial_gradient, shadow_width, 0, 1, shadow_width); //Top + painter.drawPixmap(0, shadow_width, shadow_width, rect1.height(), radial_gradient, 0, shadow_width, shadow_width, 1); //Left + painter.drawPixmap(rect1.width() + shadow_width, shadow_width, shadow_width, rect1.height(), radial_gradient, shadow_width, shadow_width, shadow_width, 1); //Right + painter.drawPixmap(shadow_width, rect1.height() + shadow_width, rect1.width(), shadow_width, radial_gradient, shadow_width, shadow_width, 1, SHADOW_BORDER_WIDTH); //Bottom } + +}// namespace pv \ No newline at end of file diff --git a/DSView/pv/winshadow.h b/DSView/pv/winshadow.h index f04b58fb..6c611de9 100644 --- a/DSView/pv/winshadow.h +++ b/DSView/pv/winshadow.h @@ -19,96 +19,52 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef WINSHADOW_H -#define WINSHADOW_H +#ifndef SHADOW_H +#define SHADOW_H #include #include -#include +#include #include -#include -#include "widgets/border.h" +#define SHADOW_BORDER_WIDTH 11 - -#define SHADOW_BORDER_WIDTH 4 - namespace pv { -class MainFrame; - class WinShadow : public QWidget { Q_OBJECT - - enum borderTypes{ - None, - TopLeft, - Left, - BottomLeft, - Bottom, - BottomRight, - Right, - TopRight, - Top - }borderTypes; - public: explicit WinShadow(HWND hwnd, QWidget *parent); - bool tryToShow(); + void moveShadow(); - void SetClean(bool bClean); - - inline void SetFrame(MainFrame *frame){ - _frame = frame; + inline void setScale(int k){ + m_scale = k; } + void showLater(); + void hideShadow(); + Q_SIGNALS: void showSignal(); + +public Q_SLOTS: + void showShadow(); + void onMoveSelf(); -public Q_SLOTS: - void showLater(); - void show(); - void hide(); +private: + bool nativeEvent(const QByteArray &eventType, void *message, long *result) override; + void paintEvent(QPaintEvent *event) override; void setActive(bool active); - int shadowWidth(); - -private: - //Functions - bool nativeEvent(const QByteArray &eventType, void *message, long *result) override; - - bool eventFilter(QObject *object, QEvent *event) override; - - -private: - + + QWidget *m_parent; QTimer *m_timer; HWND m_hwnd; bool m_active; - bool m_bClean; + int m_scale; +}; - QGridLayout *_layout; - widgets::Border *_left; - widgets::Border *_right; - widgets::Border *_top; - widgets::Border *_bottom; - widgets::Border *_top_left; - widgets::Border *_top_right; - widgets::Border *_bottom_left; - widgets::Border *_bottom_right; +} // namespace pv - MainFrame *_frame; - - int _hit_border; - bool _bDraging; - QTimer _timer; - bool _freezing; - QPoint _clickPos; - QRect _dragStartRegion; - -}; - -} - -#endif // SHADOW_H +#endif