diff --git a/CMakeLists.txt b/CMakeLists.txt index c382c9e..9f796f3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,17 @@ cmake_minimum_required(VERSION 3.10) project(spark_store) +set(EXECUTABLE_NAME sparkstore) + +# Begin Compilation Options + +# When set to ON, DTK Plugin for DDE platform will be built. +# Note that only machines with DTK and dev packages installed can build the plugin. +set(SPARK_BUILD_DTK_PLUGIN ON) + +# When set to ON, store will transmit telemetry even in Debug builds. +set(SPARK_FORCE_TELEMETRY OFF) + +# End Compilation Options set(CMAKE_CXX_STANDARD 14) set(CMAKE_AUTOMOC ON) @@ -7,16 +19,34 @@ set(CMAKE_AUTORCC ON) set(CMAKE_AUTOUIC ON) set(QT_VERSION 5) -set(REQUIRED_LIBS Core Gui Widgets) -set(REQUIRED_LIBS_QUALIFIED Qt5::Core Qt5::Gui Qt5::Widgets) +set(REQUIRED_LIBS + Core + Gui + Widgets + Concurrent) +set(REQUIRED_LIBS_QUALIFIED + Qt5::Core + Qt5::Gui + Qt5::Widgets + Qt5::Concurrent) include_directories(inc) +include_directories(plugin) set(CMAKE_INCLUDE_CURRENT_DIR ON) +set(PRE_CONFIGURE_FILE "src/gitver.cpp.in") +set(POST_CONFIGURE_FILE "${CMAKE_CURRENT_BINARY_DIR}/src/gitver.cpp") +include(cmake/git_watcher.cmake) +add_library(gitver STATIC ${POST_CONFIGURE_FILE}) +#target_include_directories(gitver PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) +add_dependencies(gitver check_git) + + set(SOURCE_FILES src/main.cpp resource/resource.qrc + inc/gitver.h gui/spkwindow.cpp inc/spkwindow.h gui/spktitlebar.cpp @@ -24,6 +54,7 @@ set(SOURCE_FILES inc/spkui_general.h gui/spkui_general.cpp inc/deepinplatform.h + inc/dtk/spkdtkplugin.h src/spklogging.cpp inc/spklogging.h inc/spkuimsg.h @@ -33,6 +64,8 @@ set(SOURCE_FILES gui/spkmsgbox.cpp inc/spkdialog.h gui/spkdialog.cpp + inc/spkabout.h + gui/spkabout.cpp inc/spkstore.h src/spkstore.cpp gui/spkmainwindow.cpp @@ -40,7 +73,7 @@ set(SOURCE_FILES gui/spkpageqsstest.cpp gui/spkcategoryselector.cpp inc/spkconfig.h - src/telemetry/collectid.cpp + inc/telemetry/collectid.h ) include(cmake/FindLibNotify.cmake) @@ -50,6 +83,7 @@ include(cmake/FindGdk3.cmake) include_directories(${GLIB_INCLUDE_DIRS}) include_directories(${GDK3_INCLUDE_DIRS}) set(LIBLINKING ${LIBLINKING} + gitver ${LIBNOTIFY_LIBRARIES} ${GLIB_LIBRARIES} ${GDK3_LIBRARIES} @@ -59,7 +93,15 @@ set(LIBLINKING ${LIBLINKING} add_compile_options(-g) add_link_options(-rdynamic) -add_executable(${PROJECT_NAME} ${SOURCE_FILES}) - +# Find Qt before adding other build targets find_package(Qt${QT_VERSION} COMPONENTS ${REQUIRED_LIBS} REQUIRED) -target_link_libraries(${PROJECT_NAME} ${REQUIRED_LIBS_QUALIFIED} ${LIBLINKING}) + +add_executable(${EXECUTABLE_NAME} ${SOURCE_FILES}) + +if(SPARK_BUILD_DTK_PLUGIN) + add_subdirectory(plugin/dtkplugin) +endif() + +target_link_libraries(${EXECUTABLE_NAME} ${REQUIRED_LIBS_QUALIFIED} ${LIBLINKING}) + +install(TARGETS ${EXECUTABLE_NAME} RUNTIME DESTINATION in) diff --git a/cmake/git_watcher.cmake b/cmake/git_watcher.cmake new file mode 100644 index 0000000..dd8a7bc --- /dev/null +++ b/cmake/git_watcher.cmake @@ -0,0 +1,335 @@ +# git_watcher.cmake +# https://raw.githubusercontent.com/andrew-hardin/cmake-git-version-tracking/master/git_watcher.cmake +# +# Released under the MIT License. +# https://raw.githubusercontent.com/andrew-hardin/cmake-git-version-tracking/master/LICENSE + + +# This file defines a target that monitors the state of a git repo. +# If the state changes (e.g. a commit is made), then a file gets reconfigured. +# Here are the primary variables that control script behavior: +# +# PRE_CONFIGURE_FILE (REQUIRED) +# -- The path to the file that'll be configured. +# +# POST_CONFIGURE_FILE (REQUIRED) +# -- The path to the configured PRE_CONFIGURE_FILE. +# +# GIT_STATE_FILE (OPTIONAL) +# -- The path to the file used to store the previous build's git state. +# Defaults to the current binary directory. +# +# GIT_WORKING_DIR (OPTIONAL) +# -- The directory from which git commands will be run. +# Defaults to the directory with the top level CMakeLists.txt. +# +# GIT_EXECUTABLE (OPTIONAL) +# -- The path to the git executable. It'll automatically be set if the +# user doesn't supply a path. +# +# GIT_FAIL_IF_NONZERO_EXIT (optional) +# -- Raise a FATAL_ERROR if any of the git commands return a non-zero +# exit code. This is set to TRUE by default. You can set this to FALSE +# if you'd like the build to continue even if a git command fails. +# +# DESIGN +# - This script was designed similar to a Python application +# with a Main() function. I wanted to keep it compact to +# simplify "copy + paste" usage. +# +# - This script is invoked under two CMake contexts: +# 1. Configure time (when build files are created). +# 2. Build time (called via CMake -P). +# The first invocation is what registers the script to +# be executed at build time. +# +# MODIFICATIONS +# You may wish to track other git properties like when the last +# commit was made. There are two sections you need to modify, +# and they're tagged with a ">>>" header. + +# Short hand for converting paths to absolute. +macro(PATH_TO_ABSOLUTE var_name) + get_filename_component(${var_name} "${${var_name}}" ABSOLUTE) +endmacro() + +# Check that a required variable is set. +macro(CHECK_REQUIRED_VARIABLE var_name) + if(NOT DEFINED ${var_name}) + message(FATAL_ERROR "The \"${var_name}\" variable must be defined.") + endif() + PATH_TO_ABSOLUTE(${var_name}) +endmacro() + +# Check that an optional variable is set, or, set it to a default value. +macro(CHECK_OPTIONAL_VARIABLE_NOPATH var_name default_value) + if(NOT DEFINED ${var_name}) + set(${var_name} ${default_value}) + endif() +endmacro() + +# Check that an optional variable is set, or, set it to a default value. +# Also converts that path to an abspath. +macro(CHECK_OPTIONAL_VARIABLE var_name default_value) + CHECK_OPTIONAL_VARIABLE_NOPATH(${var_name} ${default_value}) + PATH_TO_ABSOLUTE(${var_name}) +endmacro() + +CHECK_REQUIRED_VARIABLE(PRE_CONFIGURE_FILE) +CHECK_REQUIRED_VARIABLE(POST_CONFIGURE_FILE) +CHECK_OPTIONAL_VARIABLE(GIT_STATE_FILE "${CMAKE_BINARY_DIR}/git-state-hash") +CHECK_OPTIONAL_VARIABLE(GIT_WORKING_DIR "${CMAKE_SOURCE_DIR}") +CHECK_OPTIONAL_VARIABLE_NOPATH(GIT_FAIL_IF_NONZERO_EXIT TRUE) + +# Check the optional git variable. +# If it's not set, we'll try to find it using the CMake packaging system. +if(NOT DEFINED GIT_EXECUTABLE) + find_package(Git QUIET REQUIRED) +endif() +CHECK_REQUIRED_VARIABLE(GIT_EXECUTABLE) + + +set(_state_variable_names + GIT_RETRIEVED_STATE + GIT_HEAD_SHA1 + GIT_IS_DIRTY + GIT_AUTHOR_NAME + GIT_AUTHOR_EMAIL + GIT_COMMIT_DATE_ISO8601 + GIT_COMMIT_SUBJECT + GIT_COMMIT_BODY + GIT_DESCRIBE + # >>> + # 1. Add the name of the additional git variable you're interested in monitoring + # to this list. +) + + + +# Macro: RunGitCommand +# Description: short-hand macro for calling a git function. Outputs are the +# "exit_code" and "output" variables. +macro(RunGitCommand) + execute_process(COMMAND + "${GIT_EXECUTABLE}" ${ARGV} + WORKING_DIRECTORY "${_working_dir}" + RESULT_VARIABLE exit_code + OUTPUT_VARIABLE output + ERROR_VARIABLE stderr + OUTPUT_STRIP_TRAILING_WHITESPACE) + if(NOT exit_code EQUAL 0) + set(ENV{GIT_RETRIEVED_STATE} "false") + + # Issue 26: git info not properly set + # + # Check if we should fail if any of the exit codes are non-zero. + if(GIT_FAIL_IF_NONZERO_EXIT) + string(REPLACE ";" " " args_with_spaces "${ARGV}") + message(FATAL_ERROR "${stderr} (${GIT_EXECUTABLE} ${args_with_spaces})") + endif() + endif() +endmacro() + + + +# Function: GetGitState +# Description: gets the current state of the git repo. +# Args: +# _working_dir (in) string; the directory from which git commands will be executed. +function(GetGitState _working_dir) + + # This is an error code that'll be set to FALSE if the + # RunGitCommand ever returns a non-zero exit code. + set(ENV{GIT_RETRIEVED_STATE} "true") + + # Get whether or not the working tree is dirty. + RunGitCommand(status --porcelain) + if(NOT exit_code EQUAL 0) + set(ENV{GIT_IS_DIRTY} "false") + else() + if(NOT "${output}" STREQUAL "") + set(ENV{GIT_IS_DIRTY} "true") + else() + set(ENV{GIT_IS_DIRTY} "false") + endif() + endif() + + # There's a long list of attributes grabbed from git show. + set(object HEAD) + RunGitCommand(show -s "--format=%H" ${object}) + if(exit_code EQUAL 0) + set(ENV{GIT_HEAD_SHA1} ${output}) + endif() + + RunGitCommand(show -s "--format=%an" ${object}) + if(exit_code EQUAL 0) + set(ENV{GIT_AUTHOR_NAME} "${output}") + endif() + + RunGitCommand(show -s "--format=%ae" ${object}) + if(exit_code EQUAL 0) + set(ENV{GIT_AUTHOR_EMAIL} "${output}") + endif() + + RunGitCommand(show -s "--format=%ci" ${object}) + if(exit_code EQUAL 0) + set(ENV{GIT_COMMIT_DATE_ISO8601} "${output}") + endif() + + RunGitCommand(show -s "--format=%s" ${object}) + if(exit_code EQUAL 0) + # Escape quotes + string(REPLACE "\"" "\\\"" output "${output}") + set(ENV{GIT_COMMIT_SUBJECT} "${output}") + endif() + + RunGitCommand(show -s "--format=%b" ${object}) + if(exit_code EQUAL 0) + if(output) + # Escape quotes + string(REPLACE "\"" "\\\"" output "${output}") + # Escape line breaks in the commit message. + string(REPLACE "\r\n" "\\r\\n\\\r\n" safe "${output}") + if(safe STREQUAL output) + # Didn't have windows lines - try unix lines. + string(REPLACE "\n" "\\n\\\n" safe "${output}") + endif() + else() + # There was no commit body - set the safe string to empty. + set(safe "") + endif() + set(ENV{GIT_COMMIT_BODY} "\"${safe}\"") + else() + set(ENV{GIT_COMMIT_BODY} "\"\"") # empty string. + endif() + + # Get output of git describe + RunGitCommand(describe --tags ${object}) + if(NOT exit_code EQUAL 0) + set(ENV{GIT_DESCRIBE} "unknown") + else() + set(ENV{GIT_DESCRIBE} "${output}") + endif() + + # >>> + # 2. Additional git properties can be added here via the + # "execute_process()" command. Be sure to set them in + # the environment using the same variable name you added + # to the "_state_variable_names" list. + +endfunction() + + + +# Function: GitStateChangedAction +# Description: this function is executed when the state of the git +# repository changes (e.g. a commit is made). +function(GitStateChangedAction) + foreach(var_name ${_state_variable_names}) + set(${var_name} $ENV{${var_name}}) + endforeach() + configure_file("${PRE_CONFIGURE_FILE}" "${POST_CONFIGURE_FILE}" @ONLY) +endfunction() + + + +# Function: HashGitState +# Description: loop through the git state variables and compute a unique hash. +# Args: +# _state (out) string; a hash computed from the current git state. +function(HashGitState _state) + set(ans "") + foreach(var_name ${_state_variable_names}) + string(SHA256 ans "${ans}$ENV{${var_name}}") + endforeach() + set(${_state} ${ans} PARENT_SCOPE) +endfunction() + + + +# Function: CheckGit +# Description: check if the git repo has changed. If so, update the state file. +# Args: +# _working_dir (in) string; the directory from which git commands will be ran. +# _state_changed (out) bool; whether or no the state of the repo has changed. +function(CheckGit _working_dir _state_changed) + + # Get the current state of the repo. + GetGitState("${_working_dir}") + + # Convert that state into a hash that we can compare against + # the hash stored on-disk. + HashGitState(state) + + # Issue 14: post-configure file isn't being regenerated. + # + # Update the state to include the SHA256 for the pre-configure file. + # This forces the post-configure file to be regenerated if the + # pre-configure file has changed. + file(SHA256 ${PRE_CONFIGURE_FILE} preconfig_hash) + string(SHA256 state "${preconfig_hash}${state}") + + # Check if the state has changed compared to the backup on disk. + if(EXISTS "${GIT_STATE_FILE}") + file(READ "${GIT_STATE_FILE}" OLD_HEAD_CONTENTS) + if(OLD_HEAD_CONTENTS STREQUAL "${state}") + # State didn't change. + set(${_state_changed} "false" PARENT_SCOPE) + return() + endif() + endif() + + # The state has changed. + # We need to update the state file on disk. + # Future builds will compare their state to this file. + file(WRITE "${GIT_STATE_FILE}" "${state}") + set(${_state_changed} "true" PARENT_SCOPE) +endfunction() + + + +# Function: SetupGitMonitoring +# Description: this function sets up custom commands that make the build system +# check the state of git before every build. If the state has +# changed, then a file is configured. +function(SetupGitMonitoring) + add_custom_target(check_git + ALL + DEPENDS ${PRE_CONFIGURE_FILE} + BYPRODUCTS + ${POST_CONFIGURE_FILE} + ${GIT_STATE_FILE} + COMMENT "Checking the git repository for changes..." + COMMAND + ${CMAKE_COMMAND} + -D_BUILD_TIME_CHECK_GIT=TRUE + -DGIT_WORKING_DIR=${GIT_WORKING_DIR} + -DGIT_EXECUTABLE=${GIT_EXECUTABLE} + -DGIT_STATE_FILE=${GIT_STATE_FILE} + -DPRE_CONFIGURE_FILE=${PRE_CONFIGURE_FILE} + -DPOST_CONFIGURE_FILE=${POST_CONFIGURE_FILE} + -DGIT_FAIL_IF_NONZERO_EXIT=${GIT_FAIL_IF_NONZERO_EXIT} + -P "${CMAKE_CURRENT_LIST_FILE}") +endfunction() + + + +# Function: Main +# Description: primary entry-point to the script. Functions are selected based +# on whether it's configure or build time. +function(Main) + if(_BUILD_TIME_CHECK_GIT) + # Check if the repo has changed. + # If so, run the change action. + CheckGit("${GIT_WORKING_DIR}" changed) + if(changed OR NOT EXISTS "${POST_CONFIGURE_FILE}") + GitStateChangedAction() + endif() + else() + # >> Executes at configure time. + SetupGitMonitoring() + endif() +endfunction() + +# And off we go... +Main() diff --git a/gui/spkabout.cpp b/gui/spkabout.cpp new file mode 100644 index 0000000..45ebdb9 --- /dev/null +++ b/gui/spkabout.cpp @@ -0,0 +1,19 @@ + +#include "spkabout.h" + +SpkAbout::SpkAbout(QWidget *parent) : SpkDialog(parent) +{ + setWindowModality(Qt::ApplicationModal); +} + +void SpkAbout::Show() +{ + SpkAbout *b = new SpkAbout; + + b->GetTitleBar()->SetOperationButton(SpkTitleBar::OperationButton::Close); + + // TODO: Waiting for qygw + + b->Exec(); + delete b; +} diff --git a/gui/spkdialog.cpp b/gui/spkdialog.cpp index c1c4862..fee9810 100644 --- a/gui/spkdialog.cpp +++ b/gui/spkdialog.cpp @@ -3,7 +3,7 @@ #include "spkdialog.h" SpkDialog::SpkDialog(QWidget *parent) : - SpkWindow(parent) + SpkWindow(parent, Qt::Dialog) { mDialogWidget = new QWidget; mMainVLay = new QVBoxLayout(mDialogWidget); @@ -19,7 +19,8 @@ SpkDialog::SpkDialog(QWidget *parent) : SetCentralWidget(mDialogWidget); - connect(mBtnGroup, QOverload<int>::of(&QButtonGroup::idClicked), + // idClicked is not available on platforms we support, shouldn't change it + connect(mBtnGroup, QOverload<int>::of(&QButtonGroup::buttonClicked), this, &SpkDialog::ButtonPressed); connect(this, &SpkWindow::Closed, this, &SpkDialog::ForceClose); } diff --git a/gui/spkmsgbox.cpp b/gui/spkmsgbox.cpp index c78eb94..222fc8b 100644 --- a/gui/spkmsgbox.cpp +++ b/gui/spkmsgbox.cpp @@ -5,21 +5,23 @@ #include <QScreen> #include "spkui_general.h" #include "spkmsgbox.h" +#include "spkstore.h" // Suppress unwanted Clazy check warnings // clazy:excludeall=connect-3arg-lambda,lambda-in-connect -const QSize SpkMsgBox::IconSize; // I don't know why I need it +const QSize SpkMsgBox::IconSize; // I don't know why I need it, compiler wants that -SpkMsgBox::SpkMsgBox() +SpkMsgBox::SpkMsgBox(QWidget *parent) { + Q_UNUSED(parent); setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Minimum); } int SpkMsgBox::StaticExec(QString msg, QString title, QMessageBox::Icon icon, QMessageBox::StandardButtons buttons, QString extra) { - SpkMsgBox *b = new SpkMsgBox; + SpkMsgBox *b = new SpkMsgBox(SpkStore::Instance->GetRootWindow()); QWidget *wMsgWidget = new QWidget; QHBoxLayout *wMsg = new QHBoxLayout(wMsgWidget); QPushButton *wExpandBtn; @@ -53,7 +55,7 @@ int SpkMsgBox::StaticExec(QString msg, QString title, QMessageBox::Icon icon, wMsg->addWidget(wIcon); } wMsgText->setText(msg); - wMsgText->setAlignment(Qt::AlignCenter); + wMsgText->setAlignment(Qt::AlignLeft); wMsg->addWidget(wMsgText); wMsg->setSpacing(10); wMsgWidget->setLayout(wMsg); @@ -95,7 +97,8 @@ int SpkMsgBox::StaticExec(QString msg, QString title, QMessageBox::Icon icon, InitialHeight = b->minimumSizeHint().height(); auto pos = (SpkUi::PrimaryScreenSize - b->sizeHint()) / 2; b->move(pos.width(), pos.height()); - b->setWindowModality(Qt::WindowModal); + b->setWindowModality(Qt::ApplicationModal); + b->setFixedSize(b->sizeHint()); auto r = b->Exec(); if(r != -1) diff --git a/gui/spkui_general.cpp b/gui/spkui_general.cpp index 1b8dd48..9ac7933 100644 --- a/gui/spkui_general.cpp +++ b/gui/spkui_general.cpp @@ -11,10 +11,11 @@ #include <QDateTime> #include <QDebug> #include <QScreen> +#include <QPluginLoader> +#include <QStyleFactory> #include <csignal> -#include <dlfcn.h> #include <execinfo.h> -#include "deepinplatform.h" + #include "spkui_general.h" #include "spkmsgbox.h" #include "spklogging.h" @@ -24,6 +25,8 @@ namespace SpkUi QString StylesheetLight, StylesheetDark, *CurrentStylesheet = &StylesheetLight; QColor ColorLine, ColorBack; QSize PrimaryScreenSize; + SpkDtkPlugin *DtkPlugin = nullptr; + namespace Priv { bool CrashHandlerActivated; @@ -50,9 +53,10 @@ namespace SpkUi signal(SIGFPE, SpkUi::CrashSignalHandler); // Prepare theme following for DDE - PrepareForDeepinDesktop(); + if(CheckIsDeepinDesktop()) + PrepareForDeepinDesktop(); - // Data initialization + // Misc data initialization PrimaryScreenSize = QGuiApplication::primaryScreen()->size(); } @@ -64,6 +68,7 @@ namespace SpkUi bool CheckIsDeepinDesktop() { QString Desktop(getenv("XDG_CURRENT_DESKTOP")); + // This method of checking is from DTK source code. if(Desktop.contains("deepin", Qt::CaseInsensitive) || Desktop.contains("tablet", Qt::CaseInsensitive)) return true; @@ -73,7 +78,30 @@ namespace SpkUi void PrepareForDeepinDesktop() { +#ifndef NDEBUG + // Normally it's installed to system library path + qApp->addLibraryPath(qApp->applicationDirPath() + "/plugin/dtkplugin"); +#endif + QPluginLoader p("libspkdtkplugin"); + if(p.load()) + { + auto i = qobject_cast<SpkDtkPlugin*>(p.instance()); + if(i) + DtkPlugin = i; + } + // FIXME: Chameleon style kept adding unwanted blue focus indication border + // to widgets that shouldn't have borders. + // We need to eliminate this irritating problem. + auto styles = QStyleFactory::keys(); + styles.removeAll("chameleon"); + if(styles.contains("Fusion")) + qApp->setStyle(QStyleFactory::create("Fusion")); + else if(styles.size()) // What? This shouldn't happen. + qApp->setStyle(QStyleFactory::create(styles[0])); + else // Duh... + sWarn(QObject::tr("Cannot find styles other than 'chameleon'! You may see widgets " + "with unwanted blue borders.")); } void SetGlobalStyle(const SpkUiStyle aStyle) diff --git a/gui/spkwindow.cpp b/gui/spkwindow.cpp index 5f11741..553a2e2 100644 --- a/gui/spkwindow.cpp +++ b/gui/spkwindow.cpp @@ -12,9 +12,12 @@ #include <QDebug> -SpkWindow::SpkWindow(QWidget *parent) : QMainWindow(parent) +SpkWindow::SpkWindow(QWidget *parent, Qt::WindowFlags flags) : QMainWindow(parent, flags) { - setWindowFlags(Qt::FramelessWindowHint); // Remove default title bar, we'll have custom title bar + if(SpkUi::DtkPlugin) + SpkUi::DtkPlugin->addWindow(this, parent); // Register window to DXcb so we got Deepin + else + setWindowFlags(Qt::FramelessWindowHint); // Remove default title bar mCornerRadius = 5; mUserCentralWidget = nullptr; mResizable = true; diff --git a/inc/deepinplatform.h b/inc/deepinplatform.h index 8abc117..21a0915 100644 --- a/inc/deepinplatform.h +++ b/inc/deepinplatform.h @@ -2,8 +2,7 @@ // Created by rigoligo on 2021/5/8. // -#ifndef _DEEPINPLATFORM_H_ -#define _DEEPINPLATFORM_H_ +#pragma once // Stub diff --git a/inc/dtk/spkdtkplugin.h b/inc/dtk/spkdtkplugin.h new file mode 100644 index 0000000..8929b73 --- /dev/null +++ b/inc/dtk/spkdtkplugin.h @@ -0,0 +1,15 @@ + +#pragma once + +#include <QWidget> + +class SpkDtkPlugin +{ + public: + virtual ~SpkDtkPlugin() = default; + + virtual void addWindow(QWidget* w, QObject* parent) = 0; +}; +QT_BEGIN_NAMESPACE +Q_DECLARE_INTERFACE(SpkDtkPlugin, "org.spark-store.client.dtkplugin") +QT_END_NAMESPACE diff --git a/inc/gitver.h b/inc/gitver.h new file mode 100644 index 0000000..15e192e --- /dev/null +++ b/inc/gitver.h @@ -0,0 +1,8 @@ + +#pragma once + +namespace GitVer +{ + const char *DescribeTags(); + const char *CommitDate(); +} diff --git a/inc/spkabout.h b/inc/spkabout.h new file mode 100644 index 0000000..7565e1a --- /dev/null +++ b/inc/spkabout.h @@ -0,0 +1,11 @@ + +#pragma once + +#include "spkdialog.h" + +class SpkAbout : public SpkDialog +{ + public: + SpkAbout(QWidget* parent = nullptr); + void Show(); +}; diff --git a/inc/spkdialog.h b/inc/spkdialog.h index 97cf46b..174e185 100644 --- a/inc/spkdialog.h +++ b/inc/spkdialog.h @@ -1,5 +1,4 @@ -#ifndef SPKDIALOG_H -#define SPKDIALOG_H +#pragma once #include <QList> #include <QButtonGroup> @@ -33,5 +32,3 @@ class SpkDialog : public SpkWindow QButtonGroup *mBtnGroup; QList<QWidget*> mWidgetsList, mParentsList; }; - -#endif // SPKDIALOG_H diff --git a/inc/spklogging.h b/inc/spklogging.h index dee4625..fe5ed38 100644 --- a/inc/spklogging.h +++ b/inc/spklogging.h @@ -3,8 +3,7 @@ * @brief Simple logging for Spark Store */ -#ifndef _SPKLOGGING_H_ -#define _SPKLOGGING_H_ +#pragma once #pragma push_macro("signals") #undef signals @@ -43,5 +42,3 @@ class SpkLogger #define sErrPop(X) SpkLogger::GetInstance()->Error(X,true) #define sCritical(X) SpkLogger::GetInstance()->Critical(X) #define sNotify(X) - -#endif //_SPKLOGGING_H_ diff --git a/inc/spkmainwindow.h b/inc/spkmainwindow.h index 90ccffc..2f6d91f 100644 --- a/inc/spkmainwindow.h +++ b/inc/spkmainwindow.h @@ -2,8 +2,7 @@ // Created by rigoligo on 2021/5/9. // -#ifndef _SPKMAINWINDOW_H_ -#define _SPKMAINWINDOW_H_ +#pragma once #include "spkwindow.h" #include <QTextEdit> @@ -74,5 +73,3 @@ class SpkMainWindow : public SpkWindow void PopulateCategories(QJsonObject); }; - -#endif //_SPKMAINWINDOW_H_ diff --git a/inc/spkmsgbox.h b/inc/spkmsgbox.h index 373367a..c899b74 100644 --- a/inc/spkmsgbox.h +++ b/inc/spkmsgbox.h @@ -1,5 +1,4 @@ -#ifndef SPKMSGBOX_H -#define SPKMSGBOX_H +#pragma once #include <QStyle> #include <QMessageBox> @@ -9,7 +8,7 @@ class SpkMsgBox : public SpkDialog { Q_OBJECT public: - SpkMsgBox(); + SpkMsgBox(QWidget *parent = nullptr); static int StaticExec(QString msg, QString title, QMessageBox::Icon = QMessageBox::NoIcon, QMessageBox::StandardButtons = QMessageBox::Ok, QString extra = ""); private: @@ -18,5 +17,3 @@ class SpkMsgBox : public SpkDialog static constexpr QSize IconSize {48, 48}; static constexpr int Margin = 10; }; - -#endif // SPKMSGBOX_H diff --git a/inc/spkpageqsstest.h b/inc/spkpageqsstest.h index ab842a9..311bf4c 100644 --- a/inc/spkpageqsstest.h +++ b/inc/spkpageqsstest.h @@ -1,5 +1,4 @@ -#ifndef SPKPAGEQSSTEST_H -#define SPKPAGEQSSTEST_H +#pragma once #include <QWidget> #include <QSplitter> @@ -40,5 +39,3 @@ namespace SpkUi void FetchStylesheet(); }; } - -#endif // SPKPAGEQSSTEST_H diff --git a/inc/spkstore.h b/inc/spkstore.h index 130f0ca..85d8d70 100644 --- a/inc/spkstore.h +++ b/inc/spkstore.h @@ -2,8 +2,7 @@ // Created by rigoligo on 2021/5/12. // -#ifndef _SPKSTORE_H_ -#define _SPKSTORE_H_ +#pragma once #include <QMap> #include <QString> @@ -20,15 +19,14 @@ class SpkStore : public QObject { Q_OBJECT public: - SpkStore *Instance; + static SpkStore *Instance; SpkStore(bool aCli, QString &aLogPath); ~SpkStore(); + SpkMainWindow* GetRootWindow() { return mMainWindow; }; private: SpkLogger *mLogger; - SpkMainWindow *mMainWindow; + SpkMainWindow *mMainWindow = nullptr; }; - -#endif //_SPKSTORE_H_ diff --git a/inc/spktitlebar.h b/inc/spktitlebar.h index 37a4096..d0e3770 100644 --- a/inc/spktitlebar.h +++ b/inc/spktitlebar.h @@ -2,8 +2,7 @@ // Created by rigoligo on 2021/5/8. // -#ifndef _SPKTITLEBAR_H_ -#define _SPKTITLEBAR_H_ +#pragma once #include <QHBoxLayout> #include <QLabel> @@ -70,5 +69,3 @@ class SpkTitleBar : public QWidget void MinimizeWindow(); void MaximizeRestoreWindow(); }; - -#endif //_SPKTITLEBAR_H_ diff --git a/inc/spkui_general.h b/inc/spkui_general.h index ee38667..3f9da65 100644 --- a/inc/spkui_general.h +++ b/inc/spkui_general.h @@ -2,13 +2,15 @@ // Created by rigoligo on 2021/5/8. // -#ifndef _SPKUI_GENERAL_H_ -#define _SPKUI_GENERAL_H_ +#pragma once +#include <QWidget> #include <QString> #include <QSize> #include <QColor> +#include "dtkplugin/spkdtkplugin.h" + namespace SpkUi { constexpr int StackTraceArraySize = 64; @@ -17,6 +19,7 @@ namespace SpkUi extern QString StylesheetLight, StylesheetDark, *CurrentStylesheet; extern QColor ColorLine, ColorBack; extern QSize PrimaryScreenSize; + extern SpkDtkPlugin *DtkPlugin; enum SpkUiStyle { Light, Dark }; enum SpkButtonStyle { Normal = 0, Recommend, Warn }; @@ -34,5 +37,3 @@ namespace SpkUi void SetGlobalStyle(SpkUiStyle); }; - -#endif //_SPKUI_GENERAL_H_ diff --git a/inc/spkuimsg.h b/inc/spkuimsg.h index 97cf966..b0cc640 100644 --- a/inc/spkuimsg.h +++ b/inc/spkuimsg.h @@ -2,8 +2,7 @@ // Created by rigoligo on 2021/5/9. // -#ifndef _SPKUIMSG_H_ -#define _SPKUIMSG_H_ +#pragma once #pragma push_macro("signals") #undef signals @@ -31,5 +30,3 @@ class SpkUiMessage : public QObject signals: }; - -#endif //_SPKUIMSG_H_ diff --git a/inc/spkwindow.h b/inc/spkwindow.h index 8ef64a1..3e30ac6 100644 --- a/inc/spkwindow.h +++ b/inc/spkwindow.h @@ -2,8 +2,7 @@ // Created by rigoligo on 2021/5/8. // -#ifndef _SPKWINDOW_H_ -#define _SPKWINDOW_H_ +#pragma once #include <QMainWindow> #include <QFrame> @@ -32,7 +31,7 @@ class SpkWindow : public QMainWindow static constexpr int BorderWidth = 10; public: - SpkWindow(QWidget *parent = nullptr); + SpkWindow(QWidget *parent = nullptr, Qt::WindowFlags flags = Qt::WindowFlags()); ~SpkWindow() override; void SetCentralWidget(QWidget *); bool GetUseTitleBar(); @@ -63,5 +62,3 @@ class SpkWindow : public QMainWindow private: void PopulateUi(); }; - -#endif //_SPKWINDOW_H_ diff --git a/inc/telemetry/collectid.h b/inc/telemetry/collectid.h new file mode 100644 index 0000000..32465f3 --- /dev/null +++ b/inc/telemetry/collectid.h @@ -0,0 +1,20 @@ + +#pragma once + +#include <QObject> +#include <QFile> + +namespace SpkTelemetry +{ + void FunCollectId() + { +#if !defined(NDEBUG) || !defined(SPARK_FORCE_TELEMETRY) // Debug builds shouldn't transmit telemetry data unless asked for + return; +#else + QFile idFile("/etc/machine-id"); + if(!idFile.open(QFile::ReadOnly)) + return; + auto machineId = idFile.readAll(); +#endif + } +} diff --git a/plugin/dtkplugin/CMakeLists.txt b/plugin/dtkplugin/CMakeLists.txt new file mode 100644 index 0000000..32fffb2 --- /dev/null +++ b/plugin/dtkplugin/CMakeLists.txt @@ -0,0 +1,14 @@ +set(PLUGIN_SOURCE + spkdtkplugin.h + spkdtkplugin_impl.h + spkdtkplugin.cpp) + +find_package(PkgConfig REQUIRED) +pkg_check_modules(dtkwidget REQUIRED IMPORTED_TARGET dtkwidget) +pkg_check_modules(dtkgui REQUIRED IMPORTED_TARGET dtkgui) +pkg_check_modules(dtkcore REQUIRED IMPORTED_TARGET dtkcore) +add_library(spkdtkplugin SHARED ${PLUGIN_SOURCE}) + +target_link_libraries(spkdtkplugin PkgConfig::dtkwidget PkgConfig::dtkgui PkgConfig::dtkcore ${REQUIRED_LIBS_QUALIFIED}) + +install(TARGETS spkdtkplugin LIBRARY DESTINATION lib) diff --git a/plugin/dtkplugin/spkdtkplugin.cpp b/plugin/dtkplugin/spkdtkplugin.cpp new file mode 100644 index 0000000..d9891fe --- /dev/null +++ b/plugin/dtkplugin/spkdtkplugin.cpp @@ -0,0 +1,11 @@ +#include <DGuiApplicationHelper> +#include <DPlatformWindowHandle> +#include "spkdtkplugin_impl.h" + +using Dtk::Widget::DPlatformWindowHandle; + +void SpkDtkPluginImpl::addWindow(QWidget *w, QObject *parent) +{ + DPlatformWindowHandle *h = new DPlatformWindowHandle(w, parent); + Q_UNUSED(h); +} diff --git a/plugin/dtkplugin/spkdtkplugin.h b/plugin/dtkplugin/spkdtkplugin.h new file mode 100644 index 0000000..8929b73 --- /dev/null +++ b/plugin/dtkplugin/spkdtkplugin.h @@ -0,0 +1,15 @@ + +#pragma once + +#include <QWidget> + +class SpkDtkPlugin +{ + public: + virtual ~SpkDtkPlugin() = default; + + virtual void addWindow(QWidget* w, QObject* parent) = 0; +}; +QT_BEGIN_NAMESPACE +Q_DECLARE_INTERFACE(SpkDtkPlugin, "org.spark-store.client.dtkplugin") +QT_END_NAMESPACE diff --git a/plugin/dtkplugin/spkdtkplugin_impl.h b/plugin/dtkplugin/spkdtkplugin_impl.h new file mode 100644 index 0000000..9bbe7aa --- /dev/null +++ b/plugin/dtkplugin/spkdtkplugin_impl.h @@ -0,0 +1,16 @@ + +#pragma once + +#include <QWidget> +#include <QtPlugin> +#include "spkdtkplugin.h" + +class SpkDtkPluginImpl : public QObject, SpkDtkPlugin +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "org.spark-store.client.dtkplugin") + Q_INTERFACES(SpkDtkPlugin) + + public: + void addWindow(QWidget* w, QObject* parent) override; +}; diff --git a/src/gitver.cpp.in b/src/gitver.cpp.in new file mode 100644 index 0000000..70f3508 --- /dev/null +++ b/src/gitver.cpp.in @@ -0,0 +1,15 @@ + +#include "gitver.h" + +namespace GitVer +{ + const char *DescribeTags() + { + return "@GIT_DESCRIBE@"; + } + + const char *CommitDate() + { + return "@GIT_COMMIT_DATE_ISO8601@"; + } +} diff --git a/src/main.cpp b/src/main.cpp index d946514..3fa170d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -16,7 +16,7 @@ int main (int argc, char *argv[]) SpkStore store(false, LogPath); - //*((int*)0) = 0; + SpkMsgBox::StaticExec("E", "F"); return QApplication::exec(); } diff --git a/src/spkstore.cpp b/src/spkstore.cpp index fe58654..d4dce8c 100644 --- a/src/spkstore.cpp +++ b/src/spkstore.cpp @@ -1,19 +1,26 @@ #include <spkui_general.h> +#include "dtk/spkdtkplugin.h" +#include <QPluginLoader> +#include <QDir> +#include <QApplication> #include "spkstore.h" +SpkStore *SpkStore::Instance = nullptr; + SpkStore::SpkStore(bool aCli, QString &aLogPath) { mLogger = new SpkLogger(aLogPath); + Q_ASSERT(Instance == nullptr); Instance = this; if(aCli) return; SpkUi::Initialize(); - mMainWindow = new SpkMainWindow; + mMainWindow->show(); }