Compare commits

...

7 Commits

Author SHA1 Message Date
b15d692a0e spellchecker: fix codec segfault
Fix the segfault happening when a codec is not properly loaded by
only activated spellcheck when a dictionnary has been successfully
loaded, initializing a default codec and adding error handling.

GitLab: #2063

Change-Id: I48339ce6d13120cfbae3c6c7eb6f40e87f16f084
2025-06-13 16:03:38 -04:00
e76bcbd555 versioning: add build version to debian packaging
GitLab: #2045
Change-Id: If0f8e2fef4ed38ae9cd4238bb725158526d24658
2025-06-13 10:21:43 -04:00
b5a979e6b1 versioning: add build version propagation for unix packaging system
The application on linux systems currently has a different build version
built into it than the build version generated on Jenkins which dictates
the filenames for release packages. This commit aims to propagate a
build version defined in the gnu-linux Jenkinsfile down to the
build-package-*.sh scripts.

Changes:
- create build version (timestamp) in Jenkinsfile
- propagate build version to Makefile, then the docker containers that
will execute the build-package-*.sh scripts

GitLab: #2045
Change-Id: Ia7cbb2f707c233741039dc7bfd3e5bd6a96c2270
2025-06-12 13:32:03 -04:00
898444dd3c versioning: add build version as windows build argument
The application currently has a different build version than the one set
in Jenkins. This causes issues in the crash reports on windows where
they contain a different build version than the one defined on Jenkins.
This leads to the names of the build artifacts on dl.jami.net not
matching the crash report's build version.

Changes:
- Add build version as parameter to the build-windows.py script.
- Propagate build version value to the application through the
BUILD_VERSION symbol.
- Deprecate version.h file and VERSION_STRING symbol.

GitLab: #2045
Change-Id: I7986679aaeebf2bcbbd63a781499f5a50e089712
2025-06-12 13:31:59 -04:00
99f246016d cmake : fix output directory for windows builds
The output directory for windows builds currently matches either Release
or Beta. This does not work as Beta is only a build option, not a build
type. Changes :

- Change build output directory to match the cmake build type (Release
or Debug)
- Change Beta output path references to Release

Change-Id: Ib513f177d93e3c9fb529e00aa160443ac2e804b5
2025-06-12 13:31:54 -04:00
e24f3d91e8 spellchecker: fix greek
greek spell correction wasn't working. this is because  modern greek
is in a special encoding : ISO8859-7. The text in Jami is in utf-8.
Therefore this patch detect the encoding and decode/encode informations
in the relevent encoding between the client and the hunspell library.

GitLab: #2062
Change-Id: Ia33f154e3bf4b84f8337f669df81152ddcd25ec6
2025-06-10 10:29:11 -04:00
3a7850b398 theme: add dark mode support in keyboard shortcuts window
GitLab: #1891
Change-Id: I1e0746b00776564cc7ddbe12e4ad5665f037a092
2025-06-10 10:28:22 -04:00
22 changed files with 87 additions and 124 deletions

View File

@ -84,10 +84,8 @@ if(WIN32)
if(BETA)
message(STATUS "Beta config enabled")
add_definitions(-DBETA)
set(JAMI_OUTPUT_DIRECTORY_RELEASE ${PROJECT_SOURCE_DIR}/x64/Beta)
else()
set(JAMI_OUTPUT_DIRECTORY_RELEASE ${PROJECT_SOURCE_DIR}/x64/Release)
endif()
set(JAMI_OUTPUT_DIRECTORY_RELEASE ${PROJECT_SOURCE_DIR}/x64/${CMAKE_BUILD_TYPE})
endif()
if(WIN32)
@ -266,6 +264,7 @@ add_custom_target(
-DAPP_BINARY_DIR=${CMAKE_CURRENT_BINARY_DIR}
-DCORE_SOURCE_DIR=${DAEMON_DIR}
-DCPP_INT_FILE=${VERSION_INFO_DIR}/version_info.cpp.in
-DBUILD_VERSION=${BUILD_VERSION}
-P ${CMAKE_SCRIPTS_DIR}/generate_version_info.cmake
)
list(APPEND CLIENT_INCLUDE_DIRS ${VERSION_INFO_DIR})
@ -379,7 +378,6 @@ set(COMMON_HEADERS
${APP_SRC_DIR}/appversionmanager.h
${APP_SRC_DIR}/utils.h
${APP_SRC_DIR}/bannedlistmodel.h
${APP_SRC_DIR}/version.h
${APP_SRC_DIR}/accountlistmodel.h
${APP_SRC_DIR}/instancemanager.h
${APP_SRC_DIR}/connectivitymonitor.h

View File

@ -4,10 +4,5 @@
<?define ExeName="Jami" ?>
<?define AppName="Jami" ?>
<?define Manufacturer="Savoir-Faire Linux"?>
<?if $(var.Configuration) = Release ?>
<?define ReleaseDir="..\x64\Release"?>
<?else?>
<?define ReleaseDir="..\x64\Beta"?>
<?endif ?>
</Include>

View File

@ -16,9 +16,9 @@
<InstallerPlatform>x64</InstallerPlatform>
<DefineSolutionProperties>false</DefineSolutionProperties>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' ">
<OutputPath>bin\$(Configuration)\</OutputPath>
<IntermediateOutputPath>obj\$(Configuration)\</IntermediateOutputPath>
<PropertyGroup>
<OutputPath>bin\Release\</OutputPath>
<IntermediateOutputPath>obj\Release\</IntermediateOutputPath>
<DefineConstants>AppHarvestPath=..\x64\Release;CrtHarvestPath=$(VC_CRT_Dir)</DefineConstants>
<SuppressPdbOutput>True</SuppressPdbOutput>
<CompilerAdditionalOptions>
@ -26,16 +26,6 @@
<WixVariables>
</WixVariables>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Beta|x64' ">
<OutputPath>bin\$(Configuration)\</OutputPath>
<IntermediateOutputPath>obj\$(Configuration)\</IntermediateOutputPath>
<DefineConstants>AppHarvestPath=..\x64\Beta;CrtHarvestPath=$(VC_CRT_Dir)</DefineConstants>
<SuppressPdbOutput>True</SuppressPdbOutput>
<CompilerAdditionalOptions>
</CompilerAdditionalOptions>
<WixVariables>
</WixVariables>
</PropertyGroup>
<ItemGroup>
<Compile Include="Product.wxs" />
<Compile Include="AppComponents.wxs" />
@ -70,7 +60,7 @@
<Error Text="The WiX Toolset v3.11 (or newer) build tools must be installed to build this project. To download the WiX Toolset, see http://wixtoolset.org/releases/" />
</Target>
<Target Name="BeforeBuild">
<HeatDirectory Directory="..\x64\$(Configuration)"
<HeatDirectory Directory="..\x64\Release"
PreprocessorVariable="var.AppHarvestPath"
OutputFile="AppComponents.wxs"
ComponentGroupName="AppHeatGenerated"

View File

@ -24,6 +24,7 @@ set(CMAKE_CURRENT_BINARY_DIR ${APP_BINARY_DIR})
# Generate the version string for the application and core
configure_version_string(${APP_SOURCE_DIR} APP_VERSION_STRING)
configure_version_string(${CORE_SOURCE_DIR} CORE_VERSION_STRING)
set(BUILD_VERSION_STRING ${BUILD_VERSION})
# Get output file names with the .in extension removed
get_filename_component(VERSION_CPP_FILENAME ${CPP_INT_FILE} NAME_WE)

View File

@ -85,6 +85,10 @@ pipeline {
environment {
TARBALLS = '/var/cache/jami' // set the cache directory
BUILD_VERSION = sh(
returnStdout: true,
script: 'date +"%Y%m%d%H%M"'
).trim()
}
stages {

View File

@ -194,6 +194,7 @@ $(1)-docker-image-name := jami-packaging-$(1)
$(1)-docker-image-file := .docker-image-$$($(1)-docker-image-name)
$(1)-docker-run-command := docker run \
--rm --privileged --security-opt apparmor=docker-default \
-e BUILD_VERSION=${BUILD_VERSION} \
-e RELEASE_VERSION="$(RELEASE_VERSION)" \
-e RELEASE_DIRNAME="$(RELEASE_DIRNAME)" \
-e RELEASE_TARBALL_FILENAME="$(RELEASE_TARBALL_FILENAME)" \

View File

@ -91,6 +91,7 @@ override_dh_auto_build:
mkdir build && \
cd build && \
cmake \
-DBUILD_VERSION=$(BUILD_VERSION) \
-DCMAKE_INSTALL_PREFIX=/usr \
-DLIBJAMI_BUILD_DIR=$(CURDIR)/daemon/src \
-DENABLE_LIBWRAP=true \

View File

@ -263,7 +263,7 @@ def cmake_build(config_str, env_vars, cmake_build_dir):
return True
def build(config_str, qt_dir, tests, enable_crash_reports, crash_report_url=None):
def build(config_str, qt_dir, tests, build_version, enable_crash_reports, crash_report_url=None):
"""Use cmake to build the project."""
print("Building with Qt at " + qt_dir)
@ -294,6 +294,9 @@ def build(config_str, qt_dir, tests, enable_crash_reports, crash_report_url=None
else:
cmake_options.append("-DENABLE_CRASHREPORTS=OFF")
if build_version:
cmake_options.append("-DBUILD_VERSION=" + build_version)
# Make sure the build directory exists.
if not os.path.exists(build_dir):
os.makedirs(build_dir)
@ -307,11 +310,11 @@ def build(config_str, qt_dir, tests, enable_crash_reports, crash_report_url=None
sys.exit(1)
def deploy_runtimes(config_str, qt_dir):
def deploy_runtimes(qt_dir):
"""Deploy the dependencies to the runtime directory."""
print("Deploying runtime dependencies")
runtime_dir = os.path.join(repo_root_dir, "x64", config_str)
runtime_dir = os.path.join(repo_root_dir, "x64", "Release")
stamp_file = os.path.join(runtime_dir, ".deploy.stamp")
if os.path.exists(stamp_file):
return
@ -470,6 +473,8 @@ def parse_args():
help='Sets the Qt root path')
parser.add_argument(
"-a", "--arch", default="x64", help="Sets the build architecture")
parser.add_argument(
"--build-version", help="Sets the build version string used for defining app build version")
parser.add_argument(
"-t", "--tests", action="store_true", help="Build and run tests")
parser.add_argument(
@ -552,10 +557,11 @@ def main():
def do_build(do_tests):
if not parsed_args.skip_build:
build(config_str, parsed_args.qt, do_tests,
parsed_args.build_version,
parsed_args.enable_crash_reports,
parsed_args.crash_report_url)
if not parsed_args.skip_deploy:
deploy_runtimes(config_str, parsed_args.qt)
deploy_runtimes(parsed_args.qt)
if parsed_args.subcommand == "pack":
do_build(False)

View File

@ -18,7 +18,7 @@
#include "appversionmanager.h"
#include "lrcinstance.h"
#include "version.h"
#include "version_info.h"
#include <QProcess>
#include <QTimer>
@ -73,7 +73,7 @@ struct AppVersionManager::Impl : public QObject
Q_EMIT parent_.updateCheckReplyReceived(false);
return;
}
auto currentVersion = QString(VERSION_STRING).toULongLong();
auto currentVersion = BUILD_VERSION_STRING.toULongLong();
auto latestVersion = latestVersionString.toULongLong();
const QString channelStr = isBeta ? "beta" : "stable";
const auto newVersionFound = latestVersion > currentVersion;

View File

@ -17,7 +17,6 @@
#pragma once
#include "version.h"
#include "version_info.h"
#include <QVariantMap>
@ -108,7 +107,7 @@ protected:
{"platform", QSysInfo::prettyProductName() + "_" + QSysInfo::currentCpuArchitecture()},
{"client_sha", APP_VERSION_STRING},
{"jamicore_sha", CORE_VERSION_STRING},
{"build_id", QString(VERSION_STRING)},
{"build_id", BUILD_VERSION_STRING},
#if defined(Q_OS_WIN) && defined(BETA)
{"build_variant", "beta"},
#endif

View File

@ -17,7 +17,7 @@
#include "mainapplication.h"
#include "instancemanager.h"
#include "version.h"
#include "version_info.h"
#if defined(Q_OS_MACOS)
#include <os/macos/macutils.h>
#endif
@ -66,7 +66,7 @@ main(int argc, char* argv[])
QApplication::setApplicationName(QStringLiteral("Jami"));
QApplication::setOrganizationDomain(QStringLiteral("jami.net"));
QApplication::setQuitOnLastWindowClosed(false);
QCoreApplication::setApplicationVersion(QString(VERSION_STRING));
QCoreApplication::setApplicationVersion(BUILD_VERSION_STRING);
QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts, true);
QApplication::setHighDpiScaleFactorRoundingPolicy(
Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);

View File

@ -228,6 +228,11 @@ Window {
anchors.fill: parent
background: Rectangle {
anchors.fill: parent
color: JamiTheme.backgroundColor
}
// make a list view of keyboardShortcutsModelList[selectionBar.currentIndex]
JamiListView {
id: keyboardShortcutsListView
@ -262,6 +267,7 @@ Window {
Layout.topMargin: 8
Layout.leftMargin: 20
text: description
color: JamiTheme.textColor
background: Rectangle {
width: parent.width + 16
height: parent.height + 16
@ -269,6 +275,7 @@ Window {
border.width: 2
radius: 5
anchors.centerIn: parent
color: JamiTheme.backgroundColor
}
}
Label {
@ -277,6 +284,7 @@ Window {
Layout.topMargin: 8
Layout.rightMargin: 20
text: shortcut
color: JamiTheme.textColor
background: Rectangle {
width: parent.width + 16
height: parent.height + 16
@ -284,6 +292,7 @@ Window {
border.width: 2
radius: 5
anchors.centerIn: parent
color: JamiTheme.backgroundColor
}
}
}
@ -300,6 +309,10 @@ Window {
focus: true
background: Rectangle {
color: JamiTheme.backgroundColor
}
Repeater {
model: [JamiStrings.generalSettingsTitle, JamiStrings.conversationKeyboardShortcuts, JamiStrings.callKeyboardShortcuts, JamiStrings.markdownKeyboardShortcuts, JamiStrings.settings]
@ -339,9 +352,16 @@ Window {
footer: Item {
height: JamiTheme.keyboardShortcutTabBarSize
PageIndicator {
id: pageIndicator
anchors.centerIn: parent
count: selectionBar.count
currentIndex: selectionBar.currentIndex
delegate: Rectangle {
width: 6
height: 6
radius: 3
color: index === pageIndicator.currentIndex ? JamiTheme.textColor : JamiTheme.textColorHoveredHighContrast
}
}
}
}

View File

@ -113,9 +113,7 @@ JamiFlickable {
}
}
readonly property bool spellCheckEnabled:
AppSettingsManager.getValue(Settings.EnableSpellCheck) &&
AppSettingsManager.getValue(Settings.SpellLang) !== ""
property bool spellCheckEnabled: AppSettingsManager.getValue(Settings.EnableSpellCheck) && AppSettingsManager.getValue(Settings.SpellLang) !== ""
// Spell check is active under the following conditions:
// 1. Spell check is enabled in settings
@ -192,7 +190,7 @@ JamiFlickable {
onReleased: function (event) {
if (event.button === Qt.RightButton) {
if (spellCheckActive) {
if (spellCheckActive && SpellCheckAdapter.hasLoadedDictionary) {
var position = textArea.positionAt(event.x, event.y);
textArea.moveCursorSelection(position, TextInput.SelectWords);
textArea.selectWord();
@ -254,7 +252,7 @@ JamiFlickable {
function updateSpellCorrection() {
clearUnderlines();
// We iterate over the whole text to find words to check and underline them if needed
if (spellCheckActive) {
if (spellCheckActive && SpellCheckAdapter.hasLoadedDictionary) {
var text = textArea.text;
var words = SpellCheckAdapter.findWords(text);
if (!words)

View File

@ -83,6 +83,7 @@ Item {
property color editBackgroundColor: darkTheme ? "#373737" : lightGrey_
property color textColor: primaryForegroundColor
property color textColorHovered: darkTheme ? "#cccccc" : "#333333"
property color textColorHoveredHighContrast: darkTheme ? "#6a6a6a" : "#a7a7a7"
property color tabbarBorderColor: darkTheme ? blackColor : "#e3e3e3"
property color popupOverlayColor: darkTheme ? Qt.rgba(255, 255, 255, 0.22) : Qt.rgba(0, 0, 0, 0.33)
property real formsRadius: 30
@ -103,7 +104,7 @@ Item {
property color pressedButtonColor: darkTheme ? pressColor : "#a0a0a0"
property color hoveredButtonColor: darkTheme ? "#4d4d4d" : "#dedede"
property color hoveredButtonColorWizard: darkTheme ? "#4d4d4d" : "#dedede"
property color normalButtonColor: darkTheme ? backgroundColor : "#e0e0e0"
property color normalButtonColor: darkTheme ? "#bfbfbf" : "#e0e0e0"
property color invertedPressedButtonColor: Qt.rgba(0, 0, 0, 0.5)
property color invertedHoveredButtonColor: Qt.rgba(0, 0, 0, 0.6)

View File

@ -134,6 +134,9 @@ SpellCheckAdapter::setDictionary(const QString& locale)
auto localPath = dictionaryListModel_->pathForLocale(locale);
if (spellChecker_.replaceDictionary(localPath)) {
settingsManager_->setValue(Settings::Key::SpellLang, locale);
set_hasLoadedDictionary(true);
Q_EMIT dictionaryChanged();
} else {
qWarning() << "Failed to set dictionary for locale:" << locale;
}
}

View File

@ -33,6 +33,7 @@ class SpellCheckAdapter final : public QObject
QML_SINGLETON
QML_RO_PROPERTY(int, installedDictionaryCount)
QML_RO_PROPERTY(bool, hasLoadedDictionary)
public:
static SpellCheckAdapter* create(QQmlEngine* engine, QJSEngine*)

View File

@ -31,24 +31,28 @@
SpellChecker::SpellChecker()
: hunspell_(new Hunspell("", ""))
{}
{
// Initialize with default UTF-8 codec
codec_ = QTextCodec::codecForName("UTF-8");
}
bool
SpellChecker::spell(const QString& word)
{
// Encode from Unicode to the encoding used by current dictionary
return hunspell_->spell(word.toStdString()) != 0;
return hunspell_->spell(codec_->fromUnicode(word).toStdString()) != 0;
}
QStringList
SpellChecker::suggest(const QString& word)
{
// Encode from Unicode to the encoding used by current dictionary
std::vector<std::string> numSuggestions = hunspell_->suggest(word.toStdString());
std::vector<std::string> numSuggestions = hunspell_->suggest(
codec_->fromUnicode(word).constData());
QStringList suggestions;
for (size_t i = 0; i < numSuggestions.size(); ++i) {
suggestions << QString::fromStdString(numSuggestions.at(i));
for (const auto& suggestion : numSuggestions) {
suggestions << codec_->toUnicode(suggestion.c_str());
}
return suggestions;
}
@ -74,26 +78,26 @@ SpellChecker::replaceDictionary(const QString& dictionaryPath)
QString dictFile = dictionaryPath + ".dic";
QString affixFile = dictionaryPath + ".aff";
QByteArray dictFilePath = dictFile.toLocal8Bit();
QByteArray affixFilePath = affixFile.toLocal8Bit();
hunspell_.reset(new Hunspell(affixFilePath.constData(), dictFilePath.constData()));
// detect encoding analyzing the SET option in the affix file
encoding_ = "ISO8859-1";
QFile _affixFile(affixFile);
if (_affixFile.open(QIODevice::ReadOnly)) {
QTextStream stream(&_affixFile);
QRegExp enc_detector("^\\s*SET\\s+([A-Z0-9\\-]+)\\s*", Qt::CaseInsensitive);
for (QString line = stream.readLine(); !line.isEmpty(); line = stream.readLine()) {
if (enc_detector.indexIn(line) > -1) {
encoding_ = enc_detector.cap(1);
break;
}
}
_affixFile.close();
// Check if dictionary files exist
if (!QFile::exists(dictFile) || !QFile::exists(affixFile)) {
qWarning() << "Dictionary files not found:" << dictFile << affixFile;
return false;
}
codec_ = QTextCodec::codecForName(this->encoding_.toLatin1().constData());
QByteArray dictFilePath = dictFile.toLocal8Bit();
QByteArray affixFilePath = affixFile.toLocal8Bit();
std::unique_ptr<Hunspell> hunspell(
new Hunspell(affixFilePath.constData(), dictFilePath.constData()));
auto encoding = hunspell->get_dic_encoding();
auto codec = QTextCodec::codecForName(encoding);
if (!codec) {
return false;
}
hunspell_ = std::move(hunspell);
codec_ = codec;
currentDictionaryPath_ = dictionaryPath;
return true;
}

View File

@ -57,6 +57,5 @@ private:
std::unique_ptr<Hunspell> hunspell_;
QString currentDictionaryPath_;
QString encoding_;
QTextCodec* codec_;
};

View File

@ -20,7 +20,6 @@
#include "lrcinstance.h"
#include "systemtray.h"
#include "utils.h"
#include "version.h"
#include "version_info.h"
#include "global.h"
#include <api/datatransfermodel.h>
@ -128,7 +127,7 @@ UtilsAdapter::getProjectCredits()
const QString
UtilsAdapter::getBuildIDStr()
{
return QString(VERSION_STRING);
return BUILD_VERSION_STRING;
}
const QString

View File

@ -1,59 +0,0 @@
#pragma once
// clang-format off
#define BUILD_YEAR_CH0 (__DATE__[ 7])
#define BUILD_YEAR_CH1 (__DATE__[ 8])
#define BUILD_YEAR_CH2 (__DATE__[ 9])
#define BUILD_YEAR_CH3 (__DATE__[10])
#define BUILD_MONTH_IS_JAN (__DATE__[0] == 'J' && __DATE__[1] == 'a' && __DATE__[2] == 'n')
#define BUILD_MONTH_IS_FEB (__DATE__[0] == 'F')
#define BUILD_MONTH_IS_MAR (__DATE__[0] == 'M' && __DATE__[1] == 'a' && __DATE__[2] == 'r')
#define BUILD_MONTH_IS_APR (__DATE__[0] == 'A' && __DATE__[1] == 'p')
#define BUILD_MONTH_IS_MAY (__DATE__[0] == 'M' && __DATE__[1] == 'a' && __DATE__[2] == 'y')
#define BUILD_MONTH_IS_JUN (__DATE__[0] == 'J' && __DATE__[1] == 'u' && __DATE__[2] == 'n')
#define BUILD_MONTH_IS_JUL (__DATE__[0] == 'J' && __DATE__[1] == 'u' && __DATE__[2] == 'l')
#define BUILD_MONTH_IS_AUG (__DATE__[0] == 'A' && __DATE__[1] == 'u')
#define BUILD_MONTH_IS_SEP (__DATE__[0] == 'S')
#define BUILD_MONTH_IS_OCT (__DATE__[0] == 'O')
#define BUILD_MONTH_IS_NOV (__DATE__[0] == 'N')
#define BUILD_MONTH_IS_DEC (__DATE__[0] == 'D')
#define BUILD_MONTH_CH0 \
((BUILD_MONTH_IS_OCT || BUILD_MONTH_IS_NOV || BUILD_MONTH_IS_DEC) ? '1' : '0')
#define BUILD_MONTH_CH1 \
( \
(BUILD_MONTH_IS_JAN) ? '1' : \
(BUILD_MONTH_IS_FEB) ? '2' : \
(BUILD_MONTH_IS_MAR) ? '3' : \
(BUILD_MONTH_IS_APR) ? '4' : \
(BUILD_MONTH_IS_MAY) ? '5' : \
(BUILD_MONTH_IS_JUN) ? '6' : \
(BUILD_MONTH_IS_JUL) ? '7' : \
(BUILD_MONTH_IS_AUG) ? '8' : \
(BUILD_MONTH_IS_SEP) ? '9' : \
(BUILD_MONTH_IS_OCT) ? '0' : \
(BUILD_MONTH_IS_NOV) ? '1' : \
(BUILD_MONTH_IS_DEC) ? '2' : \
/* error default */ '?' \
)
#define BUILD_DAY_CH0 ((__DATE__[4] >= '0') ? (__DATE__[4]) : '0')
#define BUILD_DAY_CH1 (__DATE__[ 5])
#define BUILD_HOUR_CH0 (__TIME__[0])
#define BUILD_HOUR_CH1 (__TIME__[1])
#define BUILD_MIN_CH0 (__TIME__[ 3])
#define BUILD_MIN_CH1 (__TIME__[ 4])
const char VERSION_STRING[] = {
BUILD_YEAR_CH0, BUILD_YEAR_CH1, BUILD_YEAR_CH2, BUILD_YEAR_CH3,
BUILD_MONTH_CH0, BUILD_MONTH_CH1,
BUILD_DAY_CH0, BUILD_DAY_CH1,
BUILD_HOUR_CH0, BUILD_HOUR_CH1,
BUILD_MIN_CH0, BUILD_MIN_CH1,
'\0'
};
// clang-format on

View File

@ -1,4 +1,5 @@
#include "version_info.h"
const QString APP_VERSION_STRING = "@APP_VERSION_STRING@";
const QString CORE_VERSION_STRING = "@CORE_VERSION_STRING@";
const QString CORE_VERSION_STRING = "@CORE_VERSION_STRING@";
const QString BUILD_VERSION_STRING = "@BUILD_VERSION_STRING@";

View File

@ -4,3 +4,4 @@
extern const QString APP_VERSION_STRING;
extern const QString CORE_VERSION_STRING;
extern const QString BUILD_VERSION_STRING;