Compare commits

...

2 Commits

@ -1,2 +1 @@
# develop
# master

@ -0,0 +1,108 @@
# Copyright (C) 2016 Olivier Goffart <ogoffart@woboq.com>
#
# You may use this file under the terms of the 3-clause BSD license.
# See the file LICENSE from this package for details.
# This is the clang-format configuration style to be used by Qt,
# based on the rules from https://wiki.qt.io/Qt_Coding_Style and
# https://wiki.qt.io/Coding_Conventions
---
# Webkit style was loosely based on the Qt style
BasedOnStyle: WebKit
Standard: c++14
# Column width is limited to 100 in accordance with Qt Coding Style.
# https://wiki.qt.io/Qt_Coding_Style
# Note that this may be changed at some point in the future.
ColumnLimit: 100
# How much weight do extra characters after the line length limit have.
# PenaltyExcessCharacter: 4
# Disable reflow of some specific comments
# qdoc comments: indentation rules are different.
# Translation comments and SPDX license identifiers are also excluded.
CommentPragmas: "^!|^:|^ SPDX-License-Identifier:"
# We want a space between the type and the star for pointer types.
PointerBindsToType: false
# We use template< without space.
SpaceAfterTemplateKeyword: false
# We want to break before the operators, but not before a '='.
BreakBeforeBinaryOperators: NonAssignment
# Braces are usually attached, but not after functions or class declarations.
BreakBeforeBraces: Custom
BraceWrapping:
AfterClass: true
AfterControlStatement: false
AfterEnum: false
AfterFunction: true
AfterNamespace: false
AfterObjCDeclaration: false
AfterStruct: true
AfterUnion: false
BeforeCatch: false
BeforeElse: false
IndentBraces: false
# When constructor initializers do not fit on one line, put them each on a new line.
ConstructorInitializerAllOnOneLineOrOnePerLine: true
# Indent initializers by 4 spaces
ConstructorInitializerIndentWidth: 4
# Indent width for line continuations.
ContinuationIndentWidth: 8
# No indentation for namespaces.
NamespaceIndentation: None
# Allow indentation for preprocessing directives (if/ifdef/endif). https://reviews.llvm.org/rL312125
IndentPPDirectives: AfterHash
# We only indent with 2 spaces for preprocessor directives
PPIndentWidth: 2
# Horizontally align arguments after an open bracket.
# The coding style does not specify the following, but this is what gives
# results closest to the existing code.
AlignAfterOpenBracket: true
AlwaysBreakTemplateDeclarations: true
# Ideally we should also allow less short function in a single line, but
# clang-format does not handle that.
AllowShortFunctionsOnASingleLine: Inline
# The coding style specifies some include order categories, but also tells to
# separate categories with an empty line. It does not specify the order within
# the categories. Since the SortInclude feature of clang-format does not
# re-order includes separated by empty lines, the feature is not used.
SortIncludes: false
# macros for which the opening brace stays attached.
ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH, forever, Q_FOREVER, QBENCHMARK, QBENCHMARK_ONCE ]
# Break constructor initializers before the colon and after the commas.
BreakConstructorInitializers: BeforeColon
# Add "// namespace <namespace>" comments on closing brace for a namespace
# Ignored for namespaces that qualify as a short namespace,
# see 'ShortNamespaceLines'
FixNamespaceComments: true
# Definition of how short a short namespace is, default 1
ShortNamespaceLines: 1
# When escaping newlines in a macro attach the '\' as far left as possible, e.g.
##define a \
# something; \
# other; \
# thelastlineislong;
AlignEscapedNewlines: Left
# Avoids the addition of a space between an identifier and the
# initializer list in list-initialization.
SpaceBeforeCpp11BracedList: false

@ -0,0 +1,28 @@
Checks: >
-*,
bugprone-*
misc-*,
modernize-*,
performance-*,
portability-*,
readability-*,
-fuchsia-trailing-return,
-readability-magic-numbers,
-modernize-use-nodiscard,
-modernize-use-trailing-return-type,
-readability-braces-around-statements,
-readability-redundant-access-specifiers,
-readability-redundant-member-init,
-readability-redundant-string-init,
-readability-identifier-length,
CheckOptions:
- { key: readability-identifier-naming.NamespaceCase, value: lower_case }
- { key: readability-identifier-naming.ClassCase, value: CamelCase }
- { key: readability-identifier-naming.StructCase, value: CamelCase }
- { key: readability-identifier-naming.FunctionCase, value: camelBack }
- { key: readability-identifier-naming.VariableCase, value: camelBack }
- { key: readability-identifier-naming.PrivateMemberCase, value: camelBack }
- { key: readability-identifier-naming.PrivateMemberPrefix, value: m_ }
- { key: readability-identifier-naming.EnumCase, value: CamelCase }
- { key: readability-identifier-naming.EnumConstantCase, value: CamelCase }
- { key: readability-identifier-naming.GlobalConstantCase, value: UPPER_CASE }

@ -0,0 +1,241 @@
# ----------------------------------
# Options affecting listfile parsing
# ----------------------------------
with section("parse"):
# Specify structure for custom cmake functions
additional_commands = { 'foo': { 'flags': ['BAR', 'BAZ'],
'kwargs': {'DEPENDS': '*', 'HEADERS': '*', 'SOURCES': '*'}}}
# Override configurations per-command where available
override_spec = {}
# Specify variable tags.
vartags = []
# Specify property tags.
proptags = []
# -----------------------------
# Options affecting formatting.
# -----------------------------
with section("format"):
# Disable formatting entirely, making cmake-format a no-op
disable = False
# How wide to allow formatted cmake files
line_width = 80
# How many spaces to tab for indent
tab_size = 2
# If true, lines are indented using tab characters (utf-8 0x09) instead of
# <tab_size> space characters (utf-8 0x20). In cases where the layout would
# require a fractional tab character, the behavior of the fractional
# indentation is governed by <fractional_tab_policy>
use_tabchars = False
# If <use_tabchars> is True, then the value of this variable indicates how
# fractional indentions are handled during whitespace replacement. If set to
# 'use-space', fractional indentation is left as spaces (utf-8 0x20). If set
# to `round-up` fractional indentation is replaced with a single tab character
# (utf-8 0x09) effectively shifting the column to the next tabstop
fractional_tab_policy = 'use-space'
# If an argument group contains more than this many sub-groups (parg or kwarg
# groups) then force it to a vertical layout.
max_subgroups_hwrap = 2
# If a positional argument group contains more than this many arguments, then
# force it to a vertical layout.
max_pargs_hwrap = 6
# If a cmdline positional group consumes more than this many lines without
# nesting, then invalidate the layout (and nest)
max_rows_cmdline = 2
# If true, separate flow control names from their parentheses with a space
separate_ctrl_name_with_space = False
# If true, separate function names from parentheses with a space
separate_fn_name_with_space = False
# If a statement is wrapped to more than one line, than dangle the closing
# parenthesis on its own line.
dangle_parens = False
# If the trailing parenthesis must be 'dangled' on its on line, then align it
# to this reference: `prefix`: the start of the statement, `prefix-indent`:
# the start of the statement, plus one indentation level, `child`: align to
# the column of the arguments
dangle_align = 'prefix'
# If the statement spelling length (including space and parenthesis) is
# smaller than this amount, then force reject nested layouts.
min_prefix_chars = 4
# If the statement spelling length (including space and parenthesis) is larger
# than the tab width by more than this amount, then force reject un-nested
# layouts.
max_prefix_chars = 10
# If a candidate layout is wrapped horizontally but it exceeds this many
# lines, then reject the layout.
max_lines_hwrap = 2
# What style line endings to use in the output.
line_ending = 'unix'
# Format command names consistently as 'lower' or 'upper' case
command_case = 'canonical'
# Format keywords consistently as 'lower' or 'upper' case
keyword_case = 'unchanged'
# A list of command names which should always be wrapped
always_wrap = []
# If true, the argument lists which are known to be sortable will be sorted
# lexicographicall
enable_sort = True
# If true, the parsers may infer whether or not an argument list is sortable
# (without annotation).
autosort = False
# By default, if cmake-format cannot successfully fit everything into the
# desired linewidth it will apply the last, most agressive attempt that it
# made. If this flag is True, however, cmake-format will print error, exit
# with non-zero status code, and write-out nothing
require_valid_layout = False
# A dictionary mapping layout nodes to a list of wrap decisions. See the
# documentation for more information.
layout_passes = {}
# ------------------------------------------------
# Options affecting comment reflow and formatting.
# ------------------------------------------------
with section("markup"):
# What character to use for bulleted lists
bullet_char = '*'
# What character to use as punctuation after numerals in an enumerated list
enum_char = '.'
# If comment markup is enabled, don't reflow the first comment block in each
# listfile. Use this to preserve formatting of your copyright/license
# statements.
first_comment_is_literal = False
# If comment markup is enabled, don't reflow any comment block which matches
# this (regex) pattern. Default is `None` (disabled).
literal_comment_pattern = None
# Regular expression to match preformat fences in comments default=
# ``r'^\s*([`~]{3}[`~]*)(.*)$'``
fence_pattern = '^\\s*([`~]{3}[`~]*)(.*)$'
# Regular expression to match rulers in comments default=
# ``r'^\s*[^\w\s]{3}.*[^\w\s]{3}$'``
ruler_pattern = '^\\s*[^\\w\\s]{3}.*[^\\w\\s]{3}$'
# If a comment line matches starts with this pattern then it is explicitly a
# trailing comment for the preceeding argument. Default is '#<'
explicit_trailing_pattern = '#<'
# If a comment line starts with at least this many consecutive hash
# characters, then don't lstrip() them off. This allows for lazy hash rulers
# where the first hash char is not separated by space
hashruler_min_length = 10
# If true, then insert a space between the first hash char and remaining hash
# chars in a hash ruler, and normalize its length to fill the column
canonicalize_hashrulers = True
# enable comment markup parsing and reflow
enable_markup = False
# ----------------------------
# Options affecting the linter
# ----------------------------
with section("lint"):
# a list of lint codes to disable
disabled_codes = []
# regular expression pattern describing valid function names
function_pattern = '[0-9a-z_]+'
# regular expression pattern describing valid macro names
macro_pattern = '[0-9A-Z_]+'
# regular expression pattern describing valid names for variables with global
# (cache) scope
global_var_pattern = '[A-Z][0-9A-Z_]+'
# regular expression pattern describing valid names for variables with global
# scope (but internal semantic)
internal_var_pattern = '_[A-Z][0-9A-Z_]+'
# regular expression pattern describing valid names for variables with local
# scope
local_var_pattern = '[a-z][a-z0-9_]+'
# regular expression pattern describing valid names for privatedirectory
# variables
private_var_pattern = '_[0-9a-z_]+'
# regular expression pattern describing valid names for public directory
# variables
public_var_pattern = '[A-Z][0-9A-Z_]+'
# regular expression pattern describing valid names for function/macro
# arguments and loop variables.
argument_var_pattern = '[a-z][a-z0-9_]+'
# regular expression pattern describing valid names for keywords used in
# functions or macros
keyword_pattern = '[A-Z][0-9A-Z_]+'
# In the heuristic for C0201, how many conditionals to match within a loop in
# before considering the loop a parser.
max_conditionals_custom_parser = 2
# Require at least this many newlines between statements
min_statement_spacing = 1
# Require no more than this many newlines between statements
max_statement_spacing = 2
max_returns = 6
max_branches = 12
max_arguments = 5
max_localvars = 15
max_statements = 50
# -------------------------------
# Options affecting file encoding
# -------------------------------
with section("encode"):
# If true, emit the unicode byte-order mark (BOM) at the start of the file
emit_byteorder_mark = False
# Specify the encoding of the input file. Defaults to utf-8
input_encoding = 'utf-8'
# Specify the encoding of the output file. Defaults to utf-8. Note that cmake
# only claims to support utf-8 so be careful when using anything else
output_encoding = 'utf-8'
# -------------------------------------
# Miscellaneous configurations options.
# -------------------------------------
with section("misc"):
# A dictionary containing any per-command configuration overrides. Currently
# only `command_case` is supported.
per_command = {}

@ -0,0 +1,13 @@
# These are supported funding model platforms
github: nuttyartist # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
patreon: rubymamis # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']

@ -0,0 +1,37 @@
name: CI
on:
push:
branches:
- master
tags:
- v*
pull_request:
workflow_dispatch:
jobs:
format-lint:
name: Code Linting
uses: ./.github/workflows/format-lint.yml
secrets: inherit
linux:
name: Linux
needs:
- format-lint
uses: ./.github/workflows/linux.yml
secrets: inherit
macos:
name: macOS
needs:
- format-lint
uses: ./.github/workflows/macos.yml
secrets: inherit
windows:
name: Windows
needs:
- format-lint
uses: ./.github/workflows/windows.yml
secrets: inherit

@ -0,0 +1,31 @@
name: Code Linting
on:
workflow_call:
workflow_dispatch:
jobs:
lint:
name: Format / Lint
runs-on: ubuntu-latest
strategy:
fail-fast: false
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up cmake-format
run: pip install cmakelang
- name: Run clang-format
run: find src/ -iregex '.*\.\(cpp\|h\|mm\)$' -print0 | xargs -n 1 -0 clang-format -style=file --dry-run --Werror --color=true
- name: Run cmake-format
run: |
cmake-format CMakeLists.txt > CMakeLists-new.txt
if ! cmp -s CMakeLists.txt CMakeLists-new.txt
then
echo 'Please format CMakeLists.txt using cmake-format: https://github.com/cheshirekow/cmake_format'
echo 'For example: cmake-format CMakeLists.txt | sponge CMakeLists.txt'
exit 1
fi

@ -0,0 +1,391 @@
name: Linux
on:
workflow_call:
workflow_dispatch:
env:
APP_ID: io.github.nuttyartist.notes
jobs:
deb:
name: deb (${{ matrix.build-type }}, Qt ${{ matrix.qt-version-major }}, ${{ matrix.image }})
runs-on: ubuntu-latest
container:
image: zjeffer/notes:${{ matrix.image }}
strategy:
fail-fast: false
matrix:
include:
# Ubuntu's release cycle: https://wiki.ubuntu.com/Releases
- image: ubuntu-20_04
qt-version-major: 5
build-type: release
- image: ubuntu-22_04
qt-version-major: 6
build-type: release
- image: ubuntu-23_10
qt-version-major: 6
build-type: release
steps:
- name: Setup git configuration
# workaround for "detected dubious ownership in repository" git error: https://github.com/actions/checkout/issues/1169
run: git config --global --add safe.directory "${PWD}"
- name: Checkout code
uses: actions/checkout@v4
with:
submodules: recursive
- name: Set up variables
shell: bash
id: vars
run: |
set -x
distro_id=$(grep -oPm1 '^ID="?\K[^"]+' /etc/os-release)
if [ -z "${distro_id}" ]
then
echo 'Fatal: Failed to extract distro ID from /etc/os-release'
exit 1
fi
distro_codename=$(grep -oPm1 '^VERSION_CODENAME="?\K[^"]+' /etc/os-release)
if [ -z "${distro_codename}" ]
then
echo 'Fatal: Failed to extract distro codename from /etc/os-release'
exit 1
fi
echo "distro_name=${distro_id}-${distro_codename}" >> "${GITHUB_OUTPUT}"
- name: Setup GCC problem matcher
uses: ammaraskar/gcc-problem-matcher@0.3.0
- name: Build (${{ matrix.build-type }})
env:
VERBOSE: 1
run: |
cmake --warn-uninitialized --warn-unused-vars \
-B build \
-DCMAKE_BUILD_TYPE=${{ matrix.build-type }} \
-DGIT_REVISION=${{ github.ref_type != 'tag' && 'ON' || 'OFF' }} \
-DCMAKE_INSTALL_PREFIX=/usr \
-DPRO_VERSION=OFF
cmake --build build --parallel $(nproc)
- name: Create deb package
run: |
cd build
cpack -G DEB
- name: Grab deb package name
id: deb
shell: bash
run: |
set -x
if ! path=$(find build/ -maxdepth 1 -name '*.deb' -print -quit)
then
echo 'Fatal: Unable to find deb package'
exit 1;
fi
echo "name=$(basename "${path%.*}")" >> "${GITHUB_OUTPUT}"
echo "path=${path}" >> "${GITHUB_OUTPUT}"
- name: Run lintian
run: |
lintian '${{ steps.deb.outputs.path }}'
- name: Upload deb package
uses: actions/upload-artifact@v4
with:
if-no-files-found: error
name: ${{ steps.deb.outputs.name }}-qt${{ matrix.qt-version-major }}-${{ steps.vars.outputs.distro_name }}-${{ matrix.build-type }}
path: ${{ steps.deb.outputs.path }}
rpm:
name: rpm (${{ matrix.build-type }}, Qt ${{ matrix.qt-version-major }}, ${{ matrix.image }})
runs-on: ubuntu-latest
container: zjeffer/notes:${{ matrix.image }}
strategy:
fail-fast: false
matrix:
include:
- # Fedora's release cycle: https://docs.fedoraproject.org/en-US/releases/lifecycle/
image: fedora
qt-version-major: 6
build-type: release
- image: opensuse
qt-version-major: 6
build-type: release
steps:
- name: Setup git configuration
# workaround for "detected dubious ownership in repository" git error: https://github.com/actions/checkout/issues/1169
run: git config --global --add safe.directory "${PWD}"
- name: Checkout code
uses: actions/checkout@v4
with:
submodules: recursive
- name: Set up variables
shell: bash
id: vars
run: |
set -x
distro_id=$(grep -oPm1 '^ID="?\K[^"]+' /etc/os-release)
if [ -z "${distro_id}" ]
then
echo 'Failed to extract distro ID from /etc/os-release.'
exit 1
fi
version_id=$(grep -oPm1 '^VERSION_ID="?\K[^"]+' /etc/os-release)
if [ -z "${version_id}" ]
then
echo 'Failed to extract version id from /etc/os-release.'
exit 1
fi
echo "distro_name=${distro_id}-${version_id}" >> "${GITHUB_OUTPUT}"
- name: Setup GCC problem matcher
uses: ammaraskar/gcc-problem-matcher@0.3.0
- name: Build (${{ matrix.build-type }})
env:
VERBOSE: 1
# openSUSE defaults to GCC 7, which doesn't support the filesystem library from C++17,
# and causes trouble compiling for Qt 6. So we have to manully specify GCC 10 instead.
CXX: ${{ startsWith(matrix.image, 'opensuse') && 'g++-10' || 'g++' }}
run: |
cmake --warn-uninitialized --warn-unused-vars \
-B build \
-DCMAKE_BUILD_TYPE=${{ matrix.build-type }} \
-DGIT_REVISION=${{ github.ref_type != 'tag' && 'ON' || 'OFF' }} \
-DCMAKE_POSITION_INDEPENDENT_CODE=TRUE \
-DUPDATE_CHECKER=OFF \
-DUSE_QT_VERSION=${{ matrix.qt-version-major }} \
-DPRO_VERSION=OFF
cmake --build build --parallel $(nproc)
- name: Create rpm package
run: |
cd build
cpack -G RPM
- name: Grab rpm package name
id: rpm
shell: bash
run: |
set -x
if ! path=$(find build/ -maxdepth 1 -name '*.rpm' -print -quit)
then
echo 'Fatal: Unable to find rpm package!'
exit 1;
fi
echo "name=$(basename "${path%.*}")" >> "${GITHUB_OUTPUT}"
echo "path=${path}" >> "${GITHUB_OUTPUT}"
- name: Run rpmlint
run: |
rpmlint '${{ steps.rpm.outputs.path }}'
- name: Upload rpm package
uses: actions/upload-artifact@v4
with:
if-no-files-found: error
name: ${{ steps.rpm.outputs.name }}-qt${{ matrix.qt-version-major }}-${{ steps.vars.outputs.distro_name }}-${{ matrix.build-type }}
path: ${{ steps.rpm.outputs.path }}
# Build the AppImage using official Qt releases, downloaded by aqtinstall.
# This is also done for macOS and Windows, just to make sure we use the exact same Qt version across all three OSes.
#
# NOTE: This job uses a fixed Qt version (set in the 'qt-version' key below)!
# So, remember to keep it updated whenever a new Qt version is available on aqtinstall.
appimage-aqtinstall:
name: AppImage (${{ matrix.build-type }}, Qt ${{ matrix.qt-version }}, ${{ matrix.image }})
runs-on: ${{ matrix.os }}
container:
image: zjeffer/notes:${{ matrix.image }}
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-22.04
build-type: release
qt-version: 5.15.2
image: ubuntu-aqtinstall-5
- os: ubuntu-22.04
build-type: release
qt-version: 6.4.3
image: ubuntu-aqtinstall-6
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
submodules: recursive
- name: Setup variables
shell: bash
id: vars
run: |
set -x
version=$(grep -oPm1 '\bAPP_VERSION +\K[^)]+' CMakeLists.txt)
if [ -z "${version}" ]
then
echo 'Failed to extract app version from CMakeLists.txt.'
exit 1
fi
if [ '${{ github.ref_type }}' != 'tag' ]
then
version="${version}+g${GITHUB_SHA::7}"
fi
artifact_name="Notes_${version}-Qt${{ matrix.qt-version }}-x86_64"
if [ '${{ matrix.build-type }}' == 'debug' ]
then
file_name="${artifact_name}-debug.AppImage"
else
file_name="${artifact_name}.AppImage"
fi
echo "version=${version}" >> "${GITHUB_OUTPUT}"
echo "artifact_name=${artifact_name}" >> "${GITHUB_OUTPUT}"
echo "file_name=${file_name}" >> "${GITHUB_OUTPUT}"
# TODO: Figure out why this error only occurs on the Linux container when building with -DGIT_REVISION=ON
# The error: fatal: detected dubious ownership in repository
- name: Prevent git's dubious ownership message
if: github.ref_type != 'tag'
run: |
git config --global --add safe.directory "${PWD}"
- name: Build (${{ matrix.build-type }})
env:
VERBOSE: 1
run: |
cmake --warn-uninitialized --warn-unused-vars \
-B build \
-DCMAKE_BUILD_TYPE=${{ matrix.build-type }} \
-DGIT_REVISION=${{ github.ref_type != 'tag' && 'ON' || 'OFF' }} \
-DCMAKE_INSTALL_PREFIX=/usr \
-DPRO_VERSION=OFF
cmake --build build --parallel $(nproc)
- name: (FIXME) Run qmllint
if: startsWith(matrix.qt-version, '6.')
run: |
cmake --build build --target all_qmllint || true
- name: Install (${{ matrix.build-type }})
run: |
make -C build DESTDIR=Notes install
- name: Setup linuxdeploy
run: |
cd build
curl -fLO --retry 10 https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage
chmod +x linuxdeploy-x86_64.AppImage
- name: Setup Qt plugin for linuxdeploy
run: |
cd build
curl -fLO --retry 10 https://github.com/linuxdeploy/linuxdeploy-plugin-qt/releases/download/continuous/linuxdeploy-plugin-qt-x86_64.AppImage
chmod +x linuxdeploy-plugin-qt-x86_64.AppImage
- name: Deploy (${{ matrix.build-type }})
env:
APPIMAGE_EXTRACT_AND_RUN: 1
run: |
export QML_SOURCES_PATHS="${PWD}/src/qml"
cd build
./linuxdeploy-x86_64.AppImage --appdir Notes --plugin qt
- name: Remove unnecessary Qt plugins and libraries
shell: bash
run: |
set -x
set -e
cd build/Notes
if [[ '${{ matrix.qt-version }}' == 5.* ]]
then
# The bearer plugin has caused problems for us in the past. Plus, it was removed altogether in Qt 6.
rm -rv usr/plugins/bearer
fi
# We only use the SQLite Qt driver, so it's fine to delete others.
rm -v usr/plugins/sqldrivers/libqsqlodbc.so
rm -v usr/plugins/sqldrivers/libqsqlpsql.so
if [[ '${{ matrix.qt-version }}' == 6.* ]]
then
# The Qt 6 build also has a MySQL Qt driver we don't use.
rm -v usr/plugins/sqldrivers/libqsqlmysql.so
rm -v usr/lib/libmysqlclient.so.*
fi
- name: Validate AppStream metadata
if: matrix.image != 'ubuntu:20.04'
run: |
cd build/Notes
appstreamcli validate --verbose 'usr/share/metainfo/${{ env.APP_ID }}.metainfo.xml'
- name: Validate desktop file
run: |
cd build/Notes
desktop-file-validate 'usr/share/applications/${{ env.APP_ID }}.desktop'
- name: Build AppImage (${{ matrix.build-type }})
env:
APPIMAGE_EXTRACT_AND_RUN: 1
run: |
cd build
export VERSION='${{ steps.vars.outputs.version }}'
./linuxdeploy-x86_64.AppImage --appdir Notes --output appimage
mv -v Notes*.AppImage '${{ steps.vars.outputs.file_name }}'
- name: Upload AppImage artifact (${{ matrix.build-type }})
uses: actions/upload-artifact@v4
with:
if-no-files-found: error
name: ${{ steps.vars.outputs.artifact_name }}-${{ runner.os }}-${{ matrix.build-type }}
path: build/${{ steps.vars.outputs.file_name }}
snap:
name: snap
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
submodules: recursive
- name: Install snapcraft
run: |
sudo snap install snapcraft --classic
- name: Set up LXD
run: |
sudo usermod -a -G lxd "${USER}"
sudo lxd init --auto
sudo iptables -P FORWARD ACCEPT
- name: Build
run: |
sg lxd -c 'snap run snapcraft -v'
- name: Grab snap package name
id: snap
shell: bash
run: |
set -x
if ! path=$(find . -maxdepth 1 -name '*.snap' -print -quit)
then
echo 'Fatal: Unable to find snap package'
exit 1
fi
echo "name=$(basename "${path%.*}")" >> "${GITHUB_OUTPUT}"
echo "path=${path}" >> "${GITHUB_OUTPUT}"
- name: Upload snap package
uses: actions/upload-artifact@v4
with:
if-no-files-found: error
name: ${{ steps.snap.outputs.name }}.snap
path: ${{ steps.snap.outputs.path }}

@ -0,0 +1,228 @@
name: macOS
on:
workflow_call:
workflow_dispatch:
jobs:
# This job is mainly to make sure Notes will compile with Qt from homebrew's repository.
# So it doesn't make much sense to have different build types other than 'debug' here.
# The release dmg is built using aqtinstall instead (the job below this one).
build-homebrew:
name: Build (${{ matrix.build-type }}, homebrew (qt${{ matrix.qt-version-major }}), ${{ matrix.os }})
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
include:
- os: macos-12
qt-version-major: 5
build-type: debug
- os: macos-12
qt-version-major: 6
build-type: debug
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
submodules: recursive
- name: Install Qt ${{ matrix.qt-version-major }} (homebrew)
env:
# TODO: remove once https://github.com/actions/setup-python/issues/577 gets fixed.
HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK: 1
run: |
brew update
brew install ninja qt@${{ matrix.qt-version-major }}
- name: Configure Qt ${{ matrix.qt-version-major }} (homebrew)
run: |
brew link qt@${{ matrix.qt-version-major }}
cat << EOF
LDFLAGS="-L/usr/local/opt/qt@${{ matrix.qt-version-major }}/lib"
export CPPFLAGS="-I/usr/local/opt/qt@${{ matrix.qt-version-major }}/include"
export PATH="/usr/local/opt/qt@${{ matrix.qt-version-major }}/bin:$PATH"
EOF >> ~/.bashrc
- name: Setup CLang problem matcher
# Technically, this action only supports GCC, but it seems to work well for Clang too.
if: matrix.build-type == 'debug'
uses: ammaraskar/gcc-problem-matcher@0.3.0
- name: Build (${{ matrix.build-type }})
env:
VERBOSE: 1
run: |
export CMAKE_BUILD_PARALLEL_LEVEL=$(sysctl -n hw.logicalcpu)
cmake . --warn-uninitialized --warn-unused-vars \
-G Ninja -B build \
-DCMAKE_BUILD_TYPE=${{ matrix.build-type }} \
-DCMAKE_PREFIX_PATH="$(brew --prefix qt@${{ matrix.qt-version-major }})" \
-DPRO_VERSION=OFF
cmake --build build
# Build the dmg disk image using the official Qt 5 release downloaded by aqtinstall.
# This is also done for Linux and Windows, just to make sure we use the exact same Qt version across all three OSes.
#
# NOTE: This job uses a fixed Qt version (set in the 'qt-version' key below)!
# So, remember to keep it updated whenever a new Qt version is available on aqtinstall.
dmg-aqtinstall:
name: dmg (${{ matrix.build-type }}, Qt ${{ matrix.qt-version }}, ${{ matrix.os }})
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
include:
- os: macos-11
qt-version: 5.15.2
build-type: release
- os: macos-11
qt-version: 6.5.2
build-type: release
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
submodules: recursive
- name: Setup variables
id: vars
run: |
set -x
version=$(grep -Em1 '\bAPP_VERSION' CMakeLists.txt | sed -r 's/.*APP_VERSION +//; s/ *)//')
if [ -z "${version}" ]
then
echo 'Failed to extract app version from CMakeLists.txt.'
exit 1
fi
if [ '${{ github.ref_type }}' != 'tag' ]
then
version="${version}+g${GITHUB_SHA::7}"
fi
arches='x86_64'
if [[ '${{ matrix.qt-version }}' == 6.* ]]
then
arches+='-arm64'
fi
artifact_name="Notes_${version}-Qt${{ matrix.qt-version }}-${arches}"
if [ '${{ matrix.build-type }}' == 'debug' ]
then
file_name="${artifact_name}-debug.dmg"
else
file_name="${artifact_name}.dmg"
fi
echo "version=${version}" >> "${GITHUB_OUTPUT}"
echo "artifact_name=${artifact_name}" >> "${GITHUB_OUTPUT}"
echo "file_name=${file_name}" >> "${GITHUB_OUTPUT}"
- name: Install Qt ${{ matrix.qt-version }} (aqtinstall)
uses: jurplel/install-qt-action@v3
with:
version: ${{ matrix.qt-version }}
cache: true
- name: Install dependencies
run: |
brew update
brew install create-dmg ninja
- name: Build (${{ matrix.build-type }})
env:
# Only commercial Qt 5 supports targeting Apple Silicon at the moment:
# https://www.qt.io/blog/qt-on-apple-silicon
TARGET_ARCH: ${{ startsWith(matrix.qt-version, '6.') && 'x86_64;arm64' || 'x86_64' }}
VERBOSE: 1
run: |
export CMAKE_BUILD_PARALLEL_LEVEL=$(sysctl -n hw.logicalcpu)
cmake . --warn-uninitialized --warn-unused-vars \
-B build -G Ninja \
-DCMAKE_BUILD_TYPE=${{ matrix.build-type }} \
-DGIT_REVISION=${{ github.ref_type != 'tag' && 'ON' || 'OFF' }} \
-DCMAKE_OSX_ARCHITECTURES="${{ env.TARGET_ARCH }}" \
-DPRO_VERSION=OFF
cmake --build build
- name: (FIXME) Run qmllint
if: startsWith(matrix.qt-version, '6.')
run: |
cmake --build build --target all_qmllint || true
- name: Install (${{ matrix.build-type }})
run: |
cmake --install build --prefix .
- name: Deploy (${{ matrix.build-type }})
run: |
cd build
plutil -insert NSRequiresAquaSystemAppearance -bool true Notes.app/Contents/Info.plist
# Rename the app folder to "Notes Better", so it doesn't conflict with macOS' "Notes" app.
mv Notes.app 'Notes Better.app'
macdeployqt 'Notes Better.app' -qmldir=../src/qml -appstore-compliant
- name: Remove unnecessary Qt plugins and libraries
run: |
set -x
set -e
cd 'build/Notes Better.app'
if [[ '${{ matrix.qt-version }}' == 5.* ]]
then
# The bearer plugin has caused problems for us in the past. Plus, it was removed altogether in Qt 6.
rm -rv Contents/PlugIns/bearer
fi
- name: Import signing certificate
if: github.repository == 'nuttyartist/notes' && github.event_name != 'pull_request'
run: |
openssl base64 -d -out cert.p12 <<< '${{ secrets.MACOS_CERTIFICATE }}'
security create-keychain -p '${{ secrets.KEYCHAIN_PWD }}' nuttyartist/notes
security default-keychain -s nuttyartist/notes
security unlock-keychain -p '${{ secrets.KEYCHAIN_PWD }}' nuttyartist/notes
security -q import cert.p12 -f pkcs12 -k nuttyartist/notes -P '${{ secrets.MACOS_CERTIFICATE_PWD }}' -T /usr/bin/codesign -x
security set-key-partition-list -S 'apple-tool:,apple:' -s -k '${{ secrets.KEYCHAIN_PWD }}' nuttyartist/notes
- name: Sign
if: github.repository == 'nuttyartist/notes' && github.event_name != 'pull_request'
run: |
codesign --deep --force --verify --verbose --sign Mamistvalove --options runtime 'build/Notes Better.app'
- name: Build dmg (${{ matrix.build-type }})
run: |
cd build
create-dmg \
--no-internet-enable \
--format ULFO \
--background ../packaging/macos/dmg-background.png \
--hide-extension 'Notes Better.app' \
--icon 'Notes Better.app' 180 170 \
--icon-size 160 \
--text-size 12 \
--volname Notes \
--volicon ../src/images/notes_icon.icns \
--window-size 660 400 \
--app-drop-link 480 170 \
'${{ steps.vars.outputs.file_name }}' \
'Notes Better.app'
- name: Notarize
if: github.repository == 'nuttyartist/notes' && github.event_name != 'pull_request'
run: |
xcrun notarytool submit \
--apple-id '${{ secrets.NOTARIZATION_USERNAME }}' \
--password '${{ secrets.NOTARIZATION_PASSWORD }}' \
--team-id '${{ secrets.NOTARIZATION_TEAM }}' \
--wait \
'build/${{ steps.vars.outputs.file_name }}'
- name: Staple
if: github.repository == 'nuttyartist/notes' && github.event_name != 'pull_request'
run: |
xcrun stapler staple 'build/${{ steps.vars.outputs.file_name }}'
- name: Upload dmg artifact (${{ matrix.build-type }})
uses: actions/upload-artifact@v4
with:
if-no-files-found: error
name: ${{ steps.vars.outputs.artifact_name }}-${{ runner.os }}-${{ matrix.build-type }}
path: build/${{ steps.vars.outputs.file_name }}

@ -0,0 +1,248 @@
name: Windows
on:
workflow_call:
workflow_dispatch:
jobs:
# NOTE: This job uses a fixed Qt version (set in the 'qt-version' key below)!
# So, remember to keep it updated whenever a new Qt version is available on aqtinstall.
build-aqtinstall:
name: Build (${{ matrix.arch }}, ${{ matrix.build-type }}, Qt ${{ matrix.qt-version }}, ${{ matrix.os }})
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
include:
- os: windows-2019
arch: x64
qt-version: 5.15.2
build-type: release
- os: windows-2019
arch: x86
qt-version: 5.15.2
build-type: release
- os: windows-2019
arch: x64
qt-version: 6.4.3
build-type: release
outputs:
version: ${{ steps.vars.outputs.version }}
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
submodules: recursive
- name: Setup variables
id: vars
run: |
$version = Select-String -Path CMakeLists.txt -CaseSensitive -Pattern '\bAPP_VERSION +([^)]+)' | Select-Object -First 1 | %{$_.Matches.Groups[1].value}
if (!$version) {
throw "Failed to extract app version from CMakeLists.txt."
}
if ('${{ github.ref_type }}' -ne 'tag') {
$version += "+g$($env:GITHUB_SHA.Substring(0,7))"
}
$artifact_name = "Notes_$version-Qt${{ matrix.qt-version }}-${{ matrix.arch }}"
Write-Output "version=$version" >> $env:GITHUB_OUTPUT
Write-Output "artifact_name=$artifact_name" >> $env:GITHUB_OUTPUT
- name: Setup MSVC (${{ matrix.arch }})
uses: ilammy/msvc-dev-cmd@v1
with:
arch: ${{ matrix.arch }}
- name: Install Qt ${{ matrix.qt-version }} (aqtinstall, ${{ matrix.arch }})
uses: jurplel/install-qt-action@v3
with:
version: ${{ matrix.qt-version }}
cache: true
arch: ${{ matrix.arch == 'x86' && 'win32_msvc2019' || 'win64_msvc2019_64' }}
# Details about this OpenSSL build: https://kb.firedaemon.com/support/solutions/articles/4000121705
# TODO: Remove/tweak this step if/when we get rid of the x86 build or upgrade to Qt 6.5+.
- name: Download OpenSSL 1.x binaries from FireDaemon
if: ${{ startsWith(matrix.qt-version, '5.') || startsWith(matrix.qt-version, '6.4.') }}
run: |
$out_file = "openssl-1.1.1w.zip"
Invoke-WebRequest -Uri https://download.firedaemon.com/FireDaemon-OpenSSL/openssl-1.1.1w.zip -OutFile $env:Temp\$out_file
Expand-Archive -Path $env:Temp\$out_file -DestinationPath $env:Temp
Rename-Item $env:Temp\openssl-1.1 $env:Temp\OpenSSL
- name: Setup MSVC problem matcher
uses: ammaraskar/msvc-problem-matcher@0.3.0
- name: Build (${{ matrix.build-type }}, ${{ matrix.arch }})
env:
VERBOSE: 1
run: |
$env:CMAKE_BUILD_PARALLEL_LEVEL = $env:NUMBER_OF_PROCESSORS
cmake . --warn-uninitialized --warn-unused-vars `
-B build -G Ninja `
-DCMAKE_BUILD_TYPE=${{ matrix.build-type }} `
-DGIT_REVISION=${{ github.ref_type != 'tag' && 'ON' || 'OFF' }} `
-DPRO_VERSION=OFF
cmake --build build
- name: (FIXME) Run qmllint
if: startsWith(matrix.qt-version, '6.')
run: |
cmake --build build --target all_qmllint || $(exit 0)
- name: Install (${{ matrix.build-type }}, ${{ matrix.arch }})
run: |
cmake --install build --prefix build
- name: Deploy (${{ matrix.build-type }}, ${{ matrix.arch }})
run: |
windeployqt ${{ startsWith(matrix.qt-version, '5.') && '--no-qmltooling' || ' ' }} --qmldir src\qml build\bin
- name: Remove unnecessary Qt plugins and libraries
run: |
Set-Location build\bin
# We ship all required runtime DLLs individually.
Remove-Item -Verbose vc_redist.*.exe
if ('${{ matrix.qt-version }}'.StartsWith('5.')) {
# The bearer plugin has caused problems for us in the past. Plus, it was removed altogether in Qt 6.
Remove-Item -Verbose -Recurse bearer
}
# We only use the SQLite Qt driver, so it's fine to delete others.
Remove-Item -Verbose sqldrivers\qsqlodbc.dll
Remove-Item -Verbose sqldrivers\qsqlpsql.dll
- name: Include required runtime libraries (${{ matrix.build-type }}, ${{ matrix.arch }})
run: |
Set-Location build\bin
if ('${{ matrix.arch }}' -ieq 'x64') {
$openssl_lib_suffix = '-x64'
} else {
$openssl_lib_suffix = ''
}
# Include OpenSSL libraries.
Copy-Item $env:Temp\OpenSSL\${{ matrix.arch }}\bin\libcrypto-1_1$openssl_lib_suffix.dll
Copy-Item $env:Temp\OpenSSL\${{ matrix.arch }}\bin\libssl-1_1$openssl_lib_suffix.dll
# Also include OpenSSL debug symbols (when building Notes in debug mode).
if ('${{ matrix.build-type }}' -ieq 'debug') {
Copy-Item $env:Temp\OpenSSL\${{ matrix.arch }}\bin\libcrypto-1_1$openssl_lib_suffix.pdb
Copy-Item $env:Temp\OpenSSL\${{ matrix.arch }}\bin\libssl-1_1$openssl_lib_suffix.pdb
}
# Include MSVC 2019 runtime libraries.
if ('${{ matrix.build-type }}' -ieq 'release') {
Copy-Item $env:VCToolsRedistDir\${{ matrix.arch }}\Microsoft.VC142.CRT\msvcp140.dll
Copy-Item $env:VCToolsRedistDir\${{ matrix.arch }}\Microsoft.VC142.CRT\msvcp140_1.dll
# Only Qt 6 builds also need msvcp140_2.dll
if ('${{ matrix.qt-version }}'.StartsWith('6')) {
Copy-Item $env:VCToolsRedistDir\${{ matrix.arch }}\Microsoft.VC142.CRT\msvcp140_2.dll
}
Copy-Item $env:VCToolsRedistDir\${{ matrix.arch }}\Microsoft.VC142.CRT\vcruntime140.dll
if ('${{ matrix.arch }}' -ieq 'x64') {
# Only 64-bit builds also need 'vcruntime140_1.dll' (tested on Windows 7)
Copy-Item $env:VCToolsRedistDir\${{ matrix.arch }}\Microsoft.VC142.CRT\vcruntime140_1.dll
}
} else {
# On debug builds, the libraries above are included automatically, so we only need 'urtcbased.dll'.
Copy-Item $env:WindowsSdkBinPath\${{ matrix.arch }}\ucrt\ucrtbased.dll
}
- name: Upload artifacts (${{ matrix.build-type }}, ${{ matrix.arch }})
uses: actions/upload-artifact@v4
with:
if-no-files-found: error
name: ${{ steps.vars.outputs.artifact_name }}-${{ runner.os }}-${{ matrix.build-type }}
path: build\bin
unified-installer:
name: Unified x64-x86 Installer
needs: build-aqtinstall
runs-on: windows-2019
steps:
- name: Checkout code to grab the ISS script
uses: actions/checkout@v4
- name: Download build artifacts from previous job
uses: actions/download-artifact@v4
with:
path: artifacts
pattern: '*Windows*'
- name: Ensure a 64-bit Qt 6 build is present
run: |
Set-Location artifacts
$x64_build = Get-ChildItem -Filter '*Qt6*-x64-Windows-release' -Attributes Directory |
Sort-Object -Property @{Expression = "Name"; Descending = $true} |
Select-Object -First 1
if (!$x64_build) {
Throw 'Could not find a 64-bit Qt 6 build.'
}
Move-Item $x64_build Notes64
- name: Ensure a 32-bit Qt 5 build is present
run: |
Set-Location artifacts
$x86_build = Get-ChildItem -Filter '*Qt5*-x86-Windows-release' -Attributes Directory |
Sort-Object -Property @{Expression = "Name"; Descending = $true} |
Select-Object -First 1
if (!$x86_build) {
Throw 'Could not find a 32-bit Qt 5 build.'
}
Move-Item $x86_build Notes32
- name: Create unified installer
run: |
Set-Location artifacts
Copy-Item ..\packaging\windows\Notes_Inno_Script_Github.iss
$env:APP_VERSION = '${{ needs.build-aqtinstall.outputs.version }}'
iscc /Oinstaller Notes_Inno_Script_Github.iss
# This step makes sure that all files copied by windeployqt are also included in the final installer.
# This is done by parsing the 'Set-Manifest.txt' file, which is generated by Inno Setup:
# https://jrsoftware.org/ishelp/index.php?topic=setup_outputmanifestfile
- name: Verify installer files
run: |
Set-Location artifacts
$inno_setup_manifest = ".\installer\Setup-Manifest.txt"
$windeployqt_paths = @(".\Notes32", ".\Notes64")
$inno_setup_files = @()
Get-Content -LiteralPath $inno_setup_manifest -ErrorAction Stop | Select-Object -Skip 1 | Foreach-Object {
$path = ($_ -Split "\t")[1] # We only need the second column, which refers to the absolute path of the file.
$inno_setup_files += (Resolve-Path $path).ToString()
}
$missing_files = 0
Get-ChildItem -File -LiteralPath $windeployqt_paths -Recurse -ErrorAction Stop | Foreach-Object {
$path = (Resolve-Path $_).ToString()
if ($path -NotIn $inno_setup_files) {
Write-Host "File '$path' was not included in Inno Setup's list of files." -ForegroundColor Yellow
$missing_files++
}
}
if ($missing_files -gt 0) {
$is_plural = $missing_files -gt 1
Write-Host ""
Write-Host ("ERROR: {0} {1} previously copied by windeployqt {2} missing from Inno Setup's list of files." `
-F $missing_files, ($is_plural ? "files" : "file"), ($is_plural ? "are" : "is")) `
-ForegroundColor DarkRed
Write-Host (" Did you forget to include {0} in '.\packaging\windows\Notes_Inno_Script_Github.iss'?" `
-F ($is_plural ? "them" : "it")) `
-ForegroundColor DarkRed
Exit 1
}
Write-Host "SUCCESS: List of files in the installer matches the ones copied by windeployqt."
- name: Upload unified installer artifact
uses: actions/upload-artifact@v4
with:
if-no-files-found: error
name: NotesSetup_${{ needs.build-aqtinstall.outputs.version }}-${{ runner.os }}-release
path: artifacts\installer

46
source/.gitignore vendored

@ -1,9 +1,39 @@
# generated files
bin/
gen/
# Build dirs and files #
########################
*.pro.user
build-Notes-*
build-*
bin*
CMakeLists.txt.user
# Local configuration file (sdk path, etc)
project.properties
.settings/
.classpath
.project
# OS generated files #
######################
.DS_Store*
.vscode/
.cache/
ehthumbs.db
Thumbs.db
Makefile
Notes
qrc_images.cpp
*.autosave
*~
*.snap
*.swp
__pycache__
packaging/linux/deb_build/
packaging/linux/snap/stage
packaging/linux/snap/snap
packaging/linux/snap/parts/notes
packaging/linux/snap/parts/desktop
prime/
squashfs-root/
build/
install/
src/moc
src/obj
src/qrc
src/snap
src/uic
src/notes
.qmake.stash

@ -0,0 +1,9 @@
[submodule "3rdParty/qautostart"]
path = 3rdParty/qautostart
url = https://github.com/b00f/qautostart.git
[submodule "3rdParty/qmarkdowntextedit"]
path = 3rdParty/qmarkdowntextedit
url = https://github.com/pbek/qmarkdowntextedit
[submodule "3rdParty/QSimpleUpdater"]
path = 3rdParty/QSimpleUpdater
url = https://github.com/alex-spataru/QSimpleUpdater

@ -0,0 +1,2 @@
*.h whitespace=cr-at-eol
*.cpp whitespace=cr-at-eol

@ -0,0 +1,27 @@
== main developers ==
Arvid Picciani <aep@libqxt.org>
Adam Higerd <ahigerd@libqxt.org>
J-P Nurmi <jpnurmi@libqxt.org>
Benjamin Zeller <zbenjamin@libqxt.org>
== contributors ==
Gabriel Assis Bezerra
Scott Aron Bloom
Lawrence Holtsclaw
Marcin Jakubowski
Dominique Leducq
Marcus Lindblom
Konstantin Molchanov
Thomas Mueller
Bjørn Erik Nilsen
Kaleb Pederson
Matthew Schnee
André Somers
Alex Unden
Chris Vickery
Benjamin Wohlwend
thanks everyone not named for all the patches, bug reports,
beta tests, and the free beer :-)

@ -0,0 +1,30 @@
/****************************************************************************
** Copyright (c) 2006 - 2011, the LibQxt project.
** See the Qxt AUTHORS file for a list of authors and copyright holders.
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** * Neither the name of the LibQxt project nor the
** names of its contributors may be used to endorse or promote products
** derived from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
** DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**
** <http://libqxt.org> <foundation@libqxt.org>
*****************************************************************************/

@ -0,0 +1,26 @@
INCLUDEPATH += $$PWD
HEADERS += \
$$PWD/qxtglobal.h \
$$PWD/qxtglobalshortcut_p.h \
$$PWD/qxtglobalshortcut.h
SOURCES += \
$$PWD/qxtglobal.cpp \
$$PWD/qxtglobalshortcut.cpp
win32 {
LIBS+= -luser32
DEFINES += QXT_STATIC
SOURCES += $$PWD/qxtglobalshortcut_win.cpp
}
macx {
LIBS += -framework Carbon
SOURCES += $$PWD/qxtglobalshortcut_mac.cpp
}
unix:!macx {
LIBS += -lX11
SOURCES += $$PWD/qxtglobalshortcut_x11.cpp
}

@ -0,0 +1,251 @@
/****************************************************************************
** Copyright (c) 2006 - 2011, the LibQxt project.
** See the Qxt AUTHORS file for a list of authors and copyright holders.
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** * Neither the name of the LibQxt project nor the
** names of its contributors may be used to endorse or promote products
** derived from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
** DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**
** <http://libqxt.org> <foundation@libqxt.org>
*****************************************************************************/
#include "qxtglobal.h"
/*!
\headerfile <QxtGlobal>
\title Global Qxt Declarations
\inmodule QxtCore
\brief The <QxtGlobal> header provides basic declarations and
is included by all other Qxt headers.
*/
/*!
\macro QXT_VERSION
\relates <QxtGlobal>
This macro expands a numeric value of the form 0xMMNNPP (MM =
major, NN = minor, PP = patch) that specifies Qxt's version
number. For example, if you compile your application against Qxt
0.4.0, the QXT_VERSION macro will expand to 0x000400.
You can use QXT_VERSION to use the latest Qt features where
available. For example:
\code
#if QXT_VERSION >= 0x000400
qxtTabWidget->setTabMovementMode(QxtTabWidget::InPlaceMovement);
#endif
\endcode
\sa QXT_VERSION_STR, qxtVersion()
*/
/*!
\macro QXT_VERSION_STR
\relates <QxtGlobal>
This macro expands to a string that specifies Qxt's version number
(for example, "0.4.0"). This is the version against which the
application is compiled.
\sa qxtVersion(), QXT_VERSION
*/
/*!
\relates <QxtGlobal>
Returns the version number of Qxt at run-time as a string (for
example, "0.4.0"). This may be a different version than the
version the application was compiled against.
\sa QXT_VERSION_STR
*/
const char * qxtVersion()
{
return QXT_VERSION_STR;
}
/*!
\headerfile <QxtPimpl>
\title The Qxt private implementation
\inmodule QxtCore
\brief The <QxtPimpl> header provides tools for hiding
details of a class.
Application code generally doesn't have to be concerned about hiding its
implementation details, but when writing library code it is important to
maintain a constant interface, both source and binary. Maintaining a constant
source interface is easy enough, but keeping the binary interface constant
means moving implementation details into a private class. The PIMPL, or
d-pointer, idiom is a common method of implementing this separation. QxtPimpl
offers a convenient way to connect the public and private sides of your class.
\section1 Getting Started
Before you declare the public class, you need to make a forward declaration
of the private class. The private class must have the same name as the public
class, followed by the word Private. For example, a class named MyTest would
declare the private class with:
\code
class MyTestPrivate;
\endcode
\section1 The Public Class
Generally, you shouldn't keep any data members in the public class without a
good reason. Functions that are part of the public interface should be declared
in the public class, and functions that need to be available to subclasses (for
calling or overriding) should be in the protected section of the public class.
To connect the private class to the public class, include the
QXT_DECLARE_PRIVATE macro in the private section of the public class. In the
example above, the private class is connected as follows:
\code
private:
QXT_DECLARE_PRIVATE(MyTest)
\endcode
Additionally, you must include the QXT_INIT_PRIVATE macro in the public class's
constructor. Continuing with the MyTest example, your constructor might look
like this:
\code
MyTest::MyTest() {
// initialization
QXT_INIT_PRIVATE(MyTest);
}
\endcode
\section1 The Private Class
As mentioned above, data members should usually be kept in the private class.
This allows the memory layout of the private class to change without breaking
binary compatibility for the public class. Functions that exist only as
implementation details, or functions that need access to private data members,
should be implemented here.
To define the private class, inherit from the template QxtPrivate class, and
include the QXT_DECLARE_PUBLIC macro in its public section. The template
parameter should be the name of the public class. For example:
\code
class MyTestPrivate : public QxtPrivate<MyTest> {
public:
MyTestPrivate();
QXT_DECLARE_PUBLIC(MyTest)
};
\endcode
\section1 Accessing Private Members
Use the qxt_d() function (actually a function-like object) from functions in
the public class to access the private class. Similarly, functions in the
private class can invoke functions in the public class by using the qxt_p()
function (this one's actually a function).
For example, assume that MyTest has methods named getFoobar and doBaz(),
and MyTestPrivate has a member named foobar and a method named doQuux().
The code might resemble this example:
\code
int MyTest::getFoobar() {
return qxt_d().foobar;
}
void MyTestPrivate::doQuux() {
qxt_p().doBaz(foobar);
}
\endcode
*/
/*!
* \macro QXT_DECLARE_PRIVATE(PUB)
* \relates <QxtPimpl>
* Declares that a public class has a related private class.
*
* This shuold be put in the private section of the public class. The
* parameter \a PUB must be the name of the public class.
*/
/*!
* \macro QXT_DECLARE_PUBLIC(PUB)
* \relates <QxtPimpl>
* Declares that a private class has a related public class named \a PUB.
*
* This may be put anywhere in the declaration of the private class. The parameter is the name of the public class.
*/
/*!
* \macro QXT_INIT_PRIVATE(PUB)
* \relates <QxtPimpl>
* Initializes resources owned by the private class.
*
* This should be called from the public class's constructor,
* before qxt_d() is used for the first time. The parameter \a PUB must be
* the name of the public class.
*/
/*!
* \macro QXT_D(PUB)
* \relates <QxtPimpl>
* Returns a reference in the current scope named "d" to the private class
* associated with the public class \a PUB.
*
* This function is only available in a class using QXT_DECLARE_PRIVATE().
*/
/*!
* \macro QXT_P(PUB)
* \relates <QxtPimpl>
* Creates a reference in the current scope named "q" to the public class
* named \a PUB.
*
* This macro only works in a class using QXT_DECLARE_PUBLIC().
*/
/*!
* \fn QxtPrivate<PUB>& PUB::qxt_d()
* \relates <QxtPimpl>
* Returns a reference to the private class.
*
* This function is only available in a class using \a QXT_DECLARE_PRIVATE.
*/
/*!
* \fn const QxtPrivate<PUB>& PUB::qxt_d() const
* \relates <QxtPimpl>
* Returns a const reference to the private class.
*
* This function is only available in a class using \a QXT_DECLARE_PRIVATE.
* This overload will be automatically used in const functions.
*/
/*!
* \fn PUB& QxtPrivate::qxt_p()
* \relates <QxtPimpl>
* Returns a reference to the public class.
*
* This function is only available in a class using QXT_DECLARE_PUBLIC().
*/
/*!
* \fn const PUB& QxtPrivate::qxt_p() const
* \relates <QxtPimpl>
* Returns a const reference to the public class.
*
* This function is only available in a class using QXT_DECLARE_PUBLIC().
* This overload will be automatically used in const functions.
*/

@ -0,0 +1,233 @@
/****************************************************************************
** Copyright (c) 2006 - 2011, the LibQxt project.
** See the Qxt AUTHORS file for a list of authors and copyright holders.
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** * Neither the name of the LibQxt project nor the
** names of its contributors may be used to endorse or promote products
** derived from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
** DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**
** <http://libqxt.org> <foundation@libqxt.org>
*****************************************************************************/
#ifndef QXTGLOBAL_H
#define QXTGLOBAL_H
#include <QtGlobal>
#define QXT_VERSION 0x000700
#define QXT_VERSION_STR "0.7.0"
//--------------------------global macros------------------------------
#ifndef QXT_NO_MACROS
#ifndef _countof
#define _countof(x) (sizeof(x)/sizeof(*x))
#endif
#endif // QXT_NO_MACROS
//--------------------------export macros------------------------------
#define QXT_DLLEXPORT DO_NOT_USE_THIS_ANYMORE
#if !defined(QXT_STATIC) && !defined(QXT_DOXYGEN_RUN)
# if defined(BUILD_QXT_CORE)
# define QXT_CORE_EXPORT Q_DECL_EXPORT
# else
# define QXT_CORE_EXPORT Q_DECL_IMPORT
# endif
#else
# define QXT_CORE_EXPORT
#endif // BUILD_QXT_CORE
#if !defined(QXT_STATIC) && !defined(QXT_DOXYGEN_RUN)
# if defined(BUILD_QXT_GUI)
# define QXT_GUI_EXPORT Q_DECL_EXPORT
# else
# define QXT_GUI_EXPORT Q_DECL_IMPORT
# endif
#else
# define QXT_GUI_EXPORT
#endif // BUILD_QXT_GUI
#if !defined(QXT_STATIC) && !defined(QXT_DOXYGEN_RUN)
# if defined(BUILD_QXT_NETWORK)
# define QXT_NETWORK_EXPORT Q_DECL_EXPORT
# else
# define QXT_NETWORK_EXPORT Q_DECL_IMPORT
# endif
#else
# define QXT_NETWORK_EXPORT
#endif // BUILD_QXT_NETWORK
#if !defined(QXT_STATIC) && !defined(QXT_DOXYGEN_RUN)
# if defined(BUILD_QXT_SQL)
# define QXT_SQL_EXPORT Q_DECL_EXPORT
# else
# define QXT_SQL_EXPORT Q_DECL_IMPORT
# endif
#else
# define QXT_SQL_EXPORT
#endif // BUILD_QXT_SQL
#if !defined(QXT_STATIC) && !defined(QXT_DOXYGEN_RUN)
# if defined(BUILD_QXT_WEB)
# define QXT_WEB_EXPORT Q_DECL_EXPORT
# else
# define QXT_WEB_EXPORT Q_DECL_IMPORT
# endif
#else
# define QXT_WEB_EXPORT
#endif // BUILD_QXT_WEB
#if !defined(QXT_STATIC) && !defined(QXT_DOXYGEN_RUN)
# if defined(BUILD_QXT_BERKELEY)
# define QXT_BERKELEY_EXPORT Q_DECL_EXPORT
# else
# define QXT_BERKELEY_EXPORT Q_DECL_IMPORT
# endif
#else
# define QXT_BERKELEY_EXPORT
#endif // BUILD_QXT_BERKELEY
#if !defined(QXT_STATIC) && !defined(QXT_DOXYGEN_RUN)
# if defined(BUILD_QXT_ZEROCONF)
# define QXT_ZEROCONF_EXPORT Q_DECL_EXPORT
# else
# define QXT_ZEROCONF_EXPORT Q_DECL_IMPORT
# endif
#else
# define QXT_ZEROCONF_EXPORT
#endif // QXT_ZEROCONF_EXPORT
#if defined(BUILD_QXT_CORE) || defined(BUILD_QXT_GUI) || defined(BUILD_QXT_SQL) || defined(BUILD_QXT_NETWORK) || defined(BUILD_QXT_WEB) || defined(BUILD_QXT_BERKELEY) || defined(BUILD_QXT_ZEROCONF)
# define BUILD_QXT
#endif
QXT_CORE_EXPORT const char* qxtVersion();
#ifndef QT_BEGIN_NAMESPACE
#define QT_BEGIN_NAMESPACE
#endif
#ifndef QT_END_NAMESPACE
#define QT_END_NAMESPACE
#endif
#ifndef QT_FORWARD_DECLARE_CLASS
#define QT_FORWARD_DECLARE_CLASS(Class) class Class;
#endif
/****************************************************************************
** This file is derived from code bearing the following notice:
** The sole author of this file, Adam Higerd, has explicitly disclaimed all
** copyright interest and protection for the content within. This file has
** been placed in the public domain according to United States copyright
** statute and case law. In jurisdictions where this public domain dedication
** is not legally recognized, anyone who receives a copy of this file is
** permitted to use, modify, duplicate, and redistribute this file, in whole
** or in part, with no restrictions or conditions. In these jurisdictions,
** this file shall be copyright (C) 2006-2008 by Adam Higerd.
****************************************************************************/
#define QXT_DECLARE_PRIVATE(PUB) friend class PUB##Private; QxtPrivateInterface<PUB, PUB##Private> qxt_d;
#define QXT_DECLARE_PUBLIC(PUB) friend class PUB;
#define QXT_INIT_PRIVATE(PUB) qxt_d.setPublic(this);
#define QXT_D(PUB) PUB##Private& d = qxt_d()
#define QXT_P(PUB) PUB& p = qxt_p()
template <typename PUB>
class QxtPrivate
{
public:
virtual ~QxtPrivate()
{}
inline void QXT_setPublic(PUB* pub)
{
qxt_p_ptr = pub;
}
protected:
inline PUB& qxt_p()
{
return *qxt_p_ptr;
}
inline const PUB& qxt_p() const
{
return *qxt_p_ptr;
}
inline PUB* qxt_ptr()
{
return qxt_p_ptr;
}
inline const PUB* qxt_ptr() const
{
return qxt_p_ptr;
}
private:
PUB* qxt_p_ptr;
};
template <typename PUB, typename PVT>
class QxtPrivateInterface
{
friend class QxtPrivate<PUB>;
public:
QxtPrivateInterface()
{
pvt = new PVT;
}
~QxtPrivateInterface()
{
delete pvt;
}
inline void setPublic(PUB* pub)
{
pvt->QXT_setPublic(pub);
}
inline PVT& operator()()
{
return *static_cast<PVT*>(pvt);
}
inline const PVT& operator()() const
{
return *static_cast<PVT*>(pvt);
}
inline PVT * operator->()
{
return static_cast<PVT*>(pvt);
}
inline const PVT * operator->() const
{
return static_cast<PVT*>(pvt);
}
private:
QxtPrivateInterface(const QxtPrivateInterface&) { }
QxtPrivateInterface& operator=(const QxtPrivateInterface&) { }
QxtPrivate<PUB>* pvt;
};
#endif // QXT_GLOBAL

@ -0,0 +1,234 @@
#include "qxtglobalshortcut.h"
/****************************************************************************
** Copyright (c) 2006 - 2011, the LibQxt project.
** See the Qxt AUTHORS file for a list of authors and copyright holders.
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** * Neither the name of the LibQxt project nor the
** names of its contributors may be used to endorse or promote products
** derived from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
** DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**
** <http://libqxt.org> <foundation@libqxt.org>
*****************************************************************************/
#include "qxtglobalshortcut_p.h"
#include <QAbstractEventDispatcher>
#include <QtDebug>
#ifndef Q_OS_MAC
int QxtGlobalShortcutPrivate::ref = 0;
#endif // Q_OS_MAC
QHash<QPair<quint32, quint32>, QxtGlobalShortcut*> QxtGlobalShortcutPrivate::shortcuts;
QxtGlobalShortcutPrivate::QxtGlobalShortcutPrivate()
: enabled(true)
, key(Qt::Key(0))
, mods(Qt::NoModifier)
, nativeKey(0)
, nativeMods(0)
, registered(false)
{
#ifndef Q_OS_MAC
if (ref == 0) {
QAbstractEventDispatcher::instance()->installNativeEventFilter(this);
}
++ref;
#endif // Q_OS_MAC
}
QxtGlobalShortcutPrivate::~QxtGlobalShortcutPrivate()
{
unsetShortcut();
#ifndef Q_OS_MAC
--ref;
if (ref == 0) {
QAbstractEventDispatcher *ed = QAbstractEventDispatcher::instance();
if (ed != 0) {
ed->removeNativeEventFilter(this);
}
}
#endif // Q_OS_MAC
}
#include <iostream>
bool QxtGlobalShortcutPrivate::setShortcut(const QKeySequence& shortcut)
{
unsetShortcut();
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
Qt::Key key = shortcut[0].key();
Qt::KeyboardModifiers mods = shortcut[0].keyboardModifiers();
#else
const Qt::KeyboardModifiers allMods =
Qt::ShiftModifier | Qt::ControlModifier | Qt::AltModifier | Qt::MetaModifier;
const uint xkeyCode = shortcut[0];
// WORKAROUND: Qt has convert some keys to upper case which
// breaks some shortcuts on some keyboard layouts.
const uint keyCode = QChar::toLower(xkeyCode & ~allMods);
key = Qt::Key(keyCode);
mods = Qt::KeyboardModifiers(xkeyCode & allMods);
#endif
nativeKey = nativeKeycode(key);
nativeMods = nativeModifiers(mods);
registered = registerShortcut(nativeKey, nativeMods);
if (registered)
shortcuts.insert(qMakePair(nativeKey, nativeMods), &qxt_p());
return registered;
}
bool QxtGlobalShortcutPrivate::unsetShortcut()
{
if (registered
&& shortcuts.value(qMakePair(nativeKey, nativeMods)) == &qxt_p()
&& unregisterShortcut(nativeKey, nativeMods))
{
shortcuts.remove(qMakePair(nativeKey, nativeMods));
registered = false;
return true;
}
return false;
}
void QxtGlobalShortcutPrivate::activateShortcut(quint32 nativeKey, quint32 nativeMods)
{
QxtGlobalShortcut* shortcut = shortcuts.value(qMakePair(nativeKey, nativeMods));
if (shortcut && shortcut->isEnabled())
emit shortcut->activated(shortcut);
}
/*!
\class QxtGlobalShortcut
\inmodule QxtWidgets
\brief The QxtGlobalShortcut class provides a global shortcut aka "hotkey".
A global shortcut triggers even if the application is not active. This
makes it easy to implement applications that react to certain shortcuts
still if some other application is active or if the application is for
example minimized to the system tray.
Example usage:
\code
QxtGlobalShortcut* shortcut = new QxtGlobalShortcut(window);
connect(shortcut, SIGNAL(activated()), window, SLOT(toggleVisibility()));
shortcut->setShortcut(QKeySequence("Ctrl+Shift+F12"));
\endcode
\bold {Note:} Since Qxt 0.6 QxtGlobalShortcut no more requires QxtApplication.
*/
/*!
\fn QxtGlobalShortcut::activated()
This signal is emitted when the user types the shortcut's key sequence.
\sa shortcut
*/
/*!
Constructs a new QxtGlobalShortcut with \a parent.
*/
QxtGlobalShortcut::QxtGlobalShortcut(QObject* parent)
: QObject(parent)
{
QXT_INIT_PRIVATE(QxtGlobalShortcut);
}
/*!
Constructs a new QxtGlobalShortcut with \a shortcut and \a parent.
*/
QxtGlobalShortcut::QxtGlobalShortcut(const QKeySequence& shortcut, QObject* parent)
: QObject(parent)
{
QXT_INIT_PRIVATE(QxtGlobalShortcut);
setShortcut(shortcut);
}
/*!
Destructs the QxtGlobalShortcut.
*/
QxtGlobalShortcut::~QxtGlobalShortcut()
{
}
/*!
\property QxtGlobalShortcut::shortcut
\brief the shortcut key sequence
\bold {Note:} Notice that corresponding key press and release events are not
delivered for registered global shortcuts even if they are disabled.
Also, comma separated key sequences are not supported.
Only the first part is used:
\code
qxtShortcut->setShortcut(QKeySequence("Ctrl+Alt+A,Ctrl+Alt+B"));
Q_ASSERT(qxtShortcut->shortcut() == QKeySequence("Ctrl+Alt+A"));
\endcode
*/
QKeySequence QxtGlobalShortcut::shortcut() const
{
return QKeySequence(qxt_d().key | qxt_d().mods);
}
bool QxtGlobalShortcut::setShortcut(const QKeySequence& shortcut)
{
return qxt_d().setShortcut(shortcut);
}
/*!
\property QxtGlobalShortcut::enabled
\brief whether the shortcut is enabled
A disabled shortcut does not get activated.
The default value is \c true.
\sa setDisabled()
*/
bool QxtGlobalShortcut::isEnabled() const
{
return qxt_d().enabled;
}
bool QxtGlobalShortcut::isValid() const
{
return qxt_d().registered;
}
void QxtGlobalShortcut::setEnabled(bool enabled)
{
qxt_d().enabled = enabled;
}
/*!
Sets the shortcut \a disabled.
\sa enabled
*/
void QxtGlobalShortcut::setDisabled(bool disabled)
{
qxt_d().enabled = !disabled;
}

@ -0,0 +1,66 @@
#ifndef QXTGLOBALSHORTCUT_H
/****************************************************************************
** Copyright (c) 2006 - 2011, the LibQxt project.
** See the Qxt AUTHORS file for a list of authors and copyright holders.
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** * Neither the name of the LibQxt project nor the
** names of its contributors may be used to endorse or promote products
** derived from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
** DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**
** <http://libqxt.org> <foundation@libqxt.org>
*****************************************************************************/
#define QXTGLOBALSHORTCUT_H
#include "qxtglobal.h"
#include <QObject>
#include <QKeySequence>
class QxtGlobalShortcutPrivate;
class QXT_GUI_EXPORT QxtGlobalShortcut : public QObject
{
Q_OBJECT
QXT_DECLARE_PRIVATE(QxtGlobalShortcut)
Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled)
Q_PROPERTY(QKeySequence shortcut READ shortcut WRITE setShortcut)
public:
explicit QxtGlobalShortcut(QObject* parent = 0);
explicit QxtGlobalShortcut(const QKeySequence& shortcut, QObject* parent = 0);
virtual ~QxtGlobalShortcut();
QKeySequence shortcut() const;
bool setShortcut(const QKeySequence& shortcut);
bool isEnabled() const;
bool isValid() const;
public Q_SLOTS:
void setEnabled(bool enabled = true);
void setDisabled(bool disabled = true);
Q_SIGNALS:
void activated(QxtGlobalShortcut *self);
};
#endif // QXTGLOBALSHORTCUT_H

@ -0,0 +1,274 @@
#include <Carbon/Carbon.h>
/****************************************************************************
** Copyright (c) 2006 - 2011, the LibQxt project.
** See the Qxt AUTHORS file for a list of authors and copyright holders.
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** * Neither the name of the LibQxt project nor the
** names of its contributors may be used to endorse or promote products
** derived from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
** DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**
** <http://libqxt.org> <foundation@libqxt.org>
*****************************************************************************/
#include "qxtglobalshortcut_p.h"
#include <QMap>
#include <QHash>
#include <QtDebug>
#include <QApplication>
typedef QPair<uint, uint> Identifier;
static QMap<quint32, EventHotKeyRef> keyRefs;
static QHash<Identifier, quint32> keyIDs;
static quint32 hotKeySerial = 0;
static bool qxt_mac_handler_installed = false;
OSStatus qxt_mac_handle_hot_key(EventHandlerCallRef nextHandler, EventRef event, void* data)
{
Q_UNUSED(nextHandler);
Q_UNUSED(data);
if (GetEventClass(event) == kEventClassKeyboard && GetEventKind(event) == kEventHotKeyPressed)
{
EventHotKeyID keyID;
GetEventParameter(event, kEventParamDirectObject, typeEventHotKeyID, NULL, sizeof(keyID), NULL, &keyID);
Identifier id = keyIDs.key(keyID.id);
QxtGlobalShortcutPrivate::activateShortcut(id.second, id.first);
}
return noErr;
}
quint32 QxtGlobalShortcutPrivate::nativeModifiers(Qt::KeyboardModifiers modifiers)
{
quint32 native = 0;
if (modifiers & Qt::ShiftModifier)
native |= shiftKey;
if (modifiers & Qt::ControlModifier)
native |= cmdKey;
if (modifiers & Qt::AltModifier)
native |= optionKey;
if (modifiers & Qt::MetaModifier)
native |= controlKey;
if (modifiers & Qt::KeypadModifier)
native |= kEventKeyModifierNumLockMask;
return native;
}
// This is only here to get it to compile on OSX
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
bool QxtGlobalShortcutPrivate::nativeEventFilter(const QByteArray & eventType,
void * message, qintptr * result)
#else
bool QxtGlobalShortcutPrivate::nativeEventFilter(const QByteArray & eventType,
void * message, long * result)
#endif
{
Q_UNUSED(result);
Q_UNUSED(message);
Q_UNUSED(eventType);
return false;
}
quint32 QxtGlobalShortcutPrivate::nativeKeycode(Qt::Key key)
{
UTF16Char ch;
// Constants found in NSEvent.h from AppKit.framework
switch (key)
{
case Qt::Key_Return:
return kVK_Return;
case Qt::Key_Enter:
return kVK_ANSI_KeypadEnter;
case Qt::Key_Tab:
return kVK_Tab;
case Qt::Key_Space:
return kVK_Space;
case Qt::Key_Backspace:
return kVK_Delete;
case Qt::Key_Control:
return kVK_Command;
case Qt::Key_Shift:
return kVK_Shift;
case Qt::Key_CapsLock:
return kVK_CapsLock;
case Qt::Key_Option:
return kVK_Option;
case Qt::Key_Meta:
return kVK_Control;
case Qt::Key_F17:
return kVK_F17;
case Qt::Key_VolumeUp:
return kVK_VolumeUp;
case Qt::Key_VolumeDown:
return kVK_VolumeDown;
case Qt::Key_F18:
return kVK_F18;
case Qt::Key_F19:
return kVK_F19;
case Qt::Key_F20:
return kVK_F20;
case Qt::Key_F5:
return kVK_F5;
case Qt::Key_F6:
return kVK_F6;
case Qt::Key_F7:
return kVK_F7;
case Qt::Key_F3:
return kVK_F3;
case Qt::Key_F8:
return kVK_F8;
case Qt::Key_F9:
return kVK_F9;
case Qt::Key_F11:
return kVK_F11;
case Qt::Key_F13:
return kVK_F13;
case Qt::Key_F16:
return kVK_F16;
case Qt::Key_F14:
return kVK_F14;
case Qt::Key_F10:
return kVK_F10;
case Qt::Key_F12:
return kVK_F12;
case Qt::Key_F15:
return kVK_F15;
case Qt::Key_Help:
return kVK_Help;
case Qt::Key_Home:
return kVK_Home;
case Qt::Key_PageUp:
return kVK_PageUp;
case Qt::Key_Delete:
return kVK_ForwardDelete;
case Qt::Key_F4:
return kVK_F4;
case Qt::Key_End:
return kVK_End;
case Qt::Key_F2:
return kVK_F2;
case Qt::Key_PageDown:
return kVK_PageDown;
case Qt::Key_F1:
return kVK_F1;
case Qt::Key_Left:
return kVK_LeftArrow;
case Qt::Key_Right:
return kVK_RightArrow;
case Qt::Key_Down:
return kVK_DownArrow;
case Qt::Key_Up:
return kVK_UpArrow;
default:
;
}
if (key == Qt::Key_Escape) ch = 27;
else if (key == Qt::Key_Return) ch = 13;
else if (key == Qt::Key_Enter) ch = 3;
else if (key == Qt::Key_Tab) ch = 9;
else ch = key;
CFDataRef currentLayoutData;
TISInputSourceRef currentKeyboard = TISCopyCurrentKeyboardInputSource();
if (currentKeyboard == NULL)
return 0;
currentLayoutData = (CFDataRef)TISGetInputSourceProperty(currentKeyboard, kTISPropertyUnicodeKeyLayoutData);
CFRelease(currentKeyboard);
if (currentLayoutData == NULL)
return 0;
UCKeyboardLayout* header = (UCKeyboardLayout*)CFDataGetBytePtr(currentLayoutData);
UCKeyboardTypeHeader* table = header->keyboardTypeList;
uint8_t *data = (uint8_t*)header;
// God, would a little documentation for this shit kill you...
for (quint32 i=0; i < header->keyboardTypeCount; i++)
{
UCKeyStateRecordsIndex* stateRec = 0;
if (table[i].keyStateRecordsIndexOffset != 0)
{
stateRec = reinterpret_cast<UCKeyStateRecordsIndex*>(data + table[i].keyStateRecordsIndexOffset);
if (stateRec->keyStateRecordsIndexFormat != kUCKeyStateRecordsIndexFormat) stateRec = 0;
}
UCKeyToCharTableIndex* charTable = reinterpret_cast<UCKeyToCharTableIndex*>(data + table[i].keyToCharTableIndexOffset);
if (charTable->keyToCharTableIndexFormat != kUCKeyToCharTableIndexFormat) continue;
for (quint32 j=0; j < charTable->keyToCharTableCount; j++)
{
UCKeyOutput* keyToChar = reinterpret_cast<UCKeyOutput*>(data + charTable->keyToCharTableOffsets[j]);
for (quint32 k=0; k < charTable->keyToCharTableSize; k++)
{
if (keyToChar[k] & kUCKeyOutputTestForIndexMask)
{
long idx = keyToChar[k] & kUCKeyOutputGetIndexMask;
if (stateRec && idx < stateRec->keyStateRecordCount)
{
UCKeyStateRecord* rec = reinterpret_cast<UCKeyStateRecord*>(data + stateRec->keyStateRecordOffsets[idx]);
if (rec->stateZeroCharData == ch) return k;
}
}
else if (!(keyToChar[k] & kUCKeyOutputSequenceIndexMask) && keyToChar[k] < 0xFFFE)
{
if (keyToChar[k] == ch) return k;
}
} // for k
} // for j
} // for i
return 0;
}
bool QxtGlobalShortcutPrivate::registerShortcut(quint32 nativeKey, quint32 nativeMods)
{
if (!qxt_mac_handler_installed)
{
EventTypeSpec t;
t.eventClass = kEventClassKeyboard;
t.eventKind = kEventHotKeyPressed;
InstallApplicationEventHandler(&qxt_mac_handle_hot_key, 1, &t, NULL, NULL);
}
EventHotKeyID keyID;
keyID.signature = 'cute';
keyID.id = ++hotKeySerial;
EventHotKeyRef ref = 0;
bool rv = !RegisterEventHotKey(nativeKey, nativeMods, keyID, GetApplicationEventTarget(), 0, &ref);
if (rv)
{
keyIDs.insert(Identifier(nativeMods, nativeKey), keyID.id);
keyRefs.insert(keyID.id, ref);
}
return rv;
}
bool QxtGlobalShortcutPrivate::unregisterShortcut(quint32 nativeKey, quint32 nativeMods)
{
Identifier id(nativeMods, nativeKey);
if (!keyIDs.contains(id)) return false;
EventHotKeyRef ref = keyRefs.take(keyIDs[id]);
keyIDs.remove(id);
return !UnregisterEventHotKey(ref);
}

@ -0,0 +1,83 @@
#ifndef QXTGLOBALSHORTCUT_P_H
/****************************************************************************
** Copyright (c) 2006 - 2011, the LibQxt project.
** See the Qxt AUTHORS file for a list of authors and copyright holders.
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** * Neither the name of the LibQxt project nor the
** names of its contributors may be used to endorse or promote products
** derived from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
** DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**
** <http://libqxt.org> <foundation@libqxt.org>
*****************************************************************************/
#define QXTGLOBALSHORTCUT_P_H
#include "qxtglobalshortcut.h"
#include <QAbstractEventDispatcher>
#include <QKeySequence>
#include <QHash>
#include <QAbstractNativeEventFilter>
class QxtGlobalShortcutPrivate
: public QxtPrivate<QxtGlobalShortcut>
, public QAbstractNativeEventFilter
{
public:
QXT_DECLARE_PUBLIC(QxtGlobalShortcut)
QxtGlobalShortcutPrivate();
~QxtGlobalShortcutPrivate();
bool enabled;
Qt::Key key;
Qt::KeyboardModifiers mods;
quint32 nativeKey;
quint32 nativeMods;
bool registered;
bool setShortcut(const QKeySequence& shortcut);
bool unsetShortcut();
# ifndef Q_OS_MAC
static int ref;
# endif // Q_OS_MAC
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
virtual bool nativeEventFilter(const QByteArray &eventType, void *message, qintptr *result);
#else
virtual bool nativeEventFilter(const QByteArray &eventType, void *message, long *result);
#endif
static void activateShortcut(quint32 nativeKey, quint32 nativeMods);
private:
static quint32 nativeKeycode(Qt::Key keycode);
static quint32 nativeModifiers(Qt::KeyboardModifiers modifiers);
static bool registerShortcut(quint32 nativeKey, quint32 nativeMods);
static bool unregisterShortcut(quint32 nativeKey, quint32 nativeMods);
static QHash<QPair<quint32, quint32>, QxtGlobalShortcut*> shortcuts;
};
#endif // QXTGLOBALSHORTCUT_P_H

@ -0,0 +1,212 @@
#include "qxtglobalshortcut_p.h"
/****************************************************************************
** Copyright (c) 2006 - 2011, the LibQxt project.
** See the Qxt AUTHORS file for a list of authors and copyright holders.
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** * Neither the name of the LibQxt project nor the
** names of its contributors may be used to endorse or promote products
** derived from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
** DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**
** <http://libqxt.org> <foundation@libqxt.org>
*****************************************************************************/
#include <qt_windows.h>
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
bool QxtGlobalShortcutPrivate::nativeEventFilter(const QByteArray & eventType,
void * message, qintptr * result)
#else
bool QxtGlobalShortcutPrivate::nativeEventFilter(const QByteArray & eventType,
void * message, long * result)
#endif
{
Q_UNUSED(eventType);
Q_UNUSED(result);
MSG* msg = static_cast<MSG*>(message);
if (msg->message == WM_HOTKEY)
{
const quint32 keycode = HIWORD(msg->lParam);
const quint32 modifiers = LOWORD(msg->lParam);
activateShortcut(keycode, modifiers);
}
return false;
}
quint32 QxtGlobalShortcutPrivate::nativeModifiers(Qt::KeyboardModifiers modifiers)
{
// MOD_ALT, MOD_CONTROL, (MOD_KEYUP), MOD_SHIFT, MOD_WIN
quint32 native = 0;
if (modifiers & Qt::ShiftModifier)
native |= MOD_SHIFT;
if (modifiers & Qt::ControlModifier)
native |= MOD_CONTROL;
if (modifiers & Qt::AltModifier)
native |= MOD_ALT;
if (modifiers & Qt::MetaModifier)
native |= MOD_WIN;
// TODO: resolve these?
//if (modifiers & Qt::KeypadModifier)
//if (modifiers & Qt::GroupSwitchModifier)
return native;
}
quint32 QxtGlobalShortcutPrivate::nativeKeycode(Qt::Key key)
{
// Here is list of keys that presumably work on most keyboard layouts.
// Default branch is for keys that can change with keyboard layout.
switch (key)
{
case Qt::Key_Escape:
return VK_ESCAPE;
case Qt::Key_Tab:
case Qt::Key_Backtab:
return VK_TAB;
case Qt::Key_Backspace:
return VK_BACK;
case Qt::Key_Return:
case Qt::Key_Enter:
return VK_RETURN;
case Qt::Key_Insert:
return VK_INSERT;
case Qt::Key_Delete:
return VK_DELETE;
case Qt::Key_Pause:
return VK_PAUSE;
case Qt::Key_Print:
return VK_PRINT;
case Qt::Key_Clear:
return VK_CLEAR;
case Qt::Key_Home:
return VK_HOME;
case Qt::Key_End:
return VK_END;
case Qt::Key_Left:
return VK_LEFT;
case Qt::Key_Up:
return VK_UP;
case Qt::Key_Right:
return VK_RIGHT;
case Qt::Key_Down:
return VK_DOWN;
case Qt::Key_PageUp:
return VK_PRIOR;
case Qt::Key_PageDown:
return VK_NEXT;
case Qt::Key_F1:
return VK_F1;
case Qt::Key_F2:
return VK_F2;
case Qt::Key_F3:
return VK_F3;
case Qt::Key_F4:
return VK_F4;
case Qt::Key_F5:
return VK_F5;
case Qt::Key_F6:
return VK_F6;
case Qt::Key_F7:
return VK_F7;
case Qt::Key_F8:
return VK_F8;
case Qt::Key_F9:
return VK_F9;
case Qt::Key_F10:
return VK_F10;
case Qt::Key_F11:
return VK_F11;
case Qt::Key_F12:
return VK_F12;
case Qt::Key_F13:
return VK_F13;
case Qt::Key_F14:
return VK_F14;
case Qt::Key_F15:
return VK_F15;
case Qt::Key_F16:
return VK_F16;
case Qt::Key_F17:
return VK_F17;
case Qt::Key_F18:
return VK_F18;
case Qt::Key_F19:
return VK_F19;
case Qt::Key_F20:
return VK_F20;
case Qt::Key_F21:
return VK_F21;
case Qt::Key_F22:
return VK_F22;
case Qt::Key_F23:
return VK_F23;
case Qt::Key_F24:
return VK_F24;
case Qt::Key_Space:
return VK_SPACE;
case Qt::Key_Asterisk:
return VK_MULTIPLY;
case Qt::Key_Plus:
return VK_ADD;
case Qt::Key_Minus:
return VK_SUBTRACT;
case Qt::Key_Slash:
return VK_DIVIDE;
case Qt::Key_MediaNext:
return VK_MEDIA_NEXT_TRACK;
case Qt::Key_MediaPrevious:
return VK_MEDIA_PREV_TRACK;
case Qt::Key_MediaPlay:
return VK_MEDIA_PLAY_PAUSE;
case Qt::Key_MediaStop:
return VK_MEDIA_STOP;
// couldn't find those in VK_*
//case Qt::Key_MediaLast:
//case Qt::Key_MediaRecord:
case Qt::Key_VolumeDown:
return VK_VOLUME_DOWN;
case Qt::Key_VolumeUp:
return VK_VOLUME_UP;
case Qt::Key_VolumeMute:
return VK_VOLUME_MUTE;
default:
// Try to get virtual key from current keyboard layout or US.
const HKL layout = GetKeyboardLayout(0);
int vk = VkKeyScanEx(key, layout);
if (vk == -1) {
const HKL layoutUs = GetKeyboardLayout(0x409);
vk = VkKeyScanEx(key, layoutUs);
}
return vk == -1 ? 0 : vk;
}
}
bool QxtGlobalShortcutPrivate::registerShortcut(quint32 nativeKey, quint32 nativeMods)
{
return RegisterHotKey(0, nativeMods ^ nativeKey, nativeMods, nativeKey);
}
bool QxtGlobalShortcutPrivate::unregisterShortcut(quint32 nativeKey, quint32 nativeMods)
{
return UnregisterHotKey(0, nativeMods ^ nativeKey);
}

@ -0,0 +1,230 @@
#include "qxtglobalshortcut_p.h"
/****************************************************************************
** Copyright (c) 2006 - 2011, the LibQxt project.
** See the Qxt AUTHORS file for a list of authors and copyright holders.
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** * Neither the name of the LibQxt project nor the
** names of its contributors may be used to endorse or promote products
** derived from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
** DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**
** <http://libqxt.org> <foundation@libqxt.org>
*****************************************************************************/
#include <QApplication>
#include <qpa/qplatformnativeinterface.h>
#include <xcb/xcb.h>
#include <QVector>
#include <X11/Xlib.h>
namespace {
QVector<quint32> maskModifiers()
{
return QVector<quint32>() << 0 << Mod2Mask << LockMask << (Mod2Mask | LockMask);
}
typedef int (*X11ErrorHandler)(Display* display, XErrorEvent* event);
class QxtX11ErrorHandler {
public:
static bool error;
static int qxtX11ErrorHandler(Display* display, XErrorEvent *event)
{
Q_UNUSED(display);
switch (event->error_code)
{
case BadAccess:
case BadValue:
case BadWindow:
if (event->request_code == 33 /* X_GrabKey */ ||
event->request_code == 34 /* X_UngrabKey */)
{
error = true;
//TODO:
//char errstr[256];
//XGetErrorText(dpy, err->error_code, errstr, 256);
}
}
return 0;
}
QxtX11ErrorHandler()
: m_previousErrorHandler(0)
{
error = false;
m_previousErrorHandler = XSetErrorHandler(qxtX11ErrorHandler);
}
~QxtX11ErrorHandler()
{
XSetErrorHandler(m_previousErrorHandler);
}
private:
X11ErrorHandler m_previousErrorHandler;
};
bool QxtX11ErrorHandler::error = false;
class QxtX11Data {
public:
QxtX11Data()
: m_display(0)
{
QPlatformNativeInterface *native = qApp->platformNativeInterface();
void *display = native->nativeResourceForScreen(QByteArray("display"),
QGuiApplication::primaryScreen());
m_display = reinterpret_cast<Display *>(display);
}
bool isValid()
{
return m_display != 0;
}
Display *display()
{
Q_ASSERT(isValid());
return m_display;
}
Window rootWindow()
{
return DefaultRootWindow(display());
}
bool grabKey(quint32 keycode, quint32 modifiers, Window window)
{
QxtX11ErrorHandler errorHandler;
foreach (quint32 maskMods, maskModifiers()) {
XGrabKey(display(), keycode, modifiers | maskMods, window, True,
GrabModeAsync, GrabModeAsync);
if (errorHandler.error)
break;
}
if (errorHandler.error) {
ungrabKey(keycode, modifiers, window);
return false;
}
return true;
}
bool ungrabKey(quint32 keycode, quint32 modifiers, Window window)
{
QxtX11ErrorHandler errorHandler;
foreach (quint32 maskMods, maskModifiers()) {
XUngrabKey(display(), keycode, modifiers | maskMods, window);
}
return !errorHandler.error;
}
private:
Display *m_display;
};
} // namespace
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
bool QxtGlobalShortcutPrivate::nativeEventFilter(const QByteArray & eventType,
void * message, qintptr * result)
#else
bool QxtGlobalShortcutPrivate::nativeEventFilter(const QByteArray & eventType,
void * message, long * result)
#endif
{
Q_UNUSED(result);
xcb_key_press_event_t *kev = 0;
if (eventType == "xcb_generic_event_t") {
xcb_generic_event_t* ev = static_cast<xcb_generic_event_t *>(message);
if ((ev->response_type & 127) == XCB_KEY_PRESS)
kev = static_cast<xcb_key_press_event_t *>(message);
}
if (kev != 0) {
unsigned int keycode = kev->detail;
unsigned int keystate = 0;
if(kev->state & XCB_MOD_MASK_1)
keystate |= Mod1Mask;
if(kev->state & XCB_MOD_MASK_CONTROL)
keystate |= ControlMask;
if(kev->state & XCB_MOD_MASK_4)
keystate |= Mod4Mask;
if(kev->state & XCB_MOD_MASK_SHIFT)
keystate |= ShiftMask;
activateShortcut(keycode,
// Mod1Mask == Alt, Mod4Mask == Meta
keystate & (ShiftMask | ControlMask | Mod1Mask | Mod4Mask));
}
return false;
}
quint32 QxtGlobalShortcutPrivate::nativeModifiers(Qt::KeyboardModifiers modifiers)
{
// ShiftMask, LockMask, ControlMask, Mod1Mask, Mod2Mask, Mod3Mask, Mod4Mask, and Mod5Mask
quint32 native = 0;
if (modifiers & Qt::ShiftModifier)
native |= ShiftMask;
if (modifiers & Qt::ControlModifier)
native |= ControlMask;
if (modifiers & Qt::AltModifier)
native |= Mod1Mask;
if (modifiers & Qt::MetaModifier)
native |= Mod4Mask;
// TODO: resolve these?
//if (modifiers & Qt::MetaModifier)
//if (modifiers & Qt::KeypadModifier)
//if (modifiers & Qt::GroupSwitchModifier)
return native;
}
quint32 QxtGlobalShortcutPrivate::nativeKeycode(Qt::Key key)
{
QxtX11Data x11;
if (!x11.isValid())
return 0;
KeySym keysym = XStringToKeysym(QKeySequence(key).toString().toLatin1().data());
if (keysym == NoSymbol)
keysym = static_cast<ushort>(key);
return XKeysymToKeycode(x11.display(), keysym);
}
bool QxtGlobalShortcutPrivate::registerShortcut(quint32 nativeKey, quint32 nativeMods)
{
QxtX11Data x11;
return x11.isValid() && x11.grabKey(nativeKey, nativeMods, x11.rootWindow());
}
bool QxtGlobalShortcutPrivate::unregisterShortcut(quint32 nativeKey, quint32 nativeMods)
{
QxtX11Data x11;
return x11.isValid() && x11.ungrabKey(nativeKey, nativeMods, x11.rootWindow());
}

@ -1,150 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net)
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="net.micode.notes"
android:versionCode="1"
android:versionName="0.1" >
<uses-sdk android:minSdkVersion="14" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.MANAGE_ACCOUNTS" />
<uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.USE_CREDENTIALS" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<application
android:icon="@drawable/icon_app"
android:label="@string/app_name" >
<activity
android:name=".ui.NotesListActivity"
android:configChanges="keyboardHidden|orientation|screenSize"
android:label="@string/app_name"
android:launchMode="singleTop"
android:theme="@style/NoteTheme"
android:uiOptions="splitActionBarWhenNarrow"
android:windowSoftInputMode="adjustPan" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".ui.NoteEditActivity"
android:configChanges="keyboardHidden|orientation|screenSize"
android:launchMode="singleTop"
android:theme="@style/NoteTheme" >
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="vnd.android.cursor.item/text_note" />
<data android:mimeType="vnd.android.cursor.item/call_note" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.INSERT_OR_EDIT" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="vnd.android.cursor.item/text_note" />
<data android:mimeType="vnd.android.cursor.item/call_note" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEARCH" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<meta-data
android:name="android.app.searchable"
android:resource="@xml/searchable" />
</activity>
<provider
android:name="net.micode.notes.data.NotesProvider"
android:authorities="micode_notes"
android:multiprocess="true" />
<receiver
android:name=".widget.NoteWidgetProvider_2x"
android:label="@string/app_widget2x2" >
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
<action android:name="android.appwidget.action.APPWIDGET_DELETED" />
<action android:name="android.intent.action.PRIVACY_MODE_CHANGED" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/widget_2x_info" />
</receiver>
<receiver
android:name=".widget.NoteWidgetProvider_4x"
android:label="@string/app_widget4x4" >
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
<action android:name="android.appwidget.action.APPWIDGET_DELETED" />
<action android:name="android.intent.action.PRIVACY_MODE_CHANGED" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/widget_4x_info" />
</receiver>
<receiver android:name=".ui.AlarmInitReceiver" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<receiver
android:name="net.micode.notes.ui.AlarmReceiver"
android:process=":remote" >
</receiver>
<activity
android:name=".ui.AlarmAlertActivity"
android:label="@string/app_name"
android:launchMode="singleInstance"
android:theme="@android:style/Theme.Holo.Wallpaper.NoTitleBar" >
</activity>
<activity
android:name="net.micode.notes.ui.NotesPreferenceActivity"
android:label="@string/preferences_title"
android:launchMode="singleTop"
android:theme="@android:style/Theme.Holo.Light" >
</activity>
<service
android:name="net.micode.notes.gtask.remote.GTaskSyncService"
android:exported="false" >
</service>
<meta-data
android:name="android.app.default_searchable"
android:value=".ui.NoteEditActivity" />
</application>
</manifest>

@ -0,0 +1,543 @@
cmake_minimum_required(VERSION 3.10)
set(APP_VERSION 2.2.1)
set(APP_ID "io.github.nuttyartist.notes")
set(APP_AUTHOR "Ruby Mamistvalove")
set(APP_AUTHOR_EMAIL "ruby.mamistvalove@gmail.com")
set(APP_WEBSITE "https://www.get-notes.com/")
set(APP_REPOSITORY "https://github.com/nuttyartist/notes")
string(TIMESTAMP CURRENT_YEAR "%Y")
# Any of the options below can be changed by passing -D<option name>=<value> to CMake.
set(CMAKE_OSX_DEPLOYMENT_TARGET
"10.15"
CACHE STRING "Minimum macOS version to target for deployment")
set(USE_QT_VERSION
""
CACHE STRING "Use a specific version of Qt to build the app")
option(GIT_REVISION
"Append the current git revision to the app's version string" OFF)
option(UPDATE_CHECKER
"Enable or disable both the update checker and auto-updater" ON)
option(PRO_VERSION "Enable or disable Notes Pro features" ON)
project(
Notes
VERSION ${APP_VERSION}
DESCRIPTION "Note-taking app. Write down your thoughts"
LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTORCC ON)
if(POLICY CMP0083)
cmake_policy(SET CMP0083 NEW)
include(CheckPIESupported)
check_pie_supported()
endif()
if(PRO_VERSION)
add_definitions(-DPRO_VERSION)
endif()
# List of Qt components required to build the app.
set(QT_COMPONENTS
Core
Concurrent
Gui
Network
Sql
Test
Widgets
Quick)
# No Qt version was specified, try to use either Qt 6 (preferred) or Qt 5.
if(USE_QT_VERSION STREQUAL "")
# This can probably be simplified once the following bug gets resolved:
# https://gitlab.kitware.com/cmake/cmake/-/issues/23575
message(STATUS "Trying to find Qt 6...")
find_package(QT NAMES Qt6 QUIET)
if(NOT DEFINED QT_VERSION_MAJOR)
message(STATUS "Could not find Qt 6, will try Qt 5 next...")
find_package(QT NAMES Qt5 QUIET)
if(NOT DEFINED QT_VERSION_MAJOR)
message(FATAL_ERROR "Could not find Qt 5, aborting compilation.")
endif()
endif()
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS ${QT_COMPONENTS})
else()
if(NOT USE_QT_VERSION STREQUAL "5" AND NOT USE_QT_VERSION STREQUAL "6")
message(
FATAL_ERROR
"An unsupported version of Qt was specified: '${USE_QT_VERSION}'. Valid values are: 5 or 6."
)
endif()
message(STATUS "Trying to find Qt ${USE_QT_VERSION} (manually specified)...")
find_package(QT NAMES Qt${USE_QT_VERSION} QUIET)
if(NOT DEFINED QT_VERSION_MAJOR)
message(
FATAL_ERROR "Could not find Qt ${USE_QT_VERSION}, aborting compilation.")
endif()
find_package(Qt${USE_QT_VERSION} REQUIRED COMPONENTS ${QT_COMPONENTS})
endif()
message(STATUS "Success! Configuration details:")
message(STATUS "App name: ${PROJECT_NAME}")
message(STATUS "App version: ${PROJECT_VERSION}")
message(STATUS "Qt version: ${QT_VERSION}")
message(STATUS "Update checker: ${UPDATE_CHECKER}")
message(STATUS "Pro Version: ${PRO_VERSION}")
if(CMAKE_BUILD_TYPE STREQUAL "")
message(STATUS "Build type: (not set)")
else()
message(STATUS "Build type: ${CMAKE_BUILD_TYPE}")
endif()
set(GIT_REV "")
if(GIT_REVISION)
if(EXISTS "${CMAKE_SOURCE_DIR}/.git")
execute_process(
COMMAND git rev-parse --short HEAD
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
OUTPUT_VARIABLE GIT_REV
ERROR_VARIABLE GIT_REV_ERR
OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_STRIP_TRAILING_WHITESPACE)
if(GIT_REV)
message(STATUS "Git revision: ${GIT_REV}")
string(PREPEND GIT_REV "+g")
else()
message(FATAL_ERROR "Failed to retrieve git revision: ${GIT_REV_ERR}")
endif()
else()
message(
WARNING
"The GIT_REVISION option was set, but this is not a git repository.")
endif()
endif()
set(SOURCES
${PROJECT_SOURCE_DIR}/src/aboutwindow.cpp
${PROJECT_SOURCE_DIR}/src/aboutwindow.h
${PROJECT_SOURCE_DIR}/src/allnotebuttontreedelegateeditor.cpp
${PROJECT_SOURCE_DIR}/src/allnotebuttontreedelegateeditor.h
${PROJECT_SOURCE_DIR}/src/customapplicationstyle.cpp
${PROJECT_SOURCE_DIR}/src/customapplicationstyle.h
${PROJECT_SOURCE_DIR}/src/customdocument.cpp
${PROJECT_SOURCE_DIR}/src/customDocument.h
${PROJECT_SOURCE_DIR}/src/customMarkdownHighlighter.cpp
${PROJECT_SOURCE_DIR}/src/customMarkdownHighlighter.h
${PROJECT_SOURCE_DIR}/src/dbmanager.cpp
${PROJECT_SOURCE_DIR}/src/dbmanager.h
${PROJECT_SOURCE_DIR}/src/defaultnotefolderdelegateeditor.cpp
${PROJECT_SOURCE_DIR}/src/defaultnotefolderdelegateeditor.h
${PROJECT_SOURCE_DIR}/src/editorsettingsoptions.h
${PROJECT_SOURCE_DIR}/src/editorsettingsoptions.cpp
${PROJECT_SOURCE_DIR}/src/elidedlabel.cpp
${PROJECT_SOURCE_DIR}/src/elidedlabel.h
${PROJECT_SOURCE_DIR}/src/foldertreedelegateeditor.cpp
${PROJECT_SOURCE_DIR}/src/foldertreedelegateeditor.h
${PROJECT_SOURCE_DIR}/src/fontloader.cpp
${PROJECT_SOURCE_DIR}/src/fontloader.h
${PROJECT_SOURCE_DIR}/src/labeledittype.cpp
${PROJECT_SOURCE_DIR}/src/labeledittype.h
${PROJECT_SOURCE_DIR}/src/listviewlogic.cpp
${PROJECT_SOURCE_DIR}/src/listviewlogic.h
${PROJECT_SOURCE_DIR}/src/lqtutils_enum.h
${PROJECT_SOURCE_DIR}/src/main.cpp
${PROJECT_SOURCE_DIR}/src/mainwindow.cpp
${PROJECT_SOURCE_DIR}/src/mainwindow.h
${PROJECT_SOURCE_DIR}/src/nodedata.cpp
${PROJECT_SOURCE_DIR}/src/nodedata.h
${PROJECT_SOURCE_DIR}/src/nodepath.cpp
${PROJECT_SOURCE_DIR}/src/nodepath.h
${PROJECT_SOURCE_DIR}/src/nodetreedelegate.cpp
${PROJECT_SOURCE_DIR}/src/nodetreedelegate.h
${PROJECT_SOURCE_DIR}/src/nodetreemodel.cpp
${PROJECT_SOURCE_DIR}/src/nodetreemodel.h
${PROJECT_SOURCE_DIR}/src/nodetreeview.cpp
${PROJECT_SOURCE_DIR}/src/nodetreeview.h
${PROJECT_SOURCE_DIR}/src/nodetreeview_p.h
${PROJECT_SOURCE_DIR}/src/noteeditorlogic.cpp
${PROJECT_SOURCE_DIR}/src/noteeditorlogic.h
${PROJECT_SOURCE_DIR}/src/notelistdelegate.cpp
${PROJECT_SOURCE_DIR}/src/notelistdelegateeditor.cpp
${PROJECT_SOURCE_DIR}/src/notelistdelegateeditor.h
${PROJECT_SOURCE_DIR}/src/notelistdelegate.h
${PROJECT_SOURCE_DIR}/src/notelistmodel.cpp
${PROJECT_SOURCE_DIR}/src/notelistmodel.h
${PROJECT_SOURCE_DIR}/src/notelistview.cpp
${PROJECT_SOURCE_DIR}/src/notelistview.h
${PROJECT_SOURCE_DIR}/src/notelistview_p.h
${PROJECT_SOURCE_DIR}/src/pushbuttontype.cpp
${PROJECT_SOURCE_DIR}/src/pushbuttontype.h
${PROJECT_SOURCE_DIR}/src/singleinstance.cpp
${PROJECT_SOURCE_DIR}/src/singleinstance.h
${PROJECT_SOURCE_DIR}/src/splitterstyle.cpp
${PROJECT_SOURCE_DIR}/src/splitterstyle.h
${PROJECT_SOURCE_DIR}/src/tagdata.cpp
${PROJECT_SOURCE_DIR}/src/tagdata.h
${PROJECT_SOURCE_DIR}/src/taglistdelegate.cpp
${PROJECT_SOURCE_DIR}/src/taglistdelegate.h
${PROJECT_SOURCE_DIR}/src/taglistmodel.cpp
${PROJECT_SOURCE_DIR}/src/taglistmodel.h
${PROJECT_SOURCE_DIR}/src/taglistview.cpp
${PROJECT_SOURCE_DIR}/src/taglistview.h
${PROJECT_SOURCE_DIR}/src/tagpool.cpp
${PROJECT_SOURCE_DIR}/src/tagpool.h
${PROJECT_SOURCE_DIR}/src/tagtreedelegateeditor.cpp
${PROJECT_SOURCE_DIR}/src/tagtreedelegateeditor.h
${PROJECT_SOURCE_DIR}/src/trashbuttondelegateeditor.cpp
${PROJECT_SOURCE_DIR}/src/trashbuttondelegateeditor.h
${PROJECT_SOURCE_DIR}/src/treeviewlogic.cpp
${PROJECT_SOURCE_DIR}/src/treeviewlogic.h
# ui
${PROJECT_SOURCE_DIR}/src/aboutwindow.ui
${PROJECT_SOURCE_DIR}/src/mainwindow.ui
# qrc files
${PROJECT_SOURCE_DIR}/src/fonts.qrc
${PROJECT_SOURCE_DIR}/src/images.qrc
${PROJECT_SOURCE_DIR}/src/styles.qrc)
if(QT_VERSION VERSION_LESS 6.0)
list(APPEND SOURCES ${PROJECT_SOURCE_DIR}/src/qml.qrc)
endif()
# Third-party source files.
set(SOURCES_3RD_PARTY
${PROJECT_SOURCE_DIR}/3rdParty/qautostart/src/qautostart.cpp
${PROJECT_SOURCE_DIR}/3rdParty/qautostart/src/qautostart.h
${PROJECT_SOURCE_DIR}/3rdParty/qmarkdowntextedit/linenumberarea.h
${PROJECT_SOURCE_DIR}/3rdParty/qmarkdowntextedit/markdownhighlighter.cpp
${PROJECT_SOURCE_DIR}/3rdParty/qmarkdowntextedit/markdownhighlighter.h
${PROJECT_SOURCE_DIR}/3rdParty/qmarkdowntextedit/qmarkdowntextedit.cpp
${PROJECT_SOURCE_DIR}/3rdParty/qmarkdowntextedit/qmarkdowntextedit.h
${PROJECT_SOURCE_DIR}/3rdParty/qmarkdowntextedit/qownlanguagedata.cpp
${PROJECT_SOURCE_DIR}/3rdParty/qmarkdowntextedit/qownlanguagedata.h
${PROJECT_SOURCE_DIR}/3rdParty/qmarkdowntextedit/qplaintexteditsearchwidget.cpp
${PROJECT_SOURCE_DIR}/3rdParty/qmarkdowntextedit/qplaintexteditsearchwidget.h
${PROJECT_SOURCE_DIR}/3rdParty/qxt/qxtglobal.cpp
${PROJECT_SOURCE_DIR}/3rdParty/qxt/qxtglobal.h
${PROJECT_SOURCE_DIR}/3rdParty/qxt/qxtglobalshortcut.cpp
${PROJECT_SOURCE_DIR}/3rdParty/qxt/qxtglobalshortcut.h
${PROJECT_SOURCE_DIR}/3rdParty/qxt/qxtglobalshortcut_p.h)
if(UPDATE_CHECKER)
list(APPEND SOURCES ${PROJECT_SOURCE_DIR}/src/updaterwindow.cpp
${PROJECT_SOURCE_DIR}/src/updaterwindow.h
${PROJECT_SOURCE_DIR}/src/updaterwindow.ui)
list(
APPEND
SOURCES_3RD_PARTY
${PROJECT_SOURCE_DIR}/3rdParty/QSimpleUpdater/include/QSimpleUpdater.h
${PROJECT_SOURCE_DIR}/3rdParty/QSimpleUpdater/src/Downloader.cpp
${PROJECT_SOURCE_DIR}/3rdParty/QSimpleUpdater/src/Downloader.h
${PROJECT_SOURCE_DIR}/3rdParty/QSimpleUpdater/src/QSimpleUpdater.cpp
${PROJECT_SOURCE_DIR}/3rdParty/QSimpleUpdater/src/Updater.cpp
${PROJECT_SOURCE_DIR}/3rdParty/QSimpleUpdater/src/Updater.h)
endif()
if(APPLE)
list(APPEND SOURCES ${PROJECT_SOURCE_DIR}/src/framelesswindow.mm
${PROJECT_SOURCE_DIR}/src/framelesswindow.h
${PROJECT_SOURCE_DIR}/src/images/notes_icon.icns)
list(APPEND SOURCES_3RD_PARTY
${PROJECT_SOURCE_DIR}/3rdParty/qxt/qxtglobalshortcut_mac.cpp)
elseif(UNIX)
list(APPEND SOURCES_3RD_PARTY
${PROJECT_SOURCE_DIR}/3rdParty/qxt/qxtglobalshortcut_x11.cpp)
elseif(WIN32)
list(APPEND SOURCES ${PROJECT_SOURCE_DIR}/src/framelesswindow.cpp
${PROJECT_SOURCE_DIR}/src/framelesswindow.h
${PROJECT_SOURCE_DIR}/src/images/notes.rc)
list(APPEND SOURCES_3RD_PARTY
${PROJECT_SOURCE_DIR}/3rdParty/qxt/qxtglobalshortcut_win.cpp)
endif()
add_executable(${PROJECT_NAME} WIN32 MACOSX_BUNDLE ${SOURCES}
${SOURCES_3RD_PARTY})
target_include_directories(${PROJECT_NAME} PUBLIC ${PROJECT_SOURCE_DIR}/src)
# Include third-party headers as 'system' files, in order to silence compiler warnings on them.
target_include_directories(
${PROJECT_NAME} SYSTEM
PUBLIC ${PROJECT_SOURCE_DIR}/3rdParty/qautostart/src
${PROJECT_SOURCE_DIR}/3rdParty/qmarkdowntextedit
${PROJECT_SOURCE_DIR}/3rdParty/qxt)
if(UPDATE_CHECKER)
target_include_directories(
${PROJECT_NAME} SYSTEM
PUBLIC ${PROJECT_SOURCE_DIR}/3rdParty/QSimpleUpdater/include)
add_definitions(-DUPDATE_CHECKER)
endif()
target_compile_definitions(
${PROJECT_NAME}
PUBLIC APP_VERSION="${PROJECT_VERSION}${GIT_REV}" APP_ID="${APP_ID}"
QT_DISABLE_DEPRECATED_BEFORE=0x050900 QSU_INCLUDE_MOC=1)
# Enable useful compiler warnings (except on third-party code).
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES
"Clang")
target_compile_options(${PROJECT_NAME} PUBLIC -Wall -Wextra -Wpedantic
-Wshadow)
set_source_files_properties(${SOURCES_3RD_PARTY} PROPERTIES COMPILE_FLAGS -w)
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC" AND MSVC_VERSION GREATER_EQUAL
1920)
target_compile_options(${PROJECT_NAME} PUBLIC /W4)
set_source_files_properties(${SOURCES_3RD_PARTY} PROPERTIES COMPILE_FLAGS /w)
endif()
if(QT_VERSION VERSION_GREATER_EQUAL 6.2)
set(QML_FILES
src/qml/CheckBoxMaterial.qml
src/qml/CustomHorizontalScrollBar.qml
src/qml/CustomTextArea.qml
src/qml/CustomTextField.qml
src/qml/CustomVerticalScrollBar.qml
src/qml/EditorSettings.qml
src/qml/FontChooserButton.qml
src/qml/FontIconLoader.qml
src/qml/FontIconsCodes.qml
src/qml/IconButton.qml
src/qml/OptionItemButton.qml
src/qml/SubscriptionWindow.qml
src/qml/SwitchButton.qml
src/qml/TextButton.qml
src/qml/ThemeChooserButton.qml
src/qml/TodoColumnDelegate.qml
src/qml/TodoTaskDelegate.qml
src/qml/Utilities.js
src/qml/ViewChooserButton.qml
src/qml/kanbanMain.qml)
foreach(file IN LISTS QML_FILES)
get_filename_component(fileName ${file} NAME)
set_source_files_properties(${file} PROPERTIES QT_RESOURCE_ALIAS
${fileName})
# This whole shenanigans is required to silence compiler warnings on files auto-generated by rcc.
# It isn't pretty, but unfortunately there's no nicer way to do this yet:
# https://discourse.cmake.org/t/qt-autogen-source-files-custom-compilation-flags/3002
string(REPLACE "." "_" file_qml_cpp ${fileName})
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES
"Clang")
set_source_files_properties(
${CMAKE_CURRENT_BINARY_DIR}/.rcc/qmlcache/${PROJECT_NAME}_src/qml/${file_qml_cpp}.cpp
PROPERTIES COMPILE_FLAGS -w)
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC" AND MSVC_VERSION GREATER_EQUAL
1920)
set_source_files_properties(
${CMAKE_CURRENT_BINARY_DIR}/.rcc/qmlcache/${PROJECT_NAME}_src/qml/${file_qml_cpp}.cpp
PROPERTIES COMPILE_FLAGS /w)
endif()
endforeach()
# Silence an extra warning given by Clang:
# build/.rcc/qmlcache/Notes_qmlcache_loader.cpp#L46
# must specify at least one argument for '...' parameter of variadic macro [-Wgnu-zero-variadic-macro-arguments]
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
set_source_files_properties(
${CMAKE_CURRENT_BINARY_DIR}/.rcc/qmlcache/${PROJECT_NAME}_qmlcache_loader.cpp
PROPERTIES COMPILE_FLAGS -w)
endif()
qt_add_qml_module(
${PROJECT_NAME}
URI
${APP_ID}
VERSION
${PROJECT_VERSION}
NO_PLUGIN
RESOURCE_PREFIX
"/qt/qml"
QML_FILES
${QML_FILES}
NO_RESOURCE_TARGET_PATH)
endif()
target_link_libraries(
${PROJECT_NAME}
PUBLIC Qt${QT_VERSION_MAJOR}::Concurrent
Qt${QT_VERSION_MAJOR}::Core
Qt${QT_VERSION_MAJOR}::CorePrivate
Qt${QT_VERSION_MAJOR}::Gui
Qt${QT_VERSION_MAJOR}::GuiPrivate
Qt${QT_VERSION_MAJOR}::Network
Qt${QT_VERSION_MAJOR}::Sql
Qt${QT_VERSION_MAJOR}::Widgets
Qt${QT_VERSION_MAJOR}::WidgetsPrivate
Qt${QT_VERSION_MAJOR}::Quick)
if(APPLE)
set(COPYRIGHT_TEXT
"Copyright (c) 2015-${CURRENT_YEAR} ${APP_AUTHOR} and contributors.")
set_target_properties(
${PROJECT_NAME}
PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME ${PROJECT_NAME}
MACOSX_BUNDLE_GUI_IDENTIFIER ${APP_ID}
MACOSX_BUNDLE_ICON_FILE "notes_icon.icns"
MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION}
MACOSX_BUNDLE_LONG_VERSION_STRING ${PROJECT_VERSION}
MACOSX_BUNDLE_COPYRIGHT ${COPYRIGHT_TEXT}
MACOSX_BUNDLE_INFO_STRING ${COPYRIGHT_TEXT})
set_source_files_properties(${PROJECT_SOURCE_DIR}/src/images/notes_icon.icns
PROPERTIES MACOSX_PACKAGE_LOCATION "Resources")
target_link_libraries(${PROJECT_NAME} PUBLIC "-framework Carbon"
"-framework Cocoa")
elseif(UNIX)
# On Linux, it's conventional for executables to be all lowercase.
string(TOLOWER ${PROJECT_NAME} PROJECT_NAME_LOWERCASE)
set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME
${PROJECT_NAME_LOWERCASE})
find_package(X11 REQUIRED)
target_link_libraries(${PROJECT_NAME} PUBLIC ${X11_LIBRARIES})
include(GNUInstallDirs)
configure_file(${PROJECT_SOURCE_DIR}/packaging/linux/common/notes.desktop.in
${CMAKE_BINARY_DIR}/${APP_ID}.desktop)
install(FILES ${CMAKE_BINARY_DIR}/${APP_ID}.desktop
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/applications)
configure_file(
${PROJECT_SOURCE_DIR}/packaging/linux/common/notes.appdata.xml.in
${CMAKE_BINARY_DIR}/${APP_ID}.metainfo.xml)
install(FILES ${CMAKE_BINARY_DIR}/${APP_ID}.metainfo.xml
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/metainfo)
foreach(ICON_SIZE 128 256 512)
install(
FILES
${PROJECT_SOURCE_DIR}/packaging/linux/common/icons/${ICON_SIZE}x${ICON_SIZE}/notes.png
DESTINATION
${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/${ICON_SIZE}x${ICON_SIZE}/apps
RENAME ${APP_ID}.png)
endforeach()
install(
FILES ${PROJECT_SOURCE_DIR}/LICENSE
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/licenses/${PROJECT_NAME_LOWERCASE})
# On Debian-based distros, compress the changelog file and install the copyright file.
# FIXME: Find out if it's possible to only do this when creating a deb package with CPack.
if(EXISTS /etc/debian_version)
string(TIMESTAMP DATE_NOW_UTC "%a, %d %b %Y %H:%M:%S +0000")
configure_file(${PROJECT_SOURCE_DIR}/packaging/linux/debian/changelog.in
${CMAKE_BINARY_DIR}/changelog.Debian)
add_custom_command(
COMMAND gzip ARGS -9 -c -f -k -n ${CMAKE_BINARY_DIR}/changelog.Debian >
${CMAKE_BINARY_DIR}/changelog.gz
OUTPUT ${CMAKE_BINARY_DIR}/changelog.gz)
add_custom_target(changelog ALL DEPENDS ${CMAKE_BINARY_DIR}/changelog.gz)
install(
FILES ${CMAKE_BINARY_DIR}/changelog.gz
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/doc/${PROJECT_NAME_LOWERCASE})
configure_file(${PROJECT_SOURCE_DIR}/packaging/linux/debian/copyright.in
${CMAKE_BINARY_DIR}/copyright)
install(
FILES ${CMAKE_BINARY_DIR}/copyright
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/doc/${PROJECT_NAME_LOWERCASE})
endif()
set(CPACK_PACKAGE_NAME ${PROJECT_NAME_LOWERCASE})
set(CPACK_PACKAGE_VERSION ${PROJECT_VERSION}${GIT_REV})
set(CPACK_PACKAGE_VENDOR ${APP_AUTHOR})
set(CPACK_PACKAGE_CONTACT "${APP_AUTHOR} <${APP_AUTHOR_EMAIL}>")
set(CPACK_STRIP_FILES TRUE)
# Package description.
# Please keep the character count for every line at 80 (max) - it's a lintian rule.
string(CONCAT CPACK_PACKAGE_DESCRIPTION
"Note-taking app that is both beautiful and powerful.\n"
" It is written in C++ using the Qt framework.")
# Workaround for older CMake versions, where CPACK_PACKAGE_DESCRIPTION didn't exist.
if(CMAKE_VERSION VERSION_LESS 3.12)
string(CONCAT CPACK_DEBIAN_PACKAGE_DESCRIPTION "${PROJECT_DESCRIPTION}\n"
" ${CPACK_PACKAGE_DESCRIPTION}")
endif()
# deb-specific
set(CPACK_DEBIAN_FILE_NAME DEB-DEFAULT)
if(QT_VERSION_MAJOR VERSION_GREATER_EQUAL 6)
set(CPACK_DEBIAN_PACKAGE_DEPENDS "qt6-qpa-plugins")
if(QT_VERSION_MINOR VERSION_GREATER_EQUAL 2)
set(CPACK_DEBIAN_PACKAGE_DEPENDS
"${CPACK_DEBIAN_PACKAGE_DEPENDS}, qml6-module-qtqml-workerscript, qml6-module-qtquick-controls, qml6-module-qtquick-layouts, qml6-module-qtquick-particles, qml6-module-qtquick-templates, qml6-module-qtquick-window"
)
endif()
elseif(QT_VERSION_MAJOR VERSION_EQUAL 5)
set(CPACK_DEBIAN_PACKAGE_DEPENDS
"qml-module-qtquick2, qml-module-qtquick-controls2, qml-module-qtquick-window2"
)
endif()
set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON)
set(CPACK_DEBIAN_PACKAGE_HOMEPAGE ${APP_WEBSITE})
set(CPACK_DEBIAN_PACKAGE_SECTION "utils")
# rpm-specific
set(CPACK_RPM_FILE_NAME RPM-DEFAULT)
if(QT_VERSION_MAJOR VERSION_GREATER_EQUAL 6)
if(UNIX
AND NOT APPLE
AND EXISTS /etc/os-release)
file(READ /etc/os-release DISTRO_INFO)
if(DISTRO_INFO MATCHES "SUSE")
# Note: Different from Fedora 36, the SQLite library we need is not a dependency
# of the base Qt 6 package on openSUSE Leap 15.4, so we have to manually include it here.
set(CPACK_RPM_PACKAGE_REQUIRES "qt6-sql-sqlite")
endif()
endif()
endif()
set(CPACK_RPM_PACKAGE_LICENSE MPL-2.0)
set(CPACK_RPM_PACKAGE_URL ${APP_WEBSITE})
set(CPACK_RPM_PACKAGE_GROUP Applications/Text)
set(CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION /usr/share/icons)
# Remove any leading whitespace character from the description text we added for the deb package.
string(REGEX REPLACE "\n +" "\n" CPACK_RPM_PACKAGE_DESCRIPTION
${CPACK_PACKAGE_DESCRIPTION})
set(CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION /usr/share/icons)
include(CPack)
elseif(WIN32)
target_compile_definitions(${PROJECT_NAME} PUBLIC QXT_STATIC)
target_link_libraries(${PROJECT_NAME} PUBLIC user32)
endif()
install(
TARGETS ${PROJECT_NAME}
RUNTIME DESTINATION bin
BUNDLE DESTINATION bin
LIBRARY DESTINATION lib)

@ -0,0 +1,17 @@
# Docker images for CI/CD
The Dockerfiles in this folder are used to build images for CI/CD pipelines.
### Building images locally
```bash
docker build -f <path-to-dockerfile> -t <image-name> .
# for example:
docker build -f ./ubuntu-aqtinstall-6 -t zjeffer:notes/ubuntu-aqtinstall-6.4.3 .
```
### Pushing images to Docker Hub
```bash
docker push <image-name>
```

@ -0,0 +1,5 @@
FROM fedora:38
RUN dnf update -y && \
dnf install -y cmake gcc git rpm-build rpmlint \
libxkbcommon-devel qt6-qtbase-private-devel qt6-qtdeclarative-devel

@ -0,0 +1,5 @@
FROM opensuse/leap:15
RUN zypper update -y && \
zypper install -y cmake gcc git rpm-build rpmlint \
qt6-base-private-devel qt6-declarative-devel

@ -0,0 +1,10 @@
FROM ubuntu:20.04
# fix for tzdata asking for input
ENV DEBIAN_FRONTEND=noninteractive
RUN apt update && \
apt install -y git sudo \
gcc cmake lintian \
qtbase5-private-dev qtdeclarative5-dev
RUN apt clean

@ -0,0 +1,10 @@
FROM ubuntu:22.04
# fix for tzdata asking for input
ENV DEBIAN_FRONTEND=noninteractive
RUN apt update && \
apt install -y git sudo \
gcc cmake lintian \
qt6-base-private-dev qt6-declarative-dev libgl-dev
RUN apt clean

@ -0,0 +1,10 @@
FROM ubuntu:23.10
# fix for tzdata asking for input
ENV DEBIAN_FRONTEND=noninteractive
RUN apt update && \
apt install -y git sudo \
gcc cmake lintian \
qt6-base-private-dev qt6-declarative-dev libgl-dev
RUN apt clean

@ -0,0 +1,37 @@
FROM ubuntu:22.04
ENV QT_VERSION=5.15.2
ENV QT_ARCHITECTURE=gcc_64
# this image can also be used for appimage builds
# Configure the timezone, otherwise 'install-qt-action' gets stuck at 'configuring tzdata'.
RUN ln -sf /usr/share/zoneinfo/UTC /etc/localtime \
&& echo UTC > /etc/timezone
# install packages
# - appstream: Used to validate the AppStream metadata file.
# - cmake: Used to help build the application.
# - curl: Used to download the linuxdeploy AppImage tool.
# - desktop-file-utils: Used to validate the desktop file.
# - git: To clone this repository.
# - libfontconfig1: Used as dependency of the resulting AppImage.
# - libxcb-cursor0: Used as dependency of the resulting AppImage.
# - libxkbcommon-x11-0: Used as dependency of the resulting AppImage.
# - python3/python3-pip: Used by aqtinstall.
# - sudo: Used by most GitHub actions to install things.
# - libpq5: Useless, but needed to keep linuxdeploy happy
# - libodbc1: Useless, but needed to keep linuxdeploy happy
# - file: Necessary for building the AppImage
RUN apt update && \
apt install -y appstream cmake curl desktop-file-utils git libfontconfig1 libxcb-cursor0 libxkbcommon-x11-0 python3 python3-pip sudo \
libpq5 libodbc1 file \
# qt dependencies
build-essential libgl1-mesa-dev libgstreamer-gl1.0-0 libpulse-dev libxcb-glx0 libxcb-icccm4 libxcb-image0 libxcb-keysyms1 libxcb-randr0 \
libxcb-render-util0 libxcb-render0 libxcb-shape0 libxcb-shm0 libxcb-sync1 libxcb-util1 libxcb-xfixes0 libxcb-xinerama0 libxcb1 libxkbcommon-dev libxkbcommon-x11-0 libxcb-xkb-dev \
libqt5network5 libqt5sql5 libqt5widgets5 qml-module-qtquick2 qml-module-qtquick-controls2 qml-module-qtquick-window2
RUN python3 -m pip install --upgrade pip setuptools aqtinstall
# use aqtinstall to install qt
RUN python3 -m aqt install-qt --outputdir /Qt linux desktop $QT_VERSION $QT_ARCHITECTURE
ENV PATH="/Qt/$QT_VERSION/$QT_ARCHITECTURE/bin:$PATH"

@ -0,0 +1,40 @@
FROM ubuntu:22.04
ENV QT_VERSION=6.4.3
ENV QT_ARCHITECTURE=gcc_64
# this image can also be used for appimage builds
# Configure the timezone, otherwise 'install-qt-action' gets stuck at 'configuring tzdata'.
RUN ln -sf /usr/share/zoneinfo/UTC /etc/localtime \
&& echo UTC > /etc/timezone
# install packages
# - appstream: Used to validate the AppStream metadata file.
# - cmake: Used to help build the application.
# - curl: Used to download the linuxdeploy AppImage tool.
# - desktop-file-utils: Used to validate the desktop file.
# - git: To clone this repository.
# - libfontconfig1: Used as dependency of the resulting AppImage.
# - libxcb-cursor0: Used as dependency of the resulting AppImage.
# - libxkbcommon-x11-0: Used as dependency of the resulting AppImage.
# - python3/python3-pip: Used by aqtinstall.
# - sudo: Used by most GitHub actions to install things.
# - libpq5: Useless, but needed to keep linuxdeploy happy
# - libodbc1: Useless, but needed to keep linuxdeploy happy
# - file: Necessary for building the AppImage
RUN apt update && \
apt install -y appstream cmake curl desktop-file-utils git libfontconfig1 libxcb-cursor0 libxkbcommon-x11-0 python3 python3-pip sudo \
libpq5 libodbc1 file \
# qt dependencies
build-essential libgl1-mesa-dev libgstreamer-gl1.0-0 libpulse-dev libxcb-glx0 libxcb-icccm4 libxcb-image0 libxcb-keysyms1 libxcb-randr0 \
libxcb-render-util0 libxcb-render0 libxcb-shape0 libxcb-shm0 libxcb-sync1 libxcb-util1 libxcb-xfixes0 libxcb-xinerama0 libxcb1 libxkbcommon-dev libxkbcommon-x11-0 libxcb-xkb-dev \
libqt6network6 libqt6sql6 libqt6widgets6 qml6-module-qtqml-workerscript qml6-module-qtquick-controls qml6-module-qtquick-layouts qml6-module-qtquick-particles qml6-module-qtquick-templates qml6-module-qtquick-window qt6-qpa-plugins
RUN python3 -m pip install --upgrade pip setuptools aqtinstall
# qt6 dependencies
RUN apt install -y libxkbcommon-dev libmysqlclient21
# use aqtinstall to install qt
RUN python3 -m aqt install-qt --outputdir /Qt linux desktop $QT_VERSION $QT_ARCHITECTURE
ENV PATH="/Qt/$QT_VERSION/$QT_ARCHITECTURE/bin:$PATH"

@ -0,0 +1,373 @@
Mozilla Public License Version 2.0
==================================
1. Definitions
--------------
1.1. "Contributor"
means each individual or legal entity that creates, contributes to
the creation of, or owns Covered Software.
1.2. "Contributor Version"
means the combination of the Contributions of others (if any) used
by a Contributor and that particular Contributor's Contribution.
1.3. "Contribution"
means Covered Software of a particular Contributor.
1.4. "Covered Software"
means Source Code Form to which the initial Contributor has attached
the notice in Exhibit A, the Executable Form of such Source Code
Form, and Modifications of such Source Code Form, in each case
including portions thereof.
1.5. "Incompatible With Secondary Licenses"
means
(a) that the initial Contributor has attached the notice described
in Exhibit B to the Covered Software; or
(b) that the Covered Software was made available under the terms of
version 1.1 or earlier of the License, but not also under the
terms of a Secondary License.
1.6. "Executable Form"
means any form of the work other than Source Code Form.
1.7. "Larger Work"
means a work that combines Covered Software with other material, in
a separate file or files, that is not Covered Software.
1.8. "License"
means this document.
1.9. "Licensable"
means having the right to grant, to the maximum extent possible,
whether at the time of the initial grant or subsequently, any and
all of the rights conveyed by this License.
1.10. "Modifications"
means any of the following:
(a) any file in Source Code Form that results from an addition to,
deletion from, or modification of the contents of Covered
Software; or
(b) any new file in Source Code Form that contains any Covered
Software.
1.11. "Patent Claims" of a Contributor
means any patent claim(s), including without limitation, method,
process, and apparatus claims, in any patent Licensable by such
Contributor that would be infringed, but for the grant of the
License, by the making, using, selling, offering for sale, having
made, import, or transfer of either its Contributions or its
Contributor Version.
1.12. "Secondary License"
means either the GNU General Public License, Version 2.0, the GNU
Lesser General Public License, Version 2.1, the GNU Affero General
Public License, Version 3.0, or any later versions of those
licenses.
1.13. "Source Code Form"
means the form of the work preferred for making modifications.
1.14. "You" (or "Your")
means an individual or a legal entity exercising rights under this
License. For legal entities, "You" includes any entity that
controls, is controlled by, or is under common control with You. For
purposes of this definition, "control" means (a) the power, direct
or indirect, to cause the direction or management of such entity,
whether by contract or otherwise, or (b) ownership of more than
fifty percent (50%) of the outstanding shares or beneficial
ownership of such entity.
2. License Grants and Conditions
--------------------------------
2.1. Grants
Each Contributor hereby grants You a world-wide, royalty-free,
non-exclusive license:
(a) under intellectual property rights (other than patent or trademark)
Licensable by such Contributor to use, reproduce, make available,
modify, display, perform, distribute, and otherwise exploit its
Contributions, either on an unmodified basis, with Modifications, or
as part of a Larger Work; and
(b) under Patent Claims of such Contributor to make, use, sell, offer
for sale, have made, import, and otherwise transfer either its
Contributions or its Contributor Version.
2.2. Effective Date
The licenses granted in Section 2.1 with respect to any Contribution
become effective for each Contribution on the date the Contributor first
distributes such Contribution.
2.3. Limitations on Grant Scope
The licenses granted in this Section 2 are the only rights granted under
this License. No additional rights or licenses will be implied from the
distribution or licensing of Covered Software under this License.
Notwithstanding Section 2.1(b) above, no patent license is granted by a
Contributor:
(a) for any code that a Contributor has removed from Covered Software;
or
(b) for infringements caused by: (i) Your and any other third party's
modifications of Covered Software, or (ii) the combination of its
Contributions with other software (except as part of its Contributor
Version); or
(c) under Patent Claims infringed by Covered Software in the absence of
its Contributions.
This License does not grant any rights in the trademarks, service marks,
or logos of any Contributor (except as may be necessary to comply with
the notice requirements in Section 3.4).
2.4. Subsequent Licenses
No Contributor makes additional grants as a result of Your choice to
distribute the Covered Software under a subsequent version of this
License (see Section 10.2) or under the terms of a Secondary License (if
permitted under the terms of Section 3.3).
2.5. Representation
Each Contributor represents that the Contributor believes its
Contributions are its original creation(s) or it has sufficient rights
to grant the rights to its Contributions conveyed by this License.
2.6. Fair Use
This License is not intended to limit any rights You have under
applicable copyright doctrines of fair use, fair dealing, or other
equivalents.
2.7. Conditions
Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
in Section 2.1.
3. Responsibilities
-------------------
3.1. Distribution of Source Form
All distribution of Covered Software in Source Code Form, including any
Modifications that You create or to which You contribute, must be under
the terms of this License. You must inform recipients that the Source
Code Form of the Covered Software is governed by the terms of this
License, and how they can obtain a copy of this License. You may not
attempt to alter or restrict the recipients' rights in the Source Code
Form.
3.2. Distribution of Executable Form
If You distribute Covered Software in Executable Form then:
(a) such Covered Software must also be made available in Source Code
Form, as described in Section 3.1, and You must inform recipients of
the Executable Form how they can obtain a copy of such Source Code
Form by reasonable means in a timely manner, at a charge no more
than the cost of distribution to the recipient; and
(b) You may distribute such Executable Form under the terms of this
License, or sublicense it under different terms, provided that the
license for the Executable Form does not attempt to limit or alter
the recipients' rights in the Source Code Form under this License.
3.3. Distribution of a Larger Work
You may create and distribute a Larger Work under terms of Your choice,
provided that You also comply with the requirements of this License for
the Covered Software. If the Larger Work is a combination of Covered
Software with a work governed by one or more Secondary Licenses, and the
Covered Software is not Incompatible With Secondary Licenses, this
License permits You to additionally distribute such Covered Software
under the terms of such Secondary License(s), so that the recipient of
the Larger Work may, at their option, further distribute the Covered
Software under the terms of either this License or such Secondary
License(s).
3.4. Notices
You may not remove or alter the substance of any license notices
(including copyright notices, patent notices, disclaimers of warranty,
or limitations of liability) contained within the Source Code Form of
the Covered Software, except that You may alter any license notices to
the extent required to remedy known factual inaccuracies.
3.5. Application of Additional Terms
You may choose to offer, and to charge a fee for, warranty, support,
indemnity or liability obligations to one or more recipients of Covered
Software. However, You may do so only on Your own behalf, and not on
behalf of any Contributor. You must make it absolutely clear that any
such warranty, support, indemnity, or liability obligation is offered by
You alone, and You hereby agree to indemnify every Contributor for any
liability incurred by such Contributor as a result of warranty, support,
indemnity or liability terms You offer. You may include additional
disclaimers of warranty and limitations of liability specific to any
jurisdiction.
4. Inability to Comply Due to Statute or Regulation
---------------------------------------------------
If it is impossible for You to comply with any of the terms of this
License with respect to some or all of the Covered Software due to
statute, judicial order, or regulation then You must: (a) comply with
the terms of this License to the maximum extent possible; and (b)
describe the limitations and the code they affect. Such description must
be placed in a text file included with all distributions of the Covered
Software under this License. Except to the extent prohibited by statute
or regulation, such description must be sufficiently detailed for a
recipient of ordinary skill to be able to understand it.
5. Termination
--------------
5.1. The rights granted under this License will terminate automatically
if You fail to comply with any of its terms. However, if You become
compliant, then the rights granted under this License from a particular
Contributor are reinstated (a) provisionally, unless and until such
Contributor explicitly and finally terminates Your grants, and (b) on an
ongoing basis, if such Contributor fails to notify You of the
non-compliance by some reasonable means prior to 60 days after You have
come back into compliance. Moreover, Your grants from a particular
Contributor are reinstated on an ongoing basis if such Contributor
notifies You of the non-compliance by some reasonable means, this is the
first time You have received notice of non-compliance with this License
from such Contributor, and You become compliant prior to 30 days after
Your receipt of the notice.
5.2. If You initiate litigation against any entity by asserting a patent
infringement claim (excluding declaratory judgment actions,
counter-claims, and cross-claims) alleging that a Contributor Version
directly or indirectly infringes any patent, then the rights granted to
You by any and all Contributors for the Covered Software under Section
2.1 of this License shall terminate.
5.3. In the event of termination under Sections 5.1 or 5.2 above, all
end user license agreements (excluding distributors and resellers) which
have been validly granted by You or Your distributors under this License
prior to termination shall survive termination.
************************************************************************
* *
* 6. Disclaimer of Warranty *
* ------------------------- *
* *
* Covered Software is provided under this License on an "as is" *
* basis, without warranty of any kind, either expressed, implied, or *
* statutory, including, without limitation, warranties that the *
* Covered Software is free of defects, merchantable, fit for a *
* particular purpose or non-infringing. The entire risk as to the *
* quality and performance of the Covered Software is with You. *
* Should any Covered Software prove defective in any respect, You *
* (not any Contributor) assume the cost of any necessary servicing, *
* repair, or correction. This disclaimer of warranty constitutes an *
* essential part of this License. No use of any Covered Software is *
* authorized under this License except under this disclaimer. *
* *
************************************************************************
************************************************************************
* *
* 7. Limitation of Liability *
* -------------------------- *
* *
* Under no circumstances and under no legal theory, whether tort *
* (including negligence), contract, or otherwise, shall any *
* Contributor, or anyone who distributes Covered Software as *
* permitted above, be liable to You for any direct, indirect, *
* special, incidental, or consequential damages of any character *
* including, without limitation, damages for lost profits, loss of *
* goodwill, work stoppage, computer failure or malfunction, or any *
* and all other commercial damages or losses, even if such party *
* shall have been informed of the possibility of such damages. This *
* limitation of liability shall not apply to liability for death or *
* personal injury resulting from such party's negligence to the *
* extent applicable law prohibits such limitation. Some *
* jurisdictions do not allow the exclusion or limitation of *
* incidental or consequential damages, so this exclusion and *
* limitation may not apply to You. *
* *
************************************************************************
8. Litigation
-------------
Any litigation relating to this License may be brought only in the
courts of a jurisdiction where the defendant maintains its principal
place of business and such litigation shall be governed by laws of that
jurisdiction, without reference to its conflict-of-law provisions.
Nothing in this Section shall prevent a party's ability to bring
cross-claims or counter-claims.
9. Miscellaneous
----------------
This License represents the complete agreement concerning the subject
matter hereof. If any provision of this License is held to be
unenforceable, such provision shall be reformed only to the extent
necessary to make it enforceable. Any law or regulation which provides
that the language of a contract shall be construed against the drafter
shall not be used to construe this License against a Contributor.
10. Versions of the License
---------------------------
10.1. New Versions
Mozilla Foundation is the license steward. Except as provided in Section
10.3, no one other than the license steward has the right to modify or
publish new versions of this License. Each version will be given a
distinguishing version number.
10.2. Effect of New Versions
You may distribute the Covered Software under the terms of the version
of the License under which You originally received the Covered Software,
or under the terms of any subsequent version published by the license
steward.
10.3. Modified Versions
If you create software not governed by this License, and you want to
create a new license for such software, you may create and use a
modified version of this License if you rename the license and remove
any references to the name of the license steward (except to note that
such modified license differs from this License).
10.4. Distributing Source Code Form that is Incompatible With Secondary
Licenses
If You choose to distribute Source Code Form that is Incompatible With
Secondary Licenses under the terms of this version of the License, the
notice described in Exhibit B of this License must be attached.
Exhibit A - Source Code Form License Notice
-------------------------------------------
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/.
If it is not possible or desirable to put the notice in a particular
file, then You may include the notice in a location (such as a LICENSE
file in a relevant directory) where a recipient would be likely to look
for such a notice.
You may add additional accurate notices of copyright ownership.
Exhibit B - "Incompatible With Secondary Licenses" Notice
---------------------------------------------------------
This Source Code Form is "Incompatible With Secondary Licenses", as
defined by the Mozilla Public License, v. 2.0.

@ -1,190 +0,0 @@
Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net)
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS

@ -1,23 +0,0 @@
[中文]
1. MiCode便签是小米便签的社区开源版由MIUI团队(www.miui.com) 发起并贡献第一批代码遵循NOTICE文件所描述的开源协议
今后为MiCode社区(www.micode.net) 拥有,并由社区发布和维护。
2. Bug反馈和跟踪请访问Github,
https://github.com/MiCode/Notes/issues?sort=created&direction=desc&state=open
3. 功能建议和综合讨论请访问MiCode,
http://micode.net/forum.php?mod=forumdisplay&fid=38
[English]
1. MiCode Notes is open source edition of XM notepad, it's first initiated and sponsored by MIUI team (www.miui.com).
It's opened under license described by NOTICE file. It's owned by the MiCode community (www.micode.net). In future,
the MiCode community will release and maintain this project.
2. Regarding issue tracking, please visit Github,
https://github.com/MiCode/Notes/issues?sort=created&direction=desc&state=open
3. Regarding feature request and general discussion, please visit Micode forum,
http://micode.net/forum.php?mod=forumdisplay&fid=38

@ -0,0 +1,103 @@
# Notes
[![Discord](https://dcbadge.vercel.app/api/server/RP6ReXRn5j?style=flat)](https://discord.gg/RP6ReXRn5j)
[![GitHub Actions build status](https://github.com/nuttyartist/notes/actions/workflows/ci.yml/badge.svg?branch=master)](https://github.com/nuttyartist/notes/actions/workflows/ci.yml?query=branch%3Amaster)
Notes is an open source and cross-platform note-taking app that is both beautiful and powerful.
Website: <a href="https://get-notes.com" target="_blank">get-notes.com</a>
## Screenshots
https://github.com/nuttyartist/notes/assets/16375940/714ffe3e-95ef-4233-b3da-58fcea33fbfa
https://github.com/nuttyartist/notes/assets/16375940/370439b1-e42b-45c4-a807-0c3657051f97
## Features Overview
- Native app (written in C++ with Qt).
- Turn your Markdown tasks into a beautiful Kanban board.
- Fast and beautiful.
- Fully open source and cross-platform (Linux, macOS, Windows).
- Completely private - tracks nothing.
- Folders and tags. Organize your ideas hierarchically using nested folders and universally using tags.
- Markdown Support. Format text without lifting your hands from the keyboard.
- Different themes. Switch between Light, Dark, and Sepia.
- Feed View. Select multiple notes to see them all one after another in the editor.
- Always runs in the background. Use the hotkey <kbd>Win</kbd>+<kbd>Shift</kbd>+<kbd>N</kbd> to summon Notes. <kbd>Ctrl</kbd>+<kbd>N</kbd> for macOS.
- Keyboard shortcuts. Meant to have the option to be used solely with a keyboard (but more work needs to be done on that).
- What feature will you contribute?
## Keyboard shortcuts
All keyboard shortcuts are [documented here](docs/keyboard_shortcuts.md).
## Pro Version
To support our open source development you can purchase a [Pro Version license](https://notesapp.lemonsqueezy.com/checkout/buy/0e791d1e-9feb-4a67-b05a-f2f07f5c82ad?discount=0) that will allow you to edit inside the Kanban view and recieve free Pro version updates for a year. You can also donate money either through [Github Sponsors](https://github.com/sponsors/nuttyartist), or [Patreon](https://www.patreon.com/rubymamis), or put a bounty on specific issues using Bountysource. If you wish, you can access all Pro features at no cost by building the app from source. See "Building from source" below.
## Building from source
We have specific instructions for [Windows](docs/build_on_windows.md), [macOS](docs/build_on_macos.md) and [Linux](docs/build_on_linux.md) (and we also provide [build options](docs/build_options.md)).
## Database path
The notes database and settings file are stored in:
| OS | Path |
| ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
| Windows | `%APPDATA%\Awesomeness` |
| Linux | `~/.config/Awesomeness`<br>`~/snap/notes/current/.config/Awesomeness` (Snap)<br>`~/.var/app/io.github.nuttyartist.notes/config/Awesomeness` (Flatpak) |
| macOS | `~/.config/Awesomeness` |
## Contributors
### Developers:
Alex Spataru
Ali Diouri
David Planella
Diep Ngoc
Guilherme Silva
Thorbjørn Lindeijer
Tuur Vanhoutte
Waqar Ahmed
### Designers:
Kevin Doyle
And to the many of our beloved users who keep sending us feedback, you are an essential force in helping us improve, thank you!
## Roadmap
A sneak peek at what were stirring up next.
- Mobile app using the same code base (adaptable app).
- Replace database with support for arbitrary folder.
- Our own built-in syncing.
- Export/import .txt files.
- Advanced blocks editor.
- Browser version using Qt for WebAssembly.
- Much, much more.
## Notes makes use of the following third-party libraries:
- [QMarkdownTextEdit](https://github.com/pbek/qmarkdowntextedit)
- [QSimpleUpdater](https://github.com/alex-spataru/QSimpleUpdater)
- [QAutostart](https://github.com/b00f/qautostart)
- [Qxt](https://bitbucket.org/libqxt/libqxt/src/master/)
## Notes makes use of the following open source fonts:
- Roboto
- Source Sans Pro
- Trykker
- Mate
- iA Writer Mono
- iA Writer Duo
- iA Writer Quattro
- Font Awesome
- Material Symbols
[Terms & Privacy policy](https://www.get-notes.com/notes-app-terms-privacy-policy)

@ -0,0 +1,22 @@
{
"updates": {
"windows": {
"open-url": "https://github.com/nuttyartist/notes/releases/download/v2.2.1/NotesSetup_2.2.1.exe",
"latest-version": "2.2.1",
"download-url": "https://github.com/nuttyartist/notes/releases/download/v2.2.1/NotesSetup_2.2.1.exe",
"changelog": "<style>div{color:#000}kbd{color:#24292f;background-color:#f6f8fa}ul{margin-left:-2em}</style><div><p>A new release is here with many bug fixes and improvements. To sustain and further our commitment to exceptional app development, we have transitioned to a subscription-based pricing model for the Pro version.</p><p>Improvements and bug fixes:</p><ul><li>Resolved a conflict within the Kanban interface: previously, editing a task would not conclude if a separate task was concurrently edited</li><li>Addressed an issue where editing was mistakenly permitted within the editor while the Trash folder was active</li><li>Fixed bug where icons didn't show up on some Linux distributions</li><li>Corrected an inconsistency where icons were not displayed on certain Linux distributions</li><li>Resolved display issues of specific windows on Ubuntu 23.04</li><li>Addressed an issue with the Editor Settings window failing to appear on Qt 5.12.2</li><li>For Pro users, the 'Pro' label within the Editor Settings has been made redundant and is now removed for a cleaner interface</li></ul><p>I want to thank the amazing people who contributed to this release! Thank you all. We have big plans for the future of Notes.</p><p>Join our <span><a href='https://discord.gg/RP6ReXRn5j'>Discord</a></span> for discussions, and feel free to email us. We love to hear from our users.</p></div><br>"
},
"osx": {
"open-url": "https://github.com/nuttyartist/notes/releases/download/v2.2.1/Notes.2.2.1.dmg",
"latest-version": "2.2.1",
"download-url": "https://github.com/nuttyartist/notes/releases/download/v2.2.1/Notes.2.2.1.dmg",
"changelog": "<style>div{color:#000}kbd{color:#24292f;background-color:#f6f8fa}ul{margin-left:-2em}</style><div><p>A new release is here with many bug fixes and improvements. To sustain and further our commitment to exceptional app development, we have transitioned to a subscription-based pricing model for the Pro version.</p><p>Improvements and bug fixes:</p><ul><li>Resolved a conflict within the Kanban interface: previously, editing a task would not conclude if a separate task was concurrently edited</li><li>Addressed an issue where editing was mistakenly permitted within the editor while the Trash folder was active</li><li>Fixed bug where icons didn't show up on some Linux distributions</li><li>Corrected an inconsistency where icons were not displayed on certain Linux distributions</li><li>Resolved display issues of specific windows on Ubuntu 23.04</li><li>Addressed an issue with the Editor Settings window failing to appear on Qt 5.12.2</li><li>For Pro users, the 'Pro' label within the Editor Settings has been made redundant and is now removed for a cleaner interface</li></ul><p>I want to thank the amazing people who contributed to this release! Thank you all. We have big plans for the future of Notes.</p><p>Join our <span><a href='https://discord.gg/RP6ReXRn5j'>Discord</a></span> for discussions, and feel free to email us. We love to hear from our users.</p></div><br>"
},
"linux": {
"open-url": "https://github.com/nuttyartist/notes/releases/download/v2.2.1/Notes_2.2.1-Qt6.4.3-x86_64.AppImage",
"latest-version": "2.2.1",
"download-url": "https://github.com/nuttyartist/notes/releases/download/v2.2.1/Notes_2.2.1-Qt6.4.3-x86_64.AppImage",
"changelog": "<style>div{color:#000}kbd{color:#24292f;background-color:#f6f8fa}ul{margin-left:-2em}</style><div><p>A new release is here with many bug fixes and improvements. To sustain and further our commitment to exceptional app development, we have transitioned to a subscription-based pricing model for the Pro version.</p><p>Improvements and bug fixes:</p><ul><li>Resolved a conflict within the Kanban interface: previously, editing a task would not conclude if a separate task was concurrently edited</li><li>Addressed an issue where editing was mistakenly permitted within the editor while the Trash folder was active</li><li>Fixed bug where icons didn't show up on some Linux distributions</li><li>Corrected an inconsistency where icons were not displayed on certain Linux distributions</li><li>Resolved display issues of specific windows on Ubuntu 23.04</li><li>Addressed an issue with the Editor Settings window failing to appear on Qt 5.12.2</li><li>For Pro users, the 'Pro' label within the Editor Settings has been made redundant and is now removed for a cleaner interface</li></ul><p>I want to thank the amazing people who contributed to this release! Thank you all. We have big plans for the future of Notes.</p><p>Join our <span><a href='https://discord.gg/RP6ReXRn5j'>Discord</a></span> for discussions, and feel free to email us. We love to hear from our users.</p></div><br>"
}
}
}

@ -0,0 +1,75 @@
These are common steps to build Notes from source on Linux distributions.
### Requirements
It's impossible to create a guide that will work for all Linux distros out there, but thankfully the only major difference between all of them will be package names, so feel free to add the appropriate package names for your favorite distro down here *(alphabetically, please)*.
| Distro | Build dependencies[^1] | Runtime dependencies[^2] |
| ---------------------------- | --------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Arch Linux[^3] | `cmake` `gcc` `git` `qt6-base` `qt6-declarative` | `hicolor-icon-theme` `qt6-base` `qt6-declarative` |
| Fedora 37 - 39 | `cmake` `gcc` `git` `libxkbcommon-devel` `qt6-qtbase-private-devel` `qt6-qtdeclarative-devel` | `qt6-qtbase-gui` `qt6-qtdeclarative` |
| openSUSE Leap 15[^4] | `cmake` `gcc` `git` `qt6-base-private-devel` `qt6-declarative-devel` | `libQt6Concurrent6` `libQt6Gui6` `qt6-sql-sqlite` |
| Ubuntu 20.04[^5] | `cmake` `g++` `git` `qtbase5-private-dev` `qt5qtdeclarative5-dev` | `libqt5network5` `libqt5sql5` `libqt5widgets5` `qml-module-qtquick2` `qml-module-qtquick-controls2` `qml-module-qtquick-window2` |
| Ubuntu 22.04 - 23.04 | `cmake` `g++` `git` `qt6-base-private-dev` `qt6-declarative-dev` `libgl-dev` | `libqt6network6` `libqt6sql6` `libqt6widgets6` `qml6-module-qtqml-workerscript` `qml6-module-qtquick-controls` `qml6-module-qtquick-layouts` `qml6-module-qtquick-particles` `qml6-module-qtquick-templates` `qml6-module-qtquick-window` `qt6-qpa-plugins` |
[^1]: These packages are only required to build Notes, meaning you can remove all of them (or some of them) afterward.
[^2]: These packages are required to actually run Notes.
[^3]: We recommend building and installing through the [official AUR package](https://aur.archlinux.org/packages/notes).
[^4]: You may need to tell `cmake` to use use GCC 8 (or newer), e.g. run `export CXX=g++-10` before you invoke `cmake`.
[^5]: This distro can only build Notes with Qt 5.
### Build options
Please refer to [build_options.md](build_options.md).
### Building
First, use `git` to clone the project and its components, and then navigate into it:
```shell
git clone https://github.com/nuttyartist/notes.git --recurse-submodules
cd notes
```
Let's create a build folder called `build`:
```shell
mkdir build
cd build
```
After that, we're ready to build Notes!
Invoke CMake to configure and build the project into a folder called `build`, in [`Release` mode](https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html):
```shell
cmake .. -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Release
make -j$(nproc)
```
To run the binary you just built (e.g. for testing purposes), you can simply execute the `notes` binary in the `build` folder:
```shell
./notes
```
If you want to install Notes like a regular, Linux desktop application (with its own desktop file and icons), you can simply run (as root):
```shell
make install
```
Alternatively, you can also create DEB or RPM packages (see the [Packaging section](#Packaging) below).
### Packaging
After building, you could also easily create DEB or RPM packages using [CPack](https://cmake.org/cmake/help/latest/manual/cpack.1.html):
```shell
# Create a DEB package
cpack -G DEB
# Create a RPM package
cpack -G RPM
```
Please note that it only makes sense to create DEB or RPM packages on the same distro you intend to install and run Notes on.

@ -0,0 +1,58 @@
These are common steps to build Notes from source on macOS.
### Requirements
macOS Catalina 10.15 (or newer) is required to build Notes.
This guide assumes you already have Xcode Command Line Tools (version 11 or newer) and [Homebrew](https://brew.sh/) both installed.
Required Homebrew packages:
- `git`
- `qt@6` *(`qt@5` is also supported, but not recommended)*
- `cmake`
- `ninja`
### Build options
Please refer to [build_options.md](build_options.md).
### Building
First, use `git` to clone the project and its components, and then navigate into it:
```shell
git clone https://github.com/nuttyartist/notes.git --recurse-submodules
cd notes
```
Optionally, if you want to dedicate all cores of your CPU to build Notes much faster, set this environment variable:
```shell
export CMAKE_BUILD_PARALLEL_LEVEL=$(sysctl -n hw.logicalcpu)
```
After that, we're ready to build Notes!
Invoke CMake to configure and build the project into a folder called `build`, in [`Release` mode](https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html):
```shell
cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=Release
cmake --build build
```
Alternatively, if you want to target both `x86_64` and `arm64` (Apple Silicon) architectures in a single, universal binary, invoke CMake like this instead *(please note that this might be unsupported on Qt versions older than 6)*:
```shell
cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_OSX_ARCHITECTURES='x86_64;arm64'
```
After Notes is built, you can use the `macdeployqt` tool from Qt to include the required libraries to your app bundle:
```shell
macdeployqt 'build/Notes.app' -qmldir=./src/qml -appstore-compliant
```
You can now install Notes by either dragging the `Notes.app` folder (found in `build/bin`), into the `Applications` folder.
Alternatively, you can run Notes directly by executing `build/bin/Notes.app/Contents/MacOS/Notes`.

@ -0,0 +1,86 @@
These are common steps to build Notes from source on Windows.
### Requirements
Windows 7 (or newer) is required to build Notes.
Additionally, you need to install the following tools/components:
- [Git](https://gitforwindows.org/)
- [Microsoft Visual C++](https://visualstudio.microsoft.com/downloads) `>= 2017` *(only the build tools are required)*
- [Qt](https://www.qt.io/download-qt-installer) `>= 5.12` *(using the latest version is recommended)*
- [CMake](https://cmake.org/download/) *(can be installed via the Qt installer)*
- [Ninja](https://ninja-build.org/) *(can be installed via the Qt installer)*
### Build options
Please refer to [build_options.md](build_options.md).
### Building
The following steps are done all via the command line. If you're not that comfortable with it, you can also to configure the project using a graphical tool like the CMake GUI, or Qt Creator.
Additionally, these commands are meant to be run on the Windows command prompt, *not* on PowerShell (though they can be easily adapted).
First, use `git` to clone the project and its components, and then navigate into it:
```shell
git clone https://github.com/nuttyartist/notes.git --recurse-submodules
cd notes
```
Now, let's configure our build environment. In this example, we will be using Microsoft Visual C++ 2017 and Qt 5.15.2 (the MSVC 2019 build), targeting a 64-bit system.
Depending on what versions of these applications you have installed, you may need to make some path adjustments in the following steps.
Let's begin by invoking the `vcvars64.bat` script from MSVC 2017, which will set some helpful environment variables for us:
```shell
@call "C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Auxiliary\Build\vcvars64.bat"
```
Now, we need to add CMake, Ninja, Qt sources and tools to our `Path` environment variable:
```shell
set Path=C:\Qt\Tools\CMake_64\bin;%Path%
set Path=C:\Qt\Tools\Ninja;%Path%
set Path=C:\Qt\5.15.2\msvc2019_64;%Path%
set Path=C:\Qt\5.15.2\msvc2019_64\bin;%Path%
```
Optionally, if you want to dedicate all cores of your CPU to build Notes much faster, set this environment variable:
```shell
set CMAKE_BUILD_PARALLEL_LEVEL=%NUMBER_OF_PROCESSORS%
```
After that, we're ready to build Notes!
Invoke CMake to configure and build the project into a folder called `build`, in [`Release` mode](https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html):
```shell
cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=Release
cmake --build build
```
<!-- FIXME: Avoid hardcoding the output folder to `bin` on Windows? -->
Now, let's move the `Notes.exe` executable we just built into a separate folder called `bin` inside the `build` folder, where later we will copy other libraries required to run the app:
```shell
cmake --install build --prefix build
```
Now, use the `windeployqt` tool from Qt to copy the required Qt libraries to run Notes:
```shell
windeployqt --qmldir src\qml build\bin
```
And then, finally, copy the required OpenSSL libraries to make internet-dependent features work properly (like the auto-updater):
```shell
copy /B C:\Qt\Tools\OpenSSL\Win_x64\bin\libcrypto-1_1-x64.dll build\bin
copy /B C:\Qt\Tools\OpenSSL\Win_x64\bin\libssl-1_1-x64.dll build\bin
```
You can now run Notes by double-clicking the `Notes.exe` executable in the `build\bin` folder.

@ -0,0 +1,33 @@
These are options you can use to customize your own build of Notes.
You should set those while invoking CMake to build the project. See the [examples section](#examples) below.
### Options
| Name | Default value | Supported values | Description |
| ------------------------------------------ | ------------- | ------------------- | ----------------------------------------------------------- |
| `CMAKE_OSX_DEPLOYMENT_TARGET` (macOS-only) | `10.15` | (any macOS version) | Minimum macOS version to target for deployment |
| `USE_QT_VERSION` | (unset) | `5` / `6` | Use a specific version of Qt to build the app |
| `GIT_REVISION` | `OFF` | `ON` / `OFF` | Append the current git revision to the app's version string |
| `UPDATE_CHECKER` | `ON` | `ON` / `OFF` | Enable or disable both the update checker and auto-updater |
| `PRO_VERSION` | `ON` | `ON` / `OFF` | Enable or disable Notes Pro features |
### Examples
To build Notes without any update-checking feature:
```
cmake -B build -DUPDATE_CHECKER=OFF
```
To force CMake to use Qt 5 (useful when you also have Qt 6 installed, which will be chosen by default, if present):
```
cmake -B build -USE_QT_VERSION=5
```
To build Notes in `Release` mode (for other modes, check the [CMake documentation](https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html)):
```
cmake -B build -DCMAKE_BUILD_TYPE=Release
```

@ -0,0 +1,52 @@
These are the default keyboard shortcuts provided by Notes.
Right now they can't be easily customized, but [that's on the roadmap](https://github.com/nuttyartist/notes/issues/394)! :)
## Global shortcuts
On supported systems, these shortcuts can be activated even if Notes' window is not active at the moment.
| Sequence | Description |
| ------------------------------------------------------------ | ------------------------------- |
| <kbd>Win</kbd> + <kbd>Shift</kbd> + <kbd>N</kbd> *(Windows)* | Toggle Notes' window visibility |
| <kbd>Ctrl</kbd> + <kbd>N</kbd> *(macOS)* | Toggle Notes' window visibility |
| <kbd>Meta</kbd> + <kbd>Shift</kbd> + <kbd>N</kbd> *(Linux)* | Toggle Notes' window visibility |
## Local shortcuts
These shortcuts are meant to be used while the Notes window is currently focused.
| Sequence | Description |
| ----------------------------------------------------- | ------------------------------------------------------------- |
| <kbd>Ctrl</kbd> + <kbd>N</kbd> | Create a new note |
| <kbd>Ctrl</kbd> + <kbd>D</kbd> | Delete selected note |
| <kbd>Ctrl</kbd> + <kbd>F</kbd> | Focus on the search bar |
| <kbd>Ctrl</kbd> + <kbd>E</kbd> | Clear the search bar |
| <kbd>Ctrl</kbd> + <kbd></kbd> (or just <kbd></kbd>) | Select note below |
| <kbd>Ctrl</kbd> + <kbd></kbd> (or just <kbd></kbd>) | Select note above |
| <kbd>Ctrl</kbd> + <kbd>Enter</kbd> | Focus on the text editor |
| <kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd>F</kbd> | Toggle full screen mode |
| <kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd>K</kbd> | Toggle kanban view |
| <kbd>F11</kbd> | Toggle full screen mode |
| <kbd>Esc</kbd> | Exit full screen mode |
| <kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd>L</kbd> | Focus on the notes list |
| <kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd>M</kbd> | Minimize Notes |
| <kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd>S</kbd> | Toggle Editor Settings' window visibility |
| <kbd>Ctrl</kbd> + <kbd>Q</kbd> | Quit Notes |
| <kbd>Ctrl</kbd> + <kbd>K</kbd> *(macOS, Windows)* | Toggle 'stay on top' |
| <kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd>S</kbd> | Open Editor Settings |
| <kbd>Ctrl</kbd> + <kbd>J</kbd> | Toggle 'notes' panel visibility |
| <kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd>J</kbd> | Toggle 'folders' panel visibility |
| <kbd>Ctrl</kbd> + <kbd>A</kbd> | Select all listed notes |
| <kbd>Ctrl</kbd> + <kbd>\`</kbd> | Wrap current word or selection into \` \` `(code)` |
| <kbd>Ctrl</kbd> + <kbd>B</kbd> | Wrap current word or selection into \*\* \*\* **(bold)** |
| <kbd>Ctrl</kbd> + <kbd>I</kbd> | Wrap current word or selection into \* \* *(italic)* |
| <kbd>Ctrl</kbd> + <kbd>S</kbd> | Wrap current word or selection into \~ \~ ~~(strikethrough)~~ |
| <kbd>Alt</kbd> + <kbd>Up</kbd> | Move current block up |
| <kbd>Alt</kbd> + <kbd>Down</kbd> | Move current block down |
| <kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd>-</kbd> | Decrease heading size |
| <kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd>=</kbd> | Increase heading size |
| <kbd>Ctrl</kbd> + (<kbd>1</kbd> through <kbd>6</kbd>) | Set a specific heading size |
| <kbd>Ctrl</kbd> + <kbd>\\</kbd> | Remove formatting from current word or selection |
| <kbd>F10</kbd> | Toggle visibility of the dots menu |

@ -0,0 +1,7 @@
{
"purchase_pro_url": "https://www.get-notes.com/pricing",
"purchaseApiBase": "https://api.lemonsqueezy.com",
"activateLicenseEndpoint": "/v1/licenses/activate",
"validateLicenseEndpoint": "/v1/licenses/validate",
"deactivateLicenseEndpoint": "/v1/licenses/deactivate"
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB

@ -0,0 +1,139 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Copyright 2022 @APP_AUTHOR@ -->
<component type="desktop-application">
<id>@APP_ID@</id>
<launchable type="desktop-id">@APP_ID@.desktop</launchable>
<metadata_license>CC0-1.0</metadata_license>
<project_license>MPL-2.0</project_license>
<name>@PROJECT_NAME@</name>
<developer_name>@APP_AUTHOR@</developer_name>
<update_contact>@APP_AUTHOR_EMAIL@</update_contact>
<summary>@PROJECT_DESCRIPTION@</summary>
<url type="homepage">@APP_WEBSITE@</url>
<url type="bugtracker">@APP_REPOSITORY@/issues</url>
<url type="donation">https://github.com/sponsors/nuttyartist</url>
<description>
<p>Notes is an open source and cross-platform note-taking app that is both beautiful and powerful.</p>
<p>Features overview:</p>
<ul>
<li>Native app (written in C++ with Qt)</li>
<li>Turn your Markdown tasks into a beautiful Kanban board</li>
<li>Fast and beautiful</li>
<li>Fully open source and cross-platform (Linux, macOS, Windows)</li>
<li>Completely private: Tracks nothing</li>
<li>Folders and tags: Organize your ideas hierarchically using nested folders and universally using tags</li>
<li>Markdown Support: Format text without lifting your hands from the keyboard</li>
<li>Different themes: Switch between Light, Dark, and Sepia</li>
<li>Feed View: Select multiple notes to see them all one after another in the editor</li>
<li>Always runs in the background: Use the hotkey <code>Super</code> + <code>Shift</code> + <code>N</code> to summon Notes</li>
</ul>
</description>
<screenshots>
<screenshot type="default">
<image>https://www.rubymamistvalove.com/screenshots/linux/this_is_a_line_linux.png</image>
<caption>Overview</caption>
</screenshot>
<screenshot>
<image>https://www.rubymamistvalove.com/screenshots/linux/kanban.png</image>
<caption>Kanban Board</caption>
</screenshot>
<screenshot>
<image>https://www.rubymamistvalove.com/screenshots/linux/tasks.png</image>
<caption>Markdown Tasks</caption>
</screenshot>
<screenshot>
<image>https://www.rubymamistvalove.com/screenshots/linux/theme.png</image>
<caption>Dark Theme</caption>
</screenshot>
<screenshot>
<image>https://www.rubymamistvalove.com/screenshots/linux/sepia.png</image>
<caption>Sepia theme</caption>
</screenshot>
<screenshot>
<image>https://www.rubymamistvalove.com/screenshots/linux/tags.png</image>
<caption>Folders and Tags</caption>
</screenshot>
</screenshots>
<content_rating type="oars-1.1" />
<releases>
<release date="2023-08-30" version="2.2.1">
<description>
<p>A new release is here with many bug fixes and improvements. To sustain and further our commitment to exceptional app development, we have transitioned to a subscription-based pricing model for the Pro version.</p>
<p>Improvements and bug fixes:</p>
<ul>
<li>Resolved a conflict within the Kanban interface: previously, editing a task would not conclude if a separate task was concurrently edited.</li>
<li>Addressed an issue where editing was mistakenly permitted within the editor while the Trash folder was active</li>
<li>Fixed bug where icons didn't show up on some Linux distributions</li>
<li>Corrected an inconsistency where icons were not displayed on certain Linux distributions</li>
<li>Resolved display issues of specific windows on Ubuntu 23.04</li>
<li>Addressed an issue with the Editor Settings window failing to appear on Qt 5.12.2</li>
<li>For Pro users, the 'Pro' label within the Editor Settings has been made redundant and is now removed for a cleaner interface</li>
</ul>
<p>Note: Anyone can still access all Pro features at no cost by building the app from source.</p>
</description>
</release>
<release date="2023-07-27" version="2.2.0">
<description>
<p>A new release is here with major new features and many bug fixes and improvements.</p>
<p>New features:</p>
<ul>
<li>You can now turn your Markdown tasks into a beautiful Kanban board</li>
<li>Completely redesigned Editor Settings popup to quickly change the editor's settings</li>
<li>New gear icon for global app settings</li>
<li>Much improved Dark theme colors</li>
</ul>
<p>Improvements and bug fixes:</p>
<ul>
<li>Text contrast in Sepia theme is improved</li>
<li>Added alt+up/down keyboard shortcut to move the current line</li>
<li>Toggling fullscreen is now possible with F11 and Esc</li>
<li>Fixed markdown fonts not being resized properly</li>
<li>Native window decoration is now default on Windows and Linux</li>
<li>Fixed X11 linking on BSD systems</li>
<li>Many more fixes and improvements under the hood</li>
</ul>
</description>
</release>
<release date="2023-03-08" version="2.1.0">
<description>
<p>A new release is here with some new features and many bug fixes and improvements.</p>
<p>New features:</p>
<ul>
<li>You can now open external links by holding <code>Ctrl</code> while clicking them</li>
<li>You can now format text using keyboard shortcuts: <code>Ctrl</code> + <code>B</code> (Bold) | <code>Ctrl</code> + <code>I</code> (Italic) | <code>Ctrl</code> + <code>S</code> (Strikethrough)</li>
<li>You can create different heading levels with <code>Ctrl</code> + <code>1</code>...<code>6</code></li>
<li>You can increase or decrease levels by using <code>Ctrl</code> + <code>Shift</code> + (<code>+</code> or <code>-</code>)</li>
<li>You can now access the app menu by pressing <code>F10</code> (<code>Fn</code> + <code>F10</code> on macOS)</li>
</ul>
<p>Improvements and bug fixes:</p>
<ul>
<li>Automatic updates now work on Windows</li>
<li>Fixed bugs with native window decoration</li>
<li>We improved the style of selecting multiple notes</li>
<li>Fixed a bug on Windows causing extreme input delay when editing text</li>
<li>Streamlined the look and feel of some windows to match the OS better</li>
<li>Fixed issues when resizing the window's splitters and resizing the window itself</li>
<li>Fixed some bugs causing crashes</li>
<li>Many more fixes and improvements under the hood</li>
</ul>
</description>
</release>
<release date="2022-09-08" version="2.0.0">
<description>
<p>A new release is here with major new features and many bug fixes and improvements:</p>
<ul>
<li>Folders and tags: Organize your ideas hierarchically using nested folders and universally using tags</li>
<li>Pinned notes: Pin your most important notes at the top of each folder</li>
<li>Different themes: Switch between Light, Dark, and Sepia</li>
<li>Editor settings window: Change between different fonts and change the size/width of your text</li>
<li>Feed View: Select multiple notes to see them all one after another in the editor</li>
<li>Option to change the database path, so you can more easily sync your notes with a cloud provider</li>
<li>Many bug fixes</li>
</ul>
</description>
</release>
</releases>
<provides>
<binary>@PROJECT_NAME_LOWERCASE@</binary>
</provides>
</component>

@ -0,0 +1,9 @@
[Desktop Entry]
Type=Application
Name=@PROJECT_NAME@
Comment=@PROJECT_DESCRIPTION@
Categories=Utility;
Exec=@PROJECT_NAME_LOWERCASE@
Icon=@APP_ID@
StartupNotify=true
StartupWMClass=@PROJECT_NAME@

@ -0,0 +1,72 @@
@PROJECT_NAME_LOWERCASE@ (@PROJECT_VERSION@) UNRELEASED; urgency=low
* No changelog is available yet
-- @APP_AUTHOR@ <@APP_AUTHOR_EMAIL@> @DATE_NOW_UTC@
@PROJECT_NAME_LOWERCASE@ (2.2.1) stable; urgency=low
* To sustain and further our commitment to exceptional app development, we have transitioned to a subscription-based pricing model for the Pro version
* Resolved a conflict within the Kanban interface: previously, editing a task would not conclude if a separate task was concurrently edited
* Addressed an issue where editing was mistakenly permitted within the editor while the Trash folder was active
* Fixed bug where icons didn't show up on some Linux distributions
* Corrected an inconsistency where icons were not displayed on certain Linux distributions
* Resolved display issues of specific windows on Ubuntu 23.04
* Addressed an issue with the Editor Settings window failing to appear on Qt 5.12.2
* For Pro users, the 'Pro' label within the Editor Settings has been made redundant and is now removed for a cleaner interface
* Note: Anyone can still access all Pro features at no cost by building the app from source
-- @APP_AUTHOR@ <@APP_AUTHOR_EMAIL@> Wed, 30 Aug 2023 01:00:00 +0100
@PROJECT_NAME_LOWERCASE@ (2.2.0) stable; urgency=low
* You can now turn your Markdown tasks into a beautiful Kanban board
* Completely redesigned Editor Settings popup to quickly change the editor's settings
* New gear icon for global app settings
* Much improved Dark theme colors
* Text contrast in Sepia theme is improved
* Added alt+up/down keyboard shortcut to move the current line
* Toggling fullscreen is now possible with F11 & Esc
* Fixed markdown fonts not being resized properly
* Native window decoration is now default on Windows and Linux
* Fixed X11 linking on BSD systems
* Many more fixes and improvements under the hood
-- @APP_AUTHOR@ <@APP_AUTHOR_EMAIL@> Thu, 27 Jul 2023 12:09:49 +0000
@PROJECT_NAME_LOWERCASE@ (2.1.0) stable; urgency=low
* You can now open external links by holding Ctrl while clicking them
* You can now format text using keyboard shortcuts (see docs/keyboard_shortcuts.md)
* Fixed bugs with custom window decorations
* We improved the style of selecting multiple notes
* Streamlined the look and feel of some windows to match the OS better
* Fixed issues when resizing the window's splitters and resizing the window itself
* Fixed some bugs causing crashes
* Many more fixes and improvements under the hood
-- @APP_AUTHOR@ <@APP_AUTHOR_EMAIL@> Wed, 08 Mar 2023 12:27:00 +0000
@PROJECT_NAME_LOWERCASE@ (1.5.0) stable; urgency=low
* Fourth release
-- @APP_AUTHOR@ <@APP_AUTHOR_EMAIL@> Tue, 18 Mar 2020 01:00:00 +0100
@PROJECT_NAME_LOWERCASE@ (1.0.0) stable; urgency=low
* Third release
-- @APP_AUTHOR@ <@APP_AUTHOR_EMAIL@> Tue, 3 Jul 2017 01:00:00 +0100
@PROJECT_NAME_LOWERCASE@ (0.9.0) stable; urgency=low
* Second release
-- @APP_AUTHOR@ <@APP_AUTHOR_EMAIL@> Tue, 3 May 2016 01:00:00 +0100
@PROJECT_NAME_LOWERCASE@ (0.8.0) stable; urgency=low
* Initial release
-- @APP_AUTHOR@ <@APP_AUTHOR_EMAIL@> Sun, 13 Dec 2015 14:43:39 +0100

@ -0,0 +1,17 @@
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: @PROJECT_NAME_LOWERCASE@
Upstream-Contact: @APP_AUTHOR@ <@APP_AUTHOR_EMAIL@>
Source: @APP_REPOSITORY@
Files: *
Copyright: 2015-@CURRENT_YEAR@ @APP_AUTHOR@ <@APP_AUTHOR_EMAIL@>
License: MPL-2.0
Files: debian/*
Copyright: 2015-@CURRENT_YEAR@ @APP_AUTHOR@ <@APP_AUTHOR_EMAIL@>
License: MPL-2.0
License: MPL-2.0
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this file, You can
obtain one at https://mozilla.org/MPL/2.0/.

@ -0,0 +1,41 @@
#!/bin/sh
# Check if snapcraft exists
echo "Checking for snapcraft..."
if type "snapcraft" &> /dev/null ; then
echo "Snapcraft exists, we're good to go!"
else
echo "Snapcraft not found, trying to install it..."
sudo apt-get update
sudo apt-get install snapcraft
echo "Snapcraft installed, please re-run this script"
exit
fi
# Generate directory
mkdir snap_build
cd snap_build
# Copy snapcraft config.
cp -r ../snap/* .
# Copy icons & desktop files
mkdir setup
cd setup
mkdir gui
cd gui
cp ../../../common/icons/scalable/notes.svg notes.svg
cp ../../../common/notes.desktop notes.desktop
# Go to snapcraft directory
cd ..
cd ..
# Clean snapcraft config
snapcraft clean
# Build snap
snapcraft snap
# Clean snapcraft config again
snapcraft clean

@ -0,0 +1,13 @@
#!/bin/sh
# Create Debian package
read -p "Press enter to create Debian package" nothing
clear
sh make_deb.sh
echo "Debian package created"
# Create Snap package
read -p "Press enter to create Snap package" nothing
clear
sh make_snap.sh
echo "Snap package created"

Binary file not shown.

After

Width:  |  Height:  |  Size: 914 B

@ -0,0 +1,237 @@
#define Version GetEnv("APP_VERSION")
[Setup]
; NOTE: The value of AppId uniquely identifies this application.
; Do not use the same AppId value in installers for other applications.
; (To generate a new GUID, click Tools | Generate GUID inside the IDE.)
AppId={{44576435-E098-4581-A6D7-FD7FADC5B063}
AppName=Notes
AppVersion={#Version}
AppPublisher=Awesomeness
AppPublisherURL=https://www.get-notes.com/
AppSupportURL=https://www.get-notes.com/
AppUpdatesURL=https://www.get-notes.com/
UninstallDisplayIcon={app}\Notes.exe
DefaultDirName={code:GetDefaultInstallDir}\Notes
DefaultGroupName=Notes
UninstallDisplayName=Notes
OutputBaseFilename=NotesSetup_{#Version}
Compression=lzma
SolidCompression=yes
; Inno Setup can't seem to calculate the required disk space correctly, and asks for only 3.1 MB.
; Let's use an approximate value to represent the size of the Qt 6 build while installed on disk (100 MiB).
ExtraDiskSpaceRequired=104857600
OutputManifestFile=Setup-Manifest.txt
[Code]
function GetDefaultInstallDir(Param: string): string;
var
Version: TWindowsVersion;
begin
GetWindowsVersionEx(Version);
if IsWin64() and (Version.Major >= 10) and (Version.Minor >= 0) and (Version.Build >= 17763) then
Result := ExpandConstant('{autopf64}')
else
Result := ExpandConstant('{autopf32}')
end;
function ParamExists(const Param: string): boolean;
var
K: integer;
begin
for K := 1 to ParamCount() do
begin
if SameText(ParamStr(K), Param) then
begin
Result := true;
Exit;
end;
end;
Result := false;
end;
// If a different version of Notes is already installed, this function will invoke its uninstaller.
// You can disable this behavior by invoking the installer via command line with /SKIPVERSIONCHECK.
function InitializeSetup(): boolean;
var
ParamSilent, ParamVerySilent, ParamSuppressMsgBoxes: boolean;
OurRegKey, Uninstaller, UninstallerParams, InstalledVersion: string;
RootsToSearchIn: array of integer;
K, ResultCode: integer;
begin
if ParamExists('/SKIPVERSIONCHECK') then
begin
Result := true;
Exit;
end;
ParamSilent := ParamExists('/SILENT');
ParamVerySilent := ParamExists('/VERYSILENT');
ParamSuppressMsgBoxes := ParamExists('/SUPPRESSMSGBOXES');
OurRegKey := ExpandConstant('Software\Microsoft\Windows\CurrentVersion\Uninstall\{#SetupSetting("AppId")}_is1');
SetLength(RootsToSearchIn, 1);
RootsToSearchIn[0] := HKLM32;
// We have to also search in HKLM64, because some older versions of the installer ran in 64-bit install mode.
if IsWin64() then
begin
SetLength(RootsToSearchIn, 2);
RootsToSearchIn[1] := HKLM64;
end;
for K := 0 to (GetArrayLength(RootsToSearchIn) - 1) do
begin
if not RegQueryStringValue(RootsToSearchIn[K], OurRegKey, 'UninstallString', Uninstaller) then
begin
continue;
end;
if not RegQueryStringValue(RootsToSearchIn[K], OurRegKey, 'DisplayVersion', InstalledVersion) then
begin
continue;
end;
if SameText('{#SetupSetting("AppVersion")}', InstalledVersion) then
begin
continue;
end;
if not (ParamSilent or ParamVerySilent or ParamSuppressMsgBoxes) then
begin
if (MsgBox('Another version of {#SetupSetting("AppName")} is installed and must be removed first.'#13#13
'Don''t worry, all your notes will be safe.'#13#13
'Once the uninstall is complete, you''ll be prompted to install version {#SetupSetting("AppVersion")}.'#13#13
'Uninstall version ' + InstalledVersion + ' now?',
mbConfirmation, MB_YESNO) = IDNO) then
begin
Result := false;
Exit;
end;
end;
// We run the _uninstaller_ with /VERYSILENT by default.
UninstallerParams := '/VERYSILENT';
// If _this_ installer was invoked with /SILENT or /SUPPRESSMSGBOXES, we forward those to the uninstaller.
if ParamSilent then
begin
UninstallerParams := UninstallerParams + ' /SILENT';
end;
if ParamSuppressMsgBoxes then
begin
UninstallerParams := UninstallerParams + ' /SUPPRESSMSGBOXES';
end;
if not Exec(RemoveQuotes(Uninstaller), UninstallerParams, '', SW_SHOW, ewWaitUntilTerminated, ResultCode)
or (ResultCode <> 0) then
begin
// Error message boxes can't be suppressed.
MsgBox('Failed to uninstall version ' + InstalledVersion + '. Reason:'#13#13
+ SysErrorMessage(ResultCode) + '. (code ' + IntToStr(ResultCode) + ')'#13#13
'Try uninstalling it from the Windows Control Panel.',
mbCriticalError, MB_OK);
Result := false;
Exit;
end;
if not (ParamSilent or ParamVerySilent or ParamSuppressMsgBoxes) then
begin
MsgBox('Uninstall of version ' + InstalledVersion + ' is complete.'#13#13
'Installation of version {#SetupSetting("AppVersion")} will start after pressing OK...',
mbInformation, MB_OK);
end;
end;
Result := true;
end;
[Languages]
Name: "english"; MessagesFile: "compiler:Default.isl"
[Tasks]
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}";
[Files]
; Qt 6 build (64-bit)
; Minimum supported OS:
; - Windows 10 21H2 (1809 or later)
; Source: https://doc.qt.io/qt-6/supported-platforms.html#windows
Source: "{#SourcePath}\Notes64\iconengines\*"; DestDir: "{app}\iconengines"; Flags: ignoreversion recursesubdirs createallsubdirs; Check: IsWin64; MinVersion: 10.0.17763
Source: "{#SourcePath}\Notes64\imageformats\*"; DestDir: "{app}\imageformats"; Flags: ignoreversion recursesubdirs createallsubdirs; Check: IsWin64; MinVersion: 10.0.17763
Source: "{#SourcePath}\Notes64\networkinformation\*"; DestDir: "{app}\networkinformation"; Flags: ignoreversion recursesubdirs createallsubdirs; Check: IsWin64; MinVersion: 10.0.17763
Source: "{#SourcePath}\Notes64\platforms\*"; DestDir: "{app}\platforms"; Flags: ignoreversion recursesubdirs createallsubdirs; Check: IsWin64; MinVersion: 10.0.17763
Source: "{#SourcePath}\Notes64\QtQml\*"; DestDir: "{app}\QtQml"; Flags: ignoreversion recursesubdirs createallsubdirs; Check: IsWin64; MinVersion: 10.0.17763
Source: "{#SourcePath}\Notes64\QtQuick\*"; DestDir: "{app}\QtQuick"; Flags: ignoreversion recursesubdirs createallsubdirs; Check: IsWin64; MinVersion: 10.0.17763
Source: "{#SourcePath}\Notes64\sqldrivers\*"; DestDir: "{app}\sqldrivers"; Flags: ignoreversion recursesubdirs createallsubdirs; Check: IsWin64; MinVersion: 10.0.17763
Source: "{#SourcePath}\Notes64\styles\*"; DestDir: "{app}\styles"; Flags: ignoreversion recursesubdirs createallsubdirs; Check: IsWin64; MinVersion: 10.0.17763
Source: "{#SourcePath}\Notes64\tls\*"; DestDir: "{app}\tls"; Flags: ignoreversion recursesubdirs createallsubdirs; Check: IsWin64; MinVersion: 10.0.17763
Source: "{#SourcePath}\Notes64\translations\*"; DestDir: "{app}\translations"; Flags: ignoreversion recursesubdirs createallsubdirs; Check: IsWin64; MinVersion: 10.0.17763
Source: "{#SourcePath}\Notes64\d3dcompiler_47.dll"; DestDir: "{app}"; Flags: ignoreversion; Check: IsWin64; MinVersion: 10.0.17763
Source: "{#SourcePath}\Notes64\libcrypto-1_1-x64.dll"; DestDir: "{app}"; Flags: ignoreversion; Check: IsWin64; MinVersion: 10.0.17763
Source: "{#SourcePath}\Notes64\libssl-1_1-x64.dll"; DestDir: "{app}"; Flags: ignoreversion; Check: IsWin64; MinVersion: 10.0.17763
Source: "{#SourcePath}\Notes64\msvcp140.dll"; DestDir: "{app}"; Flags: ignoreversion; Check: IsWin64; MinVersion: 10.0.17763
Source: "{#SourcePath}\Notes64\msvcp140_1.dll"; DestDir: "{app}"; Flags: ignoreversion; Check: IsWin64; MinVersion: 10.0.17763
Source: "{#SourcePath}\Notes64\msvcp140_2.dll"; DestDir: "{app}"; Flags: ignoreversion; Check: IsWin64; MinVersion: 10.0.17763
Source: "{#SourcePath}\Notes64\Notes.exe"; DestDir: "{app}"; Flags: ignoreversion; Check: IsWin64; MinVersion: 10.0.17763
Source: "{#SourcePath}\Notes64\opengl32sw.dll"; DestDir: "{app}"; Flags: ignoreversion; Check: IsWin64; MinVersion: 10.0.17763
Source: "{#SourcePath}\Notes64\Qt6Core.dll"; DestDir: "{app}"; Flags: ignoreversion; Check: IsWin64; MinVersion: 10.0.17763
Source: "{#SourcePath}\Notes64\Qt6Gui.dll"; DestDir: "{app}"; Flags: ignoreversion; Check: IsWin64; MinVersion: 10.0.17763
Source: "{#SourcePath}\Notes64\Qt6Network.dll"; DestDir: "{app}"; Flags: ignoreversion; Check: IsWin64; MinVersion: 10.0.17763
Source: "{#SourcePath}\Notes64\Qt6OpenGL.dll"; DestDir: "{app}"; Flags: ignoreversion; Check: IsWin64; MinVersion: 10.0.17763
Source: "{#SourcePath}\Notes64\Qt6Qml.dll"; DestDir: "{app}"; Flags: ignoreversion; Check: IsWin64; MinVersion: 10.0.17763
Source: "{#SourcePath}\Notes64\Qt6QmlLocalStorage.dll"; DestDir: "{app}"; Flags: ignoreversion; Check: IsWin64; MinVersion: 10.0.17763
Source: "{#SourcePath}\Notes64\Qt6QmlModels.dll"; DestDir: "{app}"; Flags: ignoreversion; Check: IsWin64; MinVersion: 10.0.17763
Source: "{#SourcePath}\Notes64\Qt6QmlWorkerScript.dll"; DestDir: "{app}"; Flags: ignoreversion; Check: IsWin64; MinVersion: 10.0.17763
Source: "{#SourcePath}\Notes64\Qt6QmlXmlListModel.dll"; DestDir: "{app}"; Flags: ignoreversion; Check: IsWin64; MinVersion: 10.0.17763
Source: "{#SourcePath}\Notes64\Qt6Quick.dll"; DestDir: "{app}"; Flags: ignoreversion; Check: IsWin64; MinVersion: 10.0.17763
Source: "{#SourcePath}\Notes64\Qt6QuickControls2.dll"; DestDir: "{app}"; Flags: ignoreversion; Check: IsWin64; MinVersion: 10.0.17763
Source: "{#SourcePath}\Notes64\Qt6QuickControls2Impl.dll"; DestDir: "{app}"; Flags: ignoreversion; Check: IsWin64; MinVersion: 10.0.17763
Source: "{#SourcePath}\Notes64\Qt6QuickDialogs2.dll"; DestDir: "{app}"; Flags: ignoreversion; Check: IsWin64; MinVersion: 10.0.17763
Source: "{#SourcePath}\Notes64\Qt6QuickDialogs2QuickImpl.dll"; DestDir: "{app}"; Flags: ignoreversion; Check: IsWin64; MinVersion: 10.0.17763
Source: "{#SourcePath}\Notes64\Qt6QuickDialogs2Utils.dll"; DestDir: "{app}"; Flags: ignoreversion; Check: IsWin64; MinVersion: 10.0.17763
Source: "{#SourcePath}\Notes64\Qt6QuickLayouts.dll"; DestDir: "{app}"; Flags: ignoreversion; Check: IsWin64; MinVersion: 10.0.17763
Source: "{#SourcePath}\Notes64\Qt6QuickParticles.dll"; DestDir: "{app}"; Flags: ignoreversion; Check: IsWin64; MinVersion: 10.0.17763
Source: "{#SourcePath}\Notes64\Qt6QuickShapes.dll"; DestDir: "{app}"; Flags: ignoreversion; Check: IsWin64; MinVersion: 10.0.17763
Source: "{#SourcePath}\Notes64\Qt6QuickTemplates2.dll"; DestDir: "{app}"; Flags: ignoreversion; Check: IsWin64; MinVersion: 10.0.17763
Source: "{#SourcePath}\Notes64\Qt6Sql.dll"; DestDir: "{app}"; Flags: ignoreversion; Check: IsWin64; MinVersion: 10.0.17763
Source: "{#SourcePath}\Notes64\Qt6Svg.dll"; DestDir: "{app}"; Flags: ignoreversion; Check: IsWin64; MinVersion: 10.0.17763
Source: "{#SourcePath}\Notes64\Qt6Widgets.dll"; DestDir: "{app}"; Flags: ignoreversion; Check: IsWin64; MinVersion: 10.0.17763
Source: "{#SourcePath}\Notes64\vcruntime140.dll"; DestDir: "{app}"; Flags: ignoreversion; Check: IsWin64; MinVersion: 10.0.17763
Source: "{#SourcePath}\Notes64\vcruntime140_1.dll"; DestDir: "{app}"; Flags: ignoreversion; Check: IsWin64; MinVersion: 10.0.17763
; Qt 5 build (32-bit)
; Minimum supported OS:
; - Windows 7 (x86 and x86_64)
; Source: https://doc.qt.io/qt-5/supported-platforms.html#windows
Source: "{#SourcePath}\Notes32\iconengines\*"; DestDir: "{app}\iconengines"; Flags: ignoreversion recursesubdirs createallsubdirs; MinVersion: 6.1; OnlyBelowVersion: 10.0.17763
Source: "{#SourcePath}\Notes32\imageformats\*"; DestDir: "{app}\imageformats"; Flags: ignoreversion recursesubdirs createallsubdirs; MinVersion: 6.1; OnlyBelowVersion: 10.0.17763
Source: "{#SourcePath}\Notes32\platforms\*"; DestDir: "{app}\platforms"; Flags: ignoreversion recursesubdirs createallsubdirs; MinVersion: 6.1; OnlyBelowVersion: 10.0.17763
Source: "{#SourcePath}\Notes32\QtGraphicalEffects\*"; DestDir: "{app}\QtGraphicalEffects"; Flags: ignoreversion recursesubdirs createallsubdirs; MinVersion: 6.1; OnlyBelowVersion: 10.0.17763
Source: "{#SourcePath}\Notes32\QtQml\*"; DestDir: "{app}\QtQml"; Flags: ignoreversion recursesubdirs createallsubdirs; MinVersion: 6.1; OnlyBelowVersion: 10.0.17763
Source: "{#SourcePath}\Notes32\QtQuick\*"; DestDir: "{app}\QtQuick"; Flags: ignoreversion recursesubdirs createallsubdirs; MinVersion: 6.1; OnlyBelowVersion: 10.0.17763
Source: "{#SourcePath}\Notes32\QtQuick.2\*"; DestDir: "{app}\QtQuick.2"; Flags: ignoreversion recursesubdirs createallsubdirs; MinVersion: 6.1; OnlyBelowVersion: 10.0.17763
Source: "{#SourcePath}\Notes32\scenegraph\*"; DestDir: "{app}\scenegraph"; Flags: ignoreversion recursesubdirs createallsubdirs; MinVersion: 6.1; OnlyBelowVersion: 10.0.17763
Source: "{#SourcePath}\Notes32\sqldrivers\*"; DestDir: "{app}\sqldrivers"; Flags: ignoreversion recursesubdirs createallsubdirs; MinVersion: 6.1; OnlyBelowVersion: 10.0.17763
Source: "{#SourcePath}\Notes32\styles\*"; DestDir: "{app}\styles"; Flags: ignoreversion recursesubdirs createallsubdirs; MinVersion: 6.1; OnlyBelowVersion: 10.0.17763
Source: "{#SourcePath}\Notes32\translations\*"; DestDir: "{app}\translations"; Flags: ignoreversion recursesubdirs createallsubdirs; MinVersion: 6.1; OnlyBelowVersion: 10.0.17763
Source: "{#SourcePath}\Notes32\d3dcompiler_47.dll"; DestDir: "{app}"; Flags: ignoreversion; MinVersion: 6.1; OnlyBelowVersion: 10.0.17763
Source: "{#SourcePath}\Notes32\libcrypto-1_1.dll"; DestDir: "{app}"; Flags: ignoreversion; MinVersion: 6.1; OnlyBelowVersion: 10.0.17763
Source: "{#SourcePath}\Notes32\libEGL.dll"; DestDir: "{app}"; Flags: ignoreversion; MinVersion: 6.1; OnlyBelowVersion: 10.0.17763
Source: "{#SourcePath}\Notes32\libGLESv2.dll"; DestDir: "{app}"; Flags: ignoreversion; MinVersion: 6.1; OnlyBelowVersion: 10.0.17763
Source: "{#SourcePath}\Notes32\libssl-1_1.dll"; DestDir: "{app}"; Flags: ignoreversion; MinVersion: 6.1; OnlyBelowVersion: 10.0.17763
Source: "{#SourcePath}\Notes32\msvcp140.dll"; DestDir: "{app}"; Flags: ignoreversion; MinVersion: 6.1; OnlyBelowVersion: 10.0.17763
Source: "{#SourcePath}\Notes32\msvcp140_1.dll"; DestDir: "{app}"; Flags: ignoreversion; MinVersion: 6.1; OnlyBelowVersion: 10.0.17763
Source: "{#SourcePath}\Notes32\Notes.exe"; DestDir: "{app}"; Flags: ignoreversion; MinVersion: 6.1; OnlyBelowVersion: 10.0.17763
Source: "{#SourcePath}\Notes32\opengl32sw.dll"; DestDir: "{app}"; Flags: ignoreversion; MinVersion: 6.1; OnlyBelowVersion: 10.0.17763
Source: "{#SourcePath}\Notes32\Qt5Core.dll"; DestDir: "{app}"; Flags: ignoreversion; MinVersion: 6.1; OnlyBelowVersion: 10.0.17763
Source: "{#SourcePath}\Notes32\Qt5Gui.dll"; DestDir: "{app}"; Flags: ignoreversion; MinVersion: 6.1; OnlyBelowVersion: 10.0.17763
Source: "{#SourcePath}\Notes32\Qt5Network.dll"; DestDir: "{app}"; Flags: ignoreversion; MinVersion: 6.1; OnlyBelowVersion: 10.0.17763
Source: "{#SourcePath}\Notes32\Qt5Qml.dll"; DestDir: "{app}"; Flags: ignoreversion; MinVersion: 6.1; OnlyBelowVersion: 10.0.17763
Source: "{#SourcePath}\Notes32\Qt5QmlModels.dll"; DestDir: "{app}"; Flags: ignoreversion; MinVersion: 6.1; OnlyBelowVersion: 10.0.17763
Source: "{#SourcePath}\Notes32\Qt5QmlWorkerScript.dll"; DestDir: "{app}"; Flags: ignoreversion; MinVersion: 6.1; OnlyBelowVersion: 10.0.17763
Source: "{#SourcePath}\Notes32\Qt5Quick.dll"; DestDir: "{app}"; Flags: ignoreversion; MinVersion: 6.1; OnlyBelowVersion: 10.0.17763
Source: "{#SourcePath}\Notes32\Qt5QuickControls2.dll"; DestDir: "{app}"; Flags: ignoreversion; MinVersion: 6.1; OnlyBelowVersion: 10.0.17763
Source: "{#SourcePath}\Notes32\Qt5QuickParticles.dll"; DestDir: "{app}"; Flags: ignoreversion; MinVersion: 6.1; OnlyBelowVersion: 10.0.17763
Source: "{#SourcePath}\Notes32\Qt5QuickTemplates2.dll"; DestDir: "{app}"; Flags: ignoreversion; MinVersion: 6.1; OnlyBelowVersion: 10.0.17763
Source: "{#SourcePath}\Notes32\Qt5RemoteObjects.dll"; DestDir: "{app}"; Flags: ignoreversion; MinVersion: 6.1; OnlyBelowVersion: 10.0.17763
Source: "{#SourcePath}\Notes32\Qt5Sql.dll"; DestDir: "{app}"; Flags: ignoreversion; MinVersion: 6.1; OnlyBelowVersion: 10.0.17763
Source: "{#SourcePath}\Notes32\Qt5Svg.dll"; DestDir: "{app}"; Flags: ignoreversion; MinVersion: 6.1; OnlyBelowVersion: 10.0.17763
Source: "{#SourcePath}\Notes32\Qt5Widgets.dll"; DestDir: "{app}"; Flags: ignoreversion; MinVersion: 6.1; OnlyBelowVersion: 10.0.17763
Source: "{#SourcePath}\Notes32\vcruntime140.dll"; DestDir: "{app}"; Flags: ignoreversion; MinVersion: 6.1; OnlyBelowVersion: 10.0.17763
[Icons]
Name: "{group}\Notes"; Filename: "{app}\Notes.exe"
Name: "{group}\{cm:UninstallProgram,Notes}"; Filename: "{uninstallexe}"
Name: "{commondesktop}\Notes"; Filename: "{app}\Notes.exe"; Tasks: desktopicon
[Run]
Filename: "{app}\Notes.exe"; Description: "{cm:LaunchProgram,Notes}"; Flags: nowait postinstall skipifsilent

@ -1,22 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net)
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:color="#88555555" />
<item android:state_selected="true" android:color="#ff999999" />
<item android:color="#ff000000" />
</selector>

@ -1,20 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net)
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="#50000000" />
</selector>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 245 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 443 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 554 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save