clang format file

This commit is contained in:
Martin Rotter 2022-04-09 09:12:22 +02:00
parent 0039367fc9
commit 3beb4a6c08
5 changed files with 392 additions and 608 deletions

192
.clang-format Normal file
View File

@ -0,0 +1,192 @@
---
Language: Cpp
# BasedOnStyle: LLVM
AccessModifierOffset: 0
AlignAfterOpenBracket: Align
AlignArrayOfStructures: None
AlignConsecutiveMacros: None
AlignConsecutiveAssignments: None
AlignConsecutiveBitFields: None
AlignConsecutiveDeclarations: None
AlignEscapedNewlines: Right
AlignOperands: Align
AlignTrailingComments: true
AllowAllArgumentsOnNextLine: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortEnumsOnASingleLine: true
AllowShortBlocksOnASingleLine: Never
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: All
AllowShortLambdasOnASingleLine: All
AllowShortIfStatementsOnASingleLine: Never
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: MultiLine
AttributeMacros:
- __capability
BinPackArguments: true
BinPackParameters: true
BraceWrapping:
AfterCaseLabel: false
AfterClass: false
AfterControlStatement: Never
AfterEnum: false
AfterFunction: false
AfterNamespace: false
AfterObjCDeclaration: false
AfterStruct: false
AfterUnion: false
AfterExternBlock: false
BeforeCatch: false
BeforeElse: false
BeforeLambdaBody: false
BeforeWhile: false
IndentBraces: false
SplitEmptyFunction: true
SplitEmptyRecord: true
SplitEmptyNamespace: true
BreakBeforeBinaryOperators: None
BreakBeforeConceptDeclarations: true
BreakBeforeBraces: Attach
BreakBeforeInheritanceComma: false
BreakInheritanceList: BeforeColon
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
BreakConstructorInitializers: BeforeColon
BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: true
ColumnLimit: 120
CommentPragmas: '^ IWYU pragma:'
QualifierAlignment: Leave
CompactNamespaces: false
ConstructorInitializerIndentWidth: 2
ContinuationIndentWidth: 2
Cpp11BracedListStyle: true
DeriveLineEnding: true
DerivePointerAlignment: false
DisableFormat: false
EmptyLineAfterAccessModifier: Never
EmptyLineBeforeAccessModifier: LogicalBlock
ExperimentalAutoDetectBinPacking: false
PackConstructorInitializers: BinPack
BasedOnStyle: ''
ConstructorInitializerAllOnOneLineOrOnePerLine: false
AllowAllConstructorInitializersOnNextLine: true
FixNamespaceComments: true
ForEachMacros:
- foreach
- Q_FOREACH
- BOOST_FOREACH
IfMacros:
- KJ_IF_MAYBE
IncludeBlocks: Preserve
IncludeCategories:
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
Priority: 2
SortPriority: 0
CaseSensitive: false
- Regex: '^(<|"(gtest|gmock|isl|json)/)'
Priority: 3
SortPriority: 0
CaseSensitive: false
- Regex: '.*'
Priority: 1
SortPriority: 0
CaseSensitive: false
IncludeIsMainRegex: '(Test)?$'
IncludeIsMainSourceRegex: ''
IndentAccessModifiers: false
IndentCaseLabels: false
IndentCaseBlocks: false
IndentGotoLabels: true
IndentPPDirectives: None
IndentExternBlock: AfterExternBlock
IndentRequires: false
IndentWidth: 2
IndentWrappedFunctionNames: false
InsertTrailingCommas: None
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: true
LambdaBodyIndentation: Signature
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ObjCBinPackProtocolList: Auto
ObjCBlockIndentWidth: 2
ObjCBreakBeforeNestedBlockParam: true
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
PenaltyBreakAssignment: 2
PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakOpenParenthesis: 0
PenaltyBreakString: 1000
PenaltyBreakTemplateDeclaration: 10
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 60
PenaltyIndentedWhitespace: 0
PointerAlignment: Right
PPIndentWidth: -1
ReferenceAlignment: Pointer
ReflowComments: true
RemoveBracesLLVM: false
SeparateDefinitionBlocks: Leave
ShortNamespaceLines: 1
SortIncludes: CaseSensitive
SortJavaStaticImport: Before
SortUsingDeclarations: true
SpaceAfterCStyleCast: false
SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true
SpaceBeforeCaseColon: false
SpaceBeforeCpp11BracedList: false
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: ControlStatements
SpaceBeforeParensOptions:
AfterControlStatements: true
AfterForeachMacros: true
AfterFunctionDefinitionName: false
AfterFunctionDeclarationName: false
AfterIfMacros: true
AfterOverloadedOperator: false
BeforeNonEmptyParentheses: false
SpaceAroundPointerQualifiers: Default
SpaceBeforeRangeBasedForLoopColon: true
SpaceInEmptyBlock: false
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: Never
SpacesInConditionalStatement: false
SpacesInContainerLiterals: true
SpacesInCStyleCastParentheses: false
SpacesInLineCommentPrefix:
Minimum: 1
Maximum: -1
SpacesInParentheses: false
SpacesInSquareBrackets: false
SpaceBeforeSquareBrackets: false
BitFieldColonSpacing: Both
Standard: Latest
StatementAttributeLikeMacros:
- Q_EMIT
StatementMacros:
- Q_UNUSED
- QT_REQUIRE_VERSION
TabWidth: 8
UseCRLF: false
UseTab: Never
WhitespaceSensitiveMacros:
- STRINGIZE
- PP_STRINGIZE
- BOOST_PP_STRINGIZE
- NS_SWIFT_NAME
- CF_SWIFT_NAME
...

View File

@ -100,9 +100,6 @@ if(${FORCE_COLORED_OUTPUT})
endif() endif()
endif() endif()
# Aux files not used for build but include in project.
add_custom_target(AuxFiles SOURCES "resources/scripts/uncrustify/uncrustify.cfg")
# Global compilation switches. # Global compilation switches.
option(BUILD_WITH_QT6 "Build application with Qt 6" OFF) option(BUILD_WITH_QT6 "Build application with Qt 6" OFF)
option(USE_WEBENGINE "Use QtWebEngine for embedded web browser" ON) option(USE_WEBENGINE "Use QtWebEngine for embedded web browser" ON)

View File

@ -1,297 +0,0 @@
## Qt.
set FOR foreach
set FOR forever
# SIGNAL/SLOT Qt macros have special formatting options. See options_for_QT.cpp for details.
# Default=True
use_options_overriding_for_qt_macros = true # false/true
## General.
newlines = auto # auto/lf/crlf/cr
# The original size of tabs in the input
input_tab_size = 2 # number
# The size of tabs in the output (only used if align_with_tabs=true)
output_tab_size = 2 # number
# Control what to do with the UTF-8 BOM (recommend 'remove')
utf8_bom = remove # ignore/add/remove/force
## Spaces.
# Add or remove space around arithmetic operator '+', '-', '/', '*', etc
# also '>>>' '<<' '>>' '%' '|'
sp_arith = force # ignore/add/remove/force
# Add or remove space around assignment operator '=', '+=', etc
sp_assign = force # ignore/add/remove/force
# Add or remove space after ','
sp_after_comma = force # ignore/add/remove/force
# Add or remove space around '=' in C++11 lambda capture specifications. Overrides sp_assign
sp_cpp_lambda_assign = remove # ignore/add/remove/force
# Add or remove space after the capture specification in C++11 lambda.
sp_cpp_lambda_square_paren = remove # ignore/add/remove/force
# Add or remove space around assignment operator '=' in a prototype
sp_assign_default = force # ignore/add/remove/force
# Add or remove space around assignment '=' in enum
sp_enum_assign = force # ignore/add/remove/force
# Add or remove space between ')' and '{' of function
sp_fparen_brace = force # ignore/add/remove/force
# Add or remove space before pointer star '*'
sp_before_ptr_star = remove # ignore/add/remove/force
# Add or remove space before pointer star '*' that isn't followed by a variable name
# If set to 'ignore', sp_before_ptr_star is used instead.
sp_before_unnamed_ptr_star = remove # ignore/add/remove/force
# Add or remove space between pointer stars '*'
sp_between_ptr_star = remove # ignore/add/remove/force
# Add or remove space after pointer star '*', if followed by a word.
sp_after_ptr_star = force # ignore/add/remove/force
# Add or remove space after pointer star '*', if followed by a qualifier.
sp_after_ptr_star_qualifier = force # ignore/add/remove/force
# Add or remove space after a pointer star '*', if followed by a func proto/def.
sp_after_ptr_star_func = force # ignore/add/remove/force
# Add or remove space after a pointer star '*', if followed by an open paren (function types).
sp_ptr_star_paren = force # ignore/add/remove/force
# Add or remove space before a pointer star '*', if followed by a func proto/def.
sp_before_ptr_star_func = remove # ignore/add/remove/force
# Add or remove space before a reference sign '&'
sp_before_byref = remove # ignore/add/remove/force
# Add or remove space before a reference sign '&' that isn't followed by a variable name
# If set to 'ignore', sp_before_byref is used instead.
sp_before_unnamed_byref = remove # ignore/add/remove/force
# Add or remove space after reference sign '&', if followed by a word.
sp_after_byref = force # ignore/add/remove/force
# Add or remove space after a reference sign '&', if followed by a func proto/def.
sp_after_byref_func = force # ignore/add/remove/force
# Add or remove space before a reference sign '&', if followed by a func proto/def.
sp_before_byref_func = remove # ignore/add/remove/force
# Add or remove space between '>' and '>' in '>>' (template stuff C++/C# only). Default=Add
sp_angle_shift = remove # ignore/add/remove/force
# Permit removal of the space between '>>' in 'foo<bar<int> >' (C++11 only). Default=False
# sp_angle_shift cannot remove the space without this option.
sp_permit_cpp11_shift = true # false/true
sp_after_type_brace_init_lst_open = force
sp_before_type_brace_init_lst_close = force
## Indents.
# The number of columns to indent per level.
# Usually 2, 3, 4, or 8. Default=8
indent_columns = 2 # unsigned number
# How to use tabs when indenting code
# 0=spaces only
# 1=indent with tabs to brace level, align with spaces (default)
# 2=indent and align with tabs, using spaces when not on a tabstop
indent_with_tabs = 0 # number
# Whether to indent strings broken by '\' so that they line up
indent_align_string = true # false/true
# Whether the 'namespace' body is indented
indent_namespace = true # false/true
# Whether the 'class' body is indented
indent_class = true # false/true
# Same as indent_label, but for access specifiers that are followed by a colon. Default=1
indent_access_spec = 2 # number
# Indent the code after an access specifier by one level.
# If set, this option forces 'indent_access_spec=0'
indent_access_spec_body = true # false/true
# Spaces to indent 'case' from 'switch'
# Usually 0 or indent_columns.
indent_switch_case = 2 # unsigned number
# indent the continuation of ternary operator.
# 0: (Default) off
# 1: When the `if_false` is a continuation, indent it under `if_false`
# 2: When the `:` is a continuation, indent it under `?`
indent_ternary_operator = 2 # unsigned number
## Newlines.
# Whether to collapse empty blocks between '{' and '}'
nl_collapse_empty_body = true # false/true
# Add or remove newlines at the start of the file
nl_start_of_file = remove # ignore/add/remove/force
# The number of blank lines after a block of variable definitions at the top of a function body
# 0 = No change (default)
nl_func_var_def_blk = 1 # unsigned number
# The number of newlines before a block of typedefs
# 0 = No change (default)
# the option 'nl_after_access_spec' takes preference over 'nl_typedef_blk_start'
nl_typedef_blk_start = 2 # unsigned number
# The number of newlines after a block of typedefs
# 0 = No change (default)
nl_typedef_blk_end = 2 # unsigned number
# The maximum consecutive newlines within a block of typedefs
# 0 = No change (default)
nl_typedef_blk_in = 2 # unsigned number
# The number of newlines after a block of variable definitions not at the top of a function body
# 0 = No change (default)
nl_var_def_blk_end = 2 # unsigned number
# The maximum consecutive newlines within a block of variable definitions
# 0 = No change (default)
nl_var_def_blk_in = 1 # unsigned number
# Add or remove newline between 'enum' and '{'
nl_enum_brace = remove # ignore/add/remove/force
# Add or remove newline between 'enum' and 'class'
nl_enum_class = remove # ignore/add/remove/force
# Add or remove newline between 'enum class' and the identifier
nl_enum_class_identifier = remove # ignore/add/remove/force
# Add or remove newline between 'if' and '{'
nl_if_brace = remove # ignore/add/remove/force
# Add or remove newline between '}' and 'else'
nl_brace_else = force # ignore/add/remove/force
# Add or remove newline between 'else' and '{'
nl_else_brace = remove # ignore/add/remove/force
# Add or remove newline between 'else' and 'if'
nl_else_if = remove # ignore/add/remove/force
# Add or remove newline before 'if'/'else if' closing parenthesis
nl_before_if_closing_paren = remove # ignore/add/remove/force
# Whether to put a newline after 'case' statement
nl_after_case = false # false/true
# Whether to put a newline before 'case' statement, not after the first 'case'
nl_before_case = true # false/true
# Whether to remove blanks after '#ifxx' and '#elxx', or before '#elxx' and '#endif'. Does not affect top-level #ifdefs.
nl_squeeze_ifdef = true # false/true
# Add or remove blank line after 'if' statement.
# Add/Force work only if the next token is not a closing brace
nl_after_if = force # ignore/add/remove/force
# Add or remove blank line after 'for' statement
nl_after_for = force # ignore/add/remove/force
# Add or remove blank line after 'while' statement
nl_after_while = force # ignore/add/remove/force
# Add or remove blank line after 'switch' statement
nl_after_switch = force # ignore/add/remove/force
# Add or remove blank line after 'do/while' statement
nl_after_do = force # ignore/add/remove/force
## Blank line options
# The maximum consecutive newlines (3 = 2 blank lines)
nl_max = 2 # unsigned number
# The minimum number of newlines before a multi-line comment.
# Doesn't apply if after a brace open or another multi-line comment.
nl_before_block_comment = 2 # unsigned number
# The minimum number of newlines before a single-line C comment.
# Doesn't apply if after a brace open or other single-line C comments.
nl_before_c_comment = 2 # unsigned number
# The minimum number of newlines before a CPP comment.
# Doesn't apply if after a brace open or other CPP comments.
nl_before_cpp_comment = 2 # unsigned number
# The number of newlines before a class definition
nl_before_class = 0 # unsigned number
# The number of newlines after '}' or ';' of a class definition
nl_after_class = 2 # unsigned number
# The number of newlines after '}' or ';' of a struct/enum/union definition.
nl_after_struct = 2 # unsigned number
# The number of newlines after '}' of a multi-line function body
nl_after_func_body = 2 # unsigned number
# The number of newlines after '}' of a multi-line function body in a class declaration
nl_after_func_body_class = 2 # unsigned number
# The number of newlines after '}' of a single line function body
nl_after_func_body_one_liner = 2 # unsigned number
# The number of newlines before a 'private:', 'public:', 'protected:', 'signals:', or 'slots:' label.
# Will not change the newline count if after a brace open.
# 0 = No change.
nl_before_access_spec = 2 # unsigned number
# The number of newlines after a try-catch-finally block that isn't followed by a brace close.
# 0 = No change.
nl_after_try_catch_finally = 2 # unsigned number
# How aggressively to remove extra newlines not in preproc.
# 0: No change
# 1: Remove most newlines not handled by other config
# 2: Remove all newlines and reformat completely by config
nl_remove_extra_newlines = 0 # unsigned number
## Splitting.
# Try to limit code width to N number of columns
code_width = 160 # unsigned number
# Whether to fully split long function protos/calls at commas
ls_func_split_full = true # false/true
## Comments.
# Set the comment reflow mode (Default=0)
# 0: no reflowing (apart from the line wrapping due to cmt_width)
# 1: no touching at all
# 2: full reflow
cmt_reflow_mode = 2 # number
# Whether to convert all tabs to spaces in comments. Default is to leave tabs inside comments alone, unless used for indenting.
cmt_convert_tab_to_spaces = true # false/true
# Whether to group c-comments that look like they are in a block
cmt_c_group = true # false/true
## Modifications.
# If True, will sort consecutive single-line '#include' statements [C/C++] and '#import' statements [Obj-C]
# This is generally a bad idea, as it may break your code.
mod_sort_include = true # false/true

View File

@ -62,8 +62,8 @@
#endif #endif
#endif #endif
Application::Application(const QString& id, int& argc, char** argv, const QStringList& raw_cli_args) Application::Application(const QString &id, int &argc, char **argv, const QStringList &raw_cli_args)
: SingleApplication(id, argc, argv), m_updateFeedsLock(new Mutex()) { : SingleApplication(id, argc, argv), m_updateFeedsLock(new Mutex()) {
parseCmdArgumentsFromMyInstance(raw_cli_args); parseCmdArgumentsFromMyInstance(raw_cli_args);
qInstallMessageHandler(performLogging); qInstallMessageHandler(performLogging);
@ -86,23 +86,17 @@ Application::Application(const QString& id, int& argc, char** argv, const QStrin
#if defined(Q_OS_WIN) #if defined(Q_OS_WIN)
m_windowsTaskBar = nullptr; m_windowsTaskBar = nullptr;
const GUID qIID_ITaskbarList4 = { 0xc43dc798, 0x95d1, 0x4bea, { 0x90, 0x30, 0xbb, 0x99, 0xe2, 0x98, 0x3a, 0x1a } }; const GUID qIID_ITaskbarList4 = {0xc43dc798, 0x95d1, 0x4bea, {0x90, 0x30, 0xbb, 0x99, 0xe2, 0x98, 0x3a, 0x1a}};
HRESULT task_result = CoCreateInstance(CLSID_TaskbarList, HRESULT task_result = CoCreateInstance(CLSID_TaskbarList, nullptr, CLSCTX_INPROC_SERVER, qIID_ITaskbarList4,
nullptr, reinterpret_cast<void **>(&m_windowsTaskBar));
CLSCTX_INPROC_SERVER,
qIID_ITaskbarList4,
reinterpret_cast<void**>(&m_windowsTaskBar));
if (FAILED(task_result)) { if (FAILED(task_result)) {
qCriticalNN << LOGSEC_CORE qCriticalNN << LOGSEC_CORE << "Taskbar integration for Windows failed to initialize with HRESULT:"
<< "Taskbar integration for Windows failed to initialize with HRESULT:"
<< QUOTE_W_SPACE_DOT(task_result); << QUOTE_W_SPACE_DOT(task_result);
m_windowsTaskBar = nullptr; m_windowsTaskBar = nullptr;
} } else if (FAILED(m_windowsTaskBar->HrInit())) {
else if (FAILED(m_windowsTaskBar->HrInit())) { qCriticalNN << LOGSEC_CORE << "Taskbar integration for Windows failed to initialize with inner HRESULT:"
qCriticalNN << LOGSEC_CORE
<< "Taskbar integration for Windows failed to initialize with inner HRESULT:"
<< QUOTE_W_SPACE_DOT(m_windowsTaskBar->HrInit()); << QUOTE_W_SPACE_DOT(m_windowsTaskBar->HrInit());
m_windowsTaskBar->Release(); m_windowsTaskBar->Release();
@ -138,10 +132,12 @@ Application::Application(const QString& id, int& argc, char** argv, const QStrin
if (!app_dir.isEmpty()) { if (!app_dir.isEmpty()) {
bool success = qputenv("GST_PLUGIN_SYSTEM_PATH_1_0", bool success = qputenv("GST_PLUGIN_SYSTEM_PATH_1_0",
QSL("%1/usr/lib/gstreamer-1.0:%2").arg(app_dir, QSL("%1/usr/lib/gstreamer-1.0:%2")
QString::fromLocal8Bit(qgetenv("GST_PLUGIN_SYSTEM_PATH_1_0"))).toLocal8Bit()); .arg(app_dir, QString::fromLocal8Bit(qgetenv("GST_PLUGIN_SYSTEM_PATH_1_0")))
.toLocal8Bit());
success = qputenv("GST_PLUGIN_SCANNER_1_0", success = qputenv("GST_PLUGIN_SCANNER_1_0",
QSL("%1/usr/lib/gstreamer1.0/gstreamer-1.0/gst-plugin-scanner").arg(app_dir).toLocal8Bit()) && success; QSL("%1/usr/lib/gstreamer1.0/gstreamer-1.0/gst-plugin-scanner").arg(app_dir).toLocal8Bit()) &&
success;
if (!success) { if (!success) {
qWarningNN << LOGSEC_CORE << "Unable to set up GStreamer environment."; qWarningNN << LOGSEC_CORE << "Unable to set up GStreamer environment.";
} }
@ -160,16 +156,17 @@ Application::Application(const QString& id, int& argc, char** argv, const QStrin
qDebugNN << LOGSEC_NETWORK << "Persistent web data storage path:" qDebugNN << LOGSEC_NETWORK << "Persistent web data storage path:"
<< QUOTE_W_SPACE_DOT(QWebEngineProfile::defaultProfile()->persistentStoragePath()); << QUOTE_W_SPACE_DOT(QWebEngineProfile::defaultProfile()->persistentStoragePath());
connect(QWebEngineProfile::defaultProfile(), &QWebEngineProfile::downloadRequested, this, &Application::downloadRequested); connect(QWebEngineProfile::defaultProfile(), &QWebEngineProfile::downloadRequested, this,
&Application::downloadRequested);
#endif #endif
connect(m_webFactory->adBlock(), &AdBlockManager::processTerminated, this, &Application::onAdBlockFailure); connect(m_webFactory->adBlock(), &AdBlockManager::processTerminated, this, &Application::onAdBlockFailure);
QTimer::singleShot(3000, this, [=]() { QTimer::singleShot(3000, this, [=]() {
try { try {
m_webFactory->adBlock()->setEnabled(qApp->settings()->value(GROUP(AdBlock), SETTING(AdBlock::AdBlockEnabled)).toBool()); m_webFactory->adBlock()->setEnabled(
} qApp->settings()->value(GROUP(AdBlock), SETTING(AdBlock::AdBlockEnabled)).toBool());
catch (...) { } catch (...) {
onAdBlockFailure(); onAdBlockFailure();
} }
}); });
@ -177,29 +174,23 @@ Application::Application(const QString& id, int& argc, char** argv, const QStrin
m_webFactory->updateProxy(); m_webFactory->updateProxy();
if (isFirstRun()) { if (isFirstRun()) {
m_notifications->save({ m_notifications->save({Notification(Notification::Event::GeneralEvent, true),
Notification(Notification::Event::GeneralEvent, true), Notification(Notification::Event::NewUnreadArticlesFetched, true,
Notification(Notification::Event::NewUnreadArticlesFetched, true, QSL("%1/notify.wav").arg(SOUNDS_BUILTIN_DIRECTORY)),
QSL("%1/notify.wav").arg(SOUNDS_BUILTIN_DIRECTORY)), Notification(Notification::Event::NewAppVersionAvailable, true),
Notification(Notification::Event::NewAppVersionAvailable, true), Notification(Notification::Event::LoginFailure, true),
Notification(Notification::Event::LoginFailure, true), Notification(Notification::Event::NodePackageUpdated, true),
Notification(Notification::Event::NodePackageUpdated, true), Notification(Notification::Event::NodePackageFailedToUpdate, true)},
Notification(Notification::Event::NodePackageFailedToUpdate, true) settings());
}, settings()); } else {
}
else {
m_notifications->load(settings()); m_notifications->load(settings());
} }
QTimer::singleShot(1000, system(), &SystemFactory::checkForUpdatesOnStartup); QTimer::singleShot(1000, system(), &SystemFactory::checkForUpdatesOnStartup);
qDebugNN << LOGSEC_CORE qDebugNN << LOGSEC_CORE << "OpenSSL version:" << QUOTE_W_SPACE_DOT(QSslSocket::sslLibraryVersionString());
<< "OpenSSL version:"
<< QUOTE_W_SPACE_DOT(QSslSocket::sslLibraryVersionString());
qDebugNN << LOGSEC_CORE qDebugNN << LOGSEC_CORE << "OpenSSL supported:" << QUOTE_W_SPACE_DOT(QSslSocket::supportsSsl());
<< "OpenSSL supported:"
<< QUOTE_W_SPACE_DOT(QSslSocket::supportsSsl());
} }
Application::~Application() { Application::~Application() {
@ -215,7 +206,7 @@ Application::~Application() {
QString s_customLogFile = QString(); QString s_customLogFile = QString();
bool s_disableDebug = false; bool s_disableDebug = false;
void Application::performLogging(QtMsgType type, const QMessageLogContext& context, const QString& msg) { void Application::performLogging(QtMsgType type, const QMessageLogContext &context, const QString &msg) {
#ifndef QT_NO_DEBUG_OUTPUT #ifndef QT_NO_DEBUG_OUTPUT
QString console_message = qFormatLogMessage(type, context, msg); QString console_message = qFormatLogMessage(type, context, msg);
@ -250,27 +241,23 @@ void Application::reactOnForeignNotifications() {
void Application::hideOrShowMainForm() { void Application::hideOrShowMainForm() {
// Display main window. // Display main window.
if (qApp->settings()->value(GROUP(GUI), SETTING(GUI::MainWindowStartsHidden)).toBool() && if (qApp->settings()->value(GROUP(GUI), SETTING(GUI::MainWindowStartsHidden)).toBool() &&
SystemTrayIcon::isSystemTrayDesired() && SystemTrayIcon::isSystemTrayDesired() && SystemTrayIcon::isSystemTrayAreaAvailable()) {
SystemTrayIcon::isSystemTrayAreaAvailable()) {
qDebugNN << LOGSEC_CORE << "Hiding the main window when the application is starting."; qDebugNN << LOGSEC_CORE << "Hiding the main window when the application is starting.";
mainForm()->switchVisibility(true); mainForm()->switchVisibility(true);
} } else {
else {
qDebugNN << LOGSEC_CORE << "Showing the main window when the application is starting."; qDebugNN << LOGSEC_CORE << "Showing the main window when the application is starting.";
mainForm()->show(); mainForm()->show();
} }
} }
void Application::loadDynamicShortcuts() { void Application::loadDynamicShortcuts() { DynamicShortcuts::load(userActions()); }
DynamicShortcuts::load(userActions());
}
void Application::showPolls() const { void Application::showPolls() const {
/* /*
if(isFirstRunCurrentVersion()) { if(isFirstRunCurrentVersion()) {
qApp->showGuiMessage(Notification::Event::GeneralEvent, qApp->showGuiMessage(Notification::Event::GeneralEvent,
{ QSL("%1 survey").arg(QSL(APP_NAME)), QSL("Please, fill the survey."), QSystemTrayIcon::MessageIcon::Warning }, { QSL("%1 survey").arg(QSL(APP_NAME)), QSL("Please, fill the survey."),
{ false, true, false }); QSystemTrayIcon::MessageIcon::Warning }, { false, true, false });
qApp->web()->openUrlInExternalBrowser(QSL("https://forms.gle/9GgSa38Awqr37xLV8")); qApp->web()->openUrlInExternalBrowser(QSL("https://forms.gle/9GgSa38Awqr37xLV8"));
} }
*/ */
@ -278,40 +265,34 @@ void Application::showPolls() const {
void Application::offerChanges() const { void Application::offerChanges() const {
if (isFirstRunCurrentVersion()) { if (isFirstRunCurrentVersion()) {
qApp->showGuiMessage(Notification::Event::GeneralEvent, { qApp->showGuiMessage(Notification::Event::GeneralEvent,
tr("Welcome"), {tr("Welcome"),
tr("Welcome to %1.\n\nPlease, check NEW stuff included in this\n" tr("Welcome to %1.\n\nPlease, check NEW stuff included in this\n"
"version by clicking this popup notification.").arg(QSL(APP_LONG_NAME)), "version by clicking this popup notification.")
QSystemTrayIcon::MessageIcon::NoIcon }, .arg(QSL(APP_LONG_NAME)),
{}, QSystemTrayIcon::MessageIcon::NoIcon},
{ tr("Go to changelog"), [] { {}, {tr("Go to changelog"), [] { FormAbout(qApp->mainForm()).exec(); }});
FormAbout(qApp->mainForm()).exec();
} });
} }
} }
bool Application::isAlreadyRunning() { bool Application::isAlreadyRunning() {
return m_allowMultipleInstances return m_allowMultipleInstances
? false ? false
: sendMessage((QStringList() << QSL("-%1").arg(QSL(CLI_IS_RUNNING)) : sendMessage((QStringList() << QSL("-%1").arg(QSL(CLI_IS_RUNNING)) << Application::arguments().mid(1))
<< Application::arguments().mid(1)).join(QSL(ARGUMENTS_LIST_SEPARATOR))); .join(QSL(ARGUMENTS_LIST_SEPARATOR)));
} }
QStringList Application::builtinSounds() const { QStringList Application::builtinSounds() const {
auto builtin_sounds = QDir(QSL(SOUNDS_BUILTIN_DIRECTORY)).entryInfoList(QDir::Filter::Files, QDir::SortFlag::Name); auto builtin_sounds = QDir(QSL(SOUNDS_BUILTIN_DIRECTORY)).entryInfoList(QDir::Filter::Files, QDir::SortFlag::Name);
auto iter = boolinq::from(builtin_sounds).select([](const QFileInfo& i) { auto iter = boolinq::from(builtin_sounds).select([](const QFileInfo &i) { return i.absoluteFilePath(); }).toStdList();
return i.absoluteFilePath();
}).toStdList();
auto descs = FROM_STD_LIST(QStringList, iter); auto descs = FROM_STD_LIST(QStringList, iter);
return descs; return descs;
} }
FeedReader* Application::feedReader() { FeedReader *Application::feedReader() { return m_feedReader; }
return m_feedReader;
}
QList<QAction*> Application::userActions() { QList<QAction *> Application::userActions() {
if (m_mainForm != nullptr && m_userActions.isEmpty()) { if (m_mainForm != nullptr && m_userActions.isEmpty()) {
m_userActions = m_mainForm->allActions(); m_userActions = m_mainForm->allActions();
m_userActions.append(m_webFactory->adBlock()->adBlockIcon()); m_userActions.append(m_webFactory->adBlock()->adBlockIcon());
@ -320,37 +301,21 @@ QList<QAction*> Application::userActions() {
return m_userActions; return m_userActions;
} }
bool Application::isFirstRun() const { bool Application::isFirstRun() const { return m_firstRunEver; }
return m_firstRunEver;
}
bool Application::isFirstRunCurrentVersion() const { bool Application::isFirstRunCurrentVersion() const { return m_firstRunCurrentVersion; }
return m_firstRunCurrentVersion;
}
QCommandLineParser* Application::cmdParser() { QCommandLineParser *Application::cmdParser() { return &m_cmdParser; }
return &m_cmdParser;
}
WebFactory* Application::web() const { WebFactory *Application::web() const { return m_webFactory; }
return m_webFactory;
}
SystemFactory* Application::system() { SystemFactory *Application::system() { return m_system; }
return m_system;
}
SkinFactory* Application::skins() { SkinFactory *Application::skins() { return m_skins; }
return m_skins;
}
Localization* Application::localization() { Localization *Application::localization() { return m_localization; }
return m_localization;
}
DatabaseFactory* Application::database() { DatabaseFactory *Application::database() { return m_database; }
return m_database;
}
void Application::eliminateFirstRuns() { void Application::eliminateFirstRuns() {
settings()->setValue(GROUP(General), General::FirstRun, false); settings()->setValue(GROUP(General), General::FirstRun, false);
@ -358,21 +323,15 @@ void Application::eliminateFirstRuns() {
} }
#if defined(USE_WEBENGINE) #if defined(USE_WEBENGINE)
bool Application::forcedNoWebEngine() const { bool Application::forcedNoWebEngine() const { return m_forcedNoWebEngine; }
return m_forcedNoWebEngine;
}
#endif #endif
NodeJs* Application::nodejs() const { NodeJs *Application::nodejs() const { return m_nodejs; }
return m_nodejs;
}
NotificationFactory* Application::notifications() const { NotificationFactory *Application::notifications() const { return m_notifications; }
return m_notifications;
}
void Application::setFeedReader(FeedReader* feed_reader) { void Application::setFeedReader(FeedReader *feed_reader) {
m_feedReader = feed_reader; m_feedReader = feed_reader;
connect(m_feedReader, &FeedReader::feedUpdatesStarted, this, &Application::onFeedUpdatesStarted); connect(m_feedReader, &FeedReader::feedUpdatesStarted, this, &Application::onFeedUpdatesStarted);
@ -381,39 +340,29 @@ void Application::setFeedReader(FeedReader* feed_reader) {
connect(m_feedReader->feedsModel(), &FeedsModel::messageCountsChanged, this, &Application::showMessagesNumber); connect(m_feedReader->feedsModel(), &FeedsModel::messageCountsChanged, this, &Application::showMessagesNumber);
} }
IconFactory* Application::icons() { IconFactory *Application::icons() { return m_icons; }
return m_icons;
}
DownloadManager* Application::downloadManager() { DownloadManager *Application::downloadManager() {
if (m_downloadManager == nullptr) { if (m_downloadManager == nullptr) {
m_downloadManager = new DownloadManager(); m_downloadManager = new DownloadManager();
connect(m_downloadManager, &DownloadManager::downloadFinished, mainForm()->statusBar(), &StatusBar::clearProgressDownload); connect(m_downloadManager, &DownloadManager::downloadFinished, mainForm()->statusBar(),
connect(m_downloadManager, &DownloadManager::downloadProgressed, mainForm()->statusBar(), &StatusBar::showProgressDownload); &StatusBar::clearProgressDownload);
connect(m_downloadManager, &DownloadManager::downloadProgressed, mainForm()->statusBar(),
&StatusBar::showProgressDownload);
} }
return m_downloadManager; return m_downloadManager;
} }
Settings* Application::settings() const { Settings *Application::settings() const { return m_settings; }
return m_settings;
}
Mutex* Application::feedUpdateLock() { Mutex *Application::feedUpdateLock() { return m_updateFeedsLock.data(); }
return m_updateFeedsLock.data();
}
FormMain* Application::mainForm() { FormMain *Application::mainForm() { return m_mainForm; }
return m_mainForm;
}
QWidget* Application::mainFormWidget() { QWidget *Application::mainFormWidget() { return m_mainForm; }
return m_mainForm;
}
void Application::setMainForm(FormMain* main_form) { void Application::setMainForm(FormMain *main_form) { m_mainForm = main_form; }
m_mainForm = main_form;
}
QString Application::configFolder() const { QString Application::configFolder() const {
return IOFactory::getSystemFolder(QStandardPaths::StandardLocation::GenericConfigLocation); return IOFactory::getSystemFolder(QStandardPaths::StandardLocation::GenericConfigLocation);
@ -428,11 +377,9 @@ QString Application::userDataAppFolder() const {
QString Application::userDataFolder() { QString Application::userDataFolder() {
if (settings()->type() == SettingsProperties::SettingsType::Custom) { if (settings()->type() == SettingsProperties::SettingsType::Custom) {
return customDataFolder(); return customDataFolder();
} } else if (settings()->type() == SettingsProperties::SettingsType::Portable) {
else if (settings()->type() == SettingsProperties::SettingsType::Portable) {
return userDataAppFolder(); return userDataAppFolder();
} } else {
else {
return userDataHomeFolder(); return userDataHomeFolder();
} }
} }
@ -451,7 +398,8 @@ QStringList Application::replaceDataUserDataFolderPlaceholder(QStringList texts)
QString Application::userDataHomeFolder() const { QString Application::userDataHomeFolder() const {
#if defined(Q_OS_ANDROID) #if defined(Q_OS_ANDROID)
return IOFactory::getSystemFolder(QStandardPaths::GenericDataLocation) + QDir::separator() + QSL(APP_NAME) + QSL(" 4"); return IOFactory::getSystemFolder(QStandardPaths::GenericDataLocation) + QDir::separator() + QSL(APP_NAME) +
QSL(" 4");
#else #else
return configFolder() + QDir::separator() + QSL(APP_NAME) + QSL(" 4"); return configFolder() + QDir::separator() + QSL(APP_NAME) + QSL(" 4");
#endif #endif
@ -473,8 +421,8 @@ QString Application::homeFolder() const {
#endif #endif
} }
void Application::backupDatabaseSettings(bool backup_database, bool backup_settings, void Application::backupDatabaseSettings(bool backup_database, bool backup_settings, const QString &target_path,
const QString& target_path, const QString& backup_name) { const QString &backup_name) {
if (!QFileInfo(target_path).isWritable()) { if (!QFileInfo(target_path).isWritable()) {
throw ApplicationException(tr("Output directory is not writable.")); throw ApplicationException(tr("Output directory is not writable."));
} }
@ -482,7 +430,8 @@ void Application::backupDatabaseSettings(bool backup_database, bool backup_setti
if (backup_settings) { if (backup_settings) {
settings()->sync(); settings()->sync();
if (!IOFactory::copyFile(settings()->fileName(), target_path + QDir::separator() + backup_name + BACKUP_SUFFIX_SETTINGS)) { if (!IOFactory::copyFile(settings()->fileName(),
target_path + QDir::separator() + backup_name + BACKUP_SUFFIX_SETTINGS)) {
throw ApplicationException(tr("Settings file not copied to output directory successfully.")); throw ApplicationException(tr("Settings file not copied to output directory successfully."));
} }
} }
@ -495,26 +444,28 @@ void Application::backupDatabaseSettings(bool backup_database, bool backup_setti
} }
void Application::restoreDatabaseSettings(bool restore_database, bool restore_settings, void Application::restoreDatabaseSettings(bool restore_database, bool restore_settings,
const QString& source_database_file_path, const QString& source_settings_file_path) { const QString &source_database_file_path,
const QString &source_settings_file_path) {
if (restore_database) { if (restore_database) {
if (!qApp->database()->driver()->initiateRestoration(source_database_file_path)) { if (!qApp->database()->driver()->initiateRestoration(source_database_file_path)) {
throw ApplicationException(tr("Database restoration was not initiated. Make sure that output directory is writable.")); throw ApplicationException(
tr("Database restoration was not initiated. Make sure that output directory is writable."));
} }
} }
if (restore_settings) { if (restore_settings) {
if (!qApp->settings()->initiateRestoration(source_settings_file_path)) { if (!qApp->settings()->initiateRestoration(source_settings_file_path)) {
throw ApplicationException(tr("Settings restoration was not initiated. Make sure that output directory is writable.")); throw ApplicationException(
tr("Settings restoration was not initiated. Make sure that output directory is writable."));
} }
} }
} }
SystemTrayIcon* Application::trayIcon() { SystemTrayIcon *Application::trayIcon() {
if (m_trayIcon == nullptr) { if (m_trayIcon == nullptr) {
if (qApp->settings()->value(GROUP(GUI), SETTING(GUI::MonochromeTrayIcon)).toBool()) { if (qApp->settings()->value(GROUP(GUI), SETTING(GUI::MonochromeTrayIcon)).toBool()) {
m_trayIcon = new SystemTrayIcon(APP_ICON_MONO_PATH, APP_ICON_MONO_PLAIN_PATH, m_mainForm); m_trayIcon = new SystemTrayIcon(APP_ICON_MONO_PATH, APP_ICON_MONO_PLAIN_PATH, m_mainForm);
} } else {
else {
m_trayIcon = new SystemTrayIcon(APP_ICON_PATH, APP_ICON_PLAIN_PATH, m_mainForm); m_trayIcon = new SystemTrayIcon(APP_ICON_PATH, APP_ICON_PLAIN_PATH, m_mainForm);
} }
@ -529,8 +480,7 @@ QIcon Application::desktopAwareIcon() const {
if (!from_theme.isNull()) { if (!from_theme.isNull()) {
return from_theme; return from_theme;
} } else {
else {
return QIcon(APP_ICON_PATH); return QIcon(APP_ICON_PATH);
} }
} }
@ -544,8 +494,7 @@ void Application::showTrayIcon() {
if (SystemTrayIcon::isSystemTrayAreaAvailable()) { if (SystemTrayIcon::isSystemTrayAreaAvailable()) {
qDebugNN << LOGSEC_GUI << "Tray icon is available, showing now."; qDebugNN << LOGSEC_GUI << "Tray icon is available, showing now.";
trayIcon()->show(); trayIcon()->show();
} } else {
else {
m_feedReader->feedsModel()->notifyWithCounts(); m_feedReader->feedsModel()->notifyWithCounts();
} }
#else #else
@ -555,14 +504,12 @@ void Application::showTrayIcon() {
if (SystemTrayIcon::isSystemTrayAreaAvailable()) { if (SystemTrayIcon::isSystemTrayAreaAvailable()) {
qWarningNN << LOGSEC_GUI << "Tray icon is available, showing now."; qWarningNN << LOGSEC_GUI << "Tray icon is available, showing now.";
trayIcon()->show(); trayIcon()->show();
} } else {
else {
m_feedReader->feedsModel()->notifyWithCounts(); m_feedReader->feedsModel()->notifyWithCounts();
} }
}); });
#endif #endif
} } else {
else {
m_feedReader->feedsModel()->notifyWithCounts(); m_feedReader->feedsModel()->notifyWithCounts();
} }
} }
@ -579,61 +526,48 @@ void Application::deleteTrayIcon() {
} }
} }
void Application::showGuiMessage(Notification::Event event, void Application::showGuiMessage(Notification::Event event, const GuiMessage &msg, const GuiMessageDestination &dest,
const GuiMessage& msg, const GuiAction &action, QWidget *parent) {
const GuiMessageDestination& dest,
const GuiAction& action,
QWidget* parent) {
if (SystemTrayIcon::areNotificationsEnabled()) { if (SystemTrayIcon::areNotificationsEnabled()) {
auto notification = m_notifications->notificationForEvent(event); auto notification = m_notifications->notificationForEvent(event);
notification.playSound(this); notification.playSound(this);
if (SystemTrayIcon::isSystemTrayDesired() && if (SystemTrayIcon::isSystemTrayDesired() && SystemTrayIcon::isSystemTrayAreaAvailable() &&
SystemTrayIcon::isSystemTrayAreaAvailable() && notification.balloonEnabled() && dest.m_tray) {
notification.balloonEnabled() && trayIcon()->showMessage(msg.m_title.simplified().isEmpty() ? Notification::nameForEvent(notification.event())
dest.m_tray) { : msg.m_title,
trayIcon()->showMessage(msg.m_title.simplified().isEmpty() msg.m_message, msg.m_type, TRAY_ICON_BUBBLE_TIMEOUT, std::move(action.m_action));
? Notification::nameForEvent(notification.event())
: msg.m_title,
msg.m_message,
msg.m_type,
TRAY_ICON_BUBBLE_TIMEOUT,
std::move(action.m_action));
return; return;
} }
} }
if (dest.m_messageBox || msg.m_type == QSystemTrayIcon::MessageIcon::Critical) { if (dest.m_messageBox || msg.m_type == QSystemTrayIcon::MessageIcon::Critical) {
// Tray icon or OSD is not available, display simple text box. // Tray icon or OSD is not available, display simple text box.
MsgBox::show(parent == nullptr ? mainFormWidget() : parent, MsgBox::show(parent == nullptr ? mainFormWidget() : parent, QMessageBox::Icon(msg.m_type), msg.m_title,
QMessageBox::Icon(msg.m_type), msg.m_title, msg.m_message, msg.m_message, {}, {}, QMessageBox::StandardButton::Ok, QMessageBox::StandardButton::Ok, {},
{}, {}, QMessageBox::StandardButton::Ok, QMessageBox::StandardButton::Ok, {},
action.m_title, action.m_action); action.m_title, action.m_action);
} } else if (dest.m_statusBar && mainForm()->statusBar() != nullptr && mainForm()->statusBar()->isVisible()) {
else if (dest.m_statusBar && mainForm()->statusBar() != nullptr && mainForm()->statusBar()->isVisible()) {
mainForm()->statusBar()->showMessage(msg.m_message); mainForm()->statusBar()->showMessage(msg.m_message);
} } else {
else {
qDebugNN << LOGSEC_CORE << "Silencing GUI message:" << QUOTE_W_SPACE_DOT(msg.m_message); qDebugNN << LOGSEC_CORE << "Silencing GUI message:" << QUOTE_W_SPACE_DOT(msg.m_message);
} }
} }
WebViewer* Application::createWebView() { WebViewer *Application::createWebView() {
#if !defined(USE_WEBENGINE) #if !defined(USE_WEBENGINE)
return new LiteHtmlViewer(); return new LiteHtmlViewer();
#else #else
if (forcedNoWebEngine()) { if (forcedNoWebEngine()) {
return new LiteHtmlViewer(); return new LiteHtmlViewer();
} } else {
else {
return new WebEngineViewer(); return new WebEngineViewer();
} }
#endif #endif
} }
void Application::onCommitData(QSessionManager& manager) { void Application::onCommitData(QSessionManager &manager) {
qDebugNN << LOGSEC_CORE << "OS asked application to commit its data."; qDebugNN << LOGSEC_CORE << "OS asked application to commit its data.";
onAboutToQuit(); onAboutToQuit();
@ -642,7 +576,7 @@ void Application::onCommitData(QSessionManager& manager) {
manager.release(); manager.release();
} }
void Application::onSaveState(QSessionManager& manager) { void Application::onSaveState(QSessionManager &manager) {
qDebugNN << LOGSEC_CORE << "OS asked application to save its state."; qDebugNN << LOGSEC_CORE << "OS asked application to save its state.";
manager.setRestartHint(QSessionManager::RestartHint::RestartNever); manager.setRestartHint(QSessionManager::RestartHint::RestartNever);
@ -669,8 +603,7 @@ void Application::onAboutToQuit() {
// We locked the lock to exit peacefully, unlock it to avoid warnings. // We locked the lock to exit peacefully, unlock it to avoid warnings.
feedUpdateLock()->unlock(); feedUpdateLock()->unlock();
} } else {
else {
// Request for write lock timed-out. This means // Request for write lock timed-out. This means
// that some critical action can be processed right now. // that some critical action can be processed right now.
qWarningNN << LOGSEC_CORE << "Close lock timed-out."; qWarningNN << LOGSEC_CORE << "Close lock timed-out.";
@ -688,11 +621,9 @@ void Application::onAboutToQuit() {
finish(); finish();
qDebugNN << LOGSEC_CORE << "Killing local peer connection to allow another instance to start."; qDebugNN << LOGSEC_CORE << "Killing local peer connection to allow another instance to start.";
if (QProcess::startDetached(QDir::toNativeSeparators(applicationFilePath()), if (QProcess::startDetached(QDir::toNativeSeparators(applicationFilePath()), arguments().mid(1))) {
arguments().mid(1))) {
qDebugNN << LOGSEC_CORE << "New application instance was started."; qDebugNN << LOGSEC_CORE << "New application instance was started.";
} } else {
else {
qCriticalNN << LOGSEC_CORE << "New application instance was not started successfully."; qCriticalNN << LOGSEC_CORE << "New application instance was not started successfully.";
} }
} }
@ -706,11 +637,8 @@ void Application::showMessagesNumber(int unread_messages, bool any_feed_has_new_
// Set task bar overlay with number of unread articles. // Set task bar overlay with number of unread articles.
#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS) #if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
// Use D-Bus "LauncherEntry" service on Linux. // Use D-Bus "LauncherEntry" service on Linux.
bool task_bar_count_enabled = settings()->value(GROUP(GUI), bool task_bar_count_enabled = settings()->value(GROUP(GUI), SETTING(GUI::UnreadNumbersOnTaskBar)).toBool();
SETTING(GUI::UnreadNumbersOnTaskBar)).toBool(); QDBusMessage signal = QDBusMessage::createSignal(QSL("/"), QSL("com.canonical.Unity.LauncherEntry"), QSL("Update"));
QDBusMessage signal = QDBusMessage::createSignal(QSL("/"),
QSL("com.canonical.Unity.LauncherEntry"),
QSL("Update"));
signal << QSL("application://%1").arg(APP_DESKTOP_ENTRY_FILE); signal << QSL("application://%1").arg(APP_DESKTOP_ENTRY_FILE);
@ -724,8 +652,7 @@ void Application::showMessagesNumber(int unread_messages, bool any_feed_has_new_
QDBusConnection::sessionBus().send(signal); QDBusConnection::sessionBus().send(signal);
#elif defined(Q_OS_WIN) #elif defined(Q_OS_WIN)
// Use SetOverlayIcon Windows API method on Windows. // Use SetOverlayIcon Windows API method on Windows.
bool task_bar_count_enabled = settings()->value(GROUP(GUI), bool task_bar_count_enabled = settings()->value(GROUP(GUI), SETTING(GUI::UnreadNumbersOnTaskBar)).toBool();
SETTING(GUI::UnreadNumbersOnTaskBar)).toBool();
if (m_mainForm != nullptr) { if (m_mainForm != nullptr) {
QImage overlay_icon = generateOverlayIcon(unread_messages); QImage overlay_icon = generateOverlayIcon(unread_messages);
@ -736,11 +663,9 @@ void Application::showMessagesNumber(int unread_messages, bool any_feed_has_new_
HICON overlay_hicon = overlay_icon.toHICON(); HICON overlay_hicon = overlay_icon.toHICON();
#endif #endif
HRESULT overlay_result = m_windowsTaskBar->SetOverlayIcon(reinterpret_cast<HWND>(m_mainForm->winId()), HRESULT overlay_result = m_windowsTaskBar->SetOverlayIcon(
(task_bar_count_enabled && unread_messages > 0) reinterpret_cast<HWND>(m_mainForm->winId()),
? overlay_hicon (task_bar_count_enabled && unread_messages > 0) ? overlay_hicon : nullptr, nullptr);
: nullptr,
nullptr);
DestroyIcon(overlay_hicon); DestroyIcon(overlay_hicon);
@ -752,8 +677,8 @@ void Application::showMessagesNumber(int unread_messages, bool any_feed_has_new_
if (m_mainForm != nullptr) { if (m_mainForm != nullptr) {
m_mainForm->setWindowTitle(unread_messages > 0 m_mainForm->setWindowTitle(unread_messages > 0
? QSL("[%2] %1").arg(QSL(APP_LONG_NAME), QString::number(unread_messages)) ? QSL("[%2] %1").arg(QSL(APP_LONG_NAME), QString::number(unread_messages))
: QSL(APP_LONG_NAME)); : QSL(APP_LONG_NAME));
} }
} }
@ -765,24 +690,21 @@ QImage Application::generateOverlayIcon(int number) const {
if (number < 1000) { if (number < 1000) {
num_txt = QString::number(number); num_txt = QString::number(number);
} } else if (number < 100000) {
else if (number < 100000) {
num_txt = QSL("%1k").arg(int(number / 1000)); num_txt = QSL("%1k").arg(int(number / 1000));
} } else {
else {
num_txt = QChar(8734); num_txt = QChar(8734);
} }
QPainterPath rounded_rectangle; rounded_rectangle.addRoundedRect(QRectF(img.rect()), 15, 15); QPainterPath rounded_rectangle;
rounded_rectangle.addRoundedRect(QRectF(img.rect()), 15, 15);
QFont fon = font(); QFont fon = font();
if (num_txt.size() == 3) { if (num_txt.size() == 3) {
fon.setPixelSize(img.width() * 0.52); fon.setPixelSize(img.width() * 0.52);
} } else if (num_txt.size() == 2) {
else if (num_txt.size() == 2) {
fon.setPixelSize(img.width() * 0.68); fon.setPixelSize(img.width() * 0.68);
} } else {
else {
fon.setPixelSize(img.width() * 0.79); fon.setPixelSize(img.width() * 0.79);
} }
@ -799,8 +721,7 @@ QImage Application::generateOverlayIcon(int number) const {
p.setPen(Qt::GlobalColor::black); p.setPen(Qt::GlobalColor::black);
p.drawPath(rounded_rectangle); p.drawPath(rounded_rectangle);
p.drawText(img.rect().marginsRemoved(QMargins(0, 0, 0, img.height() * 0.05)), p.drawText(img.rect().marginsRemoved(QMargins(0, 0, 0, img.height() * 0.05)), num_txt,
num_txt,
QTextOption(Qt::AlignmentFlag::AlignCenter)); QTextOption(Qt::AlignmentFlag::AlignCenter));
p.end(); p.end();
@ -817,9 +738,9 @@ void Application::restart() {
#if defined(USE_WEBENGINE) #if defined(USE_WEBENGINE)
#if QT_VERSION_MAJOR == 6 #if QT_VERSION_MAJOR == 6
void Application::downloadRequested(QWebEngineDownloadRequest* download_item) { void Application::downloadRequested(QWebEngineDownloadRequest *download_item) {
#else #else
void Application::downloadRequested(QWebEngineDownloadItem* download_item) { void Application::downloadRequested(QWebEngineDownloadItem *download_item) {
#endif #endif
downloadManager()->download(download_item->url()); downloadManager()->download(download_item->url());
download_item->cancel(); download_item->cancel();
@ -831,44 +752,35 @@ void Application::downloadRequested(QWebEngineDownloadItem* download_item) {
void Application::onFeedUpdatesStarted() { void Application::onFeedUpdatesStarted() {
#if defined(Q_OS_WIN) #if defined(Q_OS_WIN)
// Use SetOverlayIcon Windows API method on Windows. // Use SetOverlayIcon Windows API method on Windows.
bool task_bar_count_enabled = settings()->value(GROUP(GUI), bool task_bar_count_enabled = settings()->value(GROUP(GUI), SETTING(GUI::UnreadNumbersOnTaskBar)).toBool();
SETTING(GUI::UnreadNumbersOnTaskBar)).toBool();
if (task_bar_count_enabled && m_mainForm != nullptr && m_windowsTaskBar != nullptr) { if (task_bar_count_enabled && m_mainForm != nullptr && m_windowsTaskBar != nullptr) {
m_windowsTaskBar->SetProgressValue(reinterpret_cast<HWND>(m_mainForm->winId()), m_windowsTaskBar->SetProgressValue(reinterpret_cast<HWND>(m_mainForm->winId()), 1ul, 100ul);
1ul,
100ul);
} }
#endif #endif
} }
void Application::onFeedUpdatesProgress(const Feed* feed, int current, int total) { void Application::onFeedUpdatesProgress(const Feed *feed, int current, int total) {
#if defined(Q_OS_WIN) #if defined(Q_OS_WIN)
// Use SetOverlayIcon Windows API method on Windows. // Use SetOverlayIcon Windows API method on Windows.
bool task_bar_count_enabled = settings()->value(GROUP(GUI), bool task_bar_count_enabled = settings()->value(GROUP(GUI), SETTING(GUI::UnreadNumbersOnTaskBar)).toBool();
SETTING(GUI::UnreadNumbersOnTaskBar)).toBool();
if (task_bar_count_enabled && m_mainForm != nullptr && m_windowsTaskBar != nullptr) { if (task_bar_count_enabled && m_mainForm != nullptr && m_windowsTaskBar != nullptr) {
m_windowsTaskBar->SetProgressValue(reinterpret_cast<HWND>(m_mainForm->winId()), m_windowsTaskBar->SetProgressValue(reinterpret_cast<HWND>(m_mainForm->winId()), current, total);
current,
total);
} }
#endif #endif
} }
void Application::onFeedUpdatesFinished(const FeedDownloadResults& results) { void Application::onFeedUpdatesFinished(const FeedDownloadResults &results) {
if (!results.updatedFeeds().isEmpty()) { if (!results.updatedFeeds().isEmpty()) {
// Now, inform about results via GUI message/notification. // Now, inform about results via GUI message/notification.
qApp->showGuiMessage(Notification::Event::NewUnreadArticlesFetched, { qApp->showGuiMessage(Notification::Event::NewUnreadArticlesFetched,
tr("Unread articles fetched"), {tr("Unread articles fetched"), results.overview(10), QSystemTrayIcon::MessageIcon::NoIcon});
results.overview(10),
QSystemTrayIcon::MessageIcon::NoIcon });
} }
#if defined(Q_OS_WIN) #if defined(Q_OS_WIN)
// Use SetOverlayIcon Windows API method on Windows. // Use SetOverlayIcon Windows API method on Windows.
bool task_bar_count_enabled = settings()->value(GROUP(GUI), bool task_bar_count_enabled = settings()->value(GROUP(GUI), SETTING(GUI::UnreadNumbersOnTaskBar)).toBool();
SETTING(GUI::UnreadNumbersOnTaskBar)).toBool();
if (task_bar_count_enabled && m_mainForm != nullptr && m_windowsTaskBar != nullptr) { if (task_bar_count_enabled && m_mainForm != nullptr && m_windowsTaskBar != nullptr) {
m_windowsTaskBar->SetProgressState(reinterpret_cast<HWND>(m_mainForm->winId()), TBPFLAG::TBPF_NOPROGRESS); m_windowsTaskBar->SetProgressState(reinterpret_cast<HWND>(m_mainForm->winId()), TBPFLAG::TBPF_NOPROGRESS);
@ -876,11 +788,9 @@ void Application::onFeedUpdatesFinished(const FeedDownloadResults& results) {
#endif #endif
} }
void Application::setupCustomDataFolder(const QString& data_folder) { void Application::setupCustomDataFolder(const QString &data_folder) {
if (!QDir().mkpath(data_folder)) { if (!QDir().mkpath(data_folder)) {
qCriticalNN << LOGSEC_CORE qCriticalNN << LOGSEC_CORE << "Failed to create custom data path" << QUOTE_W_SPACE(data_folder)
<< "Failed to create custom data path"
<< QUOTE_W_SPACE(data_folder)
<< "thus falling back to standard setup."; << "thus falling back to standard setup.";
m_customDataFolder = QString(); m_customDataFolder = QString();
return; return;
@ -894,35 +804,31 @@ void Application::setupCustomDataFolder(const QString& data_folder) {
} }
void Application::onAdBlockFailure() { void Application::onAdBlockFailure() {
qApp->showGuiMessage(Notification::Event::GeneralEvent, { qApp->showGuiMessage(Notification::Event::GeneralEvent,
tr("AdBlock needs to be configured"), {tr("AdBlock needs to be configured"),
tr("AdBlock is not configured properly. Go to \"Settings\" -> \"Node.js\" and check " tr("AdBlock is not configured properly. Go to \"Settings\" -> \"Node.js\" and check "
"if your Node.js is properly configured."), "if your Node.js is properly configured."),
QSystemTrayIcon::MessageIcon::Critical }, { true, true, false }); QSystemTrayIcon::MessageIcon::Critical},
{true, true, false});
qApp->settings()->setValue(GROUP(AdBlock), AdBlock::AdBlockEnabled, false); qApp->settings()->setValue(GROUP(AdBlock), AdBlock::AdBlockEnabled, false);
} }
void Application::determineFirstRuns() { void Application::determineFirstRuns() {
m_firstRunEver = settings()->value(GROUP(General), m_firstRunEver = settings()->value(GROUP(General), SETTING(General::FirstRun)).toBool();
SETTING(General::FirstRun)).toBool(); m_firstRunCurrentVersion =
m_firstRunCurrentVersion = settings()->value(GROUP(General), settings()->value(GROUP(General), QString(General::FirstRun) + QL1C('_') + APP_VERSION, true).toBool();
QString(General::FirstRun) + QL1C('_') + APP_VERSION,
true).toBool();
eliminateFirstRuns(); eliminateFirstRuns();
} }
void Application::parseCmdArgumentsFromOtherInstance(const QString& message) { void Application::parseCmdArgumentsFromOtherInstance(const QString &message) {
if (message.isEmpty()) { if (message.isEmpty()) {
qDebugNN << LOGSEC_CORE << "No execution message received from other app instances."; qDebugNN << LOGSEC_CORE << "No execution message received from other app instances.";
return; return;
} }
qDebugNN << LOGSEC_CORE qDebugNN << LOGSEC_CORE << "Received" << QUOTE_W_SPACE(message) << "execution message.";
<< "Received"
<< QUOTE_W_SPACE(message)
<< "execution message.";
#if QT_VERSION >= 0x050F00 // Qt >= 5.15.0 #if QT_VERSION >= 0x050F00 // Qt >= 5.15.0
QStringList messages = message.split(QSL(ARGUMENTS_LIST_SEPARATOR), Qt::SplitBehaviorFlags::SkipEmptyParts); QStringList messages = message.split(QSL(ARGUMENTS_LIST_SEPARATOR), Qt::SplitBehaviorFlags::SkipEmptyParts);
@ -934,11 +840,11 @@ void Application::parseCmdArgumentsFromOtherInstance(const QString& message) {
messages.prepend(qApp->applicationFilePath()); messages.prepend(qApp->applicationFilePath());
cmd_parser.addOption(QCommandLineOption({ QSL(CLI_QUIT_INSTANCE) })); cmd_parser.addOption(QCommandLineOption({QSL(CLI_QUIT_INSTANCE)}));
cmd_parser.addOption(QCommandLineOption({ QSL(CLI_IS_RUNNING) })); cmd_parser.addOption(QCommandLineOption({QSL(CLI_IS_RUNNING)}));
cmd_parser.addPositionalArgument(QSL("urls"), cmd_parser.addPositionalArgument(
QSL("List of URL addresses pointing to individual online feeds which should be added."), QSL("urls"), QSL("List of URL addresses pointing to individual online feeds which should be added."),
QSL("[url-1 ... url-n]")); QSL("[url-1 ... url-n]"));
if (!cmd_parser.parse(messages)) { if (!cmd_parser.parse(messages)) {
qCriticalNN << LOGSEC_CORE << cmd_parser.errorText(); qCriticalNN << LOGSEC_CORE << cmd_parser.errorText();
@ -947,75 +853,66 @@ void Application::parseCmdArgumentsFromOtherInstance(const QString& message) {
if (cmd_parser.isSet(QSL(CLI_QUIT_INSTANCE))) { if (cmd_parser.isSet(QSL(CLI_QUIT_INSTANCE))) {
quit(); quit();
return; return;
} } else if (cmd_parser.isSet(QSL(CLI_IS_RUNNING))) {
else if (cmd_parser.isSet(QSL(CLI_IS_RUNNING))) { showGuiMessage(Notification::Event::GeneralEvent, {tr("Already running"), tr("Application is already running."),
showGuiMessage(Notification::Event::GeneralEvent, { QSystemTrayIcon::MessageIcon::Information});
tr("Already running"),
tr("Application is already running."),
QSystemTrayIcon::MessageIcon::Information });
mainForm()->display(); mainForm()->display();
} }
messages = cmd_parser.positionalArguments(); messages = cmd_parser.positionalArguments();
for (const QString& msg : qAsConst(messages)) { for (const QString &msg : qAsConst(messages)) {
// Application was running, and someone wants to add new feed. // Application was running, and someone wants to add new feed.
ServiceRoot* rt = boolinq::from(feedReader()->feedsModel()->serviceRoots()).firstOrDefault([](ServiceRoot* root) { ServiceRoot *rt = boolinq::from(feedReader()->feedsModel()->serviceRoots()).firstOrDefault([](ServiceRoot *root) {
return root->supportsFeedAdding(); return root->supportsFeedAdding();
}); });
if (rt != nullptr) { if (rt != nullptr) {
rt->addNewFeed(nullptr, msg); rt->addNewFeed(nullptr, msg);
} } else {
else { showGuiMessage(Notification::Event::GeneralEvent,
showGuiMessage(Notification::Event::GeneralEvent, { {tr("Cannot add feed"),
tr("Cannot add feed"), tr("Feed cannot be added because there is no active account which can add feeds."),
tr("Feed cannot be added because there is no active account which can add feeds."), QSystemTrayIcon::MessageIcon::Warning});
QSystemTrayIcon::MessageIcon::Warning });
} }
} }
} }
void Application::parseCmdArgumentsFromMyInstance(const QStringList& raw_cli_args) { void Application::parseCmdArgumentsFromMyInstance(const QStringList &raw_cli_args) {
QCommandLineOption help({ QSL(CLI_HELP_SHORT), QSL(CLI_HELP_LONG) }, QCommandLineOption help({QSL(CLI_HELP_SHORT), QSL(CLI_HELP_LONG)}, QSL("Displays overview of CLI."));
QSL("Displays overview of CLI.")); QCommandLineOption version({QSL(CLI_VER_SHORT), QSL(CLI_VER_LONG)}, QSL("Displays version of the application."));
QCommandLineOption version({ QSL(CLI_VER_SHORT), QSL(CLI_VER_LONG) }, QCommandLineOption log_file(
QSL("Displays version of the application.")); {QSL(CLI_LOG_SHORT), QSL(CLI_LOG_LONG)},
QCommandLineOption log_file({ QSL(CLI_LOG_SHORT), QSL(CLI_LOG_LONG) }, QSL("Write application debug log to file. Note that logging to file may slow application down."),
QSL("Write application debug log to file. Note that logging to file may slow application down."), QSL("log-file"));
QSL("log-file")); QCommandLineOption custom_data_folder(
QCommandLineOption custom_data_folder({ QSL(CLI_DAT_SHORT), QSL(CLI_DAT_LONG) }, {QSL(CLI_DAT_SHORT), QSL(CLI_DAT_LONG)},
QSL("Use custom folder for user data and disable single instance application mode."), QSL("Use custom folder for user data and disable single instance application mode."), QSL("user-data-folder"));
QSL("user-data-folder")); QCommandLineOption disable_singleinstance({QSL(CLI_SIN_SHORT), QSL(CLI_SIN_LONG)},
QCommandLineOption disable_singleinstance({ QSL(CLI_SIN_SHORT), QSL(CLI_SIN_LONG) },
QSL("Allow running of multiple application instances.")); QSL("Allow running of multiple application instances."));
#if defined(USE_WEBENGINE) #if defined(USE_WEBENGINE)
QCommandLineOption force_nowebengine({ QSL(CLI_FORCE_NOWEBENGINE_SHORT), QSL(CLI_FORCE_NOWEBENGINE_LONG) }, QCommandLineOption force_nowebengine({QSL(CLI_FORCE_NOWEBENGINE_SHORT), QSL(CLI_FORCE_NOWEBENGINE_LONG)},
QSL("Force usage of simpler text-based embedded web browser.")); QSL("Force usage of simpler text-based embedded web browser."));
#endif #endif
QCommandLineOption disable_only_debug({ QSL(CLI_NDEBUG_SHORT), QSL(CLI_NDEBUG_LONG) }, QCommandLineOption disable_only_debug({QSL(CLI_NDEBUG_SHORT), QSL(CLI_NDEBUG_LONG)},
QSL("Disable just \"debug\" output.")); QSL("Disable just \"debug\" output."));
QCommandLineOption disable_debug({ QSL(CLI_NSTDOUTERR_SHORT), QSL(CLI_NSTDOUTERR_LONG) }, QCommandLineOption disable_debug({QSL(CLI_NSTDOUTERR_SHORT), QSL(CLI_NSTDOUTERR_LONG)},
QSL("Completely disable stdout/stderr outputs.")); QSL("Completely disable stdout/stderr outputs."));
QCommandLineOption forced_style({ QSL(CLI_STYLE_SHORT), QSL(CLI_STYLE_LONG) }, QCommandLineOption forced_style({QSL(CLI_STYLE_SHORT), QSL(CLI_STYLE_LONG)}, QSL("Force some application style."),
QSL("Force some application style."),
QSL("style-name")); QSL("style-name"));
m_cmdParser.addOptions({ help, version, m_cmdParser.addOptions({
log_file, help, version, log_file, custom_data_folder, disable_singleinstance, disable_only_debug, disable_debug,
custom_data_folder,
disable_singleinstance,
disable_only_debug,
disable_debug,
#if defined(USE_WEBENGINE) #if defined(USE_WEBENGINE)
force_nowebengine, force_nowebengine,
#endif #endif
forced_style }); forced_style
m_cmdParser.addPositionalArgument(QSL("urls"), });
QSL("List of URL addresses pointing to individual online feeds which should be added."), m_cmdParser.addPositionalArgument(
QSL("[url-1 ... url-n]")); QSL("urls"), QSL("List of URL addresses pointing to individual online feeds which should be added."),
QSL("[url-1 ... url-n]"));
m_cmdParser.setApplicationDescription(QSL(APP_NAME)); m_cmdParser.setApplicationDescription(QSL(APP_NAME));
m_cmdParser.setSingleDashWordOptionMode(QCommandLineParser::SingleDashWordOptionMode::ParseAsLongOptions); m_cmdParser.setSingleDashWordOptionMode(QCommandLineParser::SingleDashWordOptionMode::ParseAsLongOptions);
@ -1040,20 +937,17 @@ void Application::parseCmdArgumentsFromMyInstance(const QStringList& raw_cli_arg
if (!m_cmdParser.value(QSL(CLI_DAT_SHORT)).isEmpty()) { if (!m_cmdParser.value(QSL(CLI_DAT_SHORT)).isEmpty()) {
auto data_folder = QDir::toNativeSeparators(m_cmdParser.value(QSL(CLI_DAT_SHORT))); auto data_folder = QDir::toNativeSeparators(m_cmdParser.value(QSL(CLI_DAT_SHORT)));
qDebugNN << LOGSEC_CORE qDebugNN << LOGSEC_CORE << "User wants to use custom directory for user data (and disable single instance mode):"
<< "User wants to use custom directory for user data (and disable single instance mode):"
<< QUOTE_W_SPACE_DOT(data_folder); << QUOTE_W_SPACE_DOT(data_folder);
setupCustomDataFolder(data_folder); setupCustomDataFolder(data_folder);
} } else {
else {
m_allowMultipleInstances = false; m_allowMultipleInstances = false;
} }
if (m_cmdParser.isSet(QSL(CLI_HELP_SHORT))) { if (m_cmdParser.isSet(QSL(CLI_HELP_SHORT))) {
m_cmdParser.showHelp(); m_cmdParser.showHelp();
} } else if (m_cmdParser.isSet(QSL(CLI_VER_SHORT))) {
else if (m_cmdParser.isSet(QSL(CLI_VER_SHORT))) {
m_cmdParser.showVersion(); m_cmdParser.showVersion();
} }
@ -1076,23 +970,21 @@ void Application::parseCmdArgumentsFromMyInstance(const QStringList& raw_cli_arg
} }
} }
void Application::onNodeJsPackageUpdateError(const QList<NodeJs::PackageMetadata>& pkgs, const QString& error) { void Application::onNodeJsPackageUpdateError(const QList<NodeJs::PackageMetadata> &pkgs, const QString &error) {
qApp->showGuiMessage(Notification::Event::NodePackageFailedToUpdate, qApp->showGuiMessage(
{ {}, Notification::Event::NodePackageFailedToUpdate,
tr("Packages %1 were NOT updated because of error: %2.").arg(NodeJs::packagesToString(pkgs), {{},
error), tr("Packages %1 were NOT updated because of error: %2.").arg(NodeJs::packagesToString(pkgs), error),
QSystemTrayIcon::MessageIcon::Critical }); QSystemTrayIcon::MessageIcon::Critical});
} }
void Application::onNodeJsPackageInstalled(const QList<NodeJs::PackageMetadata>& pkgs, bool already_up_to_date) { void Application::onNodeJsPackageInstalled(const QList<NodeJs::PackageMetadata> &pkgs, bool already_up_to_date) {
if (!already_up_to_date) { if (!already_up_to_date) {
qApp->showGuiMessage(Notification::Event::NodePackageUpdated, qApp->showGuiMessage(Notification::Event::NodePackageUpdated,
{ {}, {{},
tr("Packages %1 were updated.").arg(NodeJs::packagesToString(pkgs)), tr("Packages %1 were updated.").arg(NodeJs::packagesToString(pkgs)),
QSystemTrayIcon::MessageIcon::Information }); QSystemTrayIcon::MessageIcon::Information});
} }
} }
QString Application::customDataFolder() const { QString Application::customDataFolder() const { return m_customDataFolder; }
return m_customDataFolder;
}