mirror of
https://gitee.com/vnotex/vnote.git
synced 2025-07-06 22:39:53 +08:00
Compare commits
157 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
856d2597df | ||
![]() |
44a0d75996 | ||
![]() |
62f6b7f3c5 | ||
![]() |
6150d327da | ||
![]() |
522ccfecc4 | ||
![]() |
4788ae4ccf | ||
![]() |
c3191e8f88 | ||
![]() |
4952c88b2e | ||
![]() |
ebd4489adf | ||
![]() |
d9aee037ad | ||
![]() |
87e87619fb | ||
![]() |
8494a714cd | ||
![]() |
3ec78f4c36 | ||
![]() |
a27485c021 | ||
![]() |
713b98f29e | ||
![]() |
82b0ec751d | ||
![]() |
a7348c0aa0 | ||
![]() |
85d2ee950d | ||
![]() |
b0b51570b0 | ||
![]() |
a5a9b32ea3 | ||
![]() |
ac20b7f80c | ||
![]() |
b462337824 | ||
![]() |
bbb88ded57 | ||
![]() |
0f0995d4fe | ||
![]() |
0881dd581a | ||
![]() |
c4512bb69a | ||
![]() |
5e4a6fa72a | ||
![]() |
5da9268aa7 | ||
![]() |
f1af78573a | ||
![]() |
a7600fa7f7 | ||
![]() |
78de724757 | ||
![]() |
05078a7857 | ||
![]() |
84d396f6c4 | ||
![]() |
b2fb5b1664 | ||
![]() |
3477469b66 | ||
![]() |
bed95b1757 | ||
![]() |
f83761d95f | ||
![]() |
84cb60d882 | ||
![]() |
313764b533 | ||
![]() |
44b5251045 | ||
![]() |
743e63edbf | ||
![]() |
74e20dcb3e | ||
![]() |
9a971860e0 | ||
![]() |
b1a1bf05d2 | ||
![]() |
06c712cb64 | ||
![]() |
84891fb2f2 | ||
![]() |
889026bece | ||
![]() |
2ebb210c57 | ||
![]() |
bfb0e5bd29 | ||
![]() |
61528de505 | ||
![]() |
f62a82364c | ||
![]() |
f461c706d1 | ||
![]() |
898c82ec8f | ||
![]() |
f5b69b73cf | ||
![]() |
5a01b4bb35 | ||
![]() |
918aa15e74 | ||
![]() |
522b37425f | ||
![]() |
a04968913c | ||
![]() |
3b755287e7 | ||
![]() |
25b556ae14 | ||
![]() |
daa2fe1785 | ||
![]() |
30712745bc | ||
![]() |
15d14359d7 | ||
![]() |
75f7250ed1 | ||
![]() |
853e9c08e0 | ||
![]() |
2f6afb2f97 | ||
![]() |
cbd3956cdc | ||
![]() |
4ab2033a81 | ||
![]() |
e8fe0726ff | ||
![]() |
f773bc0348 | ||
![]() |
d208d4f9a7 | ||
![]() |
a5f6d5a142 | ||
![]() |
cfce10b0ca | ||
![]() |
2ccfb5ca9f | ||
![]() |
c7f471cb8f | ||
![]() |
c255cd54ed | ||
![]() |
075380749c | ||
![]() |
f1a03554f0 | ||
![]() |
9353c9ef40 | ||
![]() |
d664c5a1c6 | ||
![]() |
d499b0d7be | ||
![]() |
f764fec458 | ||
![]() |
0cb502520f | ||
![]() |
b4e38409a9 | ||
![]() |
03ffb12ff1 | ||
![]() |
31d4ad151e | ||
![]() |
5229be4687 | ||
![]() |
e76c6829f7 | ||
![]() |
e7a7895c6e | ||
![]() |
7f2cfe4f52 | ||
![]() |
7f27745303 | ||
![]() |
4002cbca1b | ||
![]() |
f2c7abcc6f | ||
![]() |
e47b813b69 | ||
![]() |
0f635fba7d | ||
![]() |
9a10b210ec | ||
![]() |
038de48d54 | ||
![]() |
89cd40d0cf | ||
![]() |
3d77c29393 | ||
![]() |
aea0da5570 | ||
![]() |
7a88d1ef99 | ||
![]() |
ee2dc9ccc5 | ||
![]() |
73bb88e61f | ||
![]() |
2846e590d5 | ||
![]() |
cdf7091ae1 | ||
![]() |
bed49cf038 | ||
![]() |
4120ea2601 | ||
![]() |
0e9b6894c7 | ||
![]() |
ff6031209f | ||
![]() |
7e5ea84f37 | ||
![]() |
e87be24e5d | ||
![]() |
8141d58652 | ||
![]() |
d6631280e5 | ||
![]() |
0da7200898 | ||
![]() |
ed87ea3df1 | ||
![]() |
749c4006a2 | ||
![]() |
66ed2cdda1 | ||
![]() |
3739cfd0ef | ||
![]() |
815ef927cb | ||
![]() |
1d94617837 | ||
![]() |
a25b75f828 | ||
![]() |
e92ea5061a | ||
![]() |
d9f009953f | ||
![]() |
08fe335a80 | ||
![]() |
73ebcaeb90 | ||
![]() |
6de3663269 | ||
![]() |
12302d375d | ||
![]() |
490634b85a | ||
![]() |
cc0689d946 | ||
![]() |
fe4b6ca72e | ||
![]() |
791a5da245 | ||
![]() |
2a91577521 | ||
![]() |
08c597513c | ||
![]() |
3c64b86297 | ||
![]() |
a37d03fd02 | ||
![]() |
12eda471fc | ||
![]() |
5877366b77 | ||
![]() |
9b78d38726 | ||
![]() |
b78bd5abef | ||
![]() |
5865519402 | ||
![]() |
4f1959501d | ||
![]() |
12e18934df | ||
![]() |
05e8648d25 | ||
![]() |
e9c8225255 | ||
![]() |
14475330da | ||
![]() |
53e2b3bfa8 | ||
![]() |
8197012bcb | ||
![]() |
719c7339cf | ||
![]() |
21893fdff8 | ||
![]() |
9a3c69870c | ||
![]() |
30f73cb004 | ||
![]() |
3025e8e01c | ||
![]() |
e5f7a23157 | ||
![]() |
8c0c056c47 | ||
![]() |
17af3b8dc0 | ||
![]() |
82ec6beeb5 | ||
![]() |
1318427bb7 |
128
.github/workflows/ci-linux.yml
vendored
128
.github/workflows/ci-linux.yml
vendored
@ -8,14 +8,21 @@ on:
|
|||||||
|
|
||||||
# Allows you to run this workflow manually from the Actions tab.
|
# Allows you to run this workflow manually from the Actions tab.
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
debug_enabled:
|
||||||
|
type: boolean
|
||||||
|
description: 'Run the build with tmate debugging enabled'
|
||||||
|
required: false
|
||||||
|
default: false
|
||||||
|
|
||||||
env:
|
env:
|
||||||
VNOTE_VER: 3.13.1
|
VNOTE_VER: 3.19.2
|
||||||
|
CMAKE_VER: 3.24.3
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build-linux:
|
build-linux:
|
||||||
name: Build On Ubuntu
|
name: Build On Ubuntu
|
||||||
runs-on: ubuntu-18.04
|
runs-on: ubuntu-latest
|
||||||
timeout-minutes: 120
|
timeout-minutes: 120
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
@ -30,83 +37,86 @@ jobs:
|
|||||||
git submodule sync --recursive
|
git submodule sync --recursive
|
||||||
git -c "http.extraheader=$auth_header" -c protocol.version=2 submodule update --init --force --recursive --depth=1
|
git -c "http.extraheader=$auth_header" -c protocol.version=2 submodule update --init --force --recursive --depth=1
|
||||||
|
|
||||||
|
- name: Install a Fresh CMake
|
||||||
|
run: |
|
||||||
|
wget --no-verbose https://github.com/Kitware/CMake/releases/download/v${CMAKE_VER}/cmake-${CMAKE_VER}-Linux-x86_64.sh
|
||||||
|
chmod +x cmake-${CMAKE_VER}-Linux-x86_64.sh
|
||||||
|
mkdir ${{runner.workspace}}/cmake
|
||||||
|
sudo ./cmake-${CMAKE_VER}-Linux-x86_64.sh --skip-license --prefix=${{runner.workspace}}/cmake
|
||||||
|
sudo rm -f /usr/local/bin/cmake /usr/local/bin/cpack
|
||||||
|
sudo ln -s ${{runner.workspace}}/cmake/bin/cmake /usr/local/bin/cmake
|
||||||
|
sudo ln -s ${{runner.workspace}}/cmake/bin/cpack /usr/local/bin/cpack
|
||||||
|
|
||||||
- name: Install linuxdeploy
|
- name: Install linuxdeploy
|
||||||
uses: miurahr/install-linuxdeploy-action@v1
|
uses: miurahr/install-linuxdeploy-action@v1
|
||||||
with:
|
with:
|
||||||
plugins: qt appimage
|
plugins: qt appimage
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install Dependencies
|
||||||
run: |
|
run: |
|
||||||
sudo DEBIAN_FRONTEND=noninteractive apt-get update
|
sudo DEBIAN_FRONTEND=noninteractive apt-get update
|
||||||
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y libfcitx-qt5-dev tree
|
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y libfcitx5-qt-dev fcitx-libs-dev extra-cmake-modules libxkbcommon-dev
|
||||||
|
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y tree
|
||||||
|
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y fuse libxcb-cursor-dev
|
||||||
|
python3 -m pip config set global.break-system-packages true
|
||||||
|
|
||||||
- name: Cache Qt
|
- name: Cache Qt
|
||||||
id: cache-qt
|
id: cache-qt
|
||||||
uses: actions/cache@v1 # not v2!
|
uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: ../Qt
|
path: ${{runner.workspace}}/Qt
|
||||||
key: ${{ runner.os }}-QtCache-5.12-1
|
key: ${{ runner.os }}-QtCache-6.8
|
||||||
|
|
||||||
- name: Install Qt
|
- name: Install Qt
|
||||||
uses: jurplel/install-qt-action@v2
|
uses: jurplel/install-qt-action@v3
|
||||||
with:
|
with:
|
||||||
version: 5.12.12
|
version: 6.8.3
|
||||||
target: desktop
|
target: desktop
|
||||||
modules: qtwebengine
|
modules: 'qtwebengine qtwebchannel qtpositioning qtpdf qtimageformats qt5compat qtserialport'
|
||||||
tools: tools_openssl_x64,1.1.1-4,qt.tools.openssl.gcc_64
|
tools: 'tools_opensslv3_src'
|
||||||
cached: ${{ steps.cache-qt.outputs.cache-hit }}
|
cache: 'true'
|
||||||
|
|
||||||
|
- name: Compile OpenSSLV3
|
||||||
|
run: |
|
||||||
|
cd ${Qt6_DIR}/../../Tools/OpenSSLv3/src
|
||||||
|
./Configure
|
||||||
|
make -j2
|
||||||
|
sudo make install
|
||||||
|
|
||||||
- name: Create Build Dir
|
- name: Create Build Dir
|
||||||
run: mkdir build
|
run: mkdir build
|
||||||
working-directory: ${{runner.workspace}}
|
working-directory: ${{runner.workspace}}
|
||||||
|
|
||||||
- name: Compile qt5ct
|
- name: Compile fcitxqt5
|
||||||
run: |
|
run: |
|
||||||
wget -c https://excellmedia.dl.sourceforge.net/project/qt5ct/qt5ct-1.1.tar.bz2
|
git clone https://github.com/fcitx/fcitx-qt5
|
||||||
tar xf qt5ct-1.*.tar.bz2
|
cd fcitx-qt5
|
||||||
cd qt5ct-1.*/
|
mkdir build && cd build
|
||||||
QT_SELECT=5 qmake
|
cmake -DENABLE_QT5=OFF -DENABLE_QT6=ON ..
|
||||||
|
make -j2
|
||||||
|
sudo make install
|
||||||
|
working-directory: ${{runner.workspace}}/build
|
||||||
|
|
||||||
|
- name: Compile qt6ct
|
||||||
|
run: |
|
||||||
|
git clone https://github.com/trialuser02/qt6ct qt6ct.git
|
||||||
|
cd qt6ct.git
|
||||||
|
qmake
|
||||||
make -j$(nproc) && sudo make install
|
make -j$(nproc) && sudo make install
|
||||||
working-directory: ${{runner.workspace}}/build
|
working-directory: ${{runner.workspace}}/build
|
||||||
|
|
||||||
- name: Configure Project
|
- name: Configure Project
|
||||||
run: |
|
run: |
|
||||||
qmake -v
|
qmake -v
|
||||||
cp /usr/lib/x86_64-linux-gnu/qt5/plugins/platforminputcontexts/libfcitxplatforminputcontextplugin.so ./
|
cmake --version
|
||||||
sudo chmod +rwx ./libfcitxplatforminputcontextplugin.so
|
cmake ${GITHUB_WORKSPACE}
|
||||||
cp ./libfcitxplatforminputcontextplugin.so $Qt5_Dir/plugins/platforminputcontexts
|
|
||||||
qmake CONFIG+=release -spec linux-g++-64 ${GITHUB_WORKSPACE}/vnote.pro
|
|
||||||
working-directory: ${{runner.workspace}}/build
|
working-directory: ${{runner.workspace}}/build
|
||||||
|
|
||||||
- name: Build Project
|
- name: Build Project
|
||||||
run: make -j$(nproc)
|
|
||||||
working-directory: ${{runner.workspace}}/build
|
|
||||||
|
|
||||||
- name: Install Project
|
|
||||||
run: |
|
run: |
|
||||||
mkdir AppDir
|
# Remove the libqsqlmimer.so as libmimerapi.so is not deployed with Qt6
|
||||||
make install INSTALL_ROOT=${{runner.workspace}}/build/AppDir
|
rm ${{runner.workspace}}/Qt/6.*/gcc_64/plugins/sqldrivers/libqsqlmimer.so
|
||||||
tree AppDir
|
cmake --build . --target pack
|
||||||
working-directory: ${{runner.workspace}}/build
|
|
||||||
|
|
||||||
- name: Package Project
|
|
||||||
run: |
|
|
||||||
# Move the lib out to avoid duplication
|
|
||||||
mv AppDir/usr/lib ./
|
|
||||||
LD_LIBRARY_PATH=$PWD/lib:$LD_LIBRARY_PATH
|
|
||||||
# Copy translations
|
|
||||||
mkdir -p AppDir/usr/translations
|
|
||||||
cp $Qt5_Dir/translations/qt_zh_CN.qm AppDir/usr/translations
|
|
||||||
# Package qt5ct (EXTRA_QT_PLUGINS seems not work)
|
|
||||||
# EXTRA_QT_PLUGINS="platformthemes/libqt5ct.so;styles/libqt5ct-style.so"
|
|
||||||
mkdir -p AppDir/usr/plugins/platformthemes
|
|
||||||
mkdir -p AppDir/usr/plugins/styles
|
|
||||||
cp $Qt5_Dir/plugins/platformthemes/* AppDir/usr/plugins/platformthemes/
|
|
||||||
cp $Qt5_Dir/plugins/styles/* AppDir/usr/plugins/styles/
|
|
||||||
# Package libssl.so and libcrypto.so
|
|
||||||
Qt5_Tools=$Qt5_Dir/../../Tools
|
|
||||||
linuxdeploy-x86_64.AppImage --appdir ./AppDir --plugin qt --output appimage -l $Qt5_Tools/OpenSSL/binary/lib/libcrypto.so.1.1 -l $Qt5_Tools/OpenSSL/binary/lib/libssl.so.1.1
|
|
||||||
tree AppDir
|
|
||||||
working-directory: ${{runner.workspace}}/build
|
working-directory: ${{runner.workspace}}/build
|
||||||
|
|
||||||
- name: Fix Package
|
- name: Fix Package
|
||||||
@ -123,15 +133,14 @@ jobs:
|
|||||||
linuxdeploy-plugin-appimage-x86_64.AppImage --appdir=./squashfs-root
|
linuxdeploy-plugin-appimage-x86_64.AppImage --appdir=./squashfs-root
|
||||||
mv VNote*.AppImage ../
|
mv VNote*.AppImage ../
|
||||||
popd
|
popd
|
||||||
mv VNote*.AppImage vnote-linux-x64_v${{env.VNOTE_VER}}.AppImage
|
mv VNote*.AppImage VNote-${{env.VNOTE_VER}}-linux-x64.AppImage
|
||||||
cp vnote-linux-x64_v${{env.VNOTE_VER}}.AppImage vnote-linux-x64.AppImage
|
|
||||||
working-directory: ${{runner.workspace}}/build
|
working-directory: ${{runner.workspace}}/build
|
||||||
|
|
||||||
- name: Archive Artifacts
|
- name: Archive Artifacts
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: vnote-linux-x64_v${{env.VNOTE_VER}}
|
name: VNote-${{env.VNOTE_VER}}-linux-x64.AppImage
|
||||||
path: ${{runner.workspace}}/build/vnote-linux-x64_v${{env.VNOTE_VER}}.AppImage
|
path: ${{runner.workspace}}/build/VNote-${{env.VNOTE_VER}}-linux-x64.AppImage
|
||||||
|
|
||||||
- name: Update Tag
|
- name: Update Tag
|
||||||
if: github.ref == 'refs/heads/master'
|
if: github.ref == 'refs/heads/master'
|
||||||
@ -144,6 +153,17 @@ jobs:
|
|||||||
uses: johnwbyrd/update-release@v1.0.0
|
uses: johnwbyrd/update-release@v1.0.0
|
||||||
with:
|
with:
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
files: ${{runner.workspace}}/build/vnote-linux-x64.AppImage
|
files: ${{runner.workspace}}/build/VNote-${{env.VNOTE_VER}}-linux-x64.AppImage
|
||||||
release: Continuous Build
|
release: Continuous Build
|
||||||
tag: continuous-build
|
tag: continuous-build
|
||||||
|
|
||||||
|
- name: Release
|
||||||
|
if: github.ref == 'refs/heads/master' && startsWith(github.event.head_commit.message, '[Release]')
|
||||||
|
uses: ncipollo/release-action@v1.11.0
|
||||||
|
with:
|
||||||
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
artifacts: ${{runner.workspace}}/build/VNote-${{env.VNOTE_VER}}-linux-x64.AppImage
|
||||||
|
commit: master
|
||||||
|
tag: v${{env.VNOTE_VER}}
|
||||||
|
allowUpdates: true
|
||||||
|
draft: true
|
||||||
|
223
.github/workflows/ci-macos.yml
vendored
223
.github/workflows/ci-macos.yml
vendored
@ -8,16 +8,34 @@ on:
|
|||||||
|
|
||||||
# Allows you to run this workflow manually from the Actions tab.
|
# Allows you to run this workflow manually from the Actions tab.
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
debug_enabled:
|
||||||
|
type: boolean
|
||||||
|
description: 'Run the build with tmate debugging enabled'
|
||||||
|
required: false
|
||||||
|
default: false
|
||||||
|
|
||||||
env:
|
env:
|
||||||
VNOTE_VER: 3.13.1
|
VNOTE_VER: 3.19.2
|
||||||
|
CMAKE_VER: 3.24.3
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build-linux:
|
build:
|
||||||
|
environment: Mac-code-sign
|
||||||
name: Build On MacOS
|
name: Build On MacOS
|
||||||
runs-on: macos-latest
|
|
||||||
timeout-minutes: 120
|
timeout-minutes: 120
|
||||||
|
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
config:
|
||||||
|
- name: "Build on Arm64"
|
||||||
|
os: macos-latest
|
||||||
|
arch: universal
|
||||||
|
qt: 6.8.3
|
||||||
|
|
||||||
|
runs-on: ${{matrix.config.os}}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
# Checks-out your repository under $GITHUB_WORKSPACE.
|
# Checks-out your repository under $GITHUB_WORKSPACE.
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
@ -32,29 +50,50 @@ jobs:
|
|||||||
|
|
||||||
- name: Install Dependencies
|
- name: Install Dependencies
|
||||||
run: |
|
run: |
|
||||||
brew install tree
|
brew install tree libiodbc libpq
|
||||||
|
|
||||||
|
- name: Fix SQL
|
||||||
|
run: |
|
||||||
|
sudo mkdir -p /usr/local/opt/libiodbc/lib
|
||||||
|
sudo ln -s /opt/homebrew/opt/libiodbc/lib/libiodbc.2.dylib /usr/local/opt/libiodbc/lib/libiodbc.2.dylib
|
||||||
|
sudo mkdir -p /Applications/Postgres.app/Contents/Versions/14/lib
|
||||||
|
sudo ln -s /opt/homebrew/Cellar/libpq/16.3/lib/libpq.5.dylib /Applications/Postgres.app/Contents/Versions/14/lib/libpq.5.dylib
|
||||||
|
|
||||||
|
- name: Install a fresh CMake
|
||||||
|
run: |
|
||||||
|
wget --no-verbose https://github.com/Kitware/CMake/releases/download/v${CMAKE_VER}/cmake-${CMAKE_VER}-macos-universal.tar.gz
|
||||||
|
tar xzf cmake-${CMAKE_VER}-macos-universal.tar.gz
|
||||||
|
sudo rm -f /usr/local/bin/cmake /usr/local/bin/cpack
|
||||||
|
sudo ln -s ${{runner.workspace}}/cmake-${CMAKE_VER}-macos-universal/CMake.app/Contents/bin/cmake /usr/local/bin/cmake
|
||||||
|
sudo ln -s ${{runner.workspace}}/cmake-${CMAKE_VER}-macos-universal/CMake.app/Contents/bin/cpack /usr/local/bin/cpack
|
||||||
|
working-directory: ${{runner.workspace}}
|
||||||
|
|
||||||
- name: Install macdeployqtfix
|
- name: Install macdeployqtfix
|
||||||
run: |
|
run: |
|
||||||
git clone https://github.com/tamlok/macdeployqtfix.git macdeployqtfix --depth=1
|
git clone https://github.com/tamlok/macdeployqtfix.git macdeployqtfix --depth=1
|
||||||
working-directory: ${{runner.workspace}}
|
working-directory: ${{runner.workspace}}
|
||||||
|
|
||||||
|
- name: Install optool
|
||||||
|
run: |
|
||||||
|
wget --no-verbose https://github.com/alexzielenski/optool/releases/download/0.1/optool.zip
|
||||||
|
unzip ./optool.zip
|
||||||
|
sudo ln -s ./optool /usr/local/bin/optool
|
||||||
|
working-directory: ${{runner.workspace}}
|
||||||
|
|
||||||
- name: Cache Qt
|
- name: Cache Qt
|
||||||
id: cache-qt
|
id: cache-qt
|
||||||
uses: actions/cache@v1 # not v2!
|
uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: ../Qt
|
path: ${{runner.workspace}}/Qt
|
||||||
key: ${{ runner.os }}-QtCache-5.12-2
|
key: ${{ runner.os }}-QtCache-6.8
|
||||||
|
|
||||||
- name: Install Qt
|
- name: Install Qt
|
||||||
uses: jurplel/install-qt-action@v2
|
uses: jurplel/install-qt-action@v3
|
||||||
with:
|
with:
|
||||||
version: 5.12.12
|
version: ${{matrix.config.qt}}
|
||||||
target: desktop
|
target: desktop
|
||||||
modules: qtwebengine
|
modules: 'qtwebengine qtwebchannel qtpositioning qtpdf qtimageformats qt5compat qtserialport'
|
||||||
cached: ${{ steps.cache-qt.outputs.cache-hit }}
|
cache: 'true'
|
||||||
setup-python: 'false'
|
|
||||||
|
|
||||||
|
|
||||||
- name: Create Build Dir
|
- name: Create Build Dir
|
||||||
run: mkdir build
|
run: mkdir build
|
||||||
@ -63,76 +102,111 @@ jobs:
|
|||||||
- name: Configure Project
|
- name: Configure Project
|
||||||
run: |
|
run: |
|
||||||
qmake -v
|
qmake -v
|
||||||
qmake CONFIG+=release ${GITHUB_WORKSPACE}/vnote.pro
|
cmake --version
|
||||||
|
cmake -DMACDEPLOYQTFIX_EXECUTABLE=${{runner.workspace}}/macdeployqtfix/macdeployqtfix.py -DCMAKE_OSX_ARCHITECTURES="x86_64;arm64" ${GITHUB_WORKSPACE}
|
||||||
working-directory: ${{runner.workspace}}/build
|
working-directory: ${{runner.workspace}}/build
|
||||||
|
|
||||||
- name: Build Project
|
- name: Build Project
|
||||||
run: make -j4
|
|
||||||
working-directory: ${{runner.workspace}}/build
|
|
||||||
|
|
||||||
- name: Deploy VSyntaxHighlighting Framework
|
|
||||||
run: |
|
run: |
|
||||||
my_lib_name=VSyntaxHighlighting
|
# Keep only required SQL drivers
|
||||||
my_lib_framework=${my_lib_name}.framework
|
rm ${{env.Qt6_DIR}}/plugins/sqldrivers/libqsqlmimer.dylib
|
||||||
my_lib_dir=./libs/vtextedit/src/libs/syntax-highlighting
|
rm ${{env.Qt6_DIR}}/plugins/sqldrivers/libqsqlodbc.dylib
|
||||||
frameworks_dir=./src/vnote.app/Contents/Frameworks
|
rm ${{env.Qt6_DIR}}/plugins/sqldrivers/libqsqlpsql.dylib
|
||||||
mkdir -p ${frameworks_dir}
|
|
||||||
cp -R ${my_lib_dir}/${my_lib_framework} ${frameworks_dir}
|
# Build the project
|
||||||
|
cmake --build . --target pack
|
||||||
|
|
||||||
|
# Fix Qt frameworks
|
||||||
|
python3 ${{runner.workspace}}/macdeployqtfix/macdeployqtfix.py ./src/VNote.app/Contents/MacOS/VNote ${{env.Qt6_DIR}}/../..
|
||||||
|
|
||||||
|
# Only delete rpaths that exist to avoid errors
|
||||||
|
for rpath in $(otool -l ./src/VNote.app/Contents/MacOS/VNote | awk '/LC_RPATH/ {getline; getline; print $2}' | grep 'vnote'); do
|
||||||
|
echo "Checking rpath: $rpath"
|
||||||
|
if otool -l ./src/VNote.app/Contents/MacOS/VNote | grep -q "$rpath"; then
|
||||||
|
echo "Deleting rpath: $rpath"
|
||||||
|
install_name_tool -delete_rpath "$rpath" ./src/VNote.app/Contents/MacOS/VNote
|
||||||
|
else
|
||||||
|
echo "Rpath not found: $rpath"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
for rpath in $(otool -l ./src/VNote.app/Contents/Frameworks/libVTextEdit.dylib | awk '/LC_RPATH/ {getline; getline; print $2}' | grep 'vnote'); do
|
||||||
|
echo "Checking rpath: $rpath"
|
||||||
|
if otool -l ./src/VNote.app/Contents/Frameworks/libVTextEdit.dylib | grep -q "$rpath"; then
|
||||||
|
echo "Deleting rpath: $rpath"
|
||||||
|
install_name_tool -delete_rpath "$rpath" ./src/VNote.app/Contents/Frameworks/libVTextEdit.dylib
|
||||||
|
else
|
||||||
|
echo "Rpath not found: $rpath"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Run macdeployqtfix again to ensure all dependencies are properly fixed
|
||||||
|
python3 ${{runner.workspace}}/macdeployqtfix/macdeployqtfix.py ./src/VNote.app/Contents/MacOS/VNote ${{env.Qt6_DIR}}/../..
|
||||||
working-directory: ${{runner.workspace}}/build
|
working-directory: ${{runner.workspace}}/build
|
||||||
|
|
||||||
- name: Deploy VTextEdit Framework
|
- name: Codesign Bundle
|
||||||
|
# Extract the secrets we defined earlier as environment variables
|
||||||
|
env:
|
||||||
|
MACOS_CERTIFICATE: ${{ secrets.CLI_MACOS_CERTIFICATE }}
|
||||||
|
MACOS_CERTIFICATE_PWD: ${{ secrets.CLI_MACOS_CERTIFICATE_PWD }}
|
||||||
|
MACOS_CERTIFICATE_NAME: ${{ secrets.CLI_MACOS_CERTIFICATE_NAME }}
|
||||||
|
MACOS_CI_KEYCHAIN_PWD: ${{ secrets.CLI_MACOS_CERTIFICATE }}
|
||||||
run: |
|
run: |
|
||||||
my_lib_name=VTextEdit
|
# Turn our base64-encoded certificate back to a regular .p12 file
|
||||||
my_lib_framework=${my_lib_name}.framework
|
echo $MACOS_CERTIFICATE | base64 --decode > certificate.p12
|
||||||
my_lib_dir=./libs/vtextedit/src/editor
|
|
||||||
frameworks_dir=./src/vnote.app/Contents/Frameworks
|
# We need to create a new keychain, otherwise using the certificate will prompt
|
||||||
mkdir -p ${frameworks_dir}
|
# with a UI dialog asking for the certificate password, which we can't
|
||||||
cp -R ${my_lib_dir}/${my_lib_framework} ${frameworks_dir}
|
# use in a headless CI environment
|
||||||
|
security create-keychain -p "$MACOS_CI_KEYCHAIN_PWD" build.keychain
|
||||||
|
security default-keychain -s build.keychain
|
||||||
|
security unlock-keychain -p "$MACOS_CI_KEYCHAIN_PWD" build.keychain
|
||||||
|
security import certificate.p12 -k build.keychain -P "$MACOS_CERTIFICATE_PWD" -T /usr/bin/codesign
|
||||||
|
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$MACOS_CI_KEYCHAIN_PWD" build.keychain
|
||||||
|
|
||||||
|
echo "Codesigning main app bundle"
|
||||||
|
codesign --force --deep -s "$MACOS_CERTIFICATE_NAME" --entitlements ${{github.workspace}}/package/entitlements.xml --options runtime ./src/VNote.app
|
||||||
|
codesign -v -vvv ./src/VNote.app
|
||||||
|
|
||||||
|
hdiutil create -volname "VNote" -srcfolder ./src/VNote.app -ov -format UDZO VNote-${{env.VNOTE_VER}}-mac-${{matrix.config.arch}}.dmg
|
||||||
|
codesign --force --deep -s "$MACOS_CERTIFICATE_NAME" --entitlements ${{github.workspace}}/package/entitlements.xml --options runtime ./VNote-${{env.VNOTE_VER}}-mac-${{matrix.config.arch}}.dmg
|
||||||
|
codesign -v -vvv ./VNote-${{env.VNOTE_VER}}-mac-${{matrix.config.arch}}.dmg
|
||||||
|
|
||||||
working-directory: ${{runner.workspace}}/build
|
working-directory: ${{runner.workspace}}/build
|
||||||
|
|
||||||
- name: Cleanup rpath
|
- name: "Notarize Bundle"
|
||||||
|
# Extract the secrets we defined earlier as environment variables
|
||||||
|
env:
|
||||||
|
PROD_MACOS_NOTARIZATION_APPLE_ID: ${{ secrets.CLI_MACOS_NOTARY_USER }}
|
||||||
|
PROD_MACOS_NOTARIZATION_TEAM_ID: ${{ secrets.CLI_MACOS_TEAM_ID }}
|
||||||
|
PROD_MACOS_NOTARIZATION_PWD: ${{ secrets.CLI_MACOS_NOTARY_PWD }}
|
||||||
run: |
|
run: |
|
||||||
app_target=./src/vnote.app/Contents/MacOS/vnote
|
# Store the notarization credentials so that we can prevent a UI password dialog
|
||||||
install_name_tool -delete_rpath ${PWD}/src/../libs/vtextedit/src/editor ${app_target}
|
# from blocking the CI
|
||||||
install_name_tool -delete_rpath ${PWD}/src/../libs/vtextedit/src/libs/syntax-highlighting ${app_target}
|
echo "Create keychain profile"
|
||||||
working-directory: ${{runner.workspace}}/build
|
xcrun notarytool store-credentials "notarytool-profile" --apple-id "$PROD_MACOS_NOTARIZATION_APPLE_ID" --team-id "$PROD_MACOS_NOTARIZATION_TEAM_ID" --password "$PROD_MACOS_NOTARIZATION_PWD"
|
||||||
|
|
||||||
- name: Mac Deploy
|
# Here we send the notarization request to the Apple's Notarization service, waiting for the result.
|
||||||
run: |
|
# This typically takes a few seconds inside a CI environment, but it might take more depending on the App
|
||||||
pushd src
|
# characteristics. Visit the Notarization docs for more information and strategies on how to optimize it if
|
||||||
macdeployqt vnote.app
|
# you're curious
|
||||||
|
echo "Notarize app"
|
||||||
|
xcrun notarytool submit "${{runner.workspace}}/build/VNote-${{env.VNOTE_VER}}-mac-${{matrix.config.arch}}.dmg" --keychain-profile "notarytool-profile" --wait
|
||||||
|
|
||||||
# Remove unused sql drivers
|
# Finally, we need to "attach the staple" to our executable, which will allow our app to be
|
||||||
rm vnote.app/Contents/Plugins/sqldrivers/libqsqlodbc.dylib
|
# validated by macOS even when an internet connection is not available.
|
||||||
rm vnote.app/Contents/Plugins/sqldrivers/libqsqlpsql.dylib
|
echo "Attach staple"
|
||||||
|
xcrun stapler staple "${{runner.workspace}}/build/VNote-${{env.VNOTE_VER}}-mac-${{matrix.config.arch}}.dmg"
|
||||||
|
|
||||||
python ${{runner.workspace}}/macdeployqtfix/macdeployqtfix.py vnote.app/Contents/MacOS/vnote $Qt5_Dir
|
# Enable tmate debugging of manually-triggered workflows if the input option was provided
|
||||||
# Fix Helpers/QtWebEngineProcess.app
|
- name: Setup tmate session
|
||||||
pushd vnote.app/Contents/Frameworks/QtWebEngineCore.framework/Versions/5/Helpers
|
uses: mxschmitt/action-tmate@v3
|
||||||
python ${{runner.workspace}}/macdeployqtfix/macdeployqtfix.py QtWebEngineProcess.app/Contents/MacOS/QtWebEngineProcess $Qt5_Dir
|
if: ${{ github.event_name == 'workflow_dispatch' && inputs.debug_enabled }}
|
||||||
popd
|
|
||||||
|
|
||||||
popd
|
- name: Archive DMG
|
||||||
tree ./
|
uses: actions/upload-artifact@v4
|
||||||
working-directory: ${{runner.workspace}}/build
|
|
||||||
|
|
||||||
- name: Package Project
|
|
||||||
run: |
|
|
||||||
mkdir -p distrib/vnote
|
|
||||||
pushd distrib/vnote
|
|
||||||
mv ../../src/vnote.app ./
|
|
||||||
ln -s /Applications ./Applications
|
|
||||||
popd
|
|
||||||
sleep 1m
|
|
||||||
hdiutil create -srcfolder ./distrib/vnote -format UDBZ vnote-mac-x64_v${{env.VNOTE_VER}}.dmg
|
|
||||||
cp vnote-mac-x64_v${{env.VNOTE_VER}}.dmg vnote-mac-x64.dmg
|
|
||||||
working-directory: ${{runner.workspace}}/build
|
|
||||||
|
|
||||||
- name: Archive Artifacts
|
|
||||||
uses: actions/upload-artifact@v2
|
|
||||||
with:
|
with:
|
||||||
name: vnote-mac-x64_v${{env.VNOTE_VER}}
|
name: VNote-${{env.VNOTE_VER}}-mac-${{matrix.config.arch}}
|
||||||
path: ${{runner.workspace}}/build/vnote-mac-x64_v${{env.VNOTE_VER}}.dmg
|
path: ${{runner.workspace}}/build/VNote-${{env.VNOTE_VER}}-mac-${{matrix.config.arch}}.dmg
|
||||||
|
|
||||||
- name: Update Tag
|
- name: Update Tag
|
||||||
if: github.ref == 'refs/heads/master'
|
if: github.ref == 'refs/heads/master'
|
||||||
@ -145,6 +219,17 @@ jobs:
|
|||||||
uses: johnwbyrd/update-release@v1.0.0
|
uses: johnwbyrd/update-release@v1.0.0
|
||||||
with:
|
with:
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
files: ${{runner.workspace}}/build/vnote-mac-x64.dmg
|
files: ${{runner.workspace}}/build/VNote-${{env.VNOTE_VER}}-mac-${{matrix.config.arch}}.dmg
|
||||||
release: Continuous Build
|
release: Continuous Build
|
||||||
tag: continuous-build
|
tag: continuous-build
|
||||||
|
|
||||||
|
- name: Release
|
||||||
|
if: github.ref == 'refs/heads/master' && startsWith(github.event.head_commit.message, '[Release]')
|
||||||
|
uses: ncipollo/release-action@v1.11.0
|
||||||
|
with:
|
||||||
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
artifacts: ${{runner.workspace}}/build/VNote-${{env.VNOTE_VER}}-mac-${{matrix.config.arch}}.dmg
|
||||||
|
commit: master
|
||||||
|
tag: v${{env.VNOTE_VER}}
|
||||||
|
allowUpdates: true
|
||||||
|
draft: true
|
||||||
|
131
.github/workflows/ci-win.yml
vendored
131
.github/workflows/ci-win.yml
vendored
@ -8,29 +8,44 @@ on:
|
|||||||
|
|
||||||
# Allows you to run this workflow manually from the Actions tab.
|
# Allows you to run this workflow manually from the Actions tab.
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
debug_enabled:
|
||||||
|
type: boolean
|
||||||
|
description: 'Run the build with tmate debugging enabled'
|
||||||
|
required: false
|
||||||
|
default: false
|
||||||
|
|
||||||
env:
|
env:
|
||||||
VNOTE_VER: 3.13.1
|
VNOTE_VER: 3.19.2
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
name: ${{ matrix.config.name }}
|
name: ${{ matrix.config.name }}
|
||||||
runs-on: windows-2016
|
runs-on: windows-${{ matrix.config.vs_version }}
|
||||||
timeout-minutes: 120
|
timeout-minutes: 120
|
||||||
|
|
||||||
strategy:
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
config:
|
config:
|
||||||
- {
|
- name: "Build on Win64 Qt 5.15"
|
||||||
name: "Build On Win64",
|
arch: win64_msvc2019_64
|
||||||
arch: win64_msvc2017_64,
|
vs_version: 2019
|
||||||
platform: x64
|
vs_cmd: "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Enterprise\\VC\\Auxiliary\\Build\\vcvars64.bat"
|
||||||
}
|
qt: 5.15.2
|
||||||
- {
|
qt_modules: qtwebengine
|
||||||
name: "Build On Win32",
|
qt_tools: tools_opensslv3_x64
|
||||||
arch: win32_msvc2017,
|
qt_major: 5
|
||||||
platform: x86
|
suffix: "-windows7"
|
||||||
}
|
- name: "Build on Win64 Qt 6"
|
||||||
|
arch: win64_msvc2022_64
|
||||||
|
vs_version: 2022
|
||||||
|
vs_cmd: "C:\\Program Files\\Microsoft Visual Studio\\2022\\Enterprise\\VC\\Auxiliary\\Build\\vcvars64.bat"
|
||||||
|
qt: 6.8.3
|
||||||
|
qt_modules: "qtwebengine qtwebchannel qtpositioning qtpdf qtimageformats qt5compat"
|
||||||
|
qt_tools: tools_opensslv3_x64
|
||||||
|
qt_major: 6
|
||||||
|
suffix: ""
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
# Checks-out your repository under $GITHUB_WORKSPACE.
|
# Checks-out your repository under $GITHUB_WORKSPACE.
|
||||||
@ -47,71 +62,70 @@ jobs:
|
|||||||
|
|
||||||
- name: Cache Qt
|
- name: Cache Qt
|
||||||
id: cache-qt
|
id: cache-qt
|
||||||
uses: actions/cache@v1 # not v2!
|
uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: ../Qt
|
path: ${{runner.workspace}}/Qt
|
||||||
key: ${{ runner.os }}-${{matrix.config.arch}}-QtCache-5.12-1
|
key: ${{runner.os}}-${{matrix.config.arch}}-QtCache-${{matrix.config.qt}}
|
||||||
|
|
||||||
- name: Install Qt
|
- name: Install Qt Official Build
|
||||||
uses: jurplel/install-qt-action@v2
|
uses: jurplel/install-qt-action@v3
|
||||||
with:
|
with:
|
||||||
version: 5.12.11
|
version: ${{matrix.config.qt}}
|
||||||
target: desktop
|
target: desktop
|
||||||
arch: ${{matrix.config.arch}}
|
arch: ${{matrix.config.arch}}
|
||||||
modules: qtwebengine
|
modules: ${{matrix.config.qt_modules}}
|
||||||
tools: tools_openssl_${{matrix.config.platform}},1.1.1-4,qt.tools.openssl.win_${{matrix.config.platform}}
|
tools: ${{matrix.config.qt_tools}}
|
||||||
cached: ${{ steps.cache-qt.outputs.cache-hit }}
|
cache: 'true'
|
||||||
|
|
||||||
- name: Create Build Dir
|
- name: Create Build Dir
|
||||||
shell: bash
|
shell: bash
|
||||||
run: mkdir build
|
run: mkdir build
|
||||||
working-directory: ${{runner.workspace}}
|
working-directory: ${{runner.workspace}}
|
||||||
|
|
||||||
- name: Clone OpenSSL
|
- name: Clone OpenSSL on 5.15
|
||||||
shell: bash
|
shell: bash
|
||||||
|
if: ${{startsWith(matrix.config.qt, '5.15')}}
|
||||||
run: |
|
run: |
|
||||||
git clone https://github.com/tamlok/openssl-utils.git openssl-utils.git --depth=1
|
git clone https://github.com/tamlok/openssl-utils.git openssl-utils.git --depth=1
|
||||||
working-directory: ${{runner.workspace}}/build
|
working-directory: ${{runner.workspace}}/build
|
||||||
|
|
||||||
|
# Enable tmate debugging of manually-triggered workflows if the input option was provided
|
||||||
|
- name: Setup tmate session
|
||||||
|
uses: mxschmitt/action-tmate@v3
|
||||||
|
if: ${{ github.event_name == 'workflow_dispatch' && inputs.debug_enabled }}
|
||||||
|
|
||||||
- name: Configure and Build Project
|
- name: Configure and Build Project
|
||||||
shell: cmd
|
shell: cmd
|
||||||
run: |
|
run: |
|
||||||
call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" ${{matrix.config.platform}}
|
cmake --version
|
||||||
qmake -r -spec win32-msvc CONFIG-=debug CONFIG+=release %GITHUB_WORKSPACE%\vnote.pro
|
call "${{matrix.config.vs_cmd}}"
|
||||||
nmake
|
cmake -GNinja -DCMAKE_BUILD_TYPE=Release -DQT_DEFAULT_MAJOR_VERSION=${{matrix.config.qt_major}} -DOPENSSL_EXTRA_LIB_DIR=${{runner.workspace}}\build\openssl-utils.git\1.1.1j\Win_x64 %GITHUB_WORKSPACE%
|
||||||
|
cmake --build .
|
||||||
|
cmake --build . --target=pack
|
||||||
|
7z x VNote*.zip -o*
|
||||||
|
dir
|
||||||
working-directory: ${{runner.workspace}}/build
|
working-directory: ${{runner.workspace}}/build
|
||||||
|
|
||||||
- name: Package Project
|
- name: Rename on 5.15
|
||||||
shell: cmd
|
shell: bash
|
||||||
|
if: ${{startsWith(matrix.config.qt, '5.15')}}
|
||||||
run: |
|
run: |
|
||||||
mkdir "%DISTRIB_PATH%"
|
mv VNote-${{env.VNOTE_VER}}-win64 VNote-${{env.VNOTE_VER}}-win64${{matrix.config.suffix}}
|
||||||
call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" ${{matrix.config.platform}}
|
mv VNote-${{env.VNOTE_VER}}-win64.zip VNote-${{env.VNOTE_VER}}-win64${{matrix.config.suffix}}.zip
|
||||||
windeployqt.exe --dir "%DISTRIB_PATH%" .\src\release\vnote.exe
|
|
||||||
copy .\src\release\vnote.exe "%DISTRIB_PATH%\vnote.exe"
|
|
||||||
copy .\src\release\vnote_extra.rcc "%DISTRIB_PATH%\vnote_extra.rcc"
|
|
||||||
copy .\libs\vtextedit\src\libs\syntax-highlighting\release\VSyntaxHighlighting.dll "%DISTRIB_PATH%\VSyntaxHighlighting.dll"
|
|
||||||
copy .\libs\vtextedit\src\editor\release\VTextEdit.dll "%DISTRIB_PATH%\VTextEdit.dll"
|
|
||||||
rem set qt_dir=%Qt5_Dir:/=\%
|
|
||||||
rem for %%I in ("%qt_dir%\..\..") do set "qt_topdir=%%~fI"
|
|
||||||
rem set openssl_dir=%qt_topdir%\Tools\OpenSSL\Win_${{matrix.config.platform}}\bin
|
|
||||||
set openssl_dir=openssl-utils.git\1.1.1j\Win_${{matrix.config.platform}}
|
|
||||||
copy %openssl_dir%\lib*.dll "%DISTRIB_PATH%\"
|
|
||||||
copy "%GITHUB_WORKSPACE%\README.md" "%DISTRIB_PATH%\README.md"
|
|
||||||
copy "%GITHUB_WORKSPACE%\COPYING.LESSER" "%DISTRIB_PATH%\COPYING.LESSER"
|
|
||||||
echo %GITHUB_SHA% > "%DISTRIB_PATH%\commit"
|
|
||||||
del /F /Q "%DISTRIB_PATH%\translations\qt_*.qm"
|
|
||||||
7z a vnote-win-${{matrix.config.platform}}.zip "%DISTRIB_PATH%"
|
|
||||||
working-directory: ${{runner.workspace}}/build
|
working-directory: ${{runner.workspace}}/build
|
||||||
env:
|
|
||||||
DISTRIB_PATH: ${{runner.workspace}}/build/distrib/vnote
|
|
||||||
|
|
||||||
- name: Archive Artifacts
|
- name: Archive Artifacts
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: vnote-win-${{matrix.config.platform}}_v${{env.VNOTE_VER}}
|
name: VNote-${{env.VNOTE_VER}}-win64${{matrix.config.suffix}}
|
||||||
path: ${{env.DISTRIB_PATH}}
|
path: ${{runner.workspace}}/build/VNote-${{env.VNOTE_VER}}-win64${{matrix.config.suffix}}
|
||||||
env:
|
|
||||||
DISTRIB_PATH: ${{runner.workspace}}/build/distrib/vnote
|
- name: Archive Installer
|
||||||
|
if: ${{!startsWith(matrix.config.qt, '5.15')}}
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: VNote-${{env.VNOTE_VER}}-win64${{matrix.config.suffix}}.msi
|
||||||
|
path: ${{runner.workspace}}/build/VNote*.msi
|
||||||
|
|
||||||
- name: Update Tag
|
- name: Update Tag
|
||||||
if: github.ref == 'refs/heads/master'
|
if: github.ref == 'refs/heads/master'
|
||||||
@ -125,6 +139,19 @@ jobs:
|
|||||||
uses: johnwbyrd/update-release@v1.0.0
|
uses: johnwbyrd/update-release@v1.0.0
|
||||||
with:
|
with:
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
files: ${{runner.workspace}}/build/vnote-win-${{matrix.config.platform}}.zip
|
# glob not supported
|
||||||
|
files: ${{runner.workspace}}/build/VNote-${{env.VNOTE_VER}}-win64${{matrix.config.suffix}}.zip
|
||||||
release: Continuous Build
|
release: Continuous Build
|
||||||
tag: continuous-build
|
tag: continuous-build
|
||||||
|
|
||||||
|
- name: Release
|
||||||
|
if: github.ref == 'refs/heads/master' && startsWith(github.event.head_commit.message, '[Release]')
|
||||||
|
uses: ncipollo/release-action@v1.11.0
|
||||||
|
with:
|
||||||
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
# glob not supported
|
||||||
|
artifacts: ${{runner.workspace}}/build/VNote-${{env.VNOTE_VER}}-win64${{matrix.config.suffix}}
|
||||||
|
commit: master
|
||||||
|
tag: v${{env.VNOTE_VER}}
|
||||||
|
allowUpdates: true
|
||||||
|
draft: true
|
||||||
|
4
.gitignore
vendored
4
.gitignore
vendored
@ -2,6 +2,7 @@
|
|||||||
*.pro.user.*
|
*.pro.user.*
|
||||||
.ccls
|
.ccls
|
||||||
compile_commands.json
|
compile_commands.json
|
||||||
|
compile_commands.json.*
|
||||||
compile_flags.txt
|
compile_flags.txt
|
||||||
.cache
|
.cache
|
||||||
.tasks
|
.tasks
|
||||||
@ -11,3 +12,6 @@ GRTAGS
|
|||||||
GTAGS
|
GTAGS
|
||||||
aqtinstall.log
|
aqtinstall.log
|
||||||
tags
|
tags
|
||||||
|
CMakeLists.txt.user
|
||||||
|
build
|
||||||
|
.DS_Store
|
||||||
|
26
CMakeLists.txt
Normal file
26
CMakeLists.txt
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
cmake_minimum_required (VERSION 3.20)
|
||||||
|
|
||||||
|
set(CMAKE_OSX_DEPLOYMENT_TARGET "12.1" CACHE STRING "Minimum OS X deployment version")
|
||||||
|
|
||||||
|
project(VNote
|
||||||
|
VERSION 3.19.2
|
||||||
|
DESCRIPTION "A pleasant note-taking platform"
|
||||||
|
HOMEPAGE_URL "https://app.vnote.fun"
|
||||||
|
LANGUAGES C CXX)
|
||||||
|
|
||||||
|
set(CMAKE_BUILD_TYPE Release CACHE STRING "Build type, defaults to Release")
|
||||||
|
|
||||||
|
set(CMAKE_CXX_STANDARD 14)
|
||||||
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
|
||||||
|
set(CMAKE_AUTOMOC ON)
|
||||||
|
set(CMAKE_AUTOUIC ON)
|
||||||
|
set(CMAKE_AUTORCC ON)
|
||||||
|
|
||||||
|
set(QHOTKEY_INSTALL OFF CACHE BOOL "Disable installing QHotKey" FORCE)
|
||||||
|
add_subdirectory(libs)
|
||||||
|
|
||||||
|
add_subdirectory(src)
|
||||||
|
|
||||||
|
# TODO: find a better way to organize tests
|
||||||
|
# add_subdirectory(tests)
|
29
README.md
29
README.md
@ -1,11 +1,13 @@
|
|||||||
# VNote
|
# VNote
|
||||||
  
|
  
|
||||||
|
|
||||||
[简体中文](README_zh_CN.md)
|
[简体中文](README_zh_CN.md)
|
||||||
|
|
||||||
|
[Project on Gitee](https://gitee.com/vnotex/vnote)
|
||||||
|
|
||||||
A pleasant note-taking platform.
|
A pleasant note-taking platform.
|
||||||
|
|
||||||
For more information, please visit [**VNote's Home Page**](https://vnotex.github.io/vnote) or [Home Page on Gitee](https://tamlok.gitee.io/vnote).
|
For more information, please visit [**VNote's Home Page**](https://vnotex.github.io/vnote).
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
@ -18,39 +20,22 @@ Utilizing Qt, VNote could run on **Linux**, **Windows**, and **macOS**.
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
## Downloads
|
## Downloads
|
||||||
Continuous builds on `master` branch could be found at the [Continuous Build](https://github.com/vnotex/vnote/releases/tag/continuous-build) release.
|
Continuous builds on `master` branch could be found at the [Continuous Build](https://github.com/vnotex/vnote/releases/tag/continuous-build) release.
|
||||||
|
|
||||||
Latest stable builds could be found at the [latest release](https://github.com/vnotex/vnote/releases/latest). Alternative download services are available:
|
Latest stable builds could be found at the [latest release](https://github.com/vnotex/vnote/releases/latest). Alternative download services are available:
|
||||||
|
|
||||||
* [Tianyi Netdisk](https://cloud.189.cn/t/Av67NvmEJVBv)
|
* [Tianyi Netdisk](https://cloud.189.cn/t/Av67NvmEJVBv)
|
||||||
* [Baidu Netdisk](https://pan.baidu.com/s/1Fou1flmBsQUQ8Qs9V_M6Aw) with the code `note`
|
* [Baidu Netdisk](https://pan.baidu.com/s/1lX69oMBw8XuJshQDN3HiHw?pwd=f8fk)
|
||||||
|
|
||||||
## Supports
|
## Supports
|
||||||
* [GitHub Issues](https://github.com/vnotex/vnote/issues);
|
* [GitHub Issues](https://github.com/vnotex/vnote/issues);
|
||||||
* Email: `tamlokveer at gmail.com`;
|
* Email: `tamlokveer at gmail.com`;
|
||||||
* [Slack](https://join.slack.com/t/vnote/shared_invite/enQtNDg2MzY0NDg3NzI4LTVhMzBlOTY0YzVhMmQyMTFmZDdhY2M3MDQxYTBjOTA2Y2IxOGRiZjg2NzdhMjkzYmUyY2VkMWJlZTNhMTQyODU);
|
|
||||||
* [Telegram](https://t.me/vnotex);
|
* [Telegram](https://t.me/vnotex);
|
||||||
* WeChat Public Account: vnotex;
|
* WeChat Public Account: vnotex;
|
||||||
|
|
||||||
## Donate
|
|
||||||
You could help VNote's development in many ways.
|
|
||||||
|
|
||||||
* Keep monitoring VNote and sending feedback for improvement.
|
|
||||||
* Spread and promote VNote to your friends. Popularity is a strong power to drive developers.
|
|
||||||
* Participate in the development of VNote and send [Pull Request](https://github.com/vnotex/vnote/pulls) to make VNote perfect.
|
|
||||||
* Last, really appreciate your donations to VNote if VNote does help.
|
|
||||||
|
|
||||||
**PayPal**: [PayPal.Me/vnotemd](https://www.paypal.me/vnotemd)
|
|
||||||
|
|
||||||
**Alipay**: `tamlokveer@gmail.com`
|
|
||||||
|
|
||||||
<img src="pics/alipay.png" width="256px" height="256px" />
|
|
||||||
|
|
||||||
**WeChat**
|
|
||||||
|
|
||||||
<img src="pics/wechat_pay.png" width="256px" height="256px" />
|
|
||||||
|
|
||||||
Thank [users who donated to VNote](https://github.com/vnotex/vnote/wiki/Donate-List)!
|
Thank [users who donated to VNote](https://github.com/vnotex/vnote/wiki/Donate-List)!
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
# VNote
|
# VNote
|
||||||
  
|
  
|
||||||
|
|
||||||
[English](README.md)
|
[English](README.md)
|
||||||
|
|
||||||
|
[Gitee托管项目](https://gitee.com/vnotex/vnote)
|
||||||
|
|
||||||
一个舒适的笔记平台!
|
一个舒适的笔记平台!
|
||||||
|
|
||||||
更多信息,请访问[VNote主页](https://vnotex.github.io/vnote)或者[由Gitee托管的主页](https://tamlok.gitee.io/vnote)。
|
更多信息,请访问[VNote主页](https://vnotex.github.io/vnote)。
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
@ -18,39 +20,22 @@ VNote不是一个简单的Markdown编辑器。通过提供强大的笔记管理
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
## 下载
|
## 下载
|
||||||
基于`master`分支的[持续构建版本发布](https://github.com/vnotex/vnote/releases/tag/continuous-build)。
|
基于`master`分支的[持续构建版本发布](https://github.com/vnotex/vnote/releases/tag/continuous-build)。
|
||||||
|
|
||||||
最新的[稳定版本发布](https://github.com/vnotex/vnote/releases/latest)。其他下载选项:
|
最新的[稳定版本发布](https://github.com/vnotex/vnote/releases/latest)。其他下载选项:
|
||||||
|
|
||||||
* [天翼云盘](https://cloud.189.cn/t/Av67NvmEJVBv)
|
* [天翼云盘](https://cloud.189.cn/t/Av67NvmEJVBv)
|
||||||
* [百度云盘](https://pan.baidu.com/s/1Fou1flmBsQUQ8Qs9V_M6Aw) 提取码`note`
|
* [百度云盘](https://pan.baidu.com/s/1lX69oMBw8XuJshQDN3HiHw?pwd=f8fk)
|
||||||
|
|
||||||
## 支持
|
## 支持
|
||||||
* [GitHub Issues](https://github.com/vnotex/vnote/issues);
|
* [GitHub Issues](https://github.com/vnotex/vnote/issues);
|
||||||
* 邮件:`tamlokveer at gmail.com`;
|
* 邮件:`tamlokveer at gmail.com`;
|
||||||
* [Slack](https://join.slack.com/t/vnote/shared_invite/enQtNDg2MzY0NDg3NzI4LTVhMzBlOTY0YzVhMmQyMTFmZDdhY2M3MDQxYTBjOTA2Y2IxOGRiZjg2NzdhMjkzYmUyY2VkMWJlZTNhMTQyODU);
|
|
||||||
* [Telegram](https://t.me/vnotex);
|
* [Telegram](https://t.me/vnotex);
|
||||||
* 微信公众号:`vnotex`;
|
* 微信公众号:`vnotex`;
|
||||||
|
|
||||||
## 捐赠
|
|
||||||
有很多方式可以帮助VNote的开发:
|
|
||||||
|
|
||||||
* 持续关注VNote并反馈问题以帮助改进。
|
|
||||||
* 推荐VNote给朋友,口碑传播。
|
|
||||||
* 参与VNote的开发,发起[拉取请求](https://github.com/vnotex/vnote/pulls)一起改进VNote。
|
|
||||||
* 如果VNote真的好用,可以考虑捐赠。
|
|
||||||
|
|
||||||
**PayPal**:[PayPal.Me/vnotemd](https://www.paypal.me/vnotemd)
|
|
||||||
|
|
||||||
**支付宝**:`tamlokveer@gmail.com`
|
|
||||||
|
|
||||||
<img src="pics/alipay.png" width="256px" height="256px" />
|
|
||||||
|
|
||||||
**微信**
|
|
||||||
|
|
||||||
<img src="pics/wechat_pay.png" width="256px" height="256px" />
|
|
||||||
|
|
||||||
感谢这些[捐赠用户](https://github.com/vnotex/vnote/wiki/Donate-List)!
|
感谢这些[捐赠用户](https://github.com/vnotex/vnote/wiki/Donate-List)!
|
||||||
|
|
||||||
## 许可
|
## 许可
|
||||||
|
15
SECURITY.md
Normal file
15
SECURITY.md
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
# Security Policy
|
||||||
|
|
||||||
|
## Supported Versions
|
||||||
|
|
||||||
|
Only the latest version is supported with security updates.
|
||||||
|
|
||||||
|
## Reporting a Vulnerability
|
||||||
|
|
||||||
|
Please [contact support](mailto:tamlokveer@gmail.com) **with a proof of concept** that shows the security vulnerability. Please do not contact us without this proof of concept, as we cannot fix anything without this.
|
||||||
|
|
||||||
|
For general opinions on what makes an app more or less secure, please use the forum.
|
||||||
|
|
||||||
|
## Bounty
|
||||||
|
|
||||||
|
We **do not** offer a bounty for discovering vulnerabilities, please do not ask. We can however credit you and link to your website/profile in the changelog and release announcement.
|
53
changes.md
53
changes.md
@ -1,4 +1,57 @@
|
|||||||
# Changes
|
# Changes
|
||||||
|
## v3.19.2
|
||||||
|
* Codesign MacOS Bundle
|
||||||
|
* Fix toolbar expansion button style
|
||||||
|
* Support hot-reloading of theme via --watch-themes option
|
||||||
|
|
||||||
|
## v3.19.1
|
||||||
|
* Fix toolbar button in Qt 6.8
|
||||||
|
|
||||||
|
## v3.19.0
|
||||||
|
* Add VSCode-sytle editor shortcuts
|
||||||
|
|
||||||
|
## v3.18.1
|
||||||
|
* Fix crash caused by Qt6 change
|
||||||
|
* Fix XSS protection exemption
|
||||||
|
* Check link before open
|
||||||
|
|
||||||
|
## v3.18.0
|
||||||
|
* Upgrade to Qt6
|
||||||
|
* Support MacOS universal build
|
||||||
|
* Upgrade Mermaid, Flowchart.js, and markdown-it
|
||||||
|
* Markdown-it
|
||||||
|
* Fix XSS protection and turn it on by default
|
||||||
|
* Support mark by `==xx==`
|
||||||
|
|
||||||
|
## v3.17.0
|
||||||
|
* Quick note: create note in given scheme (@feloxx)
|
||||||
|
* MarkdownEditor: support inserting multiple images (@feloxx)
|
||||||
|
* Mermaid: upgrade and fix preview issue (@ygcaicn)
|
||||||
|
* Flowchart.js: upgrade
|
||||||
|
|
||||||
|
## v3.16.0
|
||||||
|
* Support reading PDF format
|
||||||
|
* Support Ming Map editor in suffix `*.emind`
|
||||||
|
* Support "View By" for notebooks selector
|
||||||
|
* ViewWindow: add shortcut Ctrl+G,V to alternate among view modes
|
||||||
|
* Bug fixes
|
||||||
|
|
||||||
|
## v3.15.1
|
||||||
|
* Add two themes
|
||||||
|
* Bug fixes
|
||||||
|
|
||||||
|
## v3.15.0
|
||||||
|
* Editor supports Word Count
|
||||||
|
* Add Open Windows panel
|
||||||
|
* Theme: add Vue-light theme
|
||||||
|
* Support default open mode
|
||||||
|
* NotebookSelector: support dynamic icons for notebooks
|
||||||
|
|
||||||
|
## v3.14.0
|
||||||
|
* Theme: support custom icons
|
||||||
|
* Theme: refine icons
|
||||||
|
* NavigationMode: fix issue for input method
|
||||||
|
|
||||||
## v3.13.1
|
## v3.13.1
|
||||||
* Shortcuts for Copy/Paste/Properties in node explorer
|
* Shortcuts for Copy/Paste/Properties in node explorer
|
||||||
* Global shortcut to call out main window
|
* Global shortcut to call out main window
|
||||||
|
2
libs/CMakeLists.txt
Normal file
2
libs/CMakeLists.txt
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
add_subdirectory(QHotkey)
|
||||||
|
add_subdirectory(vtextedit)
|
@ -1 +1 @@
|
|||||||
Subproject commit 18ac011008d3ae55abc19233ba94fad1ea9801d8
|
Subproject commit 8abe0b2280533af57f423f5785acc4d9d4d73ab8
|
@ -1,5 +0,0 @@
|
|||||||
TEMPLATE = subdirs
|
|
||||||
|
|
||||||
SUBDIRS += \
|
|
||||||
vtextedit \
|
|
||||||
QHotkey
|
|
@ -1 +1 @@
|
|||||||
Subproject commit a6a9a31cf64b4a159d360f0ef6ed6cf296f8eca8
|
Subproject commit 50b1421793af3882ddc62ad4e6cf5537e1d7906f
|
24
package/QtWebEngineProcess.entitlements.xml
Normal file
24
package/QtWebEngineProcess.entitlements.xml
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
|
||||||
|
<true/>
|
||||||
|
<key>com.apple.security.cs.disable-library-validation</key>
|
||||||
|
<true/>
|
||||||
|
<key>com.apple.security.cs.allow-jit</key>
|
||||||
|
<true/>
|
||||||
|
<key>com.apple.security.cs.disable-executable-page-protection</key>
|
||||||
|
<true/>
|
||||||
|
<key>com.apple.security.files.user-selected.read-write</key>
|
||||||
|
<true/>
|
||||||
|
<key>com.apple.security.network.client</key>
|
||||||
|
<true/>
|
||||||
|
<key>com.apple.security.get-task-allow</key>
|
||||||
|
<true/>
|
||||||
|
<key>com.apple.security.cs.debugger</key>
|
||||||
|
<true/>
|
||||||
|
<key>com.apple.security.inherit</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
BIN
package/banner_text.png
Normal file
BIN
package/banner_text.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.1 KiB |
24
package/entitlements.xml
Normal file
24
package/entitlements.xml
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>com.apple.security.files.user-selected.read-write</key>
|
||||||
|
<true/>
|
||||||
|
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
|
||||||
|
<true/>
|
||||||
|
<key>com.apple.security.network.client</key>
|
||||||
|
<true/>
|
||||||
|
<key>com.apple.security.cs.allow-jit</key>
|
||||||
|
<true/>
|
||||||
|
<key>com.apple.security.cs.disable-library-validation</key>
|
||||||
|
<true/>
|
||||||
|
<key>com.apple.security.cs.disable-executable-page-protection</key>
|
||||||
|
<true/>
|
||||||
|
<key>com.apple.security.get-task-allow</key>
|
||||||
|
<true/>
|
||||||
|
<key>com.apple.security.cs.debugger</key>
|
||||||
|
<true/>
|
||||||
|
<key>com.apple.security.inherit</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
110
package/lgpl-3.0.rtf
Normal file
110
package/lgpl-3.0.rtf
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
{\rtf1\ansi\deff3\adeflang1025
|
||||||
|
{\fonttbl{\f0\froman\fprq2\fcharset0 Times New Roman;}{\f1\froman\fprq2\fcharset2 Symbol;}{\f2\fswiss\fprq2\fcharset0 Arial;}{\f3\froman\fprq2\fcharset0 Liberation Serif{\*\falt Times New Roman};}{\f4\fswiss\fprq2\fcharset0 Liberation Sans{\*\falt Arial};}{\f5\froman\fprq0\fcharset128 Helvetica{\*\falt Arial};}{\f6\fnil\fprq2\fcharset0 Droid Sans Fallback;}{\f7\fnil\fprq2\fcharset0 FreeSans;}{\f8\fswiss\fprq0\fcharset128 FreeSans;}}
|
||||||
|
{\colortbl;\red0\green0\blue0;\red0\green0\blue128;\red128\green128\blue128;}
|
||||||
|
{\stylesheet{\s0\snext0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang1033 Normal;}
|
||||||
|
{\*\cs15\snext15\cf2\ul\ulc0\langfe255\alang255\lang255 Internet Link;}
|
||||||
|
{\s16\sbasedon0\snext17\sb240\sa120\keepn\dbch\af6\dbch\af7\afs28\loch\f4\fs28 Heading;}
|
||||||
|
{\s17\sbasedon0\snext17\sl288\slmult1\sb0\sa140 Text Body;}
|
||||||
|
{\s18\sbasedon17\snext18\sl288\slmult1\sb0\sa140\dbch\af8 List;}
|
||||||
|
{\s19\sbasedon0\snext19\sb120\sa120\noline\i\dbch\af8\afs24\ai\fs24 Caption;}
|
||||||
|
{\s20\sbasedon0\snext20\noline\dbch\af8 Index;}
|
||||||
|
}{\info{\creatim\yr0\mo0\dy0\hr0\min0}{\revtim\yr0\mo0\dy0\hr0\min0}{\printim\yr0\mo0\dy0\hr0\min0}{\comment LibreOffice}{\vern67241986}}\deftab720
|
||||||
|
\viewscale100
|
||||||
|
{\*\pgdsctbl
|
||||||
|
{\pgdsc0\pgdscuse451\pgwsxn12240\pghsxn15840\marglsxn1800\margrsxn1800\margtsxn1440\margbsxn1440\pgdscnxt0 Default Style;}}
|
||||||
|
\formshade{\*\pgdscno0}\paperh15840\paperw12240\margl1800\margr1800\margt1440\margb1440\sectd\sbknone\sectunlocked1\pgndec\pgwsxn12240\pghsxn15840\marglsxn1800\margrsxn1800\margtsxn1440\margbsxn1440\ftnbj\ftnstart1\ftnrstcont\ftnnar\aenddoc\aftnrstcont\aftnstart1\aftnnrlc
|
||||||
|
\pgndec\pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang1033\ql\li0\ri0\lin0\rin0\fi0\sb0\sa180{\b\rtlch \ltrch\loch\fs28\loch\f5
|
||||||
|
GNU LESSER GENERAL PUBLIC LICENSE}
|
||||||
|
\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang1033\ql\li0\ri0\lin0\rin0\fi0\sb0\sa180{\rtlch \ltrch\loch\loch\f5
|
||||||
|
Version 3, 29 June 2007}
|
||||||
|
\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang1033\ql\li0\ri0\lin0\rin0\fi0\sb0\sa180{\rtlch \ltrch\loch\loch\f5
|
||||||
|
Copyright \u169\'3f 2007 Free Software Foundation, Inc. <}{{\field{\*\fldinst HYPERLINK "https://fsf.org/" }{\fldrslt {\cf2\ul\ulc0\langfe255\alang255\lang255\ul\ulc0\rtlch \ltrch\loch\loch\f5
|
||||||
|
https://fsf.org/}{}}}\rtlch \ltrch\loch\loch\f5
|
||||||
|
>}
|
||||||
|
\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang1033\ql\li0\ri0\lin0\rin0\fi0\sb0\sa180{\rtlch \ltrch\loch\loch\f5
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.}
|
||||||
|
\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang1033\ql\li0\ri0\lin0\rin0\fi0\sb0\sa180{\rtlch \ltrch\loch\loch\f5
|
||||||
|
This version of the GNU Lesser General Public License incorporates the terms and conditions of version 3 of the GNU General Public License, supplemented by the additional permissions listed below.}
|
||||||
|
\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang1033\ql\li0\ri0\lin0\rin0\fi0\sb0\sa180{\b\rtlch \ltrch\loch\fs24\loch\f5
|
||||||
|
0. Additional Definitions.}
|
||||||
|
\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang1033\ql\li0\ri0\lin0\rin0\fi0\sb0\sa180{\rtlch \ltrch\loch\loch\f5
|
||||||
|
As used herein, \uc2 \u8220\'81\'67this License\u8221\'81\'68 refers to version 3 of the GNU Lesser General Public License, and the \u8220\'81\'67GNU GPL\u8221\'81\'68 refers to version 3 of the GNU General Public License.\uc1 }
|
||||||
|
\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang1033\ql\li0\ri0\lin0\rin0\fi0\sb0\sa180{\rtlch \ltrch\loch\f5
|
||||||
|
\uc2 \u8220\'81\'67\uc1 }{\rtlch \ltrch\loch\loch\f5
|
||||||
|
The Library\uc2 \u8221\'81\'68 refers to a covered work governed by this License, other than an Application or a Combined Work as defined below.\uc1 }
|
||||||
|
\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang1033\ql\li0\ri0\lin0\rin0\fi0\sb0\sa180{\rtlch \ltrch\loch\loch\f5
|
||||||
|
An \uc2 \u8220\'81\'67Application\u8221\'81\'68 is any work that makes use of an interface provided by the Library, but which is not otherwise based on the Library. Defining a subclass of a class defined by the Library is deemed a mode of using an interface provided by the Library.\uc1 }
|
||||||
|
\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang1033\ql\li0\ri0\lin0\rin0\fi0\sb0\sa180{\rtlch \ltrch\loch\loch\f5
|
||||||
|
A \uc2 \u8220\'81\'67Combined Work\u8221\'81\'68 is a work produced by combining or linking an Application with the Library. The particular version of the Library with which the Combined Work was made is also called the \u8220\'81\'67Linked Version\u8221\'81\'68.\uc1 }
|
||||||
|
\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang1033\ql\li0\ri0\lin0\rin0\fi0\sb0\sa180{\rtlch \ltrch\loch\loch\f5
|
||||||
|
The \uc2 \u8220\'81\'67Minimal Corresponding Source\u8221\'81\'68 for a Combined Work means the Corresponding Source for the Combined Work, excluding any source code for portions of the Combined Work that, considered in isolation, are based on the Application, and not on the Linked Version.\uc1 }
|
||||||
|
\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang1033\ql\li0\ri0\lin0\rin0\fi0\sb0\sa180{\rtlch \ltrch\loch\loch\f5
|
||||||
|
The \uc2 \u8220\'81\'67Corresponding Application Code\u8221\'81\'68 for a Combined Work means the object code and/or source code for the Application, including any data and utility programs needed for reproducing the Combined Work from the Application, but excluding the System Libraries of the Combined Work.\uc1 }
|
||||||
|
\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang1033\ql\li0\ri0\lin0\rin0\fi0\sb0\sa180{\b\rtlch \ltrch\loch\fs24\loch\f5
|
||||||
|
1. Exception to Section 3 of the GNU GPL.}
|
||||||
|
\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang1033\ql\li0\ri0\lin0\rin0\fi0\sb0\sa180{\rtlch \ltrch\loch\loch\f5
|
||||||
|
You may convey a covered work under sections 3 and 4 of this License without being bound by section 3 of the GNU GPL.}
|
||||||
|
\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang1033\ql\li0\ri0\lin0\rin0\fi0\sb0\sa180{\b\rtlch \ltrch\loch\fs24\loch\f5
|
||||||
|
2. Conveying Modified Versions.}
|
||||||
|
\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang1033\ql\li0\ri0\lin0\rin0\fi0\sb0\sa180{\rtlch \ltrch\loch\loch\f5
|
||||||
|
If you modify a copy of the Library, and, in your modifications, a facility refers to a function or data to be supplied by an Application that uses the facility (other than as an argument passed when the facility is invoked), then you may convey a copy of the modified version:}
|
||||||
|
\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang1033\ql\li360\ri0\lin360\rin0\fi-360\sb0\sa0{\rtlch \ltrch\loch\f5
|
||||||
|
\u8226\'3f}{\rtlch \ltrch\loch\loch\f5
|
||||||
|
\tab a) under this License, provided that you make a good faith effort to ensure that, in the event an Application does not supply the function or data, the facility still operates, and performs whatever part of its purpose remains meaningful, or}
|
||||||
|
\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang1033\ql\li360\ri0\lin360\rin0\fi-360\sb0\sa0{\rtlch \ltrch\loch\f5
|
||||||
|
\u8226\'3f}{\rtlch \ltrch\loch\loch\f5
|
||||||
|
\tab b) under the GNU GPL, with none of the additional permissions of this License applicable to that copy.}
|
||||||
|
\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang1033\ql\li0\ri0\lin0\rin0\fi0\sb0\sa180{\b\rtlch \ltrch\loch\fs24\loch\f5
|
||||||
|
3. Object Code Incorporating Material from Library Header Files.}
|
||||||
|
\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang1033\ql\li0\ri0\lin0\rin0\fi0\sb0\sa180{\rtlch \ltrch\loch\loch\f5
|
||||||
|
The object code form of an Application may incorporate material from a header file that is part of the Library. You may convey such object code under terms of your choice, provided that, if the incorporated material is not limited to numerical parameters, data structure layouts and accessors, or small macros, inline functions and templates (ten or fewer lines in length), you do both of the following:}
|
||||||
|
\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang1033\ql\li360\ri0\lin360\rin0\fi-360\sb0\sa0{\rtlch \ltrch\loch\f5
|
||||||
|
\u8226\'3f}{\rtlch \ltrch\loch\loch\f5
|
||||||
|
\tab a) Give prominent notice with each copy of the object code that the Library is used in it and that the Library and its use are covered by this License.}
|
||||||
|
\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang1033\ql\li360\ri0\lin360\rin0\fi-360\sb0\sa0{\rtlch \ltrch\loch\f5
|
||||||
|
\u8226\'3f}{\rtlch \ltrch\loch\loch\f5
|
||||||
|
\tab b) Accompany the object code with a copy of the GNU GPL and this license document.}
|
||||||
|
\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang1033\ql\li0\ri0\lin0\rin0\fi0\sb0\sa180{\b\rtlch \ltrch\loch\fs24\loch\f5
|
||||||
|
4. Combined Works.}
|
||||||
|
\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang1033\ql\li0\ri0\lin0\rin0\fi0\sb0\sa180{\rtlch \ltrch\loch\loch\f5
|
||||||
|
You may convey a Combined Work under terms of your choice that, taken together, effectively do not restrict modification of the portions of the Library contained in the Combined Work and reverse engineering for debugging such modifications, if you also do each of the following:}
|
||||||
|
\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang1033\ql\li360\ri0\lin360\rin0\fi-360\sb0\sa0{\rtlch \ltrch\loch\f5
|
||||||
|
\u8226\'3f}{\rtlch \ltrch\loch\loch\f5
|
||||||
|
\tab a) Give prominent notice with each copy of the Combined Work that the Library is used in it and that the Library and its use are covered by this License.}
|
||||||
|
\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang1033\ql\li360\ri0\lin360\rin0\fi-360\sb0\sa0{\rtlch \ltrch\loch\f5
|
||||||
|
\u8226\'3f}{\rtlch \ltrch\loch\loch\f5
|
||||||
|
\tab b) Accompany the Combined Work with a copy of the GNU GPL and this license document.}
|
||||||
|
\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang1033\ql\li360\ri0\lin360\rin0\fi-360\sb0\sa0{\rtlch \ltrch\loch\f5
|
||||||
|
\u8226\'3f}{\rtlch \ltrch\loch\loch\f5
|
||||||
|
\tab c) For a Combined Work that displays copyright notices during execution, include the copyright notice for the Library among these notices, as well as a reference directing the user to the copies of the GNU GPL and this license document.}
|
||||||
|
\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang1033\ql\li360\ri0\lin360\rin0\fi-360\sb0\sa0{\rtlch \ltrch\loch\f5
|
||||||
|
\u8226\'3f}{\rtlch \ltrch\loch\loch\f5
|
||||||
|
\tab d) Do one of the following:}
|
||||||
|
\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang1033\ql\li720\ri0\lin720\rin0\fi-360\sb0\sa0{\rtlch \ltrch\loch\f5
|
||||||
|
\u8211\'3f}{\rtlch \ltrch\loch\loch\f5
|
||||||
|
\tab 0) Convey the Minimal Corresponding Source under the terms of this License, and the Corresponding Application Code in a form suitable for, and under terms that permit, the user to recombine or relink the Application with a modified version of the Linked Version to produce a modified Combined Work, in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source.}
|
||||||
|
\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang1033\ql\li720\ri0\lin720\rin0\fi-360\sb0\sa0{\rtlch \ltrch\loch\f5
|
||||||
|
\u8211\'3f}{\rtlch \ltrch\loch\loch\f5
|
||||||
|
\tab 1) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (a) uses at run time a copy of the Library already present on the user's computer system, and (b) will operate properly with a modified version of the Library that is interface-compatible with the Linked Version.}
|
||||||
|
\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang1033\ql\li360\ri0\lin360\rin0\fi-360\sb0\sa0{\rtlch \ltrch\loch\f5
|
||||||
|
\u8226\'3f}{\rtlch \ltrch\loch\loch\f5
|
||||||
|
\tab e) Provide Installation Information, but only if you would otherwise be required to provide such information under section 6 of the GNU GPL, and only to the extent that such information is necessary to install and execute a modified version of the Combined Work produced by recombining or relinking the Application with a modified version of the Linked Version. (If you use option 4d0, the Installation Information must accompany the Minimal Corresponding Source and Corresponding Application Code. If you use option 4d1, you must provide the Installation Information in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source.)}
|
||||||
|
\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang1033\ql\li0\ri0\lin0\rin0\fi0\sb0\sa180{\b\rtlch \ltrch\loch\fs24\loch\f5
|
||||||
|
5. Combined Libraries.}
|
||||||
|
\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang1033\ql\li0\ri0\lin0\rin0\fi0\sb0\sa180{\rtlch \ltrch\loch\loch\f5
|
||||||
|
You may place library facilities that are a work based on the Library side by side in a single library together with other library facilities that are not Applications and are not covered by this License, and convey such a combined library under terms of your choice, if you do both of the following:}
|
||||||
|
\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang1033\ql\li360\ri0\lin360\rin0\fi-360\sb0\sa0{\rtlch \ltrch\loch\f5
|
||||||
|
\u8226\'3f}{\rtlch \ltrch\loch\loch\f5
|
||||||
|
\tab a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities, conveyed under the terms of this License.}
|
||||||
|
\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang1033\ql\li360\ri0\lin360\rin0\fi-360\sb0\sa0{\rtlch \ltrch\loch\f5
|
||||||
|
\u8226\'3f}{\rtlch \ltrch\loch\loch\f5
|
||||||
|
\tab b) Give prominent notice with the combined library that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work.}
|
||||||
|
\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang1033\ql\li0\ri0\lin0\rin0\fi0\sb0\sa180{\b\rtlch \ltrch\loch\fs24\loch\f5
|
||||||
|
6. Revised Versions of the GNU Lesser General Public License.}
|
||||||
|
\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang1033\ql\li0\ri0\lin0\rin0\fi0\sb0\sa180{\rtlch \ltrch\loch\loch\f5
|
||||||
|
The Free Software Foundation may publish revised and/or new versions of the GNU Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.}
|
||||||
|
\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang1033\ql\li0\ri0\lin0\rin0\fi0\sb0\sa180{\rtlch \ltrch\loch\loch\f5
|
||||||
|
Each version is given a distinguishing version number. If the Library as you received it specifies that a certain numbered version of the GNU Lesser General Public License \uc2 \u8220\'81\'67or any later version\u8221\'81\'68 applies to it, you have the option of following the terms and conditions either of that published version or of any later version published by the Free Software Foundation. If the Library as you received it does not specify a version number of the GNU Lesser General Public License, you may choose any version of the GNU Lesser General Public License ever published by the Free Software Foundation.\uc1 }
|
||||||
|
\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang1033\ql\li0\ri0\lin0\rin0\fi0\sb0\sa180{\rtlch \ltrch\loch\loch\f5
|
||||||
|
If the Library as you received it specifies that a proxy can decide whether future versions of the GNU Lesser General Public License shall apply, that proxy's public statement of acceptance of any version is permanent authorization for you to choose that version for the Library.}
|
||||||
|
\par }
|
2
package/qt.conf
Normal file
2
package/qt.conf
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
[Platforms]
|
||||||
|
WindowsArguments = fontengine=freetype
|
BIN
package/wix_banner.png
Normal file
BIN
package/wix_banner.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.5 KiB |
BIN
package/wix_dialog.png
Normal file
BIN
package/wix_dialog.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
BIN
pics/main2.png
Normal file
BIN
pics/main2.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 218 KiB |
26
privacy_policy.md
Normal file
26
privacy_policy.md
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
# Privacy Policy
|
||||||
|
|
||||||
|
## Introduction
|
||||||
|
Welcome to VNote! We value your privacy and are committed to protecting your personal information. This Privacy Policy explains how we handle your information when you use our application.
|
||||||
|
|
||||||
|
## Information We Collect
|
||||||
|
VNote does not collect any personal or usage data from its users. Your interactions with the app remain private and are not stored or shared.
|
||||||
|
|
||||||
|
## How We Use Your Information
|
||||||
|
Since VNote does not collect any user data, we do not use, store, or process any personal information.
|
||||||
|
|
||||||
|
## Sharing Your Information
|
||||||
|
As VNote does not collect any user data, we do not share any personal information with third parties.
|
||||||
|
|
||||||
|
## Security
|
||||||
|
While VNote does not collect any user data, we still implement security measures to ensure the integrity and safety of the application itself.
|
||||||
|
|
||||||
|
## Your Choices
|
||||||
|
Since no data is collected, there are no choices or actions required from users regarding their personal information.
|
||||||
|
|
||||||
|
## Children's Privacy
|
||||||
|
Our services are not intended for children under the age of 13. We do not knowingly collect personal information from children under 13.
|
||||||
|
|
||||||
|
## Changes to This Privacy Policy
|
||||||
|
We may update this Privacy Policy from time to time. We will notify you of any changes by posting the new Privacy Policy on our app. You are advised to review this Privacy Policy periodically for any changes.
|
||||||
|
|
@ -7,8 +7,14 @@ if len(sys.argv) < 2:
|
|||||||
exit
|
exit
|
||||||
|
|
||||||
newVersion = sys.argv[1]
|
newVersion = sys.argv[1]
|
||||||
|
shortVersion = re.match('^(\\d+\\.\\d+).', newVersion).group(1)
|
||||||
print("New version: {0}".format(newVersion))
|
print("New version: {0}".format(newVersion))
|
||||||
|
|
||||||
|
# CMakeList
|
||||||
|
regExp = re.compile('(\\s+)VERSION \\S+')
|
||||||
|
for line in fileinput.input(['CMakeLists.txt'], inplace = True):
|
||||||
|
print(regExp.sub('\\1VERSION ' + newVersion, line), end='')
|
||||||
|
|
||||||
# vnotex.json
|
# vnotex.json
|
||||||
regExp = re.compile('(\\s+)"version" : "\\S+"')
|
regExp = re.compile('(\\s+)"version" : "\\S+"')
|
||||||
for line in fileinput.input(['src/data/core/vnotex.json'], inplace = True):
|
for line in fileinput.input(['src/data/core/vnotex.json'], inplace = True):
|
||||||
@ -20,6 +26,10 @@ for line in fileinput.input(['.github/workflows/ci-win.yml', '.github/workflows/
|
|||||||
print(regExp.sub('\\1VNOTE_VER: ' + newVersion, line), end='')
|
print(regExp.sub('\\1VNOTE_VER: ' + newVersion, line), end='')
|
||||||
|
|
||||||
# Info.plist
|
# Info.plist
|
||||||
|
regExp = re.compile('(\\s+)<string>(?!10\\.15)\\d+\\.\\d+</string>')
|
||||||
|
for line in fileinput.input(['src/data/core/Info.plist'], inplace = True):
|
||||||
|
print(regExp.sub('\\1<string>' + shortVersion + '</string>', line), end='')
|
||||||
|
|
||||||
regExp = re.compile('(\\s+)<string>\\d+\\.\\d+\\.\\d+</string>')
|
regExp = re.compile('(\\s+)<string>\\d+\\.\\d+\\.\\d+</string>')
|
||||||
for line in fileinput.input(['src/data/core/Info.plist'], inplace = True):
|
for line in fileinput.input(['src/data/core/Info.plist'], inplace = True):
|
||||||
print(regExp.sub('\\1<string>' + newVersion + '</string>', line), end='')
|
print(regExp.sub('\\1<string>' + newVersion + '</string>', line), end='')
|
||||||
|
179
src/CMakeLists.txt
Normal file
179
src/CMakeLists.txt
Normal file
@ -0,0 +1,179 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.20)
|
||||||
|
|
||||||
|
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||||
|
|
||||||
|
set(CMAKE_INSTALL_BINDIR "." CACHE STRING "Binary dir for install")
|
||||||
|
|
||||||
|
set(QT_DEFAULT_MAJOR_VERSION 6 CACHE STRING "Qt version to use (5 or 6), defaults to 6")
|
||||||
|
find_package(Qt${QT_DEFAULT_MAJOR_VERSION} REQUIRED COMPONENTS Core Gui Network PrintSupport Sql Svg Widgets WebChannel WebEngineWidgets LinguistTools)
|
||||||
|
find_package(Qt${QT_DEFAULT_MAJOR_VERSION} OPTIONAL_COMPONENTS Core5Compat)
|
||||||
|
|
||||||
|
if ((QT_DEFAULT_MAJOR_VERSION GREATER 5))
|
||||||
|
qt_standard_project_setup()
|
||||||
|
else()
|
||||||
|
set(CMAKE_AUTOMOC ON)
|
||||||
|
set(CMAKE_AUTORCC ON)
|
||||||
|
set(CMAKE_AUTOUIC ON)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Application icon on Windows
|
||||||
|
set(VX_APP_ICON_RC_WIN data/core/icons/vnote.rc)
|
||||||
|
|
||||||
|
# The MACOSX_BUNDLE_ICON_FILE variable is added to the Info.plist
|
||||||
|
# generated by CMake. This variable contains the .icns file name,
|
||||||
|
# without the path.
|
||||||
|
set(MACOSX_BUNDLE_ICON_FILE vnote.icns)
|
||||||
|
# And the following tells CMake where to find and install the file itself.
|
||||||
|
set(VX_APP_ICON_MACOS data/core/icons/vnote.icns)
|
||||||
|
set_source_files_properties(${VX_APP_ICON_MACOS} PROPERTIES
|
||||||
|
MACOSX_PACKAGE_LOCATION "Resources")
|
||||||
|
|
||||||
|
# Translations
|
||||||
|
set(VX_TS_FILES data/core/translations/vnote_zh_CN.ts
|
||||||
|
data/core/translations/vnote_ja.ts)
|
||||||
|
if((QT_DEFAULT_MAJOR_VERSION EQUAL 6))
|
||||||
|
if((Qt6Widgets_VERSION VERSION_GREATER_EQUAL 6.7.0))
|
||||||
|
qt_add_lupdate(TS_FILES ${VX_TS_FILES}
|
||||||
|
SOURCE_TARGETS vnote)
|
||||||
|
else()
|
||||||
|
qt_add_lupdate(vnote TS_FILES ${VX_TS_FILES})
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
# Generate .qm files from .ts files (lrelease)
|
||||||
|
set_source_files_properties(${VX_TS_FILES} PROPERTIES
|
||||||
|
OUTPUT_LOCATION "${CMAKE_CURRENT_BINARY_DIR}/translations")
|
||||||
|
qt_add_translation(VX_QM_FILES ${VX_TS_FILES})
|
||||||
|
add_custom_target(lrelease DEPENDS ${VX_QM_FILES})
|
||||||
|
|
||||||
|
# TODO: VTextEdit translations
|
||||||
|
list(APPEND VX_QM_FILES
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/data/core/translations/qdialogbuttonbox_zh_CN.qm
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/data/core/translations/qtbase_ja.qm
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/data/core/translations/qtbase_zh_CN.qm
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/data/core/translations/qtv_ja.qm
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/data/core/translations/qtv_zh_CN.qm
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/data/core/translations/qwebengine_zh_CN.qm
|
||||||
|
)
|
||||||
|
|
||||||
|
# Resources
|
||||||
|
set(VX_RESOURCE_FILES data/core/core.qrc)
|
||||||
|
set(VX_EXTRA_RESOURCE_FILES_RCC ${CMAKE_CURRENT_BINARY_DIR}/vnote_extra.rcc)
|
||||||
|
qt_add_binary_resources(VX_EXTRA_RESOURCE data/extra/extra.qrc DESTINATION ${VX_EXTRA_RESOURCE_FILES_RCC} OPTIONS -compress 9)
|
||||||
|
|
||||||
|
add_executable(vnote WIN32 MACOSX_BUNDLE
|
||||||
|
application.cpp application.h
|
||||||
|
commandlineoptions.cpp commandlineoptions.h
|
||||||
|
fakeaccessible.cpp fakeaccessible.h
|
||||||
|
main.cpp
|
||||||
|
${VX_APP_ICON_RC_WIN} ${VX_APP_ICON_MACOS} ${VX_RESOURCE_FILES}
|
||||||
|
)
|
||||||
|
|
||||||
|
add_dependencies(vnote VX_EXTRA_RESOURCE)
|
||||||
|
|
||||||
|
set(VX_LIBS_FOLDER ../libs)
|
||||||
|
target_include_directories(vnote PRIVATE
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
|
)
|
||||||
|
|
||||||
|
find_program(GOLD_LINKER "ld.gold")
|
||||||
|
if (NOT ${GOLD_LINKER} STREQUAL GOLD_LINKER-NOTFOUND)
|
||||||
|
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fuse-ld=gold")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
target_compile_definitions(vnote PRIVATE
|
||||||
|
QT_MESSAGELOGCONTEXT
|
||||||
|
)
|
||||||
|
|
||||||
|
add_subdirectory(core)
|
||||||
|
add_subdirectory(export)
|
||||||
|
add_subdirectory(imagehost)
|
||||||
|
add_subdirectory(search)
|
||||||
|
add_subdirectory(snippet)
|
||||||
|
add_subdirectory(task)
|
||||||
|
add_subdirectory(unitedentry)
|
||||||
|
add_subdirectory(utils)
|
||||||
|
add_subdirectory(widgets)
|
||||||
|
|
||||||
|
target_link_libraries(vnote PRIVATE
|
||||||
|
Qt::Core
|
||||||
|
Qt::Gui
|
||||||
|
Qt::Network
|
||||||
|
Qt::PrintSupport
|
||||||
|
Qt::Sql
|
||||||
|
Qt::Svg
|
||||||
|
Qt::WebChannel
|
||||||
|
Qt::WebEngineWidgets
|
||||||
|
Qt::Widgets
|
||||||
|
VTextEdit
|
||||||
|
qhotkey
|
||||||
|
)
|
||||||
|
|
||||||
|
if((QT_DEFAULT_MAJOR_VERSION GREATER 5))
|
||||||
|
target_link_libraries(vnote PRIVATE
|
||||||
|
Qt::Core5Compat
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Copy the qt.conf on Windows
|
||||||
|
if(WIN32)
|
||||||
|
add_custom_command(TARGET vnote POST_BUILD
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||||
|
"${PROJECT_SOURCE_DIR}/package/qt.conf" $<TARGET_FILE_DIR:vnote>)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Installation
|
||||||
|
if (WIN32)
|
||||||
|
install(TARGETS vnote RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||||
|
install(FILES "${PROJECT_SOURCE_DIR}/package/qt.conf" DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||||
|
install(FILES ${VX_EXTRA_RESOURCE_FILES_RCC} DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||||
|
install(FILES ${VX_QM_FILES} DESTINATION "${CMAKE_INSTALL_BINDIR}/translations" OPTIONAL)
|
||||||
|
elseif(APPLE)
|
||||||
|
set(CMAKE_MACOSX_RPATH ON)
|
||||||
|
|
||||||
|
# TODO: declare install for macOS if necessary. For packing, we will manually copy files into
|
||||||
|
# the src/vnote.app bundle.
|
||||||
|
|
||||||
|
# The generated Info.plist will be overridden.
|
||||||
|
set_target_properties(vnote
|
||||||
|
PROPERTIES
|
||||||
|
OUTPUT_NAME "${PROJECT_NAME}"
|
||||||
|
MACOSX_BUNDLE_BUNDLE_NAME "${PROJECT_NAME}"
|
||||||
|
MACOSX_BUNDLE_INFO_STRING "${PROJECT_DESCRIPTION}"
|
||||||
|
MACOSX_BUNDLE_GUI_IDENTIFIER "fun.vnote.vnote"
|
||||||
|
MACOSX_BUNDLE_LONG_VERSION_STRING "${PROJECT_VERSION}"
|
||||||
|
MACOSX_BUNDLE_SHORT_VERSION_STRING "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}"
|
||||||
|
MACOSX_BUNDLE_BUNDLE_VERSION "${PROJECT_VERSION}"
|
||||||
|
MACOSX_BUNDLE_COPYRIGHT "Distributed under LGPL-3.0 license. Copyright (c) 2024 app.vnote.fun"
|
||||||
|
)
|
||||||
|
else()
|
||||||
|
install(TARGETS vnote
|
||||||
|
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||||
|
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||||
|
)
|
||||||
|
install(FILES ${VX_EXTRA_RESOURCE_FILES_RCC} DESTINATION ${CMAKE_INSTALL_DATADIR})
|
||||||
|
install(FILES ${VX_QM_FILES} DESTINATION "${CMAKE_INSTALL_DATADIR}/translations" OPTIONAL)
|
||||||
|
|
||||||
|
set(desktop.path applications)
|
||||||
|
set(desktop.files data/core/vnote.desktop)
|
||||||
|
set(icon16.path icons/hicolor/16x16/apps)
|
||||||
|
set(icon16.files data/core/logo/16x16/vnote.png)
|
||||||
|
set(icon32.path icons/hicolor/32x32/apps)
|
||||||
|
set(icon32.files data/core/logo/32x32/vnote.png)
|
||||||
|
set(icon48.path icons/hicolor/48x48/apps)
|
||||||
|
set(icon48.files data/core/logo/48x48/vnote.png)
|
||||||
|
set(icon64.path icons/hicolor/64x64/apps)
|
||||||
|
set(icon64.files data/core/logo/64x64/vnote.png)
|
||||||
|
set(icon128.path icons/hicolor/128x128/apps)
|
||||||
|
set(icon128.files data/core/logo/128x128/vnote.png)
|
||||||
|
set(icon256.path icons/hicolor/256x256/apps)
|
||||||
|
set(icon256.files data/core/logo/256x256/vnote.png)
|
||||||
|
set(iconsvg.path icons/hicolor/scalable/apps)
|
||||||
|
set(iconsvg.files data/core/logo/vnote.svg)
|
||||||
|
foreach(item IN ITEMS desktop icon16 icon32 icon48 icon64 icon128 icon256 iconsvg)
|
||||||
|
install(FILES ${CMAKE_CURRENT_LIST_DIR}/${${item}.files}
|
||||||
|
DESTINATION ${CMAKE_INSTALL_DATADIR}/${${item}.path}
|
||||||
|
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ)
|
||||||
|
endforeach()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
include(${CMAKE_CURRENT_LIST_DIR}/Packaging.cmake)
|
16
src/CPackLinuxDeployQt.cmake.in
Normal file
16
src/CPackLinuxDeployQt.cmake.in
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
message(STATUS "VX_APPIMAGE_DEST_DIR ${VX_APPIMAGE_DEST_DIR}")
|
||||||
|
message(STATUS "VX_APPIMAGE_DESKTOP_FILE ${VX_APPIMAGE_DESKTOP_FILE}")
|
||||||
|
|
||||||
|
execute_process(
|
||||||
|
COMMAND ${CMAKE_MAKE_PROGRAM} DESTDIR=${VX_APPIMAGE_DEST_DIR} install
|
||||||
|
WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
|
||||||
|
execute_process(
|
||||||
|
COMMAND env QMAKE=${QMAKE_EXECUTABLE} LD_LIBRARY_PATH=/usr/local/lib64:$ENV{LD_LIBRARY_PATH} "${LINUXDEPLOY_EXECUTABLE}" --plugin=qt --output=appimage
|
||||||
|
--appdir=${VX_APPIMAGE_DEST_DIR} -e ${CMAKE_CURRENT_BINARY_DIR}/vnote -d ${VX_APPIMAGE_DESKTOP_FILE}
|
||||||
|
-i ${CMAKE_CURRENT_LIST_DIR}/data/core/logo/64x64/vnote.png
|
||||||
|
-l ${QT_PLUGINS_DIR}/platformthemes/libqgtk3.so
|
||||||
|
-l /usr/local/lib64/libcrypto.so.3
|
||||||
|
-l /usr/local/lib64/libssl.so.3
|
||||||
|
# --exclude-library option does not work as expected
|
||||||
|
# --exclude-library=libssl.so.1.1,libcrypto.so.1.1,libnss3.so,libnssutil3.so
|
||||||
|
WORKING_DIRECTORY ${CPACK_PACKAGE_DIRECTORY})
|
6
src/CPackMacDeployQt.cmake.in
Normal file
6
src/CPackMacDeployQt.cmake.in
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
execute_process(COMMAND "optool" strip -t ${CMAKE_CURRENT_BINARY_DIR}/VNote.app
|
||||||
|
WORKING_DIRECTORY ${CPACK_PACKAGE_DIRECTORY}
|
||||||
|
)
|
||||||
|
execute_process(COMMAND "${MACDEPLOYQT_EXECUTABLE}" ${CMAKE_CURRENT_BINARY_DIR}/VNote.app -always-overwrite -verbose=1
|
||||||
|
WORKING_DIRECTORY ${CPACK_PACKAGE_DIRECTORY}
|
||||||
|
)
|
165
src/Packaging.cmake
Normal file
165
src/Packaging.cmake
Normal file
@ -0,0 +1,165 @@
|
|||||||
|
# from: https://github.com/miurahr/cmake-qt-packaging-example
|
||||||
|
find_package(Qt${QT_DEFAULT_MAJOR_VERSION} REQUIRED COMPONENTS Core)
|
||||||
|
|
||||||
|
get_target_property(QMAKE_EXECUTABLE Qt::qmake IMPORTED_LOCATION)
|
||||||
|
get_filename_component(QT_BIN_DIR "${QMAKE_EXECUTABLE}" DIRECTORY)
|
||||||
|
execute_process(COMMAND ${QMAKE_EXECUTABLE} -query QT_VERSION OUTPUT_VARIABLE QT_VERSION)
|
||||||
|
|
||||||
|
set(QT_TOOLS_DIR "${QT_BIN_DIR}/../../../Tools")
|
||||||
|
cmake_path(NORMAL_PATH QT_TOOLS_DIR OUTPUT_VARIABLE QT_TOOLS_DIR)
|
||||||
|
|
||||||
|
set(QT_PLUGINS_DIR "${QT_BIN_DIR}/../plugins")
|
||||||
|
cmake_path(NORMAL_PATH QT_PLUGINS_DIR OUTPUT_VARIABLE QT_PLUGINS_DIR)
|
||||||
|
|
||||||
|
# To use the specific version of Qt
|
||||||
|
set(WINDEPLOYQT_EXECUTABLE "${QT_BIN_DIR}/windeployqt.exe")
|
||||||
|
|
||||||
|
find_program(LINUXDEPLOY_EXECUTABLE linuxdeploy linuxdeploy-x86_64.AppImage HINTS "${QT_BIN_DIR}")
|
||||||
|
find_program(MACDEPLOYQT_EXECUTABLE macdeployqt HINTS "${QT_BIN_DIR}")
|
||||||
|
find_program(MACDEPLOYQTFIX_EXECUTABLE macdeployqtfix.py HINTS "${QT_BIN_DIR}")
|
||||||
|
find_package(Python)
|
||||||
|
|
||||||
|
function(windeployqt target)
|
||||||
|
# Bundle Library Files
|
||||||
|
string(TOUPPER ${CMAKE_BUILD_TYPE} CMAKE_BUILD_TYPE_UPPER)
|
||||||
|
|
||||||
|
if ((QT_DEFAULT_MAJOR_VERSION GREATER 5))
|
||||||
|
if(CMAKE_BUILD_TYPE_UPPER STREQUAL "DEBUG")
|
||||||
|
set(WINDEPLOYQT_ARGS --debug)
|
||||||
|
else()
|
||||||
|
set(WINDEPLOYQT_ARGS --release)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
add_custom_target(deploy
|
||||||
|
COMMAND "${CMAKE_COMMAND}" -E remove_directory "${CMAKE_CURRENT_BINARY_DIR}/winqt/"
|
||||||
|
COMMAND "${CMAKE_COMMAND}" -E
|
||||||
|
env PATH="${QT_BIN_DIR}" "${WINDEPLOYQT_EXECUTABLE}"
|
||||||
|
${WINDEPLOYQT_ARGS}
|
||||||
|
--no-quick-import
|
||||||
|
--no-opengl-sw
|
||||||
|
--no-compiler-runtime
|
||||||
|
--translations zh_CN,ja
|
||||||
|
--dir "${CMAKE_CURRENT_BINARY_DIR}/winqt/"
|
||||||
|
$<TARGET_FILE:${target}>
|
||||||
|
COMMAND "${CMAKE_COMMAND}" -E remove_directory "${CMAKE_CURRENT_BINARY_DIR}/winqt/generic/"
|
||||||
|
COMMAND "${CMAKE_COMMAND}" -E remove_directory "${CMAKE_CURRENT_BINARY_DIR}/winqt/styles/"
|
||||||
|
COMMAND "${CMAKE_COMMAND}" -E remove_directory "${CMAKE_CURRENT_BINARY_DIR}/winqt/qmltooling/"
|
||||||
|
COMMENT "Deploying Qt..."
|
||||||
|
DEPENDS vnote lrelease
|
||||||
|
)
|
||||||
|
|
||||||
|
add_dependencies(pack deploy)
|
||||||
|
|
||||||
|
install(DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/winqt/" DESTINATION "${CMAKE_INSTALL_BINDIR}" OPTIONAL)
|
||||||
|
|
||||||
|
set(OPENSSL_ROOT_DIR "${QT_TOOLS_DIR}/OpenSSL/Win_x64" CACHE STRING "OpenSSL dir")
|
||||||
|
file(GLOB OPENSSL_LIBS_FILES "${OPENSSL_ROOT_DIR}/bin/lib*.dll")
|
||||||
|
cmake_path(NORMAL_PATH OPENSSL_LIBS_FILES OUTPUT_VARIABLE OPENSSL_LIBS_FILES)
|
||||||
|
install(FILES ${OPENSSL_LIBS_FILES} DESTINATION "${CMAKE_INSTALL_BINDIR}" OPTIONAL)
|
||||||
|
|
||||||
|
message(STATUS "OpenSSLExtraLIBDIR:${OPENSSL_EXTRA_LIB_DIR}")
|
||||||
|
file(GLOB OPENSSL_EXTRA_LIB_FILES "${OPENSSL_EXTRA_LIB_DIR}/lib*.dll")
|
||||||
|
cmake_path(NORMAL_PATH OPENSSL_EXTRA_LIB_FILES OUTPUT_VARIABLE OPENSSL_EXTRA_LIB_FILES)
|
||||||
|
message(STATUS "OpenSSLExtraLibFiles:${OPENSSL_EXTRA_LIB_FILES}")
|
||||||
|
install(FILES ${OPENSSL_EXTRA_LIB_FILES} DESTINATION "${CMAKE_INSTALL_BINDIR}" OPTIONAL)
|
||||||
|
|
||||||
|
set(CMAKE_INSTALL_UCRT_LIBRARIES TRUE)
|
||||||
|
include(InstallRequiredSystemLibraries)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
set(CPACK_PACKAGE_VENDOR "VNoteX")
|
||||||
|
set(CPACK_PACKAGE_NAME ${PROJECT_NAME})
|
||||||
|
set(CPACK_PACKAGE_CONTACT "Le Tan <tamlokveer@gmail.com>")
|
||||||
|
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "${PROJECT_DESCRIPTION}")
|
||||||
|
set(CPACK_PACKAGE_DESCRIPTION_FILE "${PROJECT_SOURCE_DIR}/README.md")
|
||||||
|
set(CPACK_RESOURCE_FILE_LICENSE "${PROJECT_SOURCE_DIR}/COPYING.LESSER")
|
||||||
|
set(CPACK_PACKAGE_VERSION_MAJOR ${PROJECT_VERSION_MAJOR})
|
||||||
|
set(CPACK_PACKAGE_VERSION_MINOR ${PROJECT_VERSION_MINOR})
|
||||||
|
set(CPACK_PACKAGE_VERSION_PATCH ${PROJECT_VERSION_PATCH})
|
||||||
|
|
||||||
|
set(CPACK_PACKAGE_INSTALL_DIRECTORY "${PROJECT_NAME}")
|
||||||
|
set(CPACK_PACKAGE_DIRECTORY "${CMAKE_BINARY_DIR}")
|
||||||
|
|
||||||
|
# Start menu entry on Windows
|
||||||
|
set(CPACK_PACKAGE_EXECUTABLES "vnote" "VNote")
|
||||||
|
# Desktop link on Windows
|
||||||
|
set(CPACK_CREATE_DESKTOP_LINKS "vnote")
|
||||||
|
|
||||||
|
set(CPACK_STRIP_FILES TRUE)
|
||||||
|
|
||||||
|
# WIX generator
|
||||||
|
set(CPACK_WIX_UPGRADE_GUID BA25F337-991A-4893-9D8A-AD5E89BAF5C4)
|
||||||
|
set(CPACK_WIX_PRODUCT_GUID BA25F337-991A-4893-9D8A-AD5E89BAF5C4)
|
||||||
|
set(CPACK_WIX_LICENSE_RTF "${PROJECT_SOURCE_DIR}/package/lgpl-3.0.rtf")
|
||||||
|
set(CPACK_WIX_PRODUCT_ICON "${CMAKE_CURRENT_LIST_DIR}/data/core/icons/vnote.ico")
|
||||||
|
set(CPACK_WIX_UI_BANNER "${PROJECT_SOURCE_DIR}/package/wix_banner.png")
|
||||||
|
set(CPACK_WIX_UI_DIALOG "${PROJECT_SOURCE_DIR}/package/wix_dialog.png")
|
||||||
|
|
||||||
|
#------------------------------------------------------------------------------
|
||||||
|
# include CPack, so we get target for packages
|
||||||
|
set(CPACK_OUTPUT_CONFIG_FILE "${CMAKE_BINARY_DIR}/BundleConfig.cmake")
|
||||||
|
|
||||||
|
add_custom_target(pack
|
||||||
|
COMMAND ${CMAKE_CPACK_COMMAND} "--config" "${CMAKE_BINARY_DIR}/BundleConfig.cmake" "--verbose"
|
||||||
|
COMMENT "Running CPACK. Please wait..."
|
||||||
|
DEPENDS vnote)
|
||||||
|
add_dependencies(pack lrelease)
|
||||||
|
|
||||||
|
set(CPACK_GENERATOR)
|
||||||
|
|
||||||
|
set(CPACK_PACKAGE_ICON "${CMAKE_CURRENT_LIST_DIR}/data/core/logo/64x64/vnote.png")
|
||||||
|
|
||||||
|
if(WIN32)
|
||||||
|
find_program(WINDEPLOYQT_EXECUTABLE windeployqt HINTS "${QT_BIN_DIR}" DOC "Path to the windeployqt utility")
|
||||||
|
|
||||||
|
list(APPEND CPACK_GENERATOR ZIP)
|
||||||
|
message(STATUS "Package generation - Windows - Zip")
|
||||||
|
|
||||||
|
find_program(WIX_EXECUTABLE wix HINTS "${QT_BIN_DIR}" DOC "Path to the WiX utility")
|
||||||
|
|
||||||
|
if (NOT WIX_EXECUTABLE-NOTFOUND)
|
||||||
|
list(APPEND CPACK_GENERATOR WIX)
|
||||||
|
message(STATUS "Package generation - Windows - WiX")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
windeployqt(vnote)
|
||||||
|
elseif(APPLE)
|
||||||
|
# Manually copy resources.
|
||||||
|
set(VX_BUNDLE_CONTENTS_DIR $<TARGET_FILE_DIR:vnote>/..)
|
||||||
|
add_custom_target(deploy
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||||
|
"${CMAKE_CURRENT_LIST_DIR}/data/core/Info.plist" ${VX_BUNDLE_CONTENTS_DIR}
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||||
|
${VX_EXTRA_RESOURCE_FILES_RCC} ${VX_BUNDLE_CONTENTS_DIR}/Resources
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E make_directory ${VX_BUNDLE_CONTENTS_DIR}/Resources/translations
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||||
|
${VX_QM_FILES} ${VX_BUNDLE_CONTENTS_DIR}/Resources/translations
|
||||||
|
COMMENT "Copying resources into bundle Contents ${VX_BUNDLE_CONTENTS_DIR}"
|
||||||
|
DEPENDS vnote lrelease
|
||||||
|
)
|
||||||
|
add_dependencies(pack deploy)
|
||||||
|
|
||||||
|
message(STATUS "MACDeployQtExecutable: ${MACDEPLOYQT_EXECUTABLE}")
|
||||||
|
if (MACDEPLOYQT_EXECUTABLE)
|
||||||
|
message(STATUS "Package generation - MacOS - DMG")
|
||||||
|
|
||||||
|
list(APPEND CPACK_GENERATOR External)
|
||||||
|
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/CPackMacDeployQt.cmake.in "${CMAKE_BINARY_DIR}/CPackExternal.cmake")
|
||||||
|
set(CPACK_EXTERNAL_PACKAGE_SCRIPT "${CMAKE_BINARY_DIR}/CPackExternal.cmake")
|
||||||
|
include(InstallRequiredSystemLibraries)
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
message(STATUS "LinuxDeployExecutable: ${LINUXDEPLOY_EXECUTABLE}")
|
||||||
|
if(LINUXDEPLOY_EXECUTABLE)
|
||||||
|
message(STATUS "Package generation - Linux - AppImage")
|
||||||
|
|
||||||
|
list(APPEND CPACK_GENERATOR External)
|
||||||
|
set(VX_APPIMAGE_DEST_DIR "${CPACK_PACKAGE_DIRECTORY}/_CPack_Packages/Linux/External/AppImage")
|
||||||
|
set(VX_APPIMAGE_DESKTOP_FILE "${VX_APPIMAGE_DEST_DIR}${CMAKE_INSTALL_PREFIX}/share/applications/vnote.desktop")
|
||||||
|
configure_file(${CMAKE_CURRENT_LIST_DIR}/CPackLinuxDeployQt.cmake.in "${CMAKE_BINARY_DIR}/CPackExternal.cmake")
|
||||||
|
set(CPACK_EXTERNAL_PACKAGE_SCRIPT "${CMAKE_BINARY_DIR}/CPackExternal.cmake")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
include(CPack)
|
@ -2,6 +2,11 @@
|
|||||||
|
|
||||||
#include <QFileOpenEvent>
|
#include <QFileOpenEvent>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
#include <QDir>
|
||||||
|
#include <QStyle>
|
||||||
|
#include <QFileSystemWatcher>
|
||||||
|
#include <QTimer>
|
||||||
|
#include <core/vnotex.h>
|
||||||
|
|
||||||
using namespace vnotex;
|
using namespace vnotex;
|
||||||
|
|
||||||
@ -10,6 +15,53 @@ Application::Application(int &p_argc, char **p_argv)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Application::watchThemeFolder(const QString &p_themeFolderPath)
|
||||||
|
{
|
||||||
|
if (p_themeFolderPath.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize watchers only when needed
|
||||||
|
if (!m_styleWatcher) {
|
||||||
|
m_styleWatcher = new QFileSystemWatcher(this);
|
||||||
|
}
|
||||||
|
if (!m_reloadTimer) {
|
||||||
|
m_reloadTimer = new QTimer(this);
|
||||||
|
m_reloadTimer->setSingleShot(true);
|
||||||
|
m_reloadTimer->setInterval(500); // 500ms debounce delay
|
||||||
|
connect(m_reloadTimer, &QTimer::timeout,
|
||||||
|
this, &Application::reloadThemeResources);
|
||||||
|
|
||||||
|
// Connect file watcher to timer
|
||||||
|
connect(m_styleWatcher, &QFileSystemWatcher::directoryChanged,
|
||||||
|
m_reloadTimer, qOverload<>(&QTimer::start));
|
||||||
|
connect(m_styleWatcher, &QFileSystemWatcher::fileChanged,
|
||||||
|
m_reloadTimer, qOverload<>(&QTimer::start));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Watch the theme folder and its files
|
||||||
|
m_styleWatcher->addPath(p_themeFolderPath);
|
||||||
|
|
||||||
|
// Also watch individual files in the theme folder
|
||||||
|
QDir themeDir(p_themeFolderPath);
|
||||||
|
QStringList files = themeDir.entryList(QDir::Files);
|
||||||
|
for (const QString &file : files) {
|
||||||
|
m_styleWatcher->addPath(themeDir.filePath(file));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Application::reloadThemeResources()
|
||||||
|
{
|
||||||
|
VNoteX::getInst().getThemeMgr().refreshCurrentTheme();
|
||||||
|
|
||||||
|
auto stylesheet = VNoteX::getInst().getThemeMgr().fetchQtStyleSheet();
|
||||||
|
if (!stylesheet.isEmpty()) {
|
||||||
|
setStyleSheet(stylesheet);
|
||||||
|
style()->unpolish(this);
|
||||||
|
style()->polish(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool Application::event(QEvent *p_event)
|
bool Application::event(QEvent *p_event)
|
||||||
{
|
{
|
||||||
// On macOS, we need this to open file from Finder.
|
// On macOS, we need this to open file from Finder.
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
#ifndef APPLICATION_H
|
#ifndef APPLICATION_H
|
||||||
#define APPLICATION_H
|
#define APPLICATION_H
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
|
|
||||||
|
class QFileSystemWatcher;
|
||||||
|
class QTimer;
|
||||||
|
|
||||||
namespace vnotex
|
namespace vnotex
|
||||||
{
|
{
|
||||||
class Application : public QApplication
|
class Application : public QApplication
|
||||||
@ -11,11 +13,21 @@ namespace vnotex
|
|||||||
public:
|
public:
|
||||||
Application(int &p_argc, char **p_argv);
|
Application(int &p_argc, char **p_argv);
|
||||||
|
|
||||||
|
// Set up theme folder watcher for hot-reload
|
||||||
|
void watchThemeFolder(const QString &p_themeFolderPath);
|
||||||
|
|
||||||
|
// Reload the theme resources (stylesheet, icons, etc)
|
||||||
|
void reloadThemeResources();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void openFileRequested(const QString &p_filePath);
|
void openFileRequested(const QString &p_filePath);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool event(QEvent *p_event) Q_DECL_OVERRIDE;
|
bool event(QEvent *p_event) Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QFileSystemWatcher *m_styleWatcher = nullptr;
|
||||||
|
QTimer *m_reloadTimer = nullptr;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,6 +22,12 @@ CommandLineOptions::ParseResult CommandLineOptions::parse(const QStringList &p_a
|
|||||||
const QCommandLineOption verboseOpt("verbose", MainWindow::tr("Print more logs."));
|
const QCommandLineOption verboseOpt("verbose", MainWindow::tr("Print more logs."));
|
||||||
parser.addOption(verboseOpt);
|
parser.addOption(verboseOpt);
|
||||||
|
|
||||||
|
const QCommandLineOption logStderrOpt("log-stderr", MainWindow::tr("Log to stderr."));
|
||||||
|
parser.addOption(logStderrOpt);
|
||||||
|
|
||||||
|
const QCommandLineOption watchThemesOpt("watch-themes", MainWindow::tr("Watch theme folder for changes."));
|
||||||
|
parser.addOption(watchThemesOpt);
|
||||||
|
|
||||||
// WebEngine options.
|
// WebEngine options.
|
||||||
// No need to handle them. Just add them to the parser to avoid parse error.
|
// No need to handle them. Just add them to the parser to avoid parse error.
|
||||||
{
|
{
|
||||||
@ -63,5 +69,13 @@ CommandLineOptions::ParseResult CommandLineOptions::parse(const QStringList &p_a
|
|||||||
m_verbose = true;
|
m_verbose = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (parser.isSet(logStderrOpt)) {
|
||||||
|
m_logToStderr = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parser.isSet(watchThemesOpt)) {
|
||||||
|
m_watchThemes = true;
|
||||||
|
}
|
||||||
|
|
||||||
return ParseResult::Ok;
|
return ParseResult::Ok;
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,11 @@ public:
|
|||||||
QStringList m_pathsToOpen;
|
QStringList m_pathsToOpen;
|
||||||
|
|
||||||
bool m_verbose = false;
|
bool m_verbose = false;
|
||||||
|
|
||||||
|
bool m_logToStderr = false;
|
||||||
|
|
||||||
|
// Whether to watch theme folder for changes
|
||||||
|
bool m_watchThemes = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // COMMANDLINEOPTIONS_H
|
#endif // COMMANDLINEOPTIONS_H
|
||||||
|
87
src/core/CMakeLists.txt
Normal file
87
src/core/CMakeLists.txt
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
target_sources(vnote PRIVATE
|
||||||
|
buffer/buffer.cpp buffer/buffer.h
|
||||||
|
buffer/bufferprovider.cpp buffer/bufferprovider.h
|
||||||
|
buffer/filebufferprovider.cpp buffer/filebufferprovider.h
|
||||||
|
buffer/filetypehelper.cpp buffer/filetypehelper.h
|
||||||
|
buffer/ibufferfactory.h
|
||||||
|
buffer/markdownbuffer.cpp buffer/markdownbuffer.h
|
||||||
|
buffer/markdownbufferfactory.cpp buffer/markdownbufferfactory.h
|
||||||
|
buffer/mindmapbuffer.cpp buffer/mindmapbuffer.h
|
||||||
|
buffer/mindmapbufferfactory.cpp buffer/mindmapbufferfactory.h
|
||||||
|
buffer/nodebufferprovider.cpp buffer/nodebufferprovider.h
|
||||||
|
buffer/pdfbuffer.cpp buffer/pdfbuffer.h
|
||||||
|
buffer/pdfbufferfactory.cpp buffer/pdfbufferfactory.h
|
||||||
|
buffer/textbuffer.cpp buffer/textbuffer.h
|
||||||
|
buffer/textbufferfactory.cpp buffer/textbufferfactory.h
|
||||||
|
buffer/urlbasedbufferprovider.h
|
||||||
|
buffermgr.cpp buffermgr.h
|
||||||
|
clipboarddata.cpp clipboarddata.h
|
||||||
|
configmgr.cpp configmgr.h
|
||||||
|
coreconfig.cpp coreconfig.h
|
||||||
|
editorconfig.cpp editorconfig.h
|
||||||
|
events.h
|
||||||
|
exception.h
|
||||||
|
externalfile.cpp externalfile.h
|
||||||
|
file.cpp file.h
|
||||||
|
filelocator.h
|
||||||
|
fileopenparameters.h
|
||||||
|
global.cpp global.h
|
||||||
|
historyitem.cpp historyitem.h
|
||||||
|
historymgr.cpp historymgr.h
|
||||||
|
htmltemplatehelper.cpp htmltemplatehelper.h
|
||||||
|
iconfig.h
|
||||||
|
location.h
|
||||||
|
logger.cpp logger.h
|
||||||
|
mainconfig.cpp mainconfig.h
|
||||||
|
markdowneditorconfig.cpp markdowneditorconfig.h
|
||||||
|
mindmapeditorconfig.cpp mindmapeditorconfig.h
|
||||||
|
namebasedserver.h
|
||||||
|
noncopyable.h
|
||||||
|
notebook/bundlenotebook.cpp notebook/bundlenotebook.h
|
||||||
|
notebook/bundlenotebookfactory.cpp notebook/bundlenotebookfactory.h
|
||||||
|
notebook/externalnode.cpp notebook/externalnode.h
|
||||||
|
notebook/historyi.h
|
||||||
|
notebook/inotebookfactory.h
|
||||||
|
notebook/node.cpp notebook/node.h
|
||||||
|
notebook/nodeparameters.cpp notebook/nodeparameters.h
|
||||||
|
notebook/notebook.cpp notebook/notebook.h
|
||||||
|
notebook/notebookdatabaseaccess.cpp notebook/notebookdatabaseaccess.h
|
||||||
|
notebook/notebookparameters.cpp notebook/notebookparameters.h
|
||||||
|
notebook/notebooktagmgr.cpp notebook/notebooktagmgr.h
|
||||||
|
notebook/tag.cpp notebook/tag.h
|
||||||
|
notebook/tagi.h
|
||||||
|
notebook/vxnode.cpp notebook/vxnode.h
|
||||||
|
notebook/vxnodefile.cpp notebook/vxnodefile.h
|
||||||
|
notebookbackend/inotebookbackend.cpp notebookbackend/inotebookbackend.h
|
||||||
|
notebookbackend/inotebookbackendfactory.h
|
||||||
|
notebookbackend/localnotebookbackend.cpp notebookbackend/localnotebookbackend.h
|
||||||
|
notebookbackend/localnotebookbackendfactory.cpp notebookbackend/localnotebookbackendfactory.h
|
||||||
|
notebookconfigmgr/bundlenotebookconfigmgr.cpp notebookconfigmgr/bundlenotebookconfigmgr.h
|
||||||
|
notebookconfigmgr/inotebookconfigmgr.cpp notebookconfigmgr/inotebookconfigmgr.h
|
||||||
|
notebookconfigmgr/inotebookconfigmgrfactory.h
|
||||||
|
notebookconfigmgr/notebookconfig.cpp notebookconfigmgr/notebookconfig.h
|
||||||
|
notebookconfigmgr/vxnodeconfig.cpp notebookconfigmgr/vxnodeconfig.h
|
||||||
|
notebookconfigmgr/vxnotebookconfigmgr.cpp notebookconfigmgr/vxnotebookconfigmgr.h
|
||||||
|
notebookconfigmgr/vxnotebookconfigmgrfactory.cpp notebookconfigmgr/vxnotebookconfigmgrfactory.h
|
||||||
|
notebookmgr.cpp notebookmgr.h
|
||||||
|
pdfviewerconfig.cpp pdfviewerconfig.h
|
||||||
|
quickaccesshelper.cpp quickaccesshelper.h
|
||||||
|
sessionconfig.cpp sessionconfig.h
|
||||||
|
singleinstanceguard.cpp singleinstanceguard.h
|
||||||
|
templatemgr.cpp templatemgr.h
|
||||||
|
texteditorconfig.cpp texteditorconfig.h
|
||||||
|
theme.cpp theme.h
|
||||||
|
thememgr.cpp thememgr.h
|
||||||
|
versioncontroller/dummyversioncontroller.cpp versioncontroller/dummyversioncontroller.h
|
||||||
|
versioncontroller/dummyversioncontrollerfactory.cpp versioncontroller/dummyversioncontrollerfactory.h
|
||||||
|
versioncontroller/iversioncontroller.h
|
||||||
|
versioncontroller/iversioncontrollerfactory.h
|
||||||
|
versioncontroller/versioncontrollerserver.cpp versioncontroller/versioncontrollerserver.h
|
||||||
|
vnotex.cpp vnotex.h
|
||||||
|
webresource.h
|
||||||
|
widgetconfig.cpp widgetconfig.h
|
||||||
|
)
|
||||||
|
|
||||||
|
target_include_directories(vnote PRIVATE
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
|
)
|
@ -358,7 +358,7 @@ void Buffer::writeBackupFile()
|
|||||||
|
|
||||||
QString Buffer::generateBackupFileHead() const
|
QString Buffer::generateBackupFileHead() const
|
||||||
{
|
{
|
||||||
return QString("vnotex_backup_file %1|").arg(getContentPath());
|
return QStringLiteral("vnotex_backup_file %1|").arg(getContentPath());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Buffer::checkBackupFileOfPreviousSession()
|
void Buffer::checkBackupFileOfPreviousSession()
|
||||||
@ -373,7 +373,7 @@ void Buffer::checkBackupFileOfPreviousSession()
|
|||||||
QDir backupDir(backupDirPath);
|
QDir backupDir(backupDirPath);
|
||||||
QStringList backupFiles;
|
QStringList backupFiles;
|
||||||
{
|
{
|
||||||
const QString nameFilter = QString("%1*%2").arg(getName(), config.getBackupFileExtension());
|
const QString nameFilter = QStringLiteral("%1*%2").arg(getName(), config.getBackupFileExtension());
|
||||||
backupFiles = backupDir.entryList(QStringList(nameFilter),
|
backupFiles = backupDir.entryList(QStringList(nameFilter),
|
||||||
QDir::Files | QDir::Hidden | QDir::NoSymLinks | QDir::NoDotAndDotDot);
|
QDir::Files | QDir::Hidden | QDir::NoSymLinks | QDir::NoDotAndDotDot);
|
||||||
}
|
}
|
||||||
|
@ -1,22 +0,0 @@
|
|||||||
SOURCES += \
|
|
||||||
$$PWD/buffer.cpp \
|
|
||||||
$$PWD/bufferprovider.cpp \
|
|
||||||
$$PWD/filebufferprovider.cpp \
|
|
||||||
$$PWD/markdownbuffer.cpp \
|
|
||||||
$$PWD/markdownbufferfactory.cpp \
|
|
||||||
$$PWD/filetypehelper.cpp \
|
|
||||||
$$PWD/nodebufferprovider.cpp \
|
|
||||||
$$PWD/textbuffer.cpp \
|
|
||||||
$$PWD/textbufferfactory.cpp
|
|
||||||
|
|
||||||
HEADERS += \
|
|
||||||
$$PWD/bufferprovider.h \
|
|
||||||
$$PWD/buffer.h \
|
|
||||||
$$PWD/filebufferprovider.h \
|
|
||||||
$$PWD/ibufferfactory.h \
|
|
||||||
$$PWD/markdownbuffer.h \
|
|
||||||
$$PWD/markdownbufferfactory.h \
|
|
||||||
$$PWD/filetypehelper.h \
|
|
||||||
$$PWD/nodebufferprovider.h \
|
|
||||||
$$PWD/textbuffer.h \
|
|
||||||
$$PWD/textbufferfactory.h
|
|
@ -16,6 +16,7 @@ QDateTime BufferProvider::getLastModifiedFromFile() const
|
|||||||
|
|
||||||
bool BufferProvider::checkFileChangedOutside() const
|
bool BufferProvider::checkFileChangedOutside() const
|
||||||
{
|
{
|
||||||
|
// TODO: support non-local URLs.
|
||||||
QFileInfo info(getContentPath());
|
QFileInfo info(getContentPath());
|
||||||
if (!info.exists() || m_lastModified != info.lastModified()) {
|
if (!info.exists() || m_lastModified != info.lastModified()) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -75,6 +75,39 @@ void FileTypeHelper::setupBuiltInTypes()
|
|||||||
m_fileTypes.push_back(type);
|
m_fileTypes.push_back(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
FileType type;
|
||||||
|
type.m_type = FileType::Pdf;
|
||||||
|
type.m_typeName = QStringLiteral("PDF");
|
||||||
|
type.m_displayName = Buffer::tr("Portable Document Format");
|
||||||
|
type.m_isNewable = false;
|
||||||
|
|
||||||
|
auto suffixes = coreConfig.findFileTypeSuffix(type.m_typeName);
|
||||||
|
if (suffixes && !suffixes->isEmpty()) {
|
||||||
|
type.m_suffixes = *suffixes;
|
||||||
|
} else {
|
||||||
|
type.m_suffixes << QStringLiteral("pdf");
|
||||||
|
}
|
||||||
|
|
||||||
|
m_fileTypes.push_back(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
FileType type;
|
||||||
|
type.m_type = FileType::MindMap;
|
||||||
|
type.m_typeName = QStringLiteral("MindMap");
|
||||||
|
type.m_displayName = Buffer::tr("Mind Map");
|
||||||
|
|
||||||
|
auto suffixes = coreConfig.findFileTypeSuffix(type.m_typeName);
|
||||||
|
if (suffixes && !suffixes->isEmpty()) {
|
||||||
|
type.m_suffixes = *suffixes;
|
||||||
|
} else {
|
||||||
|
type.m_suffixes << QStringLiteral("emind");
|
||||||
|
}
|
||||||
|
|
||||||
|
m_fileTypes.push_back(type);
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
FileType type;
|
FileType type;
|
||||||
type.m_type = FileType::Others;
|
type.m_type = FileType::Others;
|
||||||
|
@ -15,9 +15,15 @@ namespace vnotex
|
|||||||
{
|
{
|
||||||
Markdown = 0,
|
Markdown = 0,
|
||||||
Text,
|
Text,
|
||||||
|
Pdf,
|
||||||
|
MindMap,
|
||||||
Others
|
Others
|
||||||
};
|
};
|
||||||
|
|
||||||
|
QString preferredSuffix() const;
|
||||||
|
|
||||||
|
bool isMarkdown() const;
|
||||||
|
|
||||||
// Type.
|
// Type.
|
||||||
int m_type = -1;
|
int m_type = -1;
|
||||||
|
|
||||||
@ -27,9 +33,8 @@ namespace vnotex
|
|||||||
|
|
||||||
QStringList m_suffixes;
|
QStringList m_suffixes;
|
||||||
|
|
||||||
QString preferredSuffix() const;
|
// Whether we can new this type of file.
|
||||||
|
bool m_isNewable = true;
|
||||||
bool isMarkdown() const;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Only handle built-in editors.
|
// Only handle built-in editors.
|
||||||
|
17
src/core/buffer/mindmapbuffer.cpp
Normal file
17
src/core/buffer/mindmapbuffer.cpp
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#include "mindmapbuffer.h"
|
||||||
|
|
||||||
|
#include <widgets/mindmapviewwindow.h>
|
||||||
|
|
||||||
|
using namespace vnotex;
|
||||||
|
|
||||||
|
MindMapBuffer::MindMapBuffer(const BufferParameters &p_parameters,
|
||||||
|
QObject *p_parent)
|
||||||
|
: Buffer(p_parameters, p_parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ViewWindow *MindMapBuffer::createViewWindowInternal(const QSharedPointer<FileOpenParameters> &p_paras, QWidget *p_parent)
|
||||||
|
{
|
||||||
|
Q_UNUSED(p_paras);
|
||||||
|
return new MindMapViewWindow(p_parent);
|
||||||
|
}
|
21
src/core/buffer/mindmapbuffer.h
Normal file
21
src/core/buffer/mindmapbuffer.h
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
#ifndef MINDMAPBUFFER_H
|
||||||
|
#define MINDMAPBUFFER_H
|
||||||
|
|
||||||
|
#include "buffer.h"
|
||||||
|
|
||||||
|
namespace vnotex
|
||||||
|
{
|
||||||
|
class MindMapBuffer : public Buffer
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
MindMapBuffer(const BufferParameters &p_parameters,
|
||||||
|
QObject *p_parent = nullptr);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
ViewWindow *createViewWindowInternal(const QSharedPointer<FileOpenParameters> &p_paras,
|
||||||
|
QWidget *p_parent) Q_DECL_OVERRIDE;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // MINDMAPBUFFER_H
|
16
src/core/buffer/mindmapbufferfactory.cpp
Normal file
16
src/core/buffer/mindmapbufferfactory.cpp
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#include "mindmapbufferfactory.h"
|
||||||
|
|
||||||
|
#include "mindmapbuffer.h"
|
||||||
|
|
||||||
|
using namespace vnotex;
|
||||||
|
|
||||||
|
Buffer *MindMapBufferFactory::createBuffer(const BufferParameters &p_parameters,
|
||||||
|
QObject *p_parent)
|
||||||
|
{
|
||||||
|
return new MindMapBuffer(p_parameters, p_parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MindMapBufferFactory::isBufferCreatedByFactory(const Buffer *p_buffer) const
|
||||||
|
{
|
||||||
|
return dynamic_cast<const MindMapBuffer *>(p_buffer) != nullptr;
|
||||||
|
}
|
19
src/core/buffer/mindmapbufferfactory.h
Normal file
19
src/core/buffer/mindmapbufferfactory.h
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
#ifndef MINDMAPBUFFERFACTORY_H
|
||||||
|
#define MINDMAPBUFFERFACTORY_H
|
||||||
|
|
||||||
|
#include "ibufferfactory.h"
|
||||||
|
|
||||||
|
namespace vnotex
|
||||||
|
{
|
||||||
|
// Buffer factory for MindMap file.
|
||||||
|
class MindMapBufferFactory : public IBufferFactory
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Buffer *createBuffer(const BufferParameters &p_parameters,
|
||||||
|
QObject *p_parent) Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
|
bool isBufferCreatedByFactory(const Buffer *p_buffer) const Q_DECL_OVERRIDE;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // MINDMAPBUFFERFACTORY_H
|
17
src/core/buffer/pdfbuffer.cpp
Normal file
17
src/core/buffer/pdfbuffer.cpp
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#include "pdfbuffer.h"
|
||||||
|
|
||||||
|
#include <widgets/pdfviewwindow.h>
|
||||||
|
|
||||||
|
using namespace vnotex;
|
||||||
|
|
||||||
|
PdfBuffer::PdfBuffer(const BufferParameters &p_parameters,
|
||||||
|
QObject *p_parent)
|
||||||
|
: Buffer(p_parameters, p_parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ViewWindow *PdfBuffer::createViewWindowInternal(const QSharedPointer<FileOpenParameters> &p_paras, QWidget *p_parent)
|
||||||
|
{
|
||||||
|
Q_UNUSED(p_paras);
|
||||||
|
return new PdfViewWindow(p_parent);
|
||||||
|
}
|
21
src/core/buffer/pdfbuffer.h
Normal file
21
src/core/buffer/pdfbuffer.h
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
#ifndef PDFBUFFER_H
|
||||||
|
#define PDFBUFFER_H
|
||||||
|
|
||||||
|
#include "buffer.h"
|
||||||
|
|
||||||
|
namespace vnotex
|
||||||
|
{
|
||||||
|
class PdfBuffer : public Buffer
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
PdfBuffer(const BufferParameters &p_parameters,
|
||||||
|
QObject *p_parent = nullptr);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
ViewWindow *createViewWindowInternal(const QSharedPointer<FileOpenParameters> &p_paras,
|
||||||
|
QWidget *p_parent) Q_DECL_OVERRIDE;
|
||||||
|
};
|
||||||
|
} // ns vnotex
|
||||||
|
|
||||||
|
#endif // PDFBUFFER_H
|
19
src/core/buffer/pdfbufferfactory.cpp
Normal file
19
src/core/buffer/pdfbufferfactory.cpp
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
#include "pdfbufferfactory.h"
|
||||||
|
|
||||||
|
#include "pdfbuffer.h"
|
||||||
|
#include "urlbasedbufferprovider.h"
|
||||||
|
|
||||||
|
using namespace vnotex;
|
||||||
|
|
||||||
|
Buffer *PdfBufferFactory::createBuffer(const BufferParameters &p_parameters,
|
||||||
|
QObject *p_parent)
|
||||||
|
{
|
||||||
|
BufferParameters paras;
|
||||||
|
paras.m_provider = QSharedPointer<UrlBasedBufferProvider>::create(p_parameters.m_provider);
|
||||||
|
return new PdfBuffer(paras, p_parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PdfBufferFactory::isBufferCreatedByFactory(const Buffer *p_buffer) const
|
||||||
|
{
|
||||||
|
return dynamic_cast<const PdfBuffer *>(p_buffer) != nullptr;
|
||||||
|
}
|
19
src/core/buffer/pdfbufferfactory.h
Normal file
19
src/core/buffer/pdfbufferfactory.h
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
#ifndef PDFBUFFERFACTORY_H
|
||||||
|
#define PDFBUFFERFACTORY_H
|
||||||
|
|
||||||
|
#include "ibufferfactory.h"
|
||||||
|
|
||||||
|
namespace vnotex
|
||||||
|
{
|
||||||
|
// Buffer factory for Pdf file.
|
||||||
|
class PdfBufferFactory : public IBufferFactory
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Buffer *createBuffer(const BufferParameters &p_parameters,
|
||||||
|
QObject *p_parent) Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
|
bool isBufferCreatedByFactory(const Buffer *p_buffer) const Q_DECL_OVERRIDE;
|
||||||
|
};
|
||||||
|
} // vnotex
|
||||||
|
|
||||||
|
#endif // PDFBUFFERFACTORY_H
|
132
src/core/buffer/urlbasedbufferprovider.h
Normal file
132
src/core/buffer/urlbasedbufferprovider.h
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
#ifndef URLBASEDBUFFERPROVIDER_H
|
||||||
|
#define URLBASEDBUFFERPROVIDER_H
|
||||||
|
|
||||||
|
#include "bufferprovider.h"
|
||||||
|
|
||||||
|
#include <QSharedPointer>
|
||||||
|
|
||||||
|
namespace vnotex
|
||||||
|
{
|
||||||
|
// A wrapper provider to provide URL-based buffer (instead of content-based).
|
||||||
|
class UrlBasedBufferProvider : public BufferProvider
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
// Will own @p_provider.
|
||||||
|
UrlBasedBufferProvider(const QSharedPointer<BufferProvider> &p_provider, QObject *p_parent = nullptr)
|
||||||
|
: BufferProvider(p_parent),
|
||||||
|
m_provider(p_provider)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Buffer::ProviderType getType() const Q_DECL_OVERRIDE {
|
||||||
|
return m_provider->getType();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool match(const Node *p_node) const Q_DECL_OVERRIDE {
|
||||||
|
return m_provider->match(p_node);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool match(const QString &p_filePath) const Q_DECL_OVERRIDE {
|
||||||
|
return m_provider->match(p_filePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString getName() const Q_DECL_OVERRIDE {
|
||||||
|
return m_provider->getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString getPath() const Q_DECL_OVERRIDE {
|
||||||
|
return m_provider->getPath();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString getContentPath() const Q_DECL_OVERRIDE {
|
||||||
|
return m_provider->getContentPath();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString getResourcePath() const Q_DECL_OVERRIDE {
|
||||||
|
return m_provider->getResourcePath();
|
||||||
|
}
|
||||||
|
|
||||||
|
void write(const QString &p_content) Q_DECL_OVERRIDE {
|
||||||
|
Q_UNUSED(p_content);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString read() const Q_DECL_OVERRIDE {
|
||||||
|
const_cast<UrlBasedBufferProvider *>(this)->m_lastModified = getLastModifiedFromFile();
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString fetchImageFolderPath() Q_DECL_OVERRIDE {
|
||||||
|
return m_provider->fetchImageFolderPath();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isChildOf(const Node *p_node) const Q_DECL_OVERRIDE {
|
||||||
|
return m_provider->isChildOf(p_node);
|
||||||
|
}
|
||||||
|
|
||||||
|
Node *getNode() const Q_DECL_OVERRIDE {
|
||||||
|
return m_provider->getNode();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString getAttachmentFolder() const Q_DECL_OVERRIDE {
|
||||||
|
return m_provider->getAttachmentFolder();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString fetchAttachmentFolderPath() Q_DECL_OVERRIDE {
|
||||||
|
return m_provider->fetchAttachmentFolderPath();
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList addAttachment(const QString &p_destFolderPath, const QStringList &p_files) Q_DECL_OVERRIDE {
|
||||||
|
return m_provider->addAttachment(p_destFolderPath, p_files);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString newAttachmentFile(const QString &p_destFolderPath, const QString &p_name) Q_DECL_OVERRIDE {
|
||||||
|
return m_provider->newAttachmentFile(p_destFolderPath, p_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString newAttachmentFolder(const QString &p_destFolderPath, const QString &p_name) Q_DECL_OVERRIDE {
|
||||||
|
return m_provider->newAttachmentFolder(p_destFolderPath, p_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString renameAttachment(const QString &p_path, const QString &p_name) Q_DECL_OVERRIDE {
|
||||||
|
return m_provider->renameAttachment(p_path, p_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void removeAttachment(const QStringList &p_paths) Q_DECL_OVERRIDE {
|
||||||
|
m_provider->removeAttachment(p_paths);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString insertImage(const QString &p_srcImagePath, const QString &p_imageFileName) Q_DECL_OVERRIDE {
|
||||||
|
return m_provider->insertImage(p_srcImagePath, p_imageFileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString insertImage(const QImage &p_image, const QString &p_imageFileName) Q_DECL_OVERRIDE {
|
||||||
|
return m_provider->insertImage(p_image, p_imageFileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
void removeImage(const QString &p_imagePath) Q_DECL_OVERRIDE {
|
||||||
|
m_provider->removeImage(p_imagePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isAttachmentSupported() const Q_DECL_OVERRIDE {
|
||||||
|
return m_provider->isAttachmentSupported();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isTagSupported() const Q_DECL_OVERRIDE {
|
||||||
|
return m_provider->isTagSupported();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isReadOnly() const Q_DECL_OVERRIDE {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
QSharedPointer<File> getFile() const Q_DECL_OVERRIDE {
|
||||||
|
return m_provider->getFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
QSharedPointer<BufferProvider> m_provider;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // URLBASEDBUFFERPROVIDER_H
|
@ -7,6 +7,8 @@
|
|||||||
#include <buffer/filetypehelper.h>
|
#include <buffer/filetypehelper.h>
|
||||||
#include <buffer/markdownbufferfactory.h>
|
#include <buffer/markdownbufferfactory.h>
|
||||||
#include <buffer/textbufferfactory.h>
|
#include <buffer/textbufferfactory.h>
|
||||||
|
#include <buffer/pdfbufferfactory.h>
|
||||||
|
#include <buffer/mindmapbufferfactory.h>
|
||||||
#include <buffer/buffer.h>
|
#include <buffer/buffer.h>
|
||||||
#include <buffer/nodebufferprovider.h>
|
#include <buffer/nodebufferprovider.h>
|
||||||
#include <buffer/filebufferprovider.h>
|
#include <buffer/filebufferprovider.h>
|
||||||
@ -52,6 +54,14 @@ void BufferMgr::initBufferServer()
|
|||||||
// Text.
|
// Text.
|
||||||
auto textFactory = QSharedPointer<TextBufferFactory>::create();
|
auto textFactory = QSharedPointer<TextBufferFactory>::create();
|
||||||
m_bufferServer->registerItem(helper.getFileType(FileType::Text).m_typeName, textFactory);
|
m_bufferServer->registerItem(helper.getFileType(FileType::Text).m_typeName, textFactory);
|
||||||
|
|
||||||
|
// Pdf.
|
||||||
|
auto pdfFactory = QSharedPointer<PdfBufferFactory>::create();
|
||||||
|
m_bufferServer->registerItem(helper.getFileType(FileType::Pdf).m_typeName, pdfFactory);
|
||||||
|
|
||||||
|
// MindMap.
|
||||||
|
auto mindMapFactory = QSharedPointer<MindMapBufferFactory>::create();
|
||||||
|
m_bufferServer->registerItem(helper.getFileType(FileType::MindMap).m_typeName, mindMapFactory);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BufferMgr::open(Node *p_node, const QSharedPointer<FileOpenParameters> &p_paras)
|
void BufferMgr::open(Node *p_node, const QSharedPointer<FileOpenParameters> &p_paras)
|
||||||
@ -65,7 +75,7 @@ void BufferMgr::open(Node *p_node, const QSharedPointer<FileOpenParameters> &p_p
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!p_node->checkExists()) {
|
if (!p_node->checkExists()) {
|
||||||
auto msg = QString("Failed to open node that does not exist (%1)").arg(p_node->fetchAbsolutePath());
|
auto msg = QStringLiteral("Failed to open node that does not exist (%1)").arg(p_node->fetchAbsolutePath());
|
||||||
qWarning() << msg;
|
qWarning() << msg;
|
||||||
VNoteX::getInst().showStatusMessageShort(msg);
|
VNoteX::getInst().showStatusMessageShort(msg);
|
||||||
return;
|
return;
|
||||||
@ -123,7 +133,7 @@ void BufferMgr::open(const QString &p_filePath, const QSharedPointer<FileOpenPar
|
|||||||
|
|
||||||
QFileInfo finfo(p_filePath);
|
QFileInfo finfo(p_filePath);
|
||||||
if (!finfo.exists()) {
|
if (!finfo.exists()) {
|
||||||
auto msg = QString("Failed to open file that does not exist (%1)").arg(p_filePath);
|
auto msg = QStringLiteral("Failed to open file that does not exist (%1)").arg(p_filePath);
|
||||||
qWarning() << msg;
|
qWarning() << msg;
|
||||||
VNoteX::getInst().showStatusMessageShort(msg);
|
VNoteX::getInst().showStatusMessageShort(msg);
|
||||||
WidgetUtils::openUrlByDesktop(QUrl::fromUserInput(p_filePath));
|
WidgetUtils::openUrlByDesktop(QUrl::fromUserInput(p_filePath));
|
||||||
@ -243,6 +253,7 @@ bool BufferMgr::openWithExternalProgram(const QString &p_filePath, const QString
|
|||||||
|
|
||||||
if (auto pro = ConfigMgr::getInst().getSessionConfig().findExternalProgram(p_name)) {
|
if (auto pro = ConfigMgr::getInst().getSessionConfig().findExternalProgram(p_name)) {
|
||||||
const auto command = pro->fetchCommand(p_filePath);
|
const auto command = pro->fetchCommand(p_filePath);
|
||||||
|
qDebug() << "external program" << command;
|
||||||
if (!command.isEmpty()) {
|
if (!command.isEmpty()) {
|
||||||
ProcessUtils::startDetached(command);
|
ProcessUtils::startDetached(command);
|
||||||
}
|
}
|
||||||
|
@ -63,14 +63,14 @@ void ClipboardData::fromJson(const QJsonObject &p_jobj)
|
|||||||
|| !p_jobj.contains(c_action)
|
|| !p_jobj.contains(c_action)
|
||||||
|| !p_jobj.contains(c_data)) {
|
|| !p_jobj.contains(c_data)) {
|
||||||
Exception::throwOne(Exception::Type::InvalidArgument,
|
Exception::throwOne(Exception::Type::InvalidArgument,
|
||||||
QString("fail to parse ClipboardData from json (%1)").arg(p_jobj.keys().join(',')));
|
QStringLiteral("fail to parse ClipboardData from json (%1)").arg(p_jobj.keys().join(',')));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto idRet = stringToID(p_jobj[c_instanceId].toString());
|
auto idRet = stringToID(p_jobj[c_instanceId].toString());
|
||||||
if (!idRet.first) {
|
if (!idRet.first) {
|
||||||
Exception::throwOne(Exception::Type::InvalidArgument,
|
Exception::throwOne(Exception::Type::InvalidArgument,
|
||||||
QString("fail to parse ClipboardData from json (%1)").arg(p_jobj.keys().join(',')));
|
QStringLiteral("fail to parse ClipboardData from json (%1)").arg(p_jobj.keys().join(',')));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
m_instanceId = idRet.second;
|
m_instanceId = idRet.second;
|
||||||
@ -79,7 +79,7 @@ void ClipboardData::fromJson(const QJsonObject &p_jobj)
|
|||||||
m_action = intToAction(act);
|
m_action = intToAction(act);
|
||||||
if (m_action == Action::Invalid) {
|
if (m_action == Action::Invalid) {
|
||||||
Exception::throwOne(Exception::Type::InvalidArgument,
|
Exception::throwOne(Exception::Type::InvalidArgument,
|
||||||
QString("fail to parse ClipboardData from json (%1)").arg(p_jobj.keys().join(',')));
|
QStringLiteral("fail to parse ClipboardData from json (%1)").arg(p_jobj.keys().join(',')));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
using namespace vnotex;
|
using namespace vnotex;
|
||||||
|
|
||||||
#ifndef QT_NO_DEBUG
|
#ifndef QT_NO_DEBUG
|
||||||
// #define VX_DEBUG_WEB
|
// #define VX_DEBUG_WEB
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
const QString ConfigMgr::c_orgName = "VNote";
|
const QString ConfigMgr::c_orgName = "VNote";
|
||||||
@ -191,12 +191,11 @@ bool ConfigMgr::checkAppConfig()
|
|||||||
|
|
||||||
// Load extra data.
|
// Load extra data.
|
||||||
splash->showMessage("Loading extra resource data");
|
splash->showMessage("Loading extra resource data");
|
||||||
const QString extraRcc(PathUtils::concatenateFilePath(QCoreApplication::applicationDirPath(),
|
const QString extraRcc("app:vnote_extra.rcc");
|
||||||
QStringLiteral("vnote_extra.rcc")));
|
|
||||||
bool ret = QResource::registerResource(extraRcc);
|
bool ret = QResource::registerResource(extraRcc);
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
Exception::throwOne(Exception::Type::FailToReadFile,
|
Exception::throwOne(Exception::Type::FailToReadFile,
|
||||||
QString("failed to register resource file %1").arg(extraRcc));
|
QStringLiteral("failed to register resource file %1").arg(extraRcc));
|
||||||
}
|
}
|
||||||
auto cleanup = qScopeGuard([extraRcc]() {
|
auto cleanup = qScopeGuard([extraRcc]() {
|
||||||
QResource::unregisterResource(extraRcc);
|
QResource::unregisterResource(extraRcc);
|
||||||
@ -571,6 +570,38 @@ QString ConfigMgr::getApplicationVersion()
|
|||||||
return appVersion;
|
return appVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ConfigMgr::initAppPrefixPath()
|
||||||
|
{
|
||||||
|
// Support QFile("app:abc.txt").
|
||||||
|
QStringList potential_dirs;
|
||||||
|
auto app_dir_path = QCoreApplication::applicationDirPath();
|
||||||
|
qInfo() << "app prefix path: " << app_dir_path;
|
||||||
|
potential_dirs << app_dir_path;
|
||||||
|
|
||||||
|
#if defined(Q_OS_LINUX)
|
||||||
|
QDir localBinDir(app_dir_path);
|
||||||
|
if (localBinDir.exists("../local/bin/vnote")) {
|
||||||
|
auto app_dir_path2 = localBinDir.cleanPath(localBinDir.filePath("../local/share"));
|
||||||
|
qInfo() << "app prefix path: " << app_dir_path2;
|
||||||
|
potential_dirs << app_dir_path2;
|
||||||
|
}
|
||||||
|
if (localBinDir.exists("../share")) {
|
||||||
|
auto app_dir_path3 = localBinDir.cleanPath(localBinDir.filePath("../share"));
|
||||||
|
qInfo() << "app prefix path: " << app_dir_path3;
|
||||||
|
potential_dirs << app_dir_path3;
|
||||||
|
}
|
||||||
|
#elif defined(Q_OS_MACOS)
|
||||||
|
QDir localBinDir(app_dir_path);
|
||||||
|
if (localBinDir.exists("../Resources")) {
|
||||||
|
auto app_dir_path2 = localBinDir.cleanPath(localBinDir.filePath("../Resources"));
|
||||||
|
qInfo() << "app prefix path: " << app_dir_path2;
|
||||||
|
potential_dirs << app_dir_path2;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
QDir::setSearchPaths("app", potential_dirs);
|
||||||
|
}
|
||||||
|
|
||||||
QJsonValue ConfigMgr::parseAndReadConfig(const QString &p_exp) const
|
QJsonValue ConfigMgr::parseAndReadConfig(const QString &p_exp) const
|
||||||
{
|
{
|
||||||
if (p_exp.startsWith(QStringLiteral("main."))) {
|
if (p_exp.startsWith(QStringLiteral("main."))) {
|
||||||
|
@ -120,6 +120,8 @@ namespace vnotex
|
|||||||
|
|
||||||
static QString getApplicationVersion();
|
static QString getApplicationVersion();
|
||||||
|
|
||||||
|
static void initAppPrefixPath();
|
||||||
|
|
||||||
static void initForUnitTest();
|
static void initForUnitTest();
|
||||||
|
|
||||||
static const QString c_orgName;
|
static const QString c_orgName;
|
||||||
|
@ -1,72 +0,0 @@
|
|||||||
INCLUDEPATH *= $$PWD
|
|
||||||
|
|
||||||
include($$PWD/notebookbackend/notebookbackend.pri)
|
|
||||||
|
|
||||||
include($$PWD/versioncontroller/versioncontroller.pri)
|
|
||||||
|
|
||||||
include($$PWD/notebookconfigmgr/notebookconfigmgr.pri)
|
|
||||||
|
|
||||||
include($$PWD/notebook/notebook.pri)
|
|
||||||
|
|
||||||
include($$PWD/buffer/buffer.pri)
|
|
||||||
|
|
||||||
SOURCES += \
|
|
||||||
$$PWD/buffermgr.cpp \
|
|
||||||
$$PWD/configmgr.cpp \
|
|
||||||
$$PWD/coreconfig.cpp \
|
|
||||||
$$PWD/editorconfig.cpp \
|
|
||||||
$$PWD/externalfile.cpp \
|
|
||||||
$$PWD/file.cpp \
|
|
||||||
$$PWD/global.cpp \
|
|
||||||
$$PWD/historyitem.cpp \
|
|
||||||
$$PWD/historymgr.cpp \
|
|
||||||
$$PWD/htmltemplatehelper.cpp \
|
|
||||||
$$PWD/logger.cpp \
|
|
||||||
$$PWD/mainconfig.cpp \
|
|
||||||
$$PWD/markdowneditorconfig.cpp \
|
|
||||||
$$PWD/quickaccesshelper.cpp \
|
|
||||||
$$PWD/singleinstanceguard.cpp \
|
|
||||||
$$PWD/templatemgr.cpp \
|
|
||||||
$$PWD/texteditorconfig.cpp \
|
|
||||||
$$PWD/vnotex.cpp \
|
|
||||||
$$PWD/thememgr.cpp \
|
|
||||||
$$PWD/notebookmgr.cpp \
|
|
||||||
$$PWD/theme.cpp \
|
|
||||||
$$PWD/sessionconfig.cpp \
|
|
||||||
$$PWD/clipboarddata.cpp \
|
|
||||||
$$PWD/widgetconfig.cpp
|
|
||||||
|
|
||||||
HEADERS += \
|
|
||||||
$$PWD/buffermgr.h \
|
|
||||||
$$PWD/configmgr.h \
|
|
||||||
$$PWD/coreconfig.h \
|
|
||||||
$$PWD/editorconfig.h \
|
|
||||||
$$PWD/events.h \
|
|
||||||
$$PWD/externalfile.h \
|
|
||||||
$$PWD/file.h \
|
|
||||||
$$PWD/filelocator.h \
|
|
||||||
$$PWD/fileopenparameters.h \
|
|
||||||
$$PWD/historyitem.h \
|
|
||||||
$$PWD/historymgr.h \
|
|
||||||
$$PWD/htmltemplatehelper.h \
|
|
||||||
$$PWD/location.h \
|
|
||||||
$$PWD/logger.h \
|
|
||||||
$$PWD/mainconfig.h \
|
|
||||||
$$PWD/markdowneditorconfig.h \
|
|
||||||
$$PWD/noncopyable.h \
|
|
||||||
$$PWD/quickaccesshelper.h \
|
|
||||||
$$PWD/singleinstanceguard.h \
|
|
||||||
$$PWD/iconfig.h \
|
|
||||||
$$PWD/templatemgr.h \
|
|
||||||
$$PWD/texteditorconfig.h \
|
|
||||||
$$PWD/vnotex.h \
|
|
||||||
$$PWD/thememgr.h \
|
|
||||||
$$PWD/global.h \
|
|
||||||
$$PWD/namebasedserver.h \
|
|
||||||
$$PWD/exception.h \
|
|
||||||
$$PWD/notebookmgr.h \
|
|
||||||
$$PWD/theme.h \
|
|
||||||
$$PWD/sessionconfig.h \
|
|
||||||
$$PWD/clipboarddata.h \
|
|
||||||
$$PWD/webresource.h \
|
|
||||||
$$PWD/widgetconfig.h
|
|
@ -66,7 +66,7 @@ void CoreConfig::init(const QJsonObject &p_app,
|
|||||||
|
|
||||||
m_docksTabBarIconSize = READINT(QStringLiteral("docks_tabbar_icon_size"));
|
m_docksTabBarIconSize = READINT(QStringLiteral("docks_tabbar_icon_size"));
|
||||||
if (m_docksTabBarIconSize <= 0) {
|
if (m_docksTabBarIconSize <= 0) {
|
||||||
m_docksTabBarIconSize = 20;
|
m_docksTabBarIconSize = 18;
|
||||||
}
|
}
|
||||||
|
|
||||||
loadNoteManagement(appObj, userObj);
|
loadNoteManagement(appObj, userObj);
|
||||||
@ -82,12 +82,16 @@ void CoreConfig::init(const QJsonObject &p_app,
|
|||||||
|
|
||||||
m_perNotebookHistoryEnabled = READBOOL(QStringLiteral("per_notebook_history"));
|
m_perNotebookHistoryEnabled = READBOOL(QStringLiteral("per_notebook_history"));
|
||||||
|
|
||||||
|
|
||||||
{
|
{
|
||||||
auto lineEnding = READSTR(QStringLiteral("line_ending"));
|
auto lineEnding = READSTR(QStringLiteral("line_ending"));
|
||||||
m_lineEnding = stringToLineEndingPolicy(lineEnding);
|
m_lineEnding = stringToLineEndingPolicy(lineEnding);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto mode = READSTR(QStringLiteral("default_open_mode"));
|
||||||
|
m_defaultOpenMode = stringToViewWindowMode(mode);
|
||||||
|
}
|
||||||
|
|
||||||
loadFileTypeSuffixes(appObj, userObj);
|
loadFileTypeSuffixes(appObj, userObj);
|
||||||
|
|
||||||
loadUnitedEntry(appObj, userObj);
|
loadUnitedEntry(appObj, userObj);
|
||||||
@ -109,6 +113,7 @@ QJsonObject CoreConfig::toJson() const
|
|||||||
obj[QStringLiteral("line_ending")] = lineEndingPolicyToString(m_lineEnding);
|
obj[QStringLiteral("line_ending")] = lineEndingPolicyToString(m_lineEnding);
|
||||||
obj[QStringLiteral("file_type_suffixes")] = saveFileTypeSuffixes();
|
obj[QStringLiteral("file_type_suffixes")] = saveFileTypeSuffixes();
|
||||||
obj[QStringLiteral("united_entry")] = saveUnitedEntry();
|
obj[QStringLiteral("united_entry")] = saveUnitedEntry();
|
||||||
|
obj[QStringLiteral("default_open_mode")] = viewWindowModeToString(m_defaultOpenMode);
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -362,3 +367,33 @@ void CoreConfig::setUnitedEntryAlias(const QJsonArray &p_alias)
|
|||||||
{
|
{
|
||||||
updateConfig(m_unitedEntryAlias, p_alias, this);
|
updateConfig(m_unitedEntryAlias, p_alias, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ViewWindowMode CoreConfig::getDefaultOpenMode() const
|
||||||
|
{
|
||||||
|
return m_defaultOpenMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CoreConfig::setDefaultOpenMode(ViewWindowMode p_mode)
|
||||||
|
{
|
||||||
|
updateConfig(m_defaultOpenMode, p_mode, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
ViewWindowMode CoreConfig::stringToViewWindowMode(const QString &p_mode)
|
||||||
|
{
|
||||||
|
if (p_mode == "edit") {
|
||||||
|
return ViewWindowMode::Edit;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ViewWindowMode::Read;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString CoreConfig::viewWindowModeToString(ViewWindowMode p_mode)
|
||||||
|
{
|
||||||
|
switch (p_mode) {
|
||||||
|
case ViewWindowMode::Edit:
|
||||||
|
return "edit";
|
||||||
|
|
||||||
|
default:
|
||||||
|
return "read";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -22,9 +22,12 @@ namespace vnotex
|
|||||||
ExpandContentArea,
|
ExpandContentArea,
|
||||||
Settings,
|
Settings,
|
||||||
NewNote,
|
NewNote,
|
||||||
|
NewQuickNote,
|
||||||
NewFolder,
|
NewFolder,
|
||||||
CloseTab,
|
CloseTab,
|
||||||
|
CloseAllTabs,
|
||||||
CloseOtherTabs,
|
CloseOtherTabs,
|
||||||
|
CloseTabsToTheLeft,
|
||||||
CloseTabsToTheRight,
|
CloseTabsToTheRight,
|
||||||
NavigationDock,
|
NavigationDock,
|
||||||
OutlineDock,
|
OutlineDock,
|
||||||
@ -32,6 +35,7 @@ namespace vnotex
|
|||||||
SnippetDock,
|
SnippetDock,
|
||||||
LocationListDock,
|
LocationListDock,
|
||||||
HistoryDock,
|
HistoryDock,
|
||||||
|
WindowsDock,
|
||||||
TagDock,
|
TagDock,
|
||||||
Search,
|
Search,
|
||||||
NavigationMode,
|
NavigationMode,
|
||||||
@ -143,6 +147,9 @@ namespace vnotex
|
|||||||
const QJsonArray &getUnitedEntryAlias() const;
|
const QJsonArray &getUnitedEntryAlias() const;
|
||||||
void setUnitedEntryAlias(const QJsonArray &p_alias);
|
void setUnitedEntryAlias(const QJsonArray &p_alias);
|
||||||
|
|
||||||
|
ViewWindowMode getDefaultOpenMode() const;
|
||||||
|
void setDefaultOpenMode(ViewWindowMode p_mode);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class MainConfig;
|
friend class MainConfig;
|
||||||
|
|
||||||
@ -160,6 +167,9 @@ namespace vnotex
|
|||||||
|
|
||||||
QJsonObject saveUnitedEntry() const;
|
QJsonObject saveUnitedEntry() const;
|
||||||
|
|
||||||
|
static ViewWindowMode stringToViewWindowMode(const QString &p_mode);
|
||||||
|
static QString viewWindowModeToString(ViewWindowMode p_mode);
|
||||||
|
|
||||||
// Theme name.
|
// Theme name.
|
||||||
QString m_theme;
|
QString m_theme;
|
||||||
|
|
||||||
@ -197,6 +207,8 @@ namespace vnotex
|
|||||||
|
|
||||||
QJsonArray m_unitedEntryAlias;
|
QJsonArray m_unitedEntryAlias;
|
||||||
|
|
||||||
|
ViewWindowMode m_defaultOpenMode = ViewWindowMode::Read;
|
||||||
|
|
||||||
static QStringList s_availableLocales;
|
static QStringList s_availableLocales;
|
||||||
};
|
};
|
||||||
} // ns vnotex
|
} // ns vnotex
|
||||||
|
@ -5,6 +5,8 @@
|
|||||||
|
|
||||||
#include "texteditorconfig.h"
|
#include "texteditorconfig.h"
|
||||||
#include "markdowneditorconfig.h"
|
#include "markdowneditorconfig.h"
|
||||||
|
#include "pdfviewerconfig.h"
|
||||||
|
#include "mindmapeditorconfig.h"
|
||||||
|
|
||||||
#include <vtextedit/viconfig.h>
|
#include <vtextedit/viconfig.h>
|
||||||
|
|
||||||
@ -41,7 +43,9 @@ QJsonObject EditorConfig::ImageHostItem::toJson() const
|
|||||||
EditorConfig::EditorConfig(ConfigMgr *p_mgr, IConfig *p_topConfig)
|
EditorConfig::EditorConfig(ConfigMgr *p_mgr, IConfig *p_topConfig)
|
||||||
: IConfig(p_mgr, p_topConfig),
|
: IConfig(p_mgr, p_topConfig),
|
||||||
m_textEditorConfig(new TextEditorConfig(p_mgr, p_topConfig)),
|
m_textEditorConfig(new TextEditorConfig(p_mgr, p_topConfig)),
|
||||||
m_markdownEditorConfig(new MarkdownEditorConfig(p_mgr, p_topConfig, m_textEditorConfig))
|
m_markdownEditorConfig(new MarkdownEditorConfig(p_mgr, p_topConfig, m_textEditorConfig)),
|
||||||
|
m_pdfViewerConfig(new PdfViewerConfig(p_mgr, p_topConfig)),
|
||||||
|
m_mindMapEditorConfig(new MindMapEditorConfig(p_mgr, p_topConfig))
|
||||||
{
|
{
|
||||||
m_sessionName = QStringLiteral("editor");
|
m_sessionName = QStringLiteral("editor");
|
||||||
}
|
}
|
||||||
@ -65,6 +69,8 @@ void EditorConfig::init(const QJsonObject &p_app,
|
|||||||
|
|
||||||
m_textEditorConfig->init(appObj, userObj);
|
m_textEditorConfig->init(appObj, userObj);
|
||||||
m_markdownEditorConfig->init(appObj, userObj);
|
m_markdownEditorConfig->init(appObj, userObj);
|
||||||
|
m_pdfViewerConfig->init(appObj, userObj);
|
||||||
|
m_mindMapEditorConfig->init(appObj, userObj);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EditorConfig::loadCore(const QJsonObject &p_app, const QJsonObject &p_user)
|
void EditorConfig::loadCore(const QJsonObject &p_app, const QJsonObject &p_user)
|
||||||
@ -148,6 +154,8 @@ QJsonObject EditorConfig::toJson() const
|
|||||||
QJsonObject obj;
|
QJsonObject obj;
|
||||||
obj[m_textEditorConfig->getSessionName()] = m_textEditorConfig->toJson();
|
obj[m_textEditorConfig->getSessionName()] = m_textEditorConfig->toJson();
|
||||||
obj[m_markdownEditorConfig->getSessionName()] = m_markdownEditorConfig->toJson();
|
obj[m_markdownEditorConfig->getSessionName()] = m_markdownEditorConfig->toJson();
|
||||||
|
obj[m_pdfViewerConfig->getSessionName()] = m_pdfViewerConfig->toJson();
|
||||||
|
obj[m_mindMapEditorConfig->getSessionName()] = m_mindMapEditorConfig->toJson();
|
||||||
obj[QStringLiteral("core")] = saveCore();
|
obj[QStringLiteral("core")] = saveCore();
|
||||||
obj[QStringLiteral("image_host")] = saveImageHost();
|
obj[QStringLiteral("image_host")] = saveImageHost();
|
||||||
|
|
||||||
@ -178,6 +186,26 @@ const MarkdownEditorConfig &EditorConfig::getMarkdownEditorConfig() const
|
|||||||
return *m_markdownEditorConfig;
|
return *m_markdownEditorConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PdfViewerConfig &EditorConfig::getPdfViewerConfig()
|
||||||
|
{
|
||||||
|
return *m_pdfViewerConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
const PdfViewerConfig &EditorConfig::getPdfViewerConfig() const
|
||||||
|
{
|
||||||
|
return *m_pdfViewerConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
MindMapEditorConfig &EditorConfig::getMindMapEditorConfig()
|
||||||
|
{
|
||||||
|
return *m_mindMapEditorConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
const MindMapEditorConfig &EditorConfig::getMindMapEditorConfig() const
|
||||||
|
{
|
||||||
|
return *m_mindMapEditorConfig;
|
||||||
|
}
|
||||||
|
|
||||||
int EditorConfig::getToolBarIconSize() const
|
int EditorConfig::getToolBarIconSize() const
|
||||||
{
|
{
|
||||||
return m_toolBarIconSize;
|
return m_toolBarIconSize;
|
||||||
|
@ -19,6 +19,8 @@ namespace vnotex
|
|||||||
{
|
{
|
||||||
class TextEditorConfig;
|
class TextEditorConfig;
|
||||||
class MarkdownEditorConfig;
|
class MarkdownEditorConfig;
|
||||||
|
class PdfViewerConfig;
|
||||||
|
class MindMapEditorConfig;
|
||||||
|
|
||||||
class EditorConfig : public IConfig
|
class EditorConfig : public IConfig
|
||||||
{
|
{
|
||||||
@ -62,6 +64,10 @@ namespace vnotex
|
|||||||
Debug,
|
Debug,
|
||||||
Print,
|
Print,
|
||||||
ClearHighlights,
|
ClearHighlights,
|
||||||
|
WordCount,
|
||||||
|
Attachment,
|
||||||
|
AlternateViewMode,
|
||||||
|
ParseToMarkdownAndPaste,
|
||||||
MaxShortcut
|
MaxShortcut
|
||||||
};
|
};
|
||||||
Q_ENUM(Shortcut)
|
Q_ENUM(Shortcut)
|
||||||
@ -101,6 +107,12 @@ namespace vnotex
|
|||||||
MarkdownEditorConfig &getMarkdownEditorConfig();
|
MarkdownEditorConfig &getMarkdownEditorConfig();
|
||||||
const MarkdownEditorConfig &getMarkdownEditorConfig() const;
|
const MarkdownEditorConfig &getMarkdownEditorConfig() const;
|
||||||
|
|
||||||
|
PdfViewerConfig &getPdfViewerConfig();
|
||||||
|
const PdfViewerConfig &getPdfViewerConfig() const;
|
||||||
|
|
||||||
|
MindMapEditorConfig &getMindMapEditorConfig();
|
||||||
|
const MindMapEditorConfig &getMindMapEditorConfig() const;
|
||||||
|
|
||||||
void init(const QJsonObject &p_app, const QJsonObject &p_user) Q_DECL_OVERRIDE;
|
void init(const QJsonObject &p_app, const QJsonObject &p_user) Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
QJsonObject toJson() const Q_DECL_OVERRIDE;
|
QJsonObject toJson() const Q_DECL_OVERRIDE;
|
||||||
@ -172,6 +184,10 @@ namespace vnotex
|
|||||||
|
|
||||||
QScopedPointer<MarkdownEditorConfig> m_markdownEditorConfig;
|
QScopedPointer<MarkdownEditorConfig> m_markdownEditorConfig;
|
||||||
|
|
||||||
|
QScopedPointer<PdfViewerConfig> m_pdfViewerConfig;
|
||||||
|
|
||||||
|
QScopedPointer<MindMapEditorConfig> m_mindMapEditorConfig;
|
||||||
|
|
||||||
bool m_spellCheckAutoDetectLanguageEnabled = false;
|
bool m_spellCheckAutoDetectLanguageEnabled = false;
|
||||||
|
|
||||||
QString m_spellCheckDefaultDictionary;
|
QString m_spellCheckDefaultDictionary;
|
||||||
|
@ -47,46 +47,46 @@ namespace vnotex
|
|||||||
{
|
{
|
||||||
switch (p_type) {
|
switch (p_type) {
|
||||||
case Type::InvalidPath:
|
case Type::InvalidPath:
|
||||||
return QString("InvalidPath");
|
return QStringLiteral("InvalidPath");
|
||||||
|
|
||||||
case Type::FailToCreateDir:
|
case Type::FailToCreateDir:
|
||||||
return QString("FailToCreateDir");
|
return QStringLiteral("FailToCreateDir");
|
||||||
|
|
||||||
case Type::FailToWriteFile:
|
case Type::FailToWriteFile:
|
||||||
return QString("FailToWriteFile");
|
return QStringLiteral("FailToWriteFile");
|
||||||
|
|
||||||
case Type::FailToReadFile:
|
case Type::FailToReadFile:
|
||||||
return QString("FailToReadFile");
|
return QStringLiteral("FailToReadFile");
|
||||||
|
|
||||||
case Type::FailToRenameFile:
|
case Type::FailToRenameFile:
|
||||||
return QString("FailToRenameFile");
|
return QStringLiteral("FailToRenameFile");
|
||||||
|
|
||||||
case Type::FailToCopyFile:
|
case Type::FailToCopyFile:
|
||||||
return QString("FailToCopyFile");
|
return QStringLiteral("FailToCopyFile");
|
||||||
|
|
||||||
case Type::FailToCopyDir:
|
case Type::FailToCopyDir:
|
||||||
return QString("FailToCopyDir");
|
return QStringLiteral("FailToCopyDir");
|
||||||
|
|
||||||
case Type::FailToRemoveFile:
|
case Type::FailToRemoveFile:
|
||||||
return QString("FailToRemoveFile");
|
return QStringLiteral("FailToRemoveFile");
|
||||||
|
|
||||||
case Type::FailToRemoveDir:
|
case Type::FailToRemoveDir:
|
||||||
return QString("FailToRemoveDir");
|
return QStringLiteral("FailToRemoveDir");
|
||||||
|
|
||||||
case Type::FileMissingOnDisk:
|
case Type::FileMissingOnDisk:
|
||||||
return QString("FileMissingOnDisk");
|
return QStringLiteral("FileMissingOnDisk");
|
||||||
|
|
||||||
case Type::EssentialFileMissing:
|
case Type::EssentialFileMissing:
|
||||||
return QString("EssentialFileMissing");
|
return QStringLiteral("EssentialFileMissing");
|
||||||
|
|
||||||
case Type::FileExistsOnCreate:
|
case Type::FileExistsOnCreate:
|
||||||
return QString("FileExistsOnCreate");
|
return QStringLiteral("FileExistsOnCreate");
|
||||||
|
|
||||||
case Type::DirExistsOnCreate:
|
case Type::DirExistsOnCreate:
|
||||||
return QString("DirExistsOnCreate");
|
return QStringLiteral("DirExistsOnCreate");
|
||||||
|
|
||||||
case Type::InvalidArgument:
|
case Type::InvalidArgument:
|
||||||
return QString("InvalidArgument");
|
return QStringLiteral("InvalidArgument");
|
||||||
}
|
}
|
||||||
|
|
||||||
return QString::number(static_cast<int>(p_type));
|
return QString::number(static_cast<int>(p_type));
|
||||||
|
@ -186,6 +186,18 @@ namespace vnotex
|
|||||||
// Used for comparison.
|
// Used for comparison.
|
||||||
ComparisonRole = 0x0103
|
ComparisonRole = 0x0103
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum ViewOrder
|
||||||
|
{
|
||||||
|
OrderedByConfiguration = 0,
|
||||||
|
OrderedByName,
|
||||||
|
OrderedByNameReversed,
|
||||||
|
OrderedByCreatedTime,
|
||||||
|
OrderedByCreatedTimeReversed,
|
||||||
|
OrderedByModifiedTime,
|
||||||
|
OrderedByModifiedTimeReversed,
|
||||||
|
ViewOrderMax
|
||||||
|
};
|
||||||
} // ns vnotex
|
} // ns vnotex
|
||||||
|
|
||||||
Q_DECLARE_OPERATORS_FOR_FLAGS(vnotex::FindOptions);
|
Q_DECLARE_OPERATORS_FOR_FLAGS(vnotex::FindOptions);
|
||||||
|
@ -94,6 +94,16 @@ const QVector<QSharedPointer<HistoryItemFull>> &HistoryMgr::getHistory() const
|
|||||||
return m_history;
|
return m_history;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void HistoryMgr::removeFromHistory(const QString &p_itemPath)
|
||||||
|
{
|
||||||
|
for (int i = m_history.size() - 1; i >= 0; --i) {
|
||||||
|
if (m_history[i]->m_item.m_path == p_itemPath) {
|
||||||
|
m_history.remove(i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void HistoryMgr::add(const QString &p_path,
|
void HistoryMgr::add(const QString &p_path,
|
||||||
int p_lineNumber,
|
int p_lineNumber,
|
||||||
ViewWindowMode p_mode,
|
ViewWindowMode p_mode,
|
||||||
@ -116,13 +126,7 @@ void HistoryMgr::add(const QString &p_path,
|
|||||||
|
|
||||||
// Maintain the combined queue.
|
// Maintain the combined queue.
|
||||||
{
|
{
|
||||||
for (int i = m_history.size() - 1; i >= 0; --i) {
|
removeFromHistory(item.m_path);
|
||||||
if (m_history[i]->m_item.m_path == item.m_path) {
|
|
||||||
// Erase it.
|
|
||||||
m_history.remove(i);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto fullItem = QSharedPointer<HistoryItemFull>::create();
|
auto fullItem = QSharedPointer<HistoryItemFull>::create();
|
||||||
fullItem->m_item = item;
|
fullItem->m_item = item;
|
||||||
@ -156,16 +160,35 @@ void HistoryMgr::add(const QString &p_path,
|
|||||||
emit historyUpdated();
|
emit historyUpdated();
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistoryMgr::insertHistoryItem(QVector<HistoryItem> &p_history, const HistoryItem &p_item)
|
void HistoryMgr::remove(const QVector<QString> &p_paths, Notebook *p_notebook)
|
||||||
|
{
|
||||||
|
for(const QString &p_itemPath : p_paths) {
|
||||||
|
if (p_notebook && m_perNotebookHistoryEnabled && p_notebook->history()) {
|
||||||
|
p_notebook->history()->removeHistory(p_itemPath);
|
||||||
|
} else {
|
||||||
|
auto &sessionConfig = ConfigMgr::getInst().getSessionConfig();
|
||||||
|
sessionConfig.removeHistory(p_itemPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
removeFromHistory(p_itemPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
emit historyUpdated();
|
||||||
|
}
|
||||||
|
|
||||||
|
void HistoryMgr::removeHistoryItem(QVector<HistoryItem> &p_history, const QString &p_itemPath)
|
||||||
{
|
{
|
||||||
for (int i = p_history.size() - 1; i >= 0; --i) {
|
for (int i = p_history.size() - 1; i >= 0; --i) {
|
||||||
if (p_history[i].m_path == p_item.m_path) {
|
if (p_history[i].m_path == p_itemPath) {
|
||||||
// Erase it.
|
|
||||||
p_history.remove(i);
|
p_history.remove(i);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void HistoryMgr::insertHistoryItem(QVector<HistoryItem> &p_history, const HistoryItem &p_item)
|
||||||
|
{
|
||||||
|
removeHistoryItem(p_history, p_item.m_path);
|
||||||
p_history.append(p_item);
|
p_history.append(p_item);
|
||||||
|
|
||||||
const int maxHistoryCount = ConfigMgr::getInst().getCoreConfig().getHistoryMaxCount();
|
const int maxHistoryCount = ConfigMgr::getInst().getCoreConfig().getHistoryMaxCount();
|
||||||
|
@ -55,10 +55,14 @@ namespace vnotex
|
|||||||
bool p_readOnly,
|
bool p_readOnly,
|
||||||
Notebook *p_notebook);
|
Notebook *p_notebook);
|
||||||
|
|
||||||
|
void remove(const QVector<QString> &p_paths, Notebook *p_notebook);
|
||||||
|
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
LastClosedFile popLastClosedFile();
|
LastClosedFile popLastClosedFile();
|
||||||
|
|
||||||
|
static void removeHistoryItem(QVector<HistoryItem> &p_history, const QString &p_itemPath);
|
||||||
|
|
||||||
static void insertHistoryItem(QVector<HistoryItem> &p_history, const HistoryItem &p_item);
|
static void insertHistoryItem(QVector<HistoryItem> &p_history, const HistoryItem &p_item);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
@ -72,6 +76,8 @@ namespace vnotex
|
|||||||
// Sorted by last accessed time ascendingly.
|
// Sorted by last accessed time ascendingly.
|
||||||
QVector<QSharedPointer<HistoryItemFull>> m_history;
|
QVector<QSharedPointer<HistoryItemFull>> m_history;
|
||||||
|
|
||||||
|
void removeFromHistory(const QString &p_itemPath);
|
||||||
|
|
||||||
QVector<LastClosedFile> m_lastClosedFiles;
|
QVector<LastClosedFile> m_lastClosedFiles;
|
||||||
|
|
||||||
const bool m_perNotebookHistoryEnabled = false;
|
const bool m_perNotebookHistoryEnabled = false;
|
||||||
|
@ -3,6 +3,8 @@
|
|||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
|
||||||
#include <core/markdowneditorconfig.h>
|
#include <core/markdowneditorconfig.h>
|
||||||
|
#include <core/pdfviewerconfig.h>
|
||||||
|
#include <core/mindmapeditorconfig.h>
|
||||||
#include <core/configmgr.h>
|
#include <core/configmgr.h>
|
||||||
#include <utils/utils.h>
|
#include <utils/utils.h>
|
||||||
#include <utils/fileutils.h>
|
#include <utils/fileutils.h>
|
||||||
@ -16,30 +18,34 @@ using namespace vnotex;
|
|||||||
|
|
||||||
HtmlTemplateHelper::Template HtmlTemplateHelper::s_markdownViewerTemplate;
|
HtmlTemplateHelper::Template HtmlTemplateHelper::s_markdownViewerTemplate;
|
||||||
|
|
||||||
QString WebGlobalOptions::toJavascriptObject() const
|
HtmlTemplateHelper::Template HtmlTemplateHelper::s_pdfViewerTemplate;
|
||||||
|
|
||||||
|
HtmlTemplateHelper::Template HtmlTemplateHelper::s_mindMapEditorTemplate;
|
||||||
|
|
||||||
|
QString MarkdownWebGlobalOptions::toJavascriptObject() const
|
||||||
{
|
{
|
||||||
return QStringLiteral("window.vxOptions = {\n")
|
return QStringLiteral("window.vxOptions = {\n")
|
||||||
+ QString("webPlantUml: %1,\n").arg(Utils::boolToString(m_webPlantUml))
|
+ QStringLiteral("webPlantUml: %1,\n").arg(Utils::boolToString(m_webPlantUml))
|
||||||
+ QString("plantUmlWebService: '%1',\n").arg(m_plantUmlWebService)
|
+ QStringLiteral("plantUmlWebService: '%1',\n").arg(m_plantUmlWebService)
|
||||||
+ QString("webGraphviz: %1,\n").arg(Utils::boolToString(m_webGraphviz))
|
+ QStringLiteral("webGraphviz: %1,\n").arg(Utils::boolToString(m_webGraphviz))
|
||||||
+ QString("mathJaxScript: '%1',\n").arg(m_mathJaxScript)
|
+ QStringLiteral("mathJaxScript: '%1',\n").arg(m_mathJaxScript)
|
||||||
+ QString("constrainImageWidthEnabled: %1,\n").arg(Utils::boolToString(m_constrainImageWidthEnabled))
|
+ QStringLiteral("constrainImageWidthEnabled: %1,\n").arg(Utils::boolToString(m_constrainImageWidthEnabled))
|
||||||
+ QString("imageAlignCenterEnabled: %1,\n").arg(Utils::boolToString(m_imageAlignCenterEnabled))
|
+ QStringLiteral("imageAlignCenterEnabled: %1,\n").arg(Utils::boolToString(m_imageAlignCenterEnabled))
|
||||||
+ QString("protectFromXss: %1,\n").arg(Utils::boolToString(m_protectFromXss))
|
+ QStringLiteral("protectFromXss: %1,\n").arg(Utils::boolToString(m_protectFromXss))
|
||||||
+ QString("htmlTagEnabled: %1,\n").arg(Utils::boolToString(m_htmlTagEnabled))
|
+ QStringLiteral("htmlTagEnabled: %1,\n").arg(Utils::boolToString(m_htmlTagEnabled))
|
||||||
+ QString("autoBreakEnabled: %1,\n").arg(Utils::boolToString(m_autoBreakEnabled))
|
+ QStringLiteral("autoBreakEnabled: %1,\n").arg(Utils::boolToString(m_autoBreakEnabled))
|
||||||
+ QString("linkifyEnabled: %1,\n").arg(Utils::boolToString(m_linkifyEnabled))
|
+ QStringLiteral("linkifyEnabled: %1,\n").arg(Utils::boolToString(m_linkifyEnabled))
|
||||||
+ QString("indentFirstLineEnabled: %1,\n").arg(Utils::boolToString(m_indentFirstLineEnabled))
|
+ QStringLiteral("indentFirstLineEnabled: %1,\n").arg(Utils::boolToString(m_indentFirstLineEnabled))
|
||||||
+ QString("codeBlockLineNumberEnabled: %1,\n").arg(Utils::boolToString(m_codeBlockLineNumberEnabled))
|
+ QStringLiteral("codeBlockLineNumberEnabled: %1,\n").arg(Utils::boolToString(m_codeBlockLineNumberEnabled))
|
||||||
+ QString("sectionNumberEnabled: %1,\n").arg(Utils::boolToString(m_sectionNumberEnabled))
|
+ QStringLiteral("sectionNumberEnabled: %1,\n").arg(Utils::boolToString(m_sectionNumberEnabled))
|
||||||
+ QString("transparentBackgroundEnabled: %1,\n").arg(Utils::boolToString(m_transparentBackgroundEnabled))
|
+ QStringLiteral("transparentBackgroundEnabled: %1,\n").arg(Utils::boolToString(m_transparentBackgroundEnabled))
|
||||||
+ QString("scrollable: %1,\n").arg(Utils::boolToString(m_scrollable))
|
+ QStringLiteral("scrollable: %1,\n").arg(Utils::boolToString(m_scrollable))
|
||||||
+ QString("bodyWidth: %1,\n").arg(m_bodyWidth)
|
+ QStringLiteral("bodyWidth: %1,\n").arg(m_bodyWidth)
|
||||||
+ QString("bodyHeight: %1,\n").arg(m_bodyHeight)
|
+ QStringLiteral("bodyHeight: %1,\n").arg(m_bodyHeight)
|
||||||
+ QString("transformSvgToPngEnabled: %1,\n").arg(Utils::boolToString(m_transformSvgToPngEnabled))
|
+ QStringLiteral("transformSvgToPngEnabled: %1,\n").arg(Utils::boolToString(m_transformSvgToPngEnabled))
|
||||||
+ QString("mathJaxScale: %1,\n").arg(m_mathJaxScale)
|
+ QStringLiteral("mathJaxScale: %1,\n").arg(m_mathJaxScale)
|
||||||
+ QString("removeCodeToolBarEnabled: %1,\n").arg(Utils::boolToString(m_removeCodeToolBarEnabled))
|
+ QStringLiteral("removeCodeToolBarEnabled: %1,\n").arg(Utils::boolToString(m_removeCodeToolBarEnabled))
|
||||||
+ QString("sectionNumberBaseLevel: %1\n").arg(m_sectionNumberBaseLevel)
|
+ QStringLiteral("sectionNumberBaseLevel: %1\n").arg(m_sectionNumberBaseLevel)
|
||||||
+ QStringLiteral("}");
|
+ QStringLiteral("}");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,7 +83,7 @@ static QString fillStyleTag(const QString &p_styleFile)
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
auto url = PathUtils::pathToUrl(p_styleFile);
|
auto url = PathUtils::pathToUrl(p_styleFile);
|
||||||
return QString("<link rel=\"stylesheet\" type=\"text/css\" href=\"%1\">\n").arg(url.toString());
|
return QStringLiteral("<link rel=\"stylesheet\" type=\"text/css\" href=\"%1\">\n").arg(url.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
static QString fillScriptTag(const QString &p_scriptFile)
|
static QString fillScriptTag(const QString &p_scriptFile)
|
||||||
@ -86,7 +92,7 @@ static QString fillScriptTag(const QString &p_scriptFile)
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
auto url = PathUtils::pathToUrl(p_scriptFile);
|
auto url = PathUtils::pathToUrl(p_scriptFile);
|
||||||
return QString("<script type=\"text/javascript\" src=\"%1\"></script>\n").arg(url.toString());
|
return QStringLiteral("<script type=\"text/javascript\" src=\"%1\"></script>\n").arg(url.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
static void fillThemeStyles(QString &p_template, const QString &p_webStyleSheetFile, const QString &p_highlightStyleSheetFile)
|
static void fillThemeStyles(QString &p_template, const QString &p_webStyleSheetFile, const QString &p_highlightStyleSheetFile)
|
||||||
@ -101,7 +107,7 @@ static void fillThemeStyles(QString &p_template, const QString &p_webStyleSheetF
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void fillGlobalOptions(QString &p_template, const WebGlobalOptions &p_opts)
|
static void fillGlobalOptions(QString &p_template, const MarkdownWebGlobalOptions &p_opts)
|
||||||
{
|
{
|
||||||
p_template.replace(QStringLiteral("/* VX_GLOBAL_OPTIONS_PLACEHOLDER */"),
|
p_template.replace(QStringLiteral("/* VX_GLOBAL_OPTIONS_PLACEHOLDER */"),
|
||||||
p_opts.toJavascriptObject());
|
p_opts.toJavascriptObject());
|
||||||
@ -187,7 +193,7 @@ void HtmlTemplateHelper::updateMarkdownViewerTemplate(const MarkdownEditorConfig
|
|||||||
|
|
||||||
s_markdownViewerTemplate.m_revision = p_config.revision();
|
s_markdownViewerTemplate.m_revision = p_config.revision();
|
||||||
|
|
||||||
Paras paras;
|
MarkdownParas paras;
|
||||||
const auto &themeMgr = VNoteX::getInst().getThemeMgr();
|
const auto &themeMgr = VNoteX::getInst().getThemeMgr();
|
||||||
paras.m_webStyleSheetFile = themeMgr.getFile(Theme::File::WebStyleSheet);
|
paras.m_webStyleSheetFile = themeMgr.getFile(Theme::File::WebStyleSheet);
|
||||||
paras.m_highlightStyleSheetFile = themeMgr.getFile(Theme::File::HighlightStyleSheet);
|
paras.m_highlightStyleSheetFile = themeMgr.getFile(Theme::File::HighlightStyleSheet);
|
||||||
@ -195,7 +201,8 @@ void HtmlTemplateHelper::updateMarkdownViewerTemplate(const MarkdownEditorConfig
|
|||||||
s_markdownViewerTemplate.m_template = generateMarkdownViewerTemplate(p_config, paras);
|
s_markdownViewerTemplate.m_template = generateMarkdownViewerTemplate(p_config, paras);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString HtmlTemplateHelper::generateMarkdownViewerTemplate(const MarkdownEditorConfig &p_config, const Paras &p_paras)
|
QString HtmlTemplateHelper::generateMarkdownViewerTemplate(const MarkdownEditorConfig &p_config,
|
||||||
|
const MarkdownParas &p_paras)
|
||||||
{
|
{
|
||||||
const auto &viewerResource = p_config.getViewerResource();
|
const auto &viewerResource = p_config.getViewerResource();
|
||||||
const auto templateFile = ConfigMgr::getInst().getUserOrAppFile(viewerResource.m_template);
|
const auto templateFile = ConfigMgr::getInst().getUserOrAppFile(viewerResource.m_template);
|
||||||
@ -212,7 +219,7 @@ QString HtmlTemplateHelper::generateMarkdownViewerTemplate(const MarkdownEditorC
|
|||||||
fillThemeStyles(htmlTemplate, p_paras.m_webStyleSheetFile, p_paras.m_highlightStyleSheetFile);
|
fillThemeStyles(htmlTemplate, p_paras.m_webStyleSheetFile, p_paras.m_highlightStyleSheetFile);
|
||||||
|
|
||||||
{
|
{
|
||||||
WebGlobalOptions opts;
|
MarkdownWebGlobalOptions opts;
|
||||||
opts.m_webPlantUml = p_config.getWebPlantUml();
|
opts.m_webPlantUml = p_config.getWebPlantUml();
|
||||||
opts.m_plantUmlWebService = p_config.getPlantUmlWebService();
|
opts.m_plantUmlWebService = p_config.getPlantUmlWebService();
|
||||||
opts.m_webGraphviz = p_config.getWebGraphviz();
|
opts.m_webGraphviz = p_config.getWebGraphviz();
|
||||||
@ -242,8 +249,8 @@ QString HtmlTemplateHelper::generateMarkdownViewerTemplate(const MarkdownEditorC
|
|||||||
return htmlTemplate;
|
return htmlTemplate;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString HtmlTemplateHelper::generateExportTemplate(const MarkdownEditorConfig &p_config,
|
QString HtmlTemplateHelper::generateMarkdownExportTemplate(const MarkdownEditorConfig &p_config,
|
||||||
bool p_addOutlinePanel)
|
bool p_addOutlinePanel)
|
||||||
{
|
{
|
||||||
auto exportResource = p_config.getExportResource();
|
auto exportResource = p_config.getExportResource();
|
||||||
const auto templateFile = ConfigMgr::getInst().getUserOrAppFile(exportResource.m_template);
|
const auto templateFile = ConfigMgr::getInst().getUserOrAppFile(exportResource.m_template);
|
||||||
@ -251,7 +258,7 @@ QString HtmlTemplateHelper::generateExportTemplate(const MarkdownEditorConfig &p
|
|||||||
try {
|
try {
|
||||||
htmlTemplate = FileUtils::readTextFile(templateFile);
|
htmlTemplate = FileUtils::readTextFile(templateFile);
|
||||||
} catch (Exception &p_e) {
|
} catch (Exception &p_e) {
|
||||||
qWarning() << "failed to read export HTML template" << templateFile << p_e.what();
|
qWarning() << "failed to read Markdown export HTML template" << templateFile << p_e.what();
|
||||||
return errorPage();
|
return errorPage();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -293,7 +300,7 @@ void HtmlTemplateHelper::fillTitle(QString &p_template, const QString &p_title)
|
|||||||
{
|
{
|
||||||
if (!p_title.isEmpty()) {
|
if (!p_title.isEmpty()) {
|
||||||
p_template.replace("<!-- VX_TITLE_PLACEHOLDER -->",
|
p_template.replace("<!-- VX_TITLE_PLACEHOLDER -->",
|
||||||
QString("<title>%1</title>").arg(HtmlUtils::escapeHtml(p_title)));
|
QStringLiteral("<title>%1</title>").arg(HtmlUtils::escapeHtml(p_title)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -322,3 +329,75 @@ QString HtmlTemplateHelper::errorPage()
|
|||||||
return VNoteX::tr("Failed to load HTML template. Check the logs for details. "
|
return VNoteX::tr("Failed to load HTML template. Check the logs for details. "
|
||||||
"Try deleting the user configuration file and the default configuration file.");
|
"Try deleting the user configuration file and the default configuration file.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const QString &HtmlTemplateHelper::getPdfViewerTemplate()
|
||||||
|
{
|
||||||
|
return s_pdfViewerTemplate.m_template;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString &HtmlTemplateHelper::getPdfViewerTemplatePath()
|
||||||
|
{
|
||||||
|
return s_pdfViewerTemplate.m_templatePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HtmlTemplateHelper::updatePdfViewerTemplate(const PdfViewerConfig &p_config, bool p_force)
|
||||||
|
{
|
||||||
|
if (!p_force && p_config.revision() == s_pdfViewerTemplate.m_revision) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
s_pdfViewerTemplate.m_revision = p_config.revision();
|
||||||
|
generatePdfViewerTemplate(p_config, s_pdfViewerTemplate);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HtmlTemplateHelper::generatePdfViewerTemplate(const PdfViewerConfig &p_config, Template& p_template)
|
||||||
|
{
|
||||||
|
const auto &viewerResource = p_config.getViewerResource();
|
||||||
|
p_template.m_templatePath = ConfigMgr::getInst().getUserOrAppFile(viewerResource.m_template);
|
||||||
|
try {
|
||||||
|
p_template.m_template = FileUtils::readTextFile(p_template.m_templatePath);
|
||||||
|
} catch (Exception &p_e) {
|
||||||
|
qWarning() << "failed to read HTML template" << p_template.m_templatePath << p_e.what();
|
||||||
|
p_template.m_template = errorPage();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fillResources(p_template.m_template, viewerResource);
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString &HtmlTemplateHelper::getMindMapEditorTemplate()
|
||||||
|
{
|
||||||
|
return s_mindMapEditorTemplate.m_template;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HtmlTemplateHelper::updateMindMapEditorTemplate(const MindMapEditorConfig &p_config, bool p_force)
|
||||||
|
{
|
||||||
|
if (!p_force && p_config.revision() == s_mindMapEditorTemplate.m_revision) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
s_mindMapEditorTemplate.m_revision = p_config.revision();
|
||||||
|
|
||||||
|
generateMindMapEditorTemplate(p_config,
|
||||||
|
QString() /* Use empty theme style for now */,
|
||||||
|
s_mindMapEditorTemplate);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HtmlTemplateHelper::generateMindMapEditorTemplate(const MindMapEditorConfig &p_config,
|
||||||
|
const QString &p_webStyleSheetFile,
|
||||||
|
Template& p_template)
|
||||||
|
{
|
||||||
|
const auto &editorResource = p_config.getEditorResource();
|
||||||
|
p_template.m_templatePath = ConfigMgr::getInst().getUserOrAppFile(editorResource.m_template);
|
||||||
|
try {
|
||||||
|
p_template.m_template = FileUtils::readTextFile(p_template.m_templatePath);
|
||||||
|
} catch (Exception &p_e) {
|
||||||
|
qWarning() << "failed to read HTML template" << p_template.m_templatePath << p_e.what();
|
||||||
|
p_template.m_template = errorPage();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fillThemeStyles(p_template.m_template, p_webStyleSheetFile, QString());
|
||||||
|
|
||||||
|
fillResources(p_template.m_template, editorResource);
|
||||||
|
}
|
||||||
|
@ -6,10 +6,12 @@
|
|||||||
namespace vnotex
|
namespace vnotex
|
||||||
{
|
{
|
||||||
class MarkdownEditorConfig;
|
class MarkdownEditorConfig;
|
||||||
|
class PdfViewerConfig;
|
||||||
|
class MindMapEditorConfig;
|
||||||
struct WebResource;
|
struct WebResource;
|
||||||
|
|
||||||
// Global options to be passed to Web side at the very beginning.
|
// Global options to be passed to Web side at the very beginning for Markdown.
|
||||||
struct WebGlobalOptions
|
struct MarkdownWebGlobalOptions
|
||||||
{
|
{
|
||||||
bool m_webPlantUml = true;
|
bool m_webPlantUml = true;
|
||||||
|
|
||||||
@ -67,7 +69,7 @@ namespace vnotex
|
|||||||
class HtmlTemplateHelper
|
class HtmlTemplateHelper
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
struct Paras
|
struct MarkdownParas
|
||||||
{
|
{
|
||||||
QString m_webStyleSheetFile;
|
QString m_webStyleSheetFile;
|
||||||
|
|
||||||
@ -90,14 +92,16 @@ namespace vnotex
|
|||||||
|
|
||||||
HtmlTemplateHelper() = delete;
|
HtmlTemplateHelper() = delete;
|
||||||
|
|
||||||
|
// For MarkdownViewer.
|
||||||
static const QString &getMarkdownViewerTemplate();
|
static const QString &getMarkdownViewerTemplate();
|
||||||
static void updateMarkdownViewerTemplate(const MarkdownEditorConfig &p_config, bool p_force = false);
|
static void updateMarkdownViewerTemplate(const MarkdownEditorConfig &p_config, bool p_force = false);
|
||||||
|
|
||||||
static QString generateMarkdownViewerTemplate(const MarkdownEditorConfig &p_config, const Paras &p_paras);
|
static QString generateMarkdownViewerTemplate(const MarkdownEditorConfig &p_config, const MarkdownParas &p_paras);
|
||||||
|
|
||||||
static QString generateExportTemplate(const MarkdownEditorConfig &p_config,
|
static QString generateMarkdownExportTemplate(const MarkdownEditorConfig &p_config,
|
||||||
bool p_addOutlinePanel);
|
bool p_addOutlinePanel);
|
||||||
|
|
||||||
|
// For common HTML content manipulation.
|
||||||
static void fillTitle(QString &p_template, const QString &p_title);
|
static void fillTitle(QString &p_template, const QString &p_title);
|
||||||
|
|
||||||
static void fillStyleContent(QString &p_template, const QString &p_styles);
|
static void fillStyleContent(QString &p_template, const QString &p_styles);
|
||||||
@ -110,17 +114,37 @@ namespace vnotex
|
|||||||
|
|
||||||
static void fillOutlinePanel(QString &p_template, WebResource &p_exportResource, bool p_addOutlinePanel);
|
static void fillOutlinePanel(QString &p_template, WebResource &p_exportResource, bool p_addOutlinePanel);
|
||||||
|
|
||||||
private:
|
// For PdfViewer.
|
||||||
static QString errorPage();
|
static const QString &getPdfViewerTemplate();
|
||||||
|
static void updatePdfViewerTemplate(const PdfViewerConfig &p_config, bool p_force = false);
|
||||||
|
|
||||||
|
static const QString &getPdfViewerTemplatePath();
|
||||||
|
|
||||||
|
// For MindMapEditor.
|
||||||
|
static const QString &getMindMapEditorTemplate();
|
||||||
|
static void updateMindMapEditorTemplate(const MindMapEditorConfig &p_config, bool p_force = false);
|
||||||
|
|
||||||
|
private:
|
||||||
struct Template
|
struct Template
|
||||||
{
|
{
|
||||||
int m_revision = -1;
|
int m_revision = -1;
|
||||||
QString m_template;
|
QString m_template;
|
||||||
|
QString m_templatePath;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Template for MarkdownViewer.
|
static QString errorPage();
|
||||||
|
|
||||||
|
static void generatePdfViewerTemplate(const PdfViewerConfig &p_config, Template& p_template);
|
||||||
|
|
||||||
|
static void generateMindMapEditorTemplate(const MindMapEditorConfig &p_config,
|
||||||
|
const QString &p_webStyleSheetFile,
|
||||||
|
Template& p_template);
|
||||||
|
|
||||||
static Template s_markdownViewerTemplate;
|
static Template s_markdownViewerTemplate;
|
||||||
|
|
||||||
|
static Template s_pdfViewerTemplate;
|
||||||
|
|
||||||
|
static Template s_mindMapEditorTemplate;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
#include <QJsonArray>
|
#include <QJsonArray>
|
||||||
#include <QBitArray>
|
#include <QBitArray>
|
||||||
#include <QDataStream>
|
#include <QDataStream>
|
||||||
|
#include <QIODevice>
|
||||||
|
|
||||||
namespace vnotex
|
namespace vnotex
|
||||||
{
|
{
|
||||||
|
@ -8,19 +8,27 @@ using namespace vnotex;
|
|||||||
|
|
||||||
QFile Logger::s_file;
|
QFile Logger::s_file;
|
||||||
|
|
||||||
bool Logger::s_debugLog = false;
|
bool Logger::s_verbose = false;
|
||||||
|
|
||||||
void Logger::init(bool p_debugLog)
|
bool Logger::s_logToStderr = false;
|
||||||
|
|
||||||
|
void Logger::init(bool p_verbose, bool p_logToStderr)
|
||||||
{
|
{
|
||||||
s_debugLog = p_debugLog;
|
s_verbose = p_verbose;
|
||||||
|
s_logToStderr = p_logToStderr;
|
||||||
|
|
||||||
#if defined(QT_NO_DEBUG)
|
#if defined(QT_NO_DEBUG)
|
||||||
s_file.setFileName(ConfigMgr::getInst().getLogFile());
|
if (!s_logToStderr) {
|
||||||
if (s_file.size() >= 5 * 1024 * 1024) {
|
s_file.setFileName(ConfigMgr::getInst().getLogFile());
|
||||||
s_file.open(QIODevice::WriteOnly | QIODevice::Text);
|
if (s_file.size() >= 5 * 1024 * 1024) {
|
||||||
} else {
|
s_file.open(QIODevice::WriteOnly | QIODevice::Text);
|
||||||
s_file.open(QIODevice::Append | QIODevice::Text);
|
} else {
|
||||||
|
s_file.open(QIODevice::Append | QIODevice::Text);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
// Always log to stderr in debug.
|
||||||
|
s_logToStderr = true;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
qInstallMessageHandler(Logger::log);
|
qInstallMessageHandler(Logger::log);
|
||||||
@ -44,7 +52,7 @@ static QString getFileName(const char *p_file)
|
|||||||
void Logger::log(QtMsgType p_type, const QMessageLogContext &p_context, const QString &p_msg)
|
void Logger::log(QtMsgType p_type, const QMessageLogContext &p_context, const QString &p_msg)
|
||||||
{
|
{
|
||||||
#if defined(QT_NO_DEBUG)
|
#if defined(QT_NO_DEBUG)
|
||||||
if (!s_debugLog && p_type == QtDebugMsg) {
|
if (!s_verbose && p_type == QtDebugMsg) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -76,43 +84,43 @@ void Logger::log(QtMsgType p_type, const QMessageLogContext &p_context, const QS
|
|||||||
|
|
||||||
QString fileName = getFileName(p_context.file);
|
QString fileName = getFileName(p_context.file);
|
||||||
|
|
||||||
#if defined(QT_NO_DEBUG)
|
if (!s_logToStderr) {
|
||||||
QTextStream stream(&s_file);
|
QTextStream stream(&s_file);
|
||||||
stream << header << (QString("(%1:%2) ").arg(fileName).arg(p_context.line))
|
stream << header << (QStringLiteral("(%1:%2) ").arg(fileName).arg(p_context.line))
|
||||||
<< localMsg << "\n";
|
<< localMsg << "\n";
|
||||||
|
|
||||||
if (p_type == QtFatalMsg) {
|
if (p_type == QtFatalMsg) {
|
||||||
s_file.close();
|
s_file.close();
|
||||||
abort();
|
abort();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
std::string fileStr = fileName.toStdString();
|
||||||
|
const char *file = fileStr.c_str();
|
||||||
|
|
||||||
|
switch (p_type) {
|
||||||
|
case QtDebugMsg:
|
||||||
|
fprintf(stderr, "%s(%s:%u) %s\n",
|
||||||
|
header.toStdString().c_str(), file, p_context.line, localMsg.constData());
|
||||||
|
break;
|
||||||
|
case QtInfoMsg:
|
||||||
|
fprintf(stderr, "%s(%s:%u) %s\n",
|
||||||
|
header.toStdString().c_str(), file, p_context.line, localMsg.constData());
|
||||||
|
break;
|
||||||
|
case QtWarningMsg:
|
||||||
|
fprintf(stderr, "%s(%s:%u) %s\n",
|
||||||
|
header.toStdString().c_str(), file, p_context.line, localMsg.constData());
|
||||||
|
break;
|
||||||
|
case QtCriticalMsg:
|
||||||
|
fprintf(stderr, "%s(%s:%u) %s\n",
|
||||||
|
header.toStdString().c_str(), file, p_context.line, localMsg.constData());
|
||||||
|
break;
|
||||||
|
case QtFatalMsg:
|
||||||
|
fprintf(stderr, "%s(%s:%u) %s\n",
|
||||||
|
header.toStdString().c_str(), file, p_context.line, localMsg.constData());
|
||||||
|
abort();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
fflush(stderr);
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
std::string fileStr = fileName.toStdString();
|
|
||||||
const char *file = fileStr.c_str();
|
|
||||||
|
|
||||||
switch (p_type) {
|
|
||||||
case QtDebugMsg:
|
|
||||||
fprintf(stderr, "%s(%s:%u) %s\n",
|
|
||||||
header.toStdString().c_str(), file, p_context.line, localMsg.constData());
|
|
||||||
break;
|
|
||||||
case QtInfoMsg:
|
|
||||||
fprintf(stderr, "%s(%s:%u) %s\n",
|
|
||||||
header.toStdString().c_str(), file, p_context.line, localMsg.constData());
|
|
||||||
break;
|
|
||||||
case QtWarningMsg:
|
|
||||||
fprintf(stderr, "%s(%s:%u) %s\n",
|
|
||||||
header.toStdString().c_str(), file, p_context.line, localMsg.constData());
|
|
||||||
break;
|
|
||||||
case QtCriticalMsg:
|
|
||||||
fprintf(stderr, "%s(%s:%u) %s\n",
|
|
||||||
header.toStdString().c_str(), file, p_context.line, localMsg.constData());
|
|
||||||
break;
|
|
||||||
case QtFatalMsg:
|
|
||||||
fprintf(stderr, "%s(%s:%u) %s\n",
|
|
||||||
header.toStdString().c_str(), file, p_context.line, localMsg.constData());
|
|
||||||
abort();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
fflush(stderr);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
@ -13,14 +13,16 @@ namespace vnotex
|
|||||||
public:
|
public:
|
||||||
Logger() = delete;
|
Logger() = delete;
|
||||||
|
|
||||||
static void init(bool p_debugLog);
|
static void init(bool p_verbose, bool p_logToStderr);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void log(QtMsgType p_type, const QMessageLogContext &p_context, const QString &p_msg);
|
static void log(QtMsgType p_type, const QMessageLogContext &p_context, const QString &p_msg);
|
||||||
|
|
||||||
static QFile s_file;
|
static QFile s_file;
|
||||||
|
|
||||||
static bool s_debugLog;
|
static bool s_verbose;
|
||||||
|
|
||||||
|
static bool s_logToStderr;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -231,7 +231,7 @@ namespace vnotex
|
|||||||
bool m_fetchImagesInParseAndPaste = true;
|
bool m_fetchImagesInParseAndPaste = true;
|
||||||
|
|
||||||
// Whether protect from Cross-Site Scripting.
|
// Whether protect from Cross-Site Scripting.
|
||||||
bool m_protectFromXss = false;
|
bool m_protectFromXss = true;
|
||||||
|
|
||||||
// Whether allow HTML tag in Markdown source.
|
// Whether allow HTML tag in Markdown source.
|
||||||
bool m_htmlTagEnabled = true;
|
bool m_htmlTagEnabled = true;
|
||||||
|
61
src/core/mindmapeditorconfig.cpp
Normal file
61
src/core/mindmapeditorconfig.cpp
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
#include "mindmapeditorconfig.h"
|
||||||
|
|
||||||
|
#include "mainconfig.h"
|
||||||
|
|
||||||
|
#define READSTR(key) readString(appObj, userObj, (key))
|
||||||
|
#define READBOOL(key) readBool(appObj, userObj, (key))
|
||||||
|
#define READINT(key) readInt(appObj, userObj, (key))
|
||||||
|
|
||||||
|
using namespace vnotex;
|
||||||
|
|
||||||
|
MindMapEditorConfig::MindMapEditorConfig(ConfigMgr *p_mgr, IConfig *p_topConfig)
|
||||||
|
: IConfig(p_mgr, p_topConfig)
|
||||||
|
{
|
||||||
|
m_sessionName = QStringLiteral("mindmap_editor");
|
||||||
|
}
|
||||||
|
|
||||||
|
void MindMapEditorConfig::init(const QJsonObject &p_app,
|
||||||
|
const QJsonObject &p_user)
|
||||||
|
{
|
||||||
|
const auto appObj = p_app.value(m_sessionName).toObject();
|
||||||
|
const auto userObj = p_user.value(m_sessionName).toObject();
|
||||||
|
|
||||||
|
loadEditorResource(appObj, userObj);
|
||||||
|
}
|
||||||
|
|
||||||
|
QJsonObject MindMapEditorConfig::toJson() const
|
||||||
|
{
|
||||||
|
QJsonObject obj;
|
||||||
|
obj[QStringLiteral("editor_resource")] = saveEditorResource();
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MindMapEditorConfig::loadEditorResource(const QJsonObject &p_app, const QJsonObject &p_user)
|
||||||
|
{
|
||||||
|
const QString name(QStringLiteral("editor_resource"));
|
||||||
|
|
||||||
|
if (MainConfig::isVersionChanged()) {
|
||||||
|
bool needOverride = p_app[QStringLiteral("override_editor_resource")].toBool();
|
||||||
|
if (needOverride) {
|
||||||
|
qInfo() << "override \"editor_resource\" in user configuration due to version change";
|
||||||
|
m_editorResource.init(p_app[name].toObject());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p_user.contains(name)) {
|
||||||
|
m_editorResource.init(p_user[name].toObject());
|
||||||
|
} else {
|
||||||
|
m_editorResource.init(p_app[name].toObject());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QJsonObject MindMapEditorConfig::saveEditorResource() const
|
||||||
|
{
|
||||||
|
return m_editorResource.toJson();
|
||||||
|
}
|
||||||
|
|
||||||
|
const WebResource &MindMapEditorConfig::getEditorResource() const
|
||||||
|
{
|
||||||
|
return m_editorResource;
|
||||||
|
}
|
31
src/core/mindmapeditorconfig.h
Normal file
31
src/core/mindmapeditorconfig.h
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
#ifndef MINDMAPEDITORCONFIG_H
|
||||||
|
#define MINDMAPEDITORCONFIG_H
|
||||||
|
|
||||||
|
#include "iconfig.h"
|
||||||
|
|
||||||
|
#include "webresource.h"
|
||||||
|
|
||||||
|
namespace vnotex
|
||||||
|
{
|
||||||
|
class MindMapEditorConfig : public IConfig
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MindMapEditorConfig(ConfigMgr *p_mgr, IConfig *p_topConfig);
|
||||||
|
|
||||||
|
void init(const QJsonObject &p_app, const QJsonObject &p_user) Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
|
QJsonObject toJson() const Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
|
const WebResource &getEditorResource() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend class MainConfig;
|
||||||
|
|
||||||
|
void loadEditorResource(const QJsonObject &p_app, const QJsonObject &p_user);
|
||||||
|
QJsonObject saveEditorResource() const;
|
||||||
|
|
||||||
|
WebResource m_editorResource;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // MINDMAPEDITORCONFIG_H
|
@ -93,7 +93,7 @@ void BundleNotebook::remove()
|
|||||||
|
|
||||||
// Remove notebook root folder if it is empty.
|
// Remove notebook root folder if it is empty.
|
||||||
if (!FileUtils::removeDirIfEmpty(getRootFolderAbsolutePath())) {
|
if (!FileUtils::removeDirIfEmpty(getRootFolderAbsolutePath())) {
|
||||||
qInfo() << QString("root folder of notebook (%1) is not empty and needs manual clean up")
|
qInfo() << QStringLiteral("root folder of notebook (%1) is not empty and needs manual clean up")
|
||||||
.arg(getRootFolderAbsolutePath());
|
.arg(getRootFolderAbsolutePath());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -108,6 +108,13 @@ const QVector<HistoryItem> &BundleNotebook::getHistory() const
|
|||||||
return m_history;
|
return m_history;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BundleNotebook::removeHistory(const QString &p_itemPath)
|
||||||
|
{
|
||||||
|
HistoryMgr::removeHistoryItem(m_history, p_itemPath);
|
||||||
|
|
||||||
|
updateNotebookConfig();
|
||||||
|
}
|
||||||
|
|
||||||
void BundleNotebook::addHistory(const HistoryItem &p_item)
|
void BundleNotebook::addHistory(const HistoryItem &p_item)
|
||||||
{
|
{
|
||||||
HistoryItem item(p_item);
|
HistoryItem item(p_item);
|
||||||
|
@ -49,6 +49,8 @@ namespace vnotex
|
|||||||
|
|
||||||
const QVector<HistoryItem> &getHistory() const Q_DECL_OVERRIDE;
|
const QVector<HistoryItem> &getHistory() const Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
|
void removeHistory(const QString &p_itemPath) Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
void addHistory(const HistoryItem &p_item) Q_DECL_OVERRIDE;
|
void addHistory(const HistoryItem &p_item) Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
void clearHistory() Q_DECL_OVERRIDE;
|
void clearHistory() Q_DECL_OVERRIDE;
|
||||||
|
@ -40,7 +40,7 @@ static void checkRootFolderForNewNotebook(const NotebookParameters &p_paras)
|
|||||||
qCritical() << msg;
|
qCritical() << msg;
|
||||||
throw Exception(Exception::Type::InvalidPath, msg);
|
throw Exception(Exception::Type::InvalidPath, msg);
|
||||||
} else if (p_paras.m_ensureEmptyRootFolder && !PathUtils::isEmptyDir(p_paras.m_rootFolderPath)) {
|
} else if (p_paras.m_ensureEmptyRootFolder && !PathUtils::isEmptyDir(p_paras.m_rootFolderPath)) {
|
||||||
QString msg = QString("local root folder must be empty: %1 (%2)")
|
QString msg = QStringLiteral("local root folder must be empty: %1 (%2)")
|
||||||
.arg(p_paras.m_rootFolderPath, PathUtils::absolutePath(p_paras.m_rootFolderPath));
|
.arg(p_paras.m_rootFolderPath, PathUtils::absolutePath(p_paras.m_rootFolderPath));
|
||||||
qCritical() << msg;
|
qCritical() << msg;
|
||||||
throw Exception(Exception::Type::InvalidPath, msg);
|
throw Exception(Exception::Type::InvalidPath, msg);
|
||||||
@ -88,7 +88,7 @@ void BundleNotebookFactory::checkParameters(const NotebookParameters &p_paras) c
|
|||||||
auto configMgr = dynamic_cast<BundleNotebookConfigMgr *>(p_paras.m_notebookConfigMgr.data());
|
auto configMgr = dynamic_cast<BundleNotebookConfigMgr *>(p_paras.m_notebookConfigMgr.data());
|
||||||
if (!configMgr) {
|
if (!configMgr) {
|
||||||
Exception::throwOne(Exception::Type::InvalidArgument,
|
Exception::throwOne(Exception::Type::InvalidArgument,
|
||||||
QString("Invalid notebook configuration manager"));
|
QStringLiteral("Invalid notebook configuration manager"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,6 +17,8 @@ namespace vnotex
|
|||||||
|
|
||||||
virtual void addHistory(const HistoryItem &p_item) = 0;
|
virtual void addHistory(const HistoryItem &p_item) = 0;
|
||||||
|
|
||||||
|
virtual void removeHistory(const QString &p_itemPath) = 0;
|
||||||
|
|
||||||
virtual void clearHistory() = 0;
|
virtual void clearHistory() = 0;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include <core/exception.h>
|
#include <core/exception.h>
|
||||||
#include "notebook.h"
|
#include "notebook.h"
|
||||||
#include "nodeparameters.h"
|
#include "nodeparameters.h"
|
||||||
|
#include <QRandomGenerator>
|
||||||
|
|
||||||
using namespace vnotex;
|
using namespace vnotex;
|
||||||
|
|
||||||
@ -483,7 +484,7 @@ QList<QSharedPointer<File>> Node::collectFiles()
|
|||||||
|
|
||||||
ID Node::generateSignature()
|
ID Node::generateSignature()
|
||||||
{
|
{
|
||||||
return static_cast<ID>(QDateTime::currentDateTime().toSecsSinceEpoch() + (static_cast<qulonglong>(qrand()) << 32));
|
return static_cast<ID>(QDateTime::currentDateTime().toSecsSinceEpoch() + (static_cast<qulonglong>(QRandomGenerator::global()->generate()) << 32));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Node::checkSignature()
|
void Node::checkSignature()
|
||||||
|
@ -254,7 +254,7 @@ QSharedPointer<Node> Notebook::copyNodeAsChildOf(const QSharedPointer<Node> &p_s
|
|||||||
|
|
||||||
if (Node::isAncestor(p_src.data(), p_dest)) {
|
if (Node::isAncestor(p_src.data(), p_dest)) {
|
||||||
Exception::throwOne(Exception::Type::InvalidArgument,
|
Exception::throwOne(Exception::Type::InvalidArgument,
|
||||||
QString("source (%1) is the ancestor of destination (%2)")
|
QStringLiteral("source (%1) is the ancestor of destination (%2)")
|
||||||
.arg(p_src->fetchPath(), p_dest->fetchPath()));
|
.arg(p_src->fetchPath(), p_dest->fetchPath()));
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -1,30 +0,0 @@
|
|||||||
SOURCES += \
|
|
||||||
$$PWD/externalnode.cpp \
|
|
||||||
$$PWD/nodeparameters.cpp \
|
|
||||||
$$PWD/notebook.cpp \
|
|
||||||
$$PWD/bundlenotebookfactory.cpp \
|
|
||||||
$$PWD/notebookdatabaseaccess.cpp \
|
|
||||||
$$PWD/notebookparameters.cpp \
|
|
||||||
$$PWD/bundlenotebook.cpp \
|
|
||||||
$$PWD/node.cpp \
|
|
||||||
$$PWD/notebooktagmgr.cpp \
|
|
||||||
$$PWD/tag.cpp \
|
|
||||||
$$PWD/vxnode.cpp \
|
|
||||||
$$PWD/vxnodefile.cpp
|
|
||||||
|
|
||||||
HEADERS += \
|
|
||||||
$$PWD/externalnode.h \
|
|
||||||
$$PWD/historyi.h \
|
|
||||||
$$PWD/nodeparameters.h \
|
|
||||||
$$PWD/notebook.h \
|
|
||||||
$$PWD/inotebookfactory.h \
|
|
||||||
$$PWD/bundlenotebookfactory.h \
|
|
||||||
$$PWD/notebookdatabaseaccess.h \
|
|
||||||
$$PWD/notebookparameters.h \
|
|
||||||
$$PWD/bundlenotebook.h \
|
|
||||||
$$PWD/node.h \
|
|
||||||
$$PWD/notebooktagmgr.h \
|
|
||||||
$$PWD/tag.h \
|
|
||||||
$$PWD/tagi.h \
|
|
||||||
$$PWD/vxnode.h \
|
|
||||||
$$PWD/vxnodefile.h
|
|
@ -30,7 +30,7 @@ bool NotebookDatabaseAccess::open()
|
|||||||
auto db = QSqlDatabase::addDatabase(QStringLiteral("QSQLITE"), m_connectionName);
|
auto db = QSqlDatabase::addDatabase(QStringLiteral("QSQLITE"), m_connectionName);
|
||||||
db.setDatabaseName(m_databaseFile);
|
db.setDatabaseName(m_databaseFile);
|
||||||
if (!db.open()) {
|
if (!db.open()) {
|
||||||
qWarning() << QString("failed to open notebook database (%1) (%2)").arg(m_databaseFile, db.lastError().text());
|
qWarning() << QStringLiteral("failed to open notebook database (%1) (%2)").arg(m_databaseFile, db.lastError().text());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,35 +71,35 @@ void NotebookDatabaseAccess::setupTables(QSqlDatabase &p_db, int p_configVersion
|
|||||||
|
|
||||||
if (m_fresh) {
|
if (m_fresh) {
|
||||||
// Node.
|
// Node.
|
||||||
bool ret = query.exec(QString("CREATE TABLE %1 (\n"
|
bool ret = query.exec(QStringLiteral("CREATE TABLE %1 (\n"
|
||||||
" id INTEGER PRIMARY KEY,\n"
|
" id INTEGER PRIMARY KEY,\n"
|
||||||
" name TEXT NOT NULL,\n"
|
" name TEXT NOT NULL,\n"
|
||||||
" signature INTEGER NOT NULL,\n"
|
" signature INTEGER NOT NULL,\n"
|
||||||
" parent_id INTEGER NULL REFERENCES %1(id) ON DELETE CASCADE ON UPDATE CASCADE)\n").arg(c_nodeTableName));
|
" parent_id INTEGER NULL REFERENCES %1(id) ON DELETE CASCADE ON UPDATE CASCADE)\n").arg(c_nodeTableName));
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
qWarning() << QString("failed to create database table (%1) (%2)").arg(c_nodeTableName, query.lastError().text());
|
qWarning() << QStringLiteral("failed to create database table (%1) (%2)").arg(c_nodeTableName, query.lastError().text());
|
||||||
m_valid = false;
|
m_valid = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tag.
|
// Tag.
|
||||||
ret = query.exec(QString("CREATE TABLE %1 (\n"
|
ret = query.exec(QStringLiteral("CREATE TABLE %1 (\n"
|
||||||
" name TEXT PRIMARY KEY,\n"
|
" name TEXT PRIMARY KEY,\n"
|
||||||
" parent_name TEXT NULL REFERENCES %1(name) ON DELETE CASCADE ON UPDATE CASCADE) WITHOUT ROWID\n").arg(c_tagTableName));
|
" parent_name TEXT NULL REFERENCES %1(name) ON DELETE CASCADE ON UPDATE CASCADE) WITHOUT ROWID\n").arg(c_tagTableName));
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
qWarning() << QString("failed to create database table (%1) (%2)").arg(c_tagTableName, query.lastError().text());
|
qWarning() << QStringLiteral("failed to create database table (%1) (%2)").arg(c_tagTableName, query.lastError().text());
|
||||||
m_valid = false;
|
m_valid = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Node_Tag.
|
// Node_Tag.
|
||||||
ret = query.exec(QString("CREATE TABLE %1 (\n"
|
ret = query.exec(QStringLiteral("CREATE TABLE %1 (\n"
|
||||||
" node_id INTEGER REFERENCES %2(id) ON DELETE CASCADE ON UPDATE CASCADE,\n"
|
" node_id INTEGER REFERENCES %2(id) ON DELETE CASCADE ON UPDATE CASCADE,\n"
|
||||||
" tag_name TEXT REFERENCES %3(name) ON DELETE CASCADE ON UPDATE CASCADE)\n").arg(c_nodeTagTableName,
|
" tag_name TEXT REFERENCES %3(name) ON DELETE CASCADE ON UPDATE CASCADE)\n").arg(c_nodeTagTableName,
|
||||||
c_nodeTableName,
|
c_nodeTableName,
|
||||||
c_tagTableName));
|
c_tagTableName));
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
qWarning() << QString("failed to create database table (%1) (%2)").arg(c_nodeTagTableName, query.lastError().text());
|
qWarning() << QStringLiteral("failed to create database table (%1) (%2)").arg(c_nodeTagTableName, query.lastError().text());
|
||||||
m_valid = false;
|
m_valid = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -130,7 +130,7 @@ bool NotebookDatabaseAccess::addNode(Node *p_node, bool p_ignoreId)
|
|||||||
auto db = getDatabase();
|
auto db = getDatabase();
|
||||||
QSqlQuery query(db);
|
QSqlQuery query(db);
|
||||||
if (p_ignoreId) {
|
if (p_ignoreId) {
|
||||||
query.prepare(QString("INSERT INTO %1 (name, signature, parent_id)\n"
|
query.prepare(QStringLiteral("INSERT INTO %1 (name, signature, parent_id)\n"
|
||||||
" VALUES (:name, :signature, :parent_id)").arg(c_nodeTableName));
|
" VALUES (:name, :signature, :parent_id)").arg(c_nodeTableName));
|
||||||
query.bindValue(":name", p_node->getName());
|
query.bindValue(":name", p_node->getName());
|
||||||
query.bindValue(":signature", p_node->getSignature());
|
query.bindValue(":signature", p_node->getSignature());
|
||||||
@ -170,10 +170,10 @@ bool NotebookDatabaseAccess::addNode(Node *p_node, bool p_ignoreId)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (useNewId) {
|
if (useNewId) {
|
||||||
query.prepare(QString("INSERT INTO %1 (name, signature, parent_id)\n"
|
query.prepare(QStringLiteral("INSERT INTO %1 (name, signature, parent_id)\n"
|
||||||
" VALUES (:name, :signature, :parent_id)").arg(c_nodeTableName));
|
" VALUES (:name, :signature, :parent_id)").arg(c_nodeTableName));
|
||||||
} else {
|
} else {
|
||||||
query.prepare(QString("INSERT INTO %1 (id, name, signature, parent_id)\n"
|
query.prepare(QStringLiteral("INSERT INTO %1 (id, name, signature, parent_id)\n"
|
||||||
" VALUES (:id, :name, :signature, :parent_id)").arg(c_nodeTableName));
|
" VALUES (:id, :name, :signature, :parent_id)").arg(c_nodeTableName));
|
||||||
query.bindValue(":id", p_node->getId());
|
query.bindValue(":id", p_node->getId());
|
||||||
}
|
}
|
||||||
@ -212,7 +212,7 @@ QSharedPointer<NotebookDatabaseAccess::NodeRecord> NotebookDatabaseAccess::query
|
|||||||
{
|
{
|
||||||
auto db = getDatabase();
|
auto db = getDatabase();
|
||||||
QSqlQuery query(db);
|
QSqlQuery query(db);
|
||||||
query.prepare(QString("SELECT id, name, signature, parent_id FROM %1 WHERE id = :id").arg(c_nodeTableName));
|
query.prepare(QStringLiteral("SELECT id, name, signature, parent_id FROM %1 WHERE id = :id").arg(c_nodeTableName));
|
||||||
query.bindValue(":id", p_id);
|
query.bindValue(":id", p_id);
|
||||||
if (!query.exec()) {
|
if (!query.exec()) {
|
||||||
qWarning() << "failed to query node" << query.executedQuery() << query.lastError().text();
|
qWarning() << "failed to query node" << query.executedQuery() << query.lastError().text();
|
||||||
@ -264,7 +264,7 @@ QStringList NotebookDatabaseAccess::queryNodeParentPath(ID p_id)
|
|||||||
{
|
{
|
||||||
auto db = getDatabase();
|
auto db = getDatabase();
|
||||||
QSqlQuery query(db);
|
QSqlQuery query(db);
|
||||||
query.prepare(QString("WITH RECURSIVE cte_parents(id, name, parent_id) AS (\n"
|
query.prepare(QStringLiteral("WITH RECURSIVE cte_parents(id, name, parent_id) AS (\n"
|
||||||
" SELECT node.id, node.name, node.parent_id\n"
|
" SELECT node.id, node.name, node.parent_id\n"
|
||||||
" FROM %1 node\n"
|
" FROM %1 node\n"
|
||||||
" WHERE node.id = :id\n"
|
" WHERE node.id = :id\n"
|
||||||
@ -315,7 +315,7 @@ bool NotebookDatabaseAccess::updateNode(const Node *p_node)
|
|||||||
|
|
||||||
auto db = getDatabase();
|
auto db = getDatabase();
|
||||||
QSqlQuery query(db);
|
QSqlQuery query(db);
|
||||||
query.prepare(QString("UPDATE %1\n"
|
query.prepare(QStringLiteral("UPDATE %1\n"
|
||||||
"SET name = :name,\n"
|
"SET name = :name,\n"
|
||||||
" signature = :signature,\n"
|
" signature = :signature,\n"
|
||||||
" parent_id = :parent_id\n"
|
" parent_id = :parent_id\n"
|
||||||
@ -367,7 +367,7 @@ bool NotebookDatabaseAccess::removeNode(ID p_id)
|
|||||||
{
|
{
|
||||||
auto db = getDatabase();
|
auto db = getDatabase();
|
||||||
QSqlQuery query(db);
|
QSqlQuery query(db);
|
||||||
query.prepare(QString("DELETE FROM %1\n"
|
query.prepare(QStringLiteral("DELETE FROM %1\n"
|
||||||
"WHERE id = :id").arg(c_nodeTableName));
|
"WHERE id = :id").arg(c_nodeTableName));
|
||||||
query.bindValue(":id", p_id);
|
query.bindValue(":id", p_id);
|
||||||
if (!query.exec()) {
|
if (!query.exec()) {
|
||||||
@ -455,7 +455,7 @@ bool NotebookDatabaseAccess::addTag(const QString &p_name, const QString &p_pare
|
|||||||
|
|
||||||
auto db = getDatabase();
|
auto db = getDatabase();
|
||||||
QSqlQuery query(db);
|
QSqlQuery query(db);
|
||||||
query.prepare(QString("INSERT INTO %1 (name, parent_name)\n"
|
query.prepare(QStringLiteral("INSERT INTO %1 (name, parent_name)\n"
|
||||||
" VALUES (:name, :parent_name)").arg(c_tagTableName));
|
" VALUES (:name, :parent_name)").arg(c_tagTableName));
|
||||||
query.bindValue(":name", p_name);
|
query.bindValue(":name", p_name);
|
||||||
query.bindValue(":parent_name", p_parentName.isEmpty() ? QVariant() : p_parentName);
|
query.bindValue(":parent_name", p_parentName.isEmpty() ? QVariant() : p_parentName);
|
||||||
@ -473,7 +473,7 @@ QSharedPointer<NotebookDatabaseAccess::TagRecord> NotebookDatabaseAccess::queryT
|
|||||||
{
|
{
|
||||||
auto db = getDatabase();
|
auto db = getDatabase();
|
||||||
QSqlQuery query(db);
|
QSqlQuery query(db);
|
||||||
query.prepare(QString("SELECT name, parent_name FROM %1 WHERE name = :name").arg(c_tagTableName));
|
query.prepare(QStringLiteral("SELECT name, parent_name FROM %1 WHERE name = :name").arg(c_tagTableName));
|
||||||
query.bindValue(":name", p_name);
|
query.bindValue(":name", p_name);
|
||||||
if (!query.exec()) {
|
if (!query.exec()) {
|
||||||
qWarning() << "failed to query tag" << query.executedQuery() << query.lastError().text();
|
qWarning() << "failed to query tag" << query.executedQuery() << query.lastError().text();
|
||||||
@ -494,7 +494,7 @@ bool NotebookDatabaseAccess::updateTagParent(const QString &p_name, const QStrin
|
|||||||
{
|
{
|
||||||
auto db = getDatabase();
|
auto db = getDatabase();
|
||||||
QSqlQuery query(db);
|
QSqlQuery query(db);
|
||||||
query.prepare(QString("UPDATE %1\n"
|
query.prepare(QStringLiteral("UPDATE %1\n"
|
||||||
"SET parent_name = :parent_name\n"
|
"SET parent_name = :parent_name\n"
|
||||||
"WHERE name = :name").arg(c_tagTableName));
|
"WHERE name = :name").arg(c_tagTableName));
|
||||||
query.bindValue(":name", p_name);
|
query.bindValue(":name", p_name);
|
||||||
@ -518,7 +518,7 @@ bool NotebookDatabaseAccess::renameTag(const QString &p_name, const QString &p_n
|
|||||||
|
|
||||||
auto db = getDatabase();
|
auto db = getDatabase();
|
||||||
QSqlQuery query(db);
|
QSqlQuery query(db);
|
||||||
query.prepare(QString("UPDATE %1\n"
|
query.prepare(QStringLiteral("UPDATE %1\n"
|
||||||
"SET name = :new_name\n"
|
"SET name = :new_name\n"
|
||||||
"WHERE name = :name").arg(c_tagTableName));
|
"WHERE name = :name").arg(c_tagTableName));
|
||||||
query.bindValue(":name", p_name);
|
query.bindValue(":name", p_name);
|
||||||
@ -537,7 +537,7 @@ bool NotebookDatabaseAccess::removeTag(const QString &p_name)
|
|||||||
{
|
{
|
||||||
auto db = getDatabase();
|
auto db = getDatabase();
|
||||||
QSqlQuery query(db);
|
QSqlQuery query(db);
|
||||||
query.prepare(QString("DELETE FROM %1\n"
|
query.prepare(QStringLiteral("DELETE FROM %1\n"
|
||||||
"WHERE name = :name").arg(c_tagTableName));
|
"WHERE name = :name").arg(c_tagTableName));
|
||||||
query.bindValue(":name", p_name);
|
query.bindValue(":name", p_name);
|
||||||
if (!query.exec()) {
|
if (!query.exec()) {
|
||||||
@ -560,7 +560,12 @@ bool NotebookDatabaseAccess::updateNodeTags(Node *p_node)
|
|||||||
const auto &nodeTags = p_node->getTags();
|
const auto &nodeTags = p_node->getTags();
|
||||||
|
|
||||||
{
|
{
|
||||||
const auto tags = QSet<QString>::fromList(queryNodeTags(p_node->getId()));
|
QStringList tagsList = queryNodeTags(p_node->getId());
|
||||||
|
QSet<QString> tags;
|
||||||
|
for (const auto &s : tagsList)
|
||||||
|
{
|
||||||
|
tags.insert(s);
|
||||||
|
}
|
||||||
if (tags.isEmpty() && nodeTags.isEmpty()) {
|
if (tags.isEmpty() && nodeTags.isEmpty()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -598,7 +603,7 @@ QStringList NotebookDatabaseAccess::queryNodeTags(ID p_id)
|
|||||||
{
|
{
|
||||||
auto db = getDatabase();
|
auto db = getDatabase();
|
||||||
QSqlQuery query(db);
|
QSqlQuery query(db);
|
||||||
query.prepare(QString("SELECT tag_name FROM %1 WHERE node_id = :node_id").arg(c_nodeTagTableName));
|
query.prepare(QStringLiteral("SELECT tag_name FROM %1 WHERE node_id = :node_id").arg(c_nodeTagTableName));
|
||||||
query.bindValue(":node_id", p_id);
|
query.bindValue(":node_id", p_id);
|
||||||
if (!query.exec()) {
|
if (!query.exec()) {
|
||||||
qWarning() << "failed to query node's tags" << query.executedQuery() << query.lastError().text();
|
qWarning() << "failed to query node's tags" << query.executedQuery() << query.lastError().text();
|
||||||
@ -616,7 +621,7 @@ bool NotebookDatabaseAccess::removeNodeTags(ID p_id)
|
|||||||
{
|
{
|
||||||
auto db = getDatabase();
|
auto db = getDatabase();
|
||||||
QSqlQuery query(db);
|
QSqlQuery query(db);
|
||||||
query.prepare(QString("DELETE FROM %1\n"
|
query.prepare(QStringLiteral("DELETE FROM %1\n"
|
||||||
"WHERE node_id = :node_id").arg(c_nodeTagTableName));
|
"WHERE node_id = :node_id").arg(c_nodeTagTableName));
|
||||||
query.bindValue(":node_id", p_id);
|
query.bindValue(":node_id", p_id);
|
||||||
if (!query.exec()) {
|
if (!query.exec()) {
|
||||||
@ -636,7 +641,7 @@ bool NotebookDatabaseAccess::addNodeTags(ID p_id, const QStringList &p_tags)
|
|||||||
|
|
||||||
auto db = getDatabase();
|
auto db = getDatabase();
|
||||||
QSqlQuery query(db);
|
QSqlQuery query(db);
|
||||||
query.prepare(QString("INSERT INTO %1 (node_id, tag_name)\n"
|
query.prepare(QStringLiteral("INSERT INTO %1 (node_id, tag_name)\n"
|
||||||
" VALUES (?, ?)").arg(c_nodeTagTableName));
|
" VALUES (?, ?)").arg(c_nodeTagTableName));
|
||||||
|
|
||||||
QVariantList ids;
|
QVariantList ids;
|
||||||
@ -663,7 +668,7 @@ QList<ID> NotebookDatabaseAccess::queryTagNodes(const QString &p_tag)
|
|||||||
QList<ID> nodes;
|
QList<ID> nodes;
|
||||||
auto db = getDatabase();
|
auto db = getDatabase();
|
||||||
QSqlQuery query(db);
|
QSqlQuery query(db);
|
||||||
query.prepare(QString("SELECT node_id FROM %1 WHERE tag_name = :tag_name").arg(c_nodeTagTableName));
|
query.prepare(QStringLiteral("SELECT node_id FROM %1 WHERE tag_name = :tag_name").arg(c_nodeTagTableName));
|
||||||
query.bindValue(":tag_name", p_tag);
|
query.bindValue(":tag_name", p_tag);
|
||||||
if (!query.exec()) {
|
if (!query.exec()) {
|
||||||
qWarning() << "failed to query nodes of tag" << query.executedQuery() << query.lastError().text();
|
qWarning() << "failed to query nodes of tag" << query.executedQuery() << query.lastError().text();
|
||||||
@ -691,14 +696,14 @@ QList<ID> NotebookDatabaseAccess::queryTagNodesRecursive(const QString &p_tag)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return allIds.toList();
|
return allIds.values();
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList NotebookDatabaseAccess::queryTagAndChildren(const QString &p_tag)
|
QStringList NotebookDatabaseAccess::queryTagAndChildren(const QString &p_tag)
|
||||||
{
|
{
|
||||||
auto db = getDatabase();
|
auto db = getDatabase();
|
||||||
QSqlQuery query(db);
|
QSqlQuery query(db);
|
||||||
query.prepare(QString("WITH RECURSIVE cte_children(name, parent_name) AS (\n"
|
query.prepare(QStringLiteral("WITH RECURSIVE cte_children(name, parent_name) AS (\n"
|
||||||
" SELECT tag.name, tag.parent_name\n"
|
" SELECT tag.name, tag.parent_name\n"
|
||||||
" FROM %1 tag\n"
|
" FROM %1 tag\n"
|
||||||
" WHERE tag.name = :name\n"
|
" WHERE tag.name = :name\n"
|
||||||
@ -742,7 +747,7 @@ QStringList NotebookDatabaseAccess::getNodesOfTags(const QStringList &p_tags)
|
|||||||
allIds.insert(id);
|
allIds.insert(id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
nodeIds = allIds.toList();
|
nodeIds = allIds.values();
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const auto &id : nodeIds) {
|
for (const auto &id : nodeIds) {
|
||||||
@ -763,7 +768,7 @@ QList<NotebookDatabaseAccess::TagRecord> NotebookDatabaseAccess::getAllTags()
|
|||||||
|
|
||||||
auto db = getDatabase();
|
auto db = getDatabase();
|
||||||
QSqlQuery query(db);
|
QSqlQuery query(db);
|
||||||
query.prepare(QString("SELECT name, parent_name FROM %1 ORDER BY parent_name, name").arg(c_tagTableName));
|
query.prepare(QStringLiteral("SELECT name, parent_name FROM %1 ORDER BY parent_name, name").arg(c_tagTableName));
|
||||||
if (!query.exec()) {
|
if (!query.exec()) {
|
||||||
qWarning() << "failed to query tags" << query.executedQuery() << query.lastError().text();
|
qWarning() << "failed to query tags" << query.executedQuery() << query.lastError().text();
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -11,7 +11,7 @@ void INotebookBackend::constrainPath(const QString &p_path) const
|
|||||||
{
|
{
|
||||||
if (!PathUtils::pathContains(m_rootPath, p_path)) {
|
if (!PathUtils::pathContains(m_rootPath, p_path)) {
|
||||||
Exception::throwOne(Exception::Type::InvalidArgument,
|
Exception::throwOne(Exception::Type::InvalidArgument,
|
||||||
QString("path (%1) does not locate in root folder (%2)")
|
QStringLiteral("path (%1) does not locate in root folder (%2)")
|
||||||
.arg(p_path, m_rootPath));
|
.arg(p_path, m_rootPath));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -52,7 +52,7 @@ void LocalNotebookBackend::makePath(const QString &p_dirPath)
|
|||||||
QDir dir(getRootPath());
|
QDir dir(getRootPath());
|
||||||
if (!dir.mkpath(p_dirPath)) {
|
if (!dir.mkpath(p_dirPath)) {
|
||||||
Exception::throwOne(Exception::Type::FailToCreateDir,
|
Exception::throwOne(Exception::Type::FailToCreateDir,
|
||||||
QString("fail to create directory: %1").arg(p_dirPath));
|
QStringLiteral("fail to create directory: %1").arg(p_dirPath));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,10 +0,0 @@
|
|||||||
SOURCES += \
|
|
||||||
$$PWD/localnotebookbackend.cpp \
|
|
||||||
$$PWD/localnotebookbackendfactory.cpp \
|
|
||||||
$$PWD/inotebookbackend.cpp
|
|
||||||
|
|
||||||
HEADERS += \
|
|
||||||
$$PWD/inotebookbackend.h \
|
|
||||||
$$PWD/localnotebookbackend.h \
|
|
||||||
$$PWD/inotebookbackendfactory.h \
|
|
||||||
$$PWD/localnotebookbackendfactory.h
|
|
@ -56,7 +56,7 @@ void NotebookConfig::fromJson(const QJsonObject &p_jobj)
|
|||||||
|| !p_jobj.contains(QStringLiteral("version_controller"))
|
|| !p_jobj.contains(QStringLiteral("version_controller"))
|
||||||
|| !p_jobj.contains(QStringLiteral("config_mgr"))) {
|
|| !p_jobj.contains(QStringLiteral("config_mgr"))) {
|
||||||
Exception::throwOne(Exception::Type::InvalidArgument,
|
Exception::throwOne(Exception::Type::InvalidArgument,
|
||||||
QString("failed to read notebook configuration from JSON (%1)").arg(QJsonObjectToString(p_jobj)));
|
QStringLiteral("failed to read notebook configuration from JSON (%1)").arg(QJsonObjectToString(p_jobj)));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,16 +0,0 @@
|
|||||||
SOURCES += \
|
|
||||||
$$PWD/vxnodeconfig.cpp \
|
|
||||||
$$PWD/vxnotebookconfigmgr.cpp \
|
|
||||||
$$PWD/vxnotebookconfigmgrfactory.cpp \
|
|
||||||
$$PWD/inotebookconfigmgr.cpp \
|
|
||||||
$$PWD/notebookconfig.cpp \
|
|
||||||
$$PWD/bundlenotebookconfigmgr.cpp
|
|
||||||
|
|
||||||
HEADERS += \
|
|
||||||
$$PWD/inotebookconfigmgr.h \
|
|
||||||
$$PWD/vxnodeconfig.h \
|
|
||||||
$$PWD/vxnotebookconfigmgr.h \
|
|
||||||
$$PWD/inotebookconfigmgrfactory.h \
|
|
||||||
$$PWD/vxnotebookconfigmgrfactory.h \
|
|
||||||
$$PWD/notebookconfig.h \
|
|
||||||
$$PWD/bundlenotebookconfigmgr.h
|
|
@ -4,6 +4,7 @@
|
|||||||
#include <QJsonArray>
|
#include <QJsonArray>
|
||||||
#include <QJsonDocument>
|
#include <QJsonDocument>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
#include <QSet>
|
||||||
|
|
||||||
#include <notebookbackend/inotebookbackend.h>
|
#include <notebookbackend/inotebookbackend.h>
|
||||||
#include <notebook/notebookparameters.h>
|
#include <notebook/notebookparameters.h>
|
||||||
@ -125,12 +126,12 @@ QSharedPointer<NodeConfig> VXNotebookConfigMgr::readNodeConfig(const QString &p_
|
|||||||
auto backend = getBackend();
|
auto backend = getBackend();
|
||||||
if (!backend->exists(p_path)) {
|
if (!backend->exists(p_path)) {
|
||||||
Exception::throwOne(Exception::Type::InvalidArgument,
|
Exception::throwOne(Exception::Type::InvalidArgument,
|
||||||
QString("node path (%1) does not exist").arg(p_path));
|
QStringLiteral("node path (%1) does not exist").arg(p_path));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (backend->isFile(p_path)) {
|
if (backend->isFile(p_path)) {
|
||||||
Exception::throwOne(Exception::Type::InvalidArgument,
|
Exception::throwOne(Exception::Type::InvalidArgument,
|
||||||
QString("node (%1) is a file node without config").arg(p_path));
|
QStringLiteral("node (%1) is a file node without config").arg(p_path));
|
||||||
} else {
|
} else {
|
||||||
auto configPath = PathUtils::concatenateFilePath(p_path, c_nodeConfigName);
|
auto configPath = PathUtils::concatenateFilePath(p_path, c_nodeConfigName);
|
||||||
auto data = backend->readFile(configPath);
|
auto data = backend->readFile(configPath);
|
||||||
@ -170,6 +171,8 @@ QSharedPointer<Node> VXNotebookConfigMgr::nodeConfigToNode(const NodeConfig &p_c
|
|||||||
|
|
||||||
void VXNotebookConfigMgr::loadFolderNode(Node *p_node, const NodeConfig &p_config)
|
void VXNotebookConfigMgr::loadFolderNode(Node *p_node, const NodeConfig &p_config)
|
||||||
{
|
{
|
||||||
|
QSet<QString> seenNames;
|
||||||
|
|
||||||
QVector<QSharedPointer<Node>> children;
|
QVector<QSharedPointer<Node>> children;
|
||||||
children.reserve(p_config.m_files.size() + p_config.m_folders.size());
|
children.reserve(p_config.m_files.size() + p_config.m_folders.size());
|
||||||
const auto basePath = p_node->fetchPath();
|
const auto basePath = p_node->fetchPath();
|
||||||
@ -183,6 +186,12 @@ void VXNotebookConfigMgr::loadFolderNode(Node *p_node, const NodeConfig &p_confi
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (seenNames.contains(folder.m_name)) {
|
||||||
|
qWarning() << "skipped loading node with duplicated name under" << p_node->fetchPath();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
seenNames.insert(folder.m_name);
|
||||||
|
|
||||||
auto folderNode = QSharedPointer<VXNode>::create(folder.m_name,
|
auto folderNode = QSharedPointer<VXNode>::create(folder.m_name,
|
||||||
getNotebook(),
|
getNotebook(),
|
||||||
p_node);
|
p_node);
|
||||||
@ -198,6 +207,12 @@ void VXNotebookConfigMgr::loadFolderNode(Node *p_node, const NodeConfig &p_confi
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (seenNames.contains(file.m_name)) {
|
||||||
|
qWarning() << "skipped loading node with duplicated name under" << p_node->fetchPath();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
seenNames.insert(file.m_name);
|
||||||
|
|
||||||
// For compability only.
|
// For compability only.
|
||||||
needUpdateConfig = needUpdateConfig || file.m_signature == Node::InvalidId;
|
needUpdateConfig = needUpdateConfig || file.m_signature == Node::InvalidId;
|
||||||
|
|
||||||
@ -294,7 +309,7 @@ QSharedPointer<Node> VXNotebookConfigMgr::newFileNode(Node *p_parent,
|
|||||||
if (getBackend()->childExistsCaseInsensitive(p_parent->fetchPath(), p_name)) {
|
if (getBackend()->childExistsCaseInsensitive(p_parent->fetchPath(), p_name)) {
|
||||||
// File already exists. Exception.
|
// File already exists. Exception.
|
||||||
Exception::throwOne(Exception::Type::FileExistsOnCreate,
|
Exception::throwOne(Exception::Type::FileExistsOnCreate,
|
||||||
QString("file (%1) already exists when creating new node").arg(node->fetchPath()));
|
QStringLiteral("file (%1) already exists when creating new node").arg(node->fetchPath()));
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -330,7 +345,7 @@ QSharedPointer<Node> VXNotebookConfigMgr::newFolderNode(Node *p_parent,
|
|||||||
if (getBackend()->childExistsCaseInsensitive(p_parent->fetchPath(), p_name)) {
|
if (getBackend()->childExistsCaseInsensitive(p_parent->fetchPath(), p_name)) {
|
||||||
// Dir already exists. Exception.
|
// Dir already exists. Exception.
|
||||||
Exception::throwOne(Exception::Type::DirExistsOnCreate,
|
Exception::throwOne(Exception::Type::DirExistsOnCreate,
|
||||||
QString("dir (%1) already exists when creating new node").arg(node->fetchPath()));
|
QStringLiteral("dir (%1) already exists when creating new node").arg(node->fetchPath()));
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -446,7 +461,11 @@ void VXNotebookConfigMgr::addChildNode(Node *p_parent, const QSharedPointer<Node
|
|||||||
QSharedPointer<Node> VXNotebookConfigMgr::loadNodeByPath(const QSharedPointer<Node> &p_root, const QString &p_relativePath)
|
QSharedPointer<Node> VXNotebookConfigMgr::loadNodeByPath(const QSharedPointer<Node> &p_root, const QString &p_relativePath)
|
||||||
{
|
{
|
||||||
auto p = PathUtils::cleanPath(p_relativePath);
|
auto p = PathUtils::cleanPath(p_relativePath);
|
||||||
auto paths = p.split('/', QString::SkipEmptyParts);
|
if (p == ".") {
|
||||||
|
return p_root;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto paths = p.split('/', Qt::SkipEmptyParts);
|
||||||
auto node = p_root;
|
auto node = p_root;
|
||||||
for (auto &pa : paths) {
|
for (auto &pa : paths) {
|
||||||
// Find child @pa in @node.
|
// Find child @pa in @node.
|
||||||
|
@ -108,7 +108,7 @@ QSharedPointer<INotebookBackend> NotebookMgr::createNotebookBackend(const QStrin
|
|||||||
return factory->createNotebookBackend(p_rootFolderPath);
|
return factory->createNotebookBackend(p_rootFolderPath);
|
||||||
} else {
|
} else {
|
||||||
Exception::throwOne(Exception::Type::InvalidArgument,
|
Exception::throwOne(Exception::Type::InvalidArgument,
|
||||||
QString("failed to find notebook backend factory %1").arg(p_backendName));
|
QStringLiteral("failed to find notebook backend factory %1").arg(p_backendName));
|
||||||
}
|
}
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@ -121,7 +121,7 @@ QSharedPointer<IVersionController> NotebookMgr::createVersionController(const QS
|
|||||||
return factory->createVersionController();
|
return factory->createVersionController();
|
||||||
} else {
|
} else {
|
||||||
Exception::throwOne(Exception::Type::InvalidArgument,
|
Exception::throwOne(Exception::Type::InvalidArgument,
|
||||||
QString("failed to find version controller factory %1").arg(p_controllerName));
|
QStringLiteral("failed to find version controller factory %1").arg(p_controllerName));
|
||||||
}
|
}
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@ -135,7 +135,7 @@ QSharedPointer<INotebookConfigMgr> NotebookMgr::createNotebookConfigMgr(const QS
|
|||||||
return factory->createNotebookConfigMgr(p_backend);
|
return factory->createNotebookConfigMgr(p_backend);
|
||||||
} else {
|
} else {
|
||||||
Exception::throwOne(Exception::Type::InvalidArgument,
|
Exception::throwOne(Exception::Type::InvalidArgument,
|
||||||
QString("failed to find notebook config manager factory %1").arg(p_mgrName));
|
QStringLiteral("failed to find notebook config manager factory %1").arg(p_mgrName));
|
||||||
}
|
}
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@ -171,7 +171,7 @@ QSharedPointer<Notebook> NotebookMgr::newNotebook(const QSharedPointer<NotebookP
|
|||||||
auto factory = m_notebookServer->getItem(p_parameters->m_type);
|
auto factory = m_notebookServer->getItem(p_parameters->m_type);
|
||||||
if (!factory) {
|
if (!factory) {
|
||||||
Exception::throwOne(Exception::Type::InvalidArgument,
|
Exception::throwOne(Exception::Type::InvalidArgument,
|
||||||
QString("failed to find notebook factory %1").arg(p_parameters->m_type));
|
QStringLiteral("failed to find notebook factory %1").arg(p_parameters->m_type));
|
||||||
}
|
}
|
||||||
|
|
||||||
auto notebook = factory->newNotebook(*p_parameters);
|
auto notebook = factory->newNotebook(*p_parameters);
|
||||||
@ -246,7 +246,7 @@ QSharedPointer<Notebook> NotebookMgr::readNotebookFromConfig(const SessionConfig
|
|||||||
auto factory = m_notebookServer->getItem(p_item.m_type);
|
auto factory = m_notebookServer->getItem(p_item.m_type);
|
||||||
if (!factory) {
|
if (!factory) {
|
||||||
Exception::throwOne(Exception::Type::InvalidArgument,
|
Exception::throwOne(Exception::Type::InvalidArgument,
|
||||||
QString("failed to find notebook factory %1").arg(p_item.m_type));
|
QStringLiteral("failed to find notebook factory %1").arg(p_item.m_type));
|
||||||
}
|
}
|
||||||
|
|
||||||
auto backend = createNotebookBackend(p_item.m_backend, p_item.m_rootFolderPath);
|
auto backend = createNotebookBackend(p_item.m_backend, p_item.m_rootFolderPath);
|
||||||
@ -330,7 +330,7 @@ void NotebookMgr::closeNotebook(ID p_id)
|
|||||||
emit notebooksUpdated();
|
emit notebooksUpdated();
|
||||||
setCurrentNotebookAfterUpdate();
|
setCurrentNotebookAfterUpdate();
|
||||||
|
|
||||||
qInfo() << QString("notebook %1 (%2) is closed").arg(notebookToClose->getName(),
|
qInfo() << QStringLiteral("notebook %1 (%2) is closed").arg(notebookToClose->getName(),
|
||||||
notebookToClose->getRootFolderPath());
|
notebookToClose->getRootFolderPath());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -359,13 +359,13 @@ void NotebookMgr::removeNotebook(ID p_id)
|
|||||||
try {
|
try {
|
||||||
nbToRemove->remove();
|
nbToRemove->remove();
|
||||||
} catch (Exception &p_e) {
|
} catch (Exception &p_e) {
|
||||||
qWarning() << QString("failed to remove notebook %1 (%2) (%3)").arg(nbToRemove->getName(),
|
qWarning() << QStringLiteral("failed to remove notebook %1 (%2) (%3)").arg(nbToRemove->getName(),
|
||||||
nbToRemove->getRootFolderPath(),
|
nbToRemove->getRootFolderPath(),
|
||||||
p_e.what());
|
p_e.what());
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
|
||||||
qInfo() << QString("notebook %1 (%2) is removed").arg(nbToRemove->getName(),
|
qInfo() << QStringLiteral("notebook %1 (%2) is removed").arg(nbToRemove->getName(),
|
||||||
nbToRemove->getRootFolderPath());
|
nbToRemove->getRootFolderPath());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
61
src/core/pdfviewerconfig.cpp
Normal file
61
src/core/pdfviewerconfig.cpp
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
#include "pdfviewerconfig.h"
|
||||||
|
|
||||||
|
#include "mainconfig.h"
|
||||||
|
|
||||||
|
#define READSTR(key) readString(appObj, userObj, (key))
|
||||||
|
#define READBOOL(key) readBool(appObj, userObj, (key))
|
||||||
|
#define READINT(key) readInt(appObj, userObj, (key))
|
||||||
|
|
||||||
|
using namespace vnotex;
|
||||||
|
|
||||||
|
PdfViewerConfig::PdfViewerConfig(ConfigMgr *p_mgr, IConfig *p_topConfig)
|
||||||
|
: IConfig(p_mgr, p_topConfig)
|
||||||
|
{
|
||||||
|
m_sessionName = QStringLiteral("pdf_viewer");
|
||||||
|
}
|
||||||
|
|
||||||
|
void PdfViewerConfig::init(const QJsonObject &p_app,
|
||||||
|
const QJsonObject &p_user)
|
||||||
|
{
|
||||||
|
const auto appObj = p_app.value(m_sessionName).toObject();
|
||||||
|
const auto userObj = p_user.value(m_sessionName).toObject();
|
||||||
|
|
||||||
|
loadViewerResource(appObj, userObj);
|
||||||
|
}
|
||||||
|
|
||||||
|
QJsonObject PdfViewerConfig::toJson() const
|
||||||
|
{
|
||||||
|
QJsonObject obj;
|
||||||
|
obj[QStringLiteral("viewer_resource")] = saveViewerResource();
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PdfViewerConfig::loadViewerResource(const QJsonObject &p_app, const QJsonObject &p_user)
|
||||||
|
{
|
||||||
|
const QString name(QStringLiteral("viewer_resource"));
|
||||||
|
|
||||||
|
if (MainConfig::isVersionChanged()) {
|
||||||
|
bool needOverride = p_app[QStringLiteral("override_viewer_resource")].toBool();
|
||||||
|
if (needOverride) {
|
||||||
|
qInfo() << "override \"viewer_resource\" in user configuration due to version change";
|
||||||
|
m_viewerResource.init(p_app[name].toObject());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p_user.contains(name)) {
|
||||||
|
m_viewerResource.init(p_user[name].toObject());
|
||||||
|
} else {
|
||||||
|
m_viewerResource.init(p_app[name].toObject());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QJsonObject PdfViewerConfig::saveViewerResource() const
|
||||||
|
{
|
||||||
|
return m_viewerResource.toJson();
|
||||||
|
}
|
||||||
|
|
||||||
|
const WebResource &PdfViewerConfig::getViewerResource() const
|
||||||
|
{
|
||||||
|
return m_viewerResource;
|
||||||
|
}
|
31
src/core/pdfviewerconfig.h
Normal file
31
src/core/pdfviewerconfig.h
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
#ifndef PDFVIEWERCONFIG_H
|
||||||
|
#define PDFVIEWERCONFIG_H
|
||||||
|
|
||||||
|
#include "iconfig.h"
|
||||||
|
|
||||||
|
#include "webresource.h"
|
||||||
|
|
||||||
|
namespace vnotex
|
||||||
|
{
|
||||||
|
class PdfViewerConfig : public IConfig
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PdfViewerConfig(ConfigMgr *p_mgr, IConfig *p_topConfig);
|
||||||
|
|
||||||
|
void init(const QJsonObject &p_app, const QJsonObject &p_user) Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
|
QJsonObject toJson() const Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
|
const WebResource &getViewerResource() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend class MainConfig;
|
||||||
|
|
||||||
|
void loadViewerResource(const QJsonObject &p_app, const QJsonObject &p_user);
|
||||||
|
QJsonObject saveViewerResource() const;
|
||||||
|
|
||||||
|
WebResource m_viewerResource;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // PDFVIEWERCONFIG_H
|
@ -38,6 +38,34 @@ QJsonObject SessionConfig::NotebookItem::toJson() const
|
|||||||
return jobj;
|
return jobj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SessionConfig::QuickNoteScheme::operator==(const QuickNoteScheme &p_other) const
|
||||||
|
{
|
||||||
|
return m_name == p_other.m_name &&
|
||||||
|
m_folderPath == p_other.m_folderPath &&
|
||||||
|
m_noteName == p_other.m_noteName &&
|
||||||
|
m_template == p_other.m_template;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SessionConfig::QuickNoteScheme::fromJson(const QJsonObject &p_jobj)
|
||||||
|
{
|
||||||
|
m_name = p_jobj[QStringLiteral("name")].toString();
|
||||||
|
m_folderPath = p_jobj[QStringLiteral("folder_path")].toString();
|
||||||
|
m_noteName = p_jobj[QStringLiteral("note_name")].toString();
|
||||||
|
m_template = p_jobj[QStringLiteral("template")].toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
QJsonObject SessionConfig::QuickNoteScheme::toJson() const
|
||||||
|
{
|
||||||
|
QJsonObject jobj;
|
||||||
|
|
||||||
|
jobj[QStringLiteral("name")] = m_name;
|
||||||
|
jobj[QStringLiteral("folder_path")] = m_folderPath;
|
||||||
|
jobj[QStringLiteral("note_name")] = m_noteName;
|
||||||
|
jobj[QStringLiteral("template")] = m_template;
|
||||||
|
|
||||||
|
return jobj;
|
||||||
|
}
|
||||||
|
|
||||||
void SessionConfig::ExternalProgram::fromJson(const QJsonObject &p_jobj)
|
void SessionConfig::ExternalProgram::fromJson(const QJsonObject &p_jobj)
|
||||||
{
|
{
|
||||||
m_name = p_jobj[QStringLiteral("name")].toString();
|
m_name = p_jobj[QStringLiteral("name")].toString();
|
||||||
@ -59,7 +87,7 @@ QJsonObject SessionConfig::ExternalProgram::toJson() const
|
|||||||
QString SessionConfig::ExternalProgram::fetchCommand(const QString &p_file) const
|
QString SessionConfig::ExternalProgram::fetchCommand(const QString &p_file) const
|
||||||
{
|
{
|
||||||
auto command(m_command);
|
auto command(m_command);
|
||||||
command.replace(QStringLiteral("%1"), QString("\"%1\"").arg(p_file));
|
command.replace(QStringLiteral("%1"), QStringLiteral("\"%1\"").arg(p_file));
|
||||||
return command;
|
return command;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -97,6 +125,8 @@ void SessionConfig::init()
|
|||||||
|
|
||||||
loadHistory(sessionJobj);
|
loadHistory(sessionJobj);
|
||||||
|
|
||||||
|
loadQuickNoteSchemes(sessionJobj);
|
||||||
|
|
||||||
if (MainConfig::isVersionChanged()) {
|
if (MainConfig::isVersionChanged()) {
|
||||||
doVersionSpecificOverride();
|
doVersionSpecificOverride();
|
||||||
}
|
}
|
||||||
@ -131,6 +161,11 @@ void SessionConfig::loadCore(const QJsonObject &p_session)
|
|||||||
m_flashPage = readString(coreObj, QStringLiteral("flash_page"));
|
m_flashPage = readString(coreObj, QStringLiteral("flash_page"));
|
||||||
|
|
||||||
m_quickAccessFiles = readStringList(coreObj, QStringLiteral("quick_access"));
|
m_quickAccessFiles = readStringList(coreObj, QStringLiteral("quick_access"));
|
||||||
|
|
||||||
|
m_externalMediaDefaultPath = readString(coreObj, QStringLiteral("external_media_default_path"));
|
||||||
|
if (m_externalMediaDefaultPath.isEmpty()) {
|
||||||
|
m_externalMediaDefaultPath = QDir::homePath();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QJsonObject SessionConfig::saveCore() const
|
QJsonObject SessionConfig::saveCore() const
|
||||||
@ -145,6 +180,7 @@ QJsonObject SessionConfig::saveCore() const
|
|||||||
}
|
}
|
||||||
coreObj[QStringLiteral("flash_page")] = m_flashPage;
|
coreObj[QStringLiteral("flash_page")] = m_flashPage;
|
||||||
writeStringList(coreObj, QStringLiteral("quick_access"), m_quickAccessFiles);
|
writeStringList(coreObj, QStringLiteral("quick_access"), m_quickAccessFiles);
|
||||||
|
coreObj[QStringLiteral("external_media_default_path")] = m_externalMediaDefaultPath;
|
||||||
return coreObj;
|
return coreObj;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -160,6 +196,16 @@ void SessionConfig::setNewNotebookDefaultRootFolderPath(const QString &p_path)
|
|||||||
this);
|
this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const QString &SessionConfig::getExternalMediaDefaultPath() const
|
||||||
|
{
|
||||||
|
return m_externalMediaDefaultPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SessionConfig::setExternalMediaDefaultPath(const QString &p_path)
|
||||||
|
{
|
||||||
|
updateConfig(m_externalMediaDefaultPath, p_path, this);
|
||||||
|
}
|
||||||
|
|
||||||
const QVector<SessionConfig::NotebookItem> &SessionConfig::getNotebooks() const
|
const QVector<SessionConfig::NotebookItem> &SessionConfig::getNotebooks() const
|
||||||
{
|
{
|
||||||
return m_notebooks;
|
return m_notebooks;
|
||||||
@ -219,6 +265,7 @@ QJsonObject SessionConfig::toJson() const
|
|||||||
writeByteArray(obj, QStringLiteral("notebook_explorer_session"), m_notebookExplorerSession);
|
writeByteArray(obj, QStringLiteral("notebook_explorer_session"), m_notebookExplorerSession);
|
||||||
obj[QStringLiteral("external_programs")] = saveExternalPrograms();
|
obj[QStringLiteral("external_programs")] = saveExternalPrograms();
|
||||||
obj[QStringLiteral("history")] = saveHistory();
|
obj[QStringLiteral("history")] = saveHistory();
|
||||||
|
obj[QStringLiteral("quick_note_schemes")] = saveQuickNoteSchemes();
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -230,6 +277,7 @@ QJsonObject SessionConfig::saveStateAndGeometry() const
|
|||||||
writeStringList(obj, QStringLiteral("visible_docks_before_expand"), m_mainWindowStateGeometry.m_visibleDocksBeforeExpand);
|
writeStringList(obj, QStringLiteral("visible_docks_before_expand"), m_mainWindowStateGeometry.m_visibleDocksBeforeExpand);
|
||||||
writeByteArray(obj, QStringLiteral("tag_explorer_state"), m_mainWindowStateGeometry.m_tagExplorerState);
|
writeByteArray(obj, QStringLiteral("tag_explorer_state"), m_mainWindowStateGeometry.m_tagExplorerState);
|
||||||
writeByteArray(obj, QStringLiteral("notebook_explorer_state"), m_mainWindowStateGeometry.m_notebookExplorerState);
|
writeByteArray(obj, QStringLiteral("notebook_explorer_state"), m_mainWindowStateGeometry.m_notebookExplorerState);
|
||||||
|
writeByteArray(obj, QStringLiteral("location_list_state"), m_mainWindowStateGeometry.m_locationListState);
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -362,6 +410,7 @@ void SessionConfig::loadStateAndGeometry(const QJsonObject &p_session)
|
|||||||
m_mainWindowStateGeometry.m_visibleDocksBeforeExpand = readStringList(obj, QStringLiteral("visible_docks_before_expand"));
|
m_mainWindowStateGeometry.m_visibleDocksBeforeExpand = readStringList(obj, QStringLiteral("visible_docks_before_expand"));
|
||||||
m_mainWindowStateGeometry.m_tagExplorerState = readByteArray(obj, QStringLiteral("tag_explorer_state"));
|
m_mainWindowStateGeometry.m_tagExplorerState = readByteArray(obj, QStringLiteral("tag_explorer_state"));
|
||||||
m_mainWindowStateGeometry.m_notebookExplorerState = readByteArray(obj, QStringLiteral("notebook_explorer_state"));
|
m_mainWindowStateGeometry.m_notebookExplorerState = readByteArray(obj, QStringLiteral("notebook_explorer_state"));
|
||||||
|
m_mainWindowStateGeometry.m_locationListState = readByteArray(obj, QStringLiteral("location_list_state"));
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray SessionConfig::getViewAreaSessionAndClear()
|
QByteArray SessionConfig::getViewAreaSessionAndClear()
|
||||||
@ -440,6 +489,24 @@ QJsonArray SessionConfig::saveExternalPrograms() const
|
|||||||
return arr;
|
return arr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SessionConfig::loadQuickNoteSchemes(const QJsonObject &p_session)
|
||||||
|
{
|
||||||
|
const auto arr = p_session.value(QStringLiteral("quick_note_schemes")).toArray();
|
||||||
|
m_quickNoteSchemes.resize(arr.size());
|
||||||
|
for (int i = 0; i < arr.size(); ++i) {
|
||||||
|
m_quickNoteSchemes[i].fromJson(arr[i].toObject());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QJsonArray SessionConfig::saveQuickNoteSchemes() const
|
||||||
|
{
|
||||||
|
QJsonArray arr;
|
||||||
|
for (const auto &scheme : m_quickNoteSchemes) {
|
||||||
|
arr.append(scheme.toJson());
|
||||||
|
}
|
||||||
|
return arr;
|
||||||
|
}
|
||||||
|
|
||||||
const QVector<SessionConfig::ExternalProgram> &SessionConfig::getExternalPrograms() const
|
const QVector<SessionConfig::ExternalProgram> &SessionConfig::getExternalPrograms() const
|
||||||
{
|
{
|
||||||
return m_externalPrograms;
|
return m_externalPrograms;
|
||||||
@ -466,6 +533,12 @@ void SessionConfig::addHistory(const HistoryItem &p_item)
|
|||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SessionConfig::removeHistory(const QString &p_itemPath)
|
||||||
|
{
|
||||||
|
HistoryMgr::removeHistoryItem(m_history, p_itemPath);
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
void SessionConfig::clearHistory()
|
void SessionConfig::clearHistory()
|
||||||
{
|
{
|
||||||
m_history.clear();
|
m_history.clear();
|
||||||
@ -517,3 +590,13 @@ QJsonObject SessionConfig::saveExportOption() const
|
|||||||
|
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const QVector<SessionConfig::QuickNoteScheme> &SessionConfig::getQuickNoteSchemes() const
|
||||||
|
{
|
||||||
|
return m_quickNoteSchemes;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SessionConfig::setQuickNoteSchemes(const QVector<QuickNoteScheme>& p_schemes)
|
||||||
|
{
|
||||||
|
updateConfig(m_quickNoteSchemes, p_schemes, this);
|
||||||
|
}
|
||||||
|
@ -38,7 +38,8 @@ namespace vnotex
|
|||||||
&& m_mainGeometry == p_other.m_mainGeometry
|
&& m_mainGeometry == p_other.m_mainGeometry
|
||||||
&& m_visibleDocksBeforeExpand == p_other.m_visibleDocksBeforeExpand
|
&& m_visibleDocksBeforeExpand == p_other.m_visibleDocksBeforeExpand
|
||||||
&& m_tagExplorerState == p_other.m_tagExplorerState
|
&& m_tagExplorerState == p_other.m_tagExplorerState
|
||||||
&& m_notebookExplorerState == p_other.m_notebookExplorerState;
|
&& m_notebookExplorerState == p_other.m_notebookExplorerState
|
||||||
|
&& m_locationListState == p_other.m_locationListState;
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray m_mainState;
|
QByteArray m_mainState;
|
||||||
@ -50,6 +51,27 @@ namespace vnotex
|
|||||||
QByteArray m_tagExplorerState;
|
QByteArray m_tagExplorerState;
|
||||||
|
|
||||||
QByteArray m_notebookExplorerState;
|
QByteArray m_notebookExplorerState;
|
||||||
|
|
||||||
|
QByteArray m_locationListState;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct QuickNoteScheme
|
||||||
|
{
|
||||||
|
bool operator==(const QuickNoteScheme &p_other) const;
|
||||||
|
|
||||||
|
void fromJson(const QJsonObject &p_jobj);
|
||||||
|
|
||||||
|
QJsonObject toJson() const;
|
||||||
|
|
||||||
|
QString m_name;
|
||||||
|
|
||||||
|
// Where to create the quick note.
|
||||||
|
QString m_folderPath;
|
||||||
|
|
||||||
|
// Name of the quick note. Snippet is supported.
|
||||||
|
QString m_noteName;
|
||||||
|
|
||||||
|
QString m_template;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum OpenGL
|
enum OpenGL
|
||||||
@ -85,6 +107,9 @@ namespace vnotex
|
|||||||
const QString &getNewNotebookDefaultRootFolderPath() const;
|
const QString &getNewNotebookDefaultRootFolderPath() const;
|
||||||
void setNewNotebookDefaultRootFolderPath(const QString &p_path);
|
void setNewNotebookDefaultRootFolderPath(const QString &p_path);
|
||||||
|
|
||||||
|
const QString &getExternalMediaDefaultPath() const;
|
||||||
|
void setExternalMediaDefaultPath(const QString &p_path);
|
||||||
|
|
||||||
const QString &getCurrentNotebookRootFolderPath() const;
|
const QString &getCurrentNotebookRootFolderPath() const;
|
||||||
void setCurrentNotebookRootFolderPath(const QString &p_path);
|
void setCurrentNotebookRootFolderPath(const QString &p_path);
|
||||||
|
|
||||||
@ -140,8 +165,12 @@ namespace vnotex
|
|||||||
|
|
||||||
const QVector<HistoryItem> &getHistory() const;
|
const QVector<HistoryItem> &getHistory() const;
|
||||||
void addHistory(const HistoryItem &p_item);
|
void addHistory(const HistoryItem &p_item);
|
||||||
|
void removeHistory(const QString &p_itemPath);
|
||||||
void clearHistory();
|
void clearHistory();
|
||||||
|
|
||||||
|
const QVector<QuickNoteScheme> &getQuickNoteSchemes() const;
|
||||||
|
void setQuickNoteSchemes(const QVector<QuickNoteScheme>& p_schemes);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void loadCore(const QJsonObject &p_session);
|
void loadCore(const QJsonObject &p_session);
|
||||||
|
|
||||||
@ -159,6 +188,10 @@ namespace vnotex
|
|||||||
|
|
||||||
QJsonArray saveExternalPrograms() const;
|
QJsonArray saveExternalPrograms() const;
|
||||||
|
|
||||||
|
void loadQuickNoteSchemes(const QJsonObject &p_session);
|
||||||
|
|
||||||
|
QJsonArray saveQuickNoteSchemes() const;
|
||||||
|
|
||||||
void doVersionSpecificOverride();
|
void doVersionSpecificOverride();
|
||||||
|
|
||||||
void loadHistory(const QJsonObject &p_session);
|
void loadHistory(const QJsonObject &p_session);
|
||||||
@ -206,6 +239,11 @@ namespace vnotex
|
|||||||
QVector<ExternalProgram> m_externalPrograms;
|
QVector<ExternalProgram> m_externalPrograms;
|
||||||
|
|
||||||
QVector<HistoryItem> m_history;
|
QVector<HistoryItem> m_history;
|
||||||
|
|
||||||
|
// Default folder path to open for external media like images and files.
|
||||||
|
QString m_externalMediaDefaultPath;
|
||||||
|
|
||||||
|
QVector<QuickNoteScheme> m_quickNoteSchemes;
|
||||||
};
|
};
|
||||||
} // ns vnotex
|
} // ns vnotex
|
||||||
|
|
||||||
|
@ -14,14 +14,8 @@ const QString SingleInstanceGuard::c_serverName = "vnote";
|
|||||||
|
|
||||||
const QChar SingleInstanceGuard::c_stringListSeparator = '>';
|
const QChar SingleInstanceGuard::c_stringListSeparator = '>';
|
||||||
|
|
||||||
SingleInstanceGuard::SingleInstanceGuard()
|
|
||||||
{
|
|
||||||
qInfo() << "guarding is on";
|
|
||||||
}
|
|
||||||
|
|
||||||
SingleInstanceGuard::~SingleInstanceGuard()
|
SingleInstanceGuard::~SingleInstanceGuard()
|
||||||
{
|
{
|
||||||
qInfo() << "guarding is off";
|
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ namespace vnotex
|
|||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
SingleInstanceGuard();
|
SingleInstanceGuard() = default;
|
||||||
|
|
||||||
~SingleInstanceGuard();
|
~SingleInstanceGuard();
|
||||||
|
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
|
|
||||||
|
#include <utils/fileutils.h>
|
||||||
|
|
||||||
#include "configmgr.h"
|
#include "configmgr.h"
|
||||||
|
|
||||||
using namespace vnotex;
|
using namespace vnotex;
|
||||||
@ -20,5 +22,17 @@ QStringList TemplateMgr::getTemplates() const
|
|||||||
|
|
||||||
QString TemplateMgr::getTemplateFilePath(const QString &p_name) const
|
QString TemplateMgr::getTemplateFilePath(const QString &p_name) const
|
||||||
{
|
{
|
||||||
|
if (p_name.isEmpty()) {
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
return QDir(getTemplateFolder()).filePath(p_name);
|
return QDir(getTemplateFolder()).filePath(p_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString TemplateMgr::getTemplateContent(const QString &p_name) const
|
||||||
|
{
|
||||||
|
const auto filePath = getTemplateFilePath(p_name);
|
||||||
|
if (filePath.isEmpty()) {
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
return FileUtils::readTextFile(filePath);
|
||||||
|
}
|
||||||
|
@ -24,6 +24,8 @@ namespace vnotex
|
|||||||
|
|
||||||
QString getTemplateFilePath(const QString &p_name) const;
|
QString getTemplateFilePath(const QString &p_name) const;
|
||||||
|
|
||||||
|
QString getTemplateContent(const QString &p_name) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TemplateMgr() = default;
|
TemplateMgr() = default;
|
||||||
};
|
};
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#include <QSettings>
|
#include <QSettings>
|
||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
#include <QJsonDocument>
|
#include <QJsonDocument>
|
||||||
|
#include <QApplication>
|
||||||
|
|
||||||
#include "exception.h"
|
#include "exception.h"
|
||||||
#include <utils/fileutils.h>
|
#include <utils/fileutils.h>
|
||||||
@ -23,6 +24,11 @@ Theme::Theme(const QString &p_themeFolderPath,
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString vnotex::Theme::getThemeFolder() const
|
||||||
|
{
|
||||||
|
return m_themeFolderPath;
|
||||||
|
}
|
||||||
|
|
||||||
bool Theme::isValidThemeFolder(const QString &p_folder)
|
bool Theme::isValidThemeFolder(const QString &p_folder)
|
||||||
{
|
{
|
||||||
QDir dir(p_folder);
|
QDir dir(p_folder);
|
||||||
@ -49,12 +55,12 @@ QString Theme::getDisplayName(const QString &p_folder, const QString &p_locale)
|
|||||||
|
|
||||||
if (!p_locale.isEmpty()) {
|
if (!p_locale.isEmpty()) {
|
||||||
// Check full locale.
|
// Check full locale.
|
||||||
auto fullLocale = QString("%1_%2").arg(prefix, p_locale);
|
auto fullLocale = QStringLiteral("%1_%2").arg(prefix, p_locale);
|
||||||
if (metaObj.contains(fullLocale)) {
|
if (metaObj.contains(fullLocale)) {
|
||||||
return metaObj.value(fullLocale).toString();
|
return metaObj.value(fullLocale).toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto shortLocale = QString("%1_%2").arg(prefix, p_locale.split('_')[0]);
|
auto shortLocale = QStringLiteral("%1_%2").arg(prefix, p_locale.split('_')[0]);
|
||||||
if (metaObj.contains(shortLocale)) {
|
if (metaObj.contains(shortLocale)) {
|
||||||
return metaObj.value(shortLocale).toString();
|
return metaObj.value(shortLocale).toString();
|
||||||
}
|
}
|
||||||
@ -71,7 +77,7 @@ Theme *Theme::fromFolder(const QString &p_folder)
|
|||||||
Q_ASSERT(!p_folder.isEmpty());
|
Q_ASSERT(!p_folder.isEmpty());
|
||||||
auto obj = readPaletteFile(p_folder);
|
auto obj = readPaletteFile(p_folder);
|
||||||
auto metadata = readMetadata(obj);
|
auto metadata = readMetadata(obj);
|
||||||
auto paletteObj = translatePalette(obj);
|
auto paletteObj = translatePalette(obj, metadata.m_backfillSystemPalette);
|
||||||
return new Theme(p_folder,
|
return new Theme(p_folder,
|
||||||
metadata,
|
metadata,
|
||||||
paletteObj);
|
paletteObj);
|
||||||
@ -86,11 +92,68 @@ Theme::Metadata Theme::readMetadata(const Palette &p_obj)
|
|||||||
data.m_revision = metaObj[QStringLiteral("revision")].toInt();
|
data.m_revision = metaObj[QStringLiteral("revision")].toInt();
|
||||||
data.m_editorHighlightTheme = metaObj[QStringLiteral("editor-highlight-theme")].toString();
|
data.m_editorHighlightTheme = metaObj[QStringLiteral("editor-highlight-theme")].toString();
|
||||||
data.m_markdownEditorHighlightTheme = metaObj[QStringLiteral("markdown-editor-highlight-theme")].toString();
|
data.m_markdownEditorHighlightTheme = metaObj[QStringLiteral("markdown-editor-highlight-theme")].toString();
|
||||||
|
data.m_backfillSystemPalette = metaObj[QStringLiteral("backfill-system-palette")].toBool(false);
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
Theme::Palette Theme::translatePalette(const QJsonObject &p_obj)
|
QJsonObject Theme::backfillSystemPalette(QJsonObject p_obj)
|
||||||
|
{
|
||||||
|
const auto qpalette = QApplication::palette();
|
||||||
|
// Active.
|
||||||
|
{
|
||||||
|
QJsonObject obj;
|
||||||
|
obj["window"] = qpalette.color(QPalette::Active, QPalette::Window).name();
|
||||||
|
obj["window_text"] = qpalette.color(QPalette::Active, QPalette::WindowText).name();
|
||||||
|
obj["base"] = qpalette.color(QPalette::Active, QPalette::Base).name();
|
||||||
|
obj["alternate_base"] = qpalette.color(QPalette::Active, QPalette::AlternateBase).name();
|
||||||
|
obj["text"] = qpalette.color(QPalette::Active, QPalette::Text).name();
|
||||||
|
obj["button"] = qpalette.color(QPalette::Active, QPalette::Button).name();
|
||||||
|
obj["button_text"] = qpalette.color(QPalette::Active, QPalette::ButtonText).name();
|
||||||
|
obj["bright_text"] = qpalette.color(QPalette::Active, QPalette::BrightText).name();
|
||||||
|
obj["light"] = qpalette.color(QPalette::Active, QPalette::Light).name();
|
||||||
|
obj["midlight"] = qpalette.color(QPalette::Active, QPalette::Midlight).name();
|
||||||
|
obj["dark"] = qpalette.color(QPalette::Active, QPalette::Dark).name();
|
||||||
|
obj["highlight"] = qpalette.color(QPalette::Active, QPalette::Highlight).name();
|
||||||
|
obj["highlighted_text"] = qpalette.color(QPalette::Active, QPalette::HighlightedText).name();
|
||||||
|
obj["link"] = qpalette.color(QPalette::Active, QPalette::Link).name();
|
||||||
|
obj["link_visited"] = qpalette.color(QPalette::Active, QPalette::LinkVisited).name();
|
||||||
|
|
||||||
|
p_obj["active"] = obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Inactive.
|
||||||
|
{
|
||||||
|
QJsonObject obj;
|
||||||
|
p_obj["inactive"] = obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Disabled.
|
||||||
|
{
|
||||||
|
QJsonObject obj;
|
||||||
|
obj["window"] = qpalette.color(QPalette::Disabled, QPalette::Window).name();
|
||||||
|
obj["window_text"] = qpalette.color(QPalette::Disabled, QPalette::WindowText).name();
|
||||||
|
obj["base"] = qpalette.color(QPalette::Disabled, QPalette::Base).name();
|
||||||
|
obj["alternate_base"] = qpalette.color(QPalette::Disabled, QPalette::AlternateBase).name();
|
||||||
|
obj["text"] = qpalette.color(QPalette::Disabled, QPalette::Text).name();
|
||||||
|
obj["button"] = qpalette.color(QPalette::Disabled, QPalette::Button).name();
|
||||||
|
obj["button_text"] = qpalette.color(QPalette::Disabled, QPalette::ButtonText).name();
|
||||||
|
obj["bright_text"] = qpalette.color(QPalette::Disabled, QPalette::BrightText).name();
|
||||||
|
obj["light"] = qpalette.color(QPalette::Disabled, QPalette::Light).name();
|
||||||
|
obj["midlight"] = qpalette.color(QPalette::Disabled, QPalette::Midlight).name();
|
||||||
|
obj["dark"] = qpalette.color(QPalette::Disabled, QPalette::Dark).name();
|
||||||
|
obj["highlight"] = qpalette.color(QPalette::Disabled, QPalette::Highlight).name();
|
||||||
|
obj["highlighted_text"] = qpalette.color(QPalette::Disabled, QPalette::HighlightedText).name();
|
||||||
|
obj["link"] = qpalette.color(QPalette::Disabled, QPalette::Link).name();
|
||||||
|
obj["link_visited"] = qpalette.color(QPalette::Disabled, QPalette::LinkVisited).name();
|
||||||
|
|
||||||
|
p_obj["disabled"] = obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
return p_obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
Theme::Palette Theme::translatePalette(const QJsonObject &p_obj, bool p_backfillSystemPalette)
|
||||||
{
|
{
|
||||||
const QString paletteSection("palette");
|
const QString paletteSection("palette");
|
||||||
const QString baseSection("base");
|
const QString baseSection("base");
|
||||||
@ -99,7 +162,12 @@ Theme::Palette Theme::translatePalette(const QJsonObject &p_obj)
|
|||||||
// @p_palette may contain referenced definitons: derived=@base#sub#sub2.
|
// @p_palette may contain referenced definitons: derived=@base#sub#sub2.
|
||||||
Palette palette;
|
Palette palette;
|
||||||
|
|
||||||
palette[paletteSection] = p_obj[paletteSection];
|
if (p_backfillSystemPalette) {
|
||||||
|
palette[paletteSection] = backfillSystemPalette(p_obj[paletteSection].toObject());
|
||||||
|
} else {
|
||||||
|
palette[paletteSection] = p_obj[paletteSection];
|
||||||
|
}
|
||||||
|
|
||||||
palette[baseSection] = p_obj[baseSection];
|
palette[baseSection] = p_obj[baseSection];
|
||||||
palette[widgetsSection] = p_obj[widgetsSection];
|
palette[widgetsSection] = p_obj[widgetsSection];
|
||||||
|
|
||||||
@ -162,8 +230,9 @@ QPair<bool, int> Theme::translatePaletteObjectOnce(const Palette &p_palette,
|
|||||||
}
|
}
|
||||||
|
|
||||||
Q_ASSERT_X(refVal.isString(), "translatePaletteObjectOnce", val.toString().toStdString().c_str());
|
Q_ASSERT_X(refVal.isString(), "translatePaletteObjectOnce", val.toString().toStdString().c_str());
|
||||||
it.value() = refVal.toString();
|
const auto refValStr = refVal.toString();
|
||||||
if (isRef(refVal.toString())) {
|
it.value() = refValStr;
|
||||||
|
if (isRef(refValStr)) {
|
||||||
// It is another ref again.
|
// It is another ref again.
|
||||||
++unresolvedRefs;
|
++unresolvedRefs;
|
||||||
}
|
}
|
||||||
@ -194,7 +263,6 @@ QString Theme::fetchQtStyleSheet() const
|
|||||||
translateStyleByPalette(m_palette, style);
|
translateStyleByPalette(m_palette, style);
|
||||||
translateUrlToAbsolute(m_themeFolderPath, style);
|
translateUrlToAbsolute(m_themeFolderPath, style);
|
||||||
translateFontFamilyList(style);
|
translateFontFamilyList(style);
|
||||||
translateScaledSize(WidgetUtils::calculateScaleFactor(), style);
|
|
||||||
return style;
|
return style;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -233,7 +301,7 @@ void Theme::translateUrlToAbsolute(const QString &p_basePath, QString &p_style)
|
|||||||
const int urlCapturedIdx = 2;
|
const int urlCapturedIdx = 2;
|
||||||
|
|
||||||
QDir dir(p_basePath);
|
QDir dir(p_basePath);
|
||||||
const int literalSize = QString("url(").size();
|
const int literalSize = QStringLiteral("url(").size();
|
||||||
int pos = 0;
|
int pos = 0;
|
||||||
QRegularExpressionMatch match;
|
QRegularExpressionMatch match;
|
||||||
while (pos < p_style.size()) {
|
while (pos < p_style.size()) {
|
||||||
@ -282,7 +350,7 @@ void Theme::translateFontFamilyList(QString &p_style)
|
|||||||
family = "\"" + family + "\"";
|
family = "\"" + family + "\"";
|
||||||
}
|
}
|
||||||
|
|
||||||
auto newStr = QString("%1font-family: %2;").arg(match.captured(prefixCapturedIdx), family);
|
auto newStr = QStringLiteral("%1font-family: %2;").arg(match.captured(prefixCapturedIdx), family);
|
||||||
p_style.replace(idx, match.capturedLength(), newStr);
|
p_style.replace(idx, match.capturedLength(), newStr);
|
||||||
pos = idx + newStr.size();
|
pos = idx + newStr.size();
|
||||||
} else {
|
} else {
|
||||||
@ -291,40 +359,6 @@ void Theme::translateFontFamilyList(QString &p_style)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Theme::translateScaledSize(qreal p_factor, QString &p_style)
|
|
||||||
{
|
|
||||||
QRegularExpression scaleRe("(\\s|:)\\$([+-]?)(\\d+)(?=\\D)");
|
|
||||||
const int prefixCapturedIdx = 1;
|
|
||||||
const int signCapturedIdx = 2;
|
|
||||||
const int numCapturedIdx = 3;
|
|
||||||
|
|
||||||
qDebug() << "translateScaledSize of Qt style sheet" << p_factor;
|
|
||||||
|
|
||||||
int pos = 0;
|
|
||||||
QRegularExpressionMatch match;
|
|
||||||
while (pos < p_style.size()) {
|
|
||||||
int idx = p_style.indexOf(scaleRe, pos, &match);
|
|
||||||
if (idx == -1) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto numStr = match.captured(numCapturedIdx);
|
|
||||||
bool ok = false;
|
|
||||||
int val = numStr.toInt(&ok);
|
|
||||||
if (!ok) {
|
|
||||||
pos = idx + match.capturedLength();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
val = val * p_factor + 0.5;
|
|
||||||
auto newStr = QString("%1%2%3").arg(match.captured(prefixCapturedIdx),
|
|
||||||
match.captured(signCapturedIdx),
|
|
||||||
QString::number(val));
|
|
||||||
p_style.replace(idx, match.capturedLength(), newStr);
|
|
||||||
pos = idx + newStr.size();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QString Theme::paletteColor(const QString &p_name) const
|
QString Theme::paletteColor(const QString &p_name) const
|
||||||
{
|
{
|
||||||
auto val = findValueByKeyPath(m_palette, p_name).toString();
|
auto val = findValueByKeyPath(m_palette, p_name).toString();
|
||||||
@ -332,7 +366,7 @@ QString Theme::paletteColor(const QString &p_name) const
|
|||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
qWarning() << "undefined or invalid palette color" << p_name;
|
qWarning() << "undefined or invalid palette color" << p_name;
|
||||||
return QString("#ff0000");
|
return QString();
|
||||||
}
|
}
|
||||||
|
|
||||||
QJsonObject Theme::readJsonFile(const QString &p_filePath)
|
QJsonObject Theme::readJsonFile(const QString &p_filePath)
|
||||||
@ -408,6 +442,8 @@ QString Theme::getFileName(File p_fileType)
|
|||||||
return QStringLiteral("markdown-editor-highlight.theme");
|
return QStringLiteral("markdown-editor-highlight.theme");
|
||||||
case File::Cover:
|
case File::Cover:
|
||||||
return QStringLiteral("cover.png");
|
return QStringLiteral("cover.png");
|
||||||
|
case File::Icon:
|
||||||
|
return QStringLiteral("icons");
|
||||||
default:
|
default:
|
||||||
Q_ASSERT(false);
|
Q_ASSERT(false);
|
||||||
return "";
|
return "";
|
||||||
|
@ -28,6 +28,7 @@ namespace vnotex
|
|||||||
EditorHighlightStyle,
|
EditorHighlightStyle,
|
||||||
MarkdownEditorHighlightStyle,
|
MarkdownEditorHighlightStyle,
|
||||||
Cover,
|
Cover,
|
||||||
|
Icon,
|
||||||
Max
|
Max
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -46,6 +47,8 @@ namespace vnotex
|
|||||||
|
|
||||||
QString name() const;
|
QString name() const;
|
||||||
|
|
||||||
|
QString getThemeFolder() const;
|
||||||
|
|
||||||
static bool isValidThemeFolder(const QString &p_folder);
|
static bool isValidThemeFolder(const QString &p_folder);
|
||||||
|
|
||||||
static Theme *fromFolder(const QString &p_folder);
|
static Theme *fromFolder(const QString &p_folder);
|
||||||
@ -69,6 +72,9 @@ namespace vnotex
|
|||||||
// If not specified, will use m_editorHighlightTheme.
|
// If not specified, will use m_editorHighlightTheme.
|
||||||
// Valid only when KSyntaxCodeBlockHighlighter is used.
|
// Valid only when KSyntaxCodeBlockHighlighter is used.
|
||||||
QString m_markdownEditorHighlightTheme;
|
QString m_markdownEditorHighlightTheme;
|
||||||
|
|
||||||
|
// Whether this theme needs to backfill current standard palette to the theme palette.
|
||||||
|
bool m_backfillSystemPalette = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef QJsonObject Palette;
|
typedef QJsonObject Palette;
|
||||||
@ -85,7 +91,9 @@ namespace vnotex
|
|||||||
|
|
||||||
static Metadata readMetadata(const QJsonObject &p_obj);
|
static Metadata readMetadata(const QJsonObject &p_obj);
|
||||||
|
|
||||||
static Theme::Palette translatePalette(const QJsonObject &p_obj);
|
static Theme::Palette translatePalette(const QJsonObject &p_obj, bool p_backfillSystemPalette);
|
||||||
|
|
||||||
|
static QJsonObject backfillSystemPalette(QJsonObject p_obj);
|
||||||
|
|
||||||
static void translatePaletteObject(const Palette &p_palette,
|
static void translatePaletteObject(const Palette &p_palette,
|
||||||
QJsonObject &p_obj,
|
QJsonObject &p_obj,
|
||||||
@ -107,8 +115,6 @@ namespace vnotex
|
|||||||
// Thus we need to choose one available font from the list.
|
// Thus we need to choose one available font from the list.
|
||||||
static void translateFontFamilyList(QString &p_style);
|
static void translateFontFamilyList(QString &p_style);
|
||||||
|
|
||||||
static void translateScaledSize(qreal p_factor, QString &p_style);
|
|
||||||
|
|
||||||
static QJsonObject readJsonFile(const QString &p_filePath);
|
static QJsonObject readJsonFile(const QString &p_filePath);
|
||||||
|
|
||||||
static QJsonObject readPaletteFile(const QString &p_folder);
|
static QJsonObject readPaletteFile(const QString &p_folder);
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#include <vtextedit/vtexteditor.h>
|
#include <vtextedit/vtexteditor.h>
|
||||||
#include "configmgr.h"
|
#include "configmgr.h"
|
||||||
#include "coreconfig.h"
|
#include "coreconfig.h"
|
||||||
|
#include "theme.h"
|
||||||
|
|
||||||
using namespace vnotex;
|
using namespace vnotex;
|
||||||
|
|
||||||
@ -23,8 +24,6 @@ ThemeMgr::ThemeMgr(const QString &p_currentThemeName, QObject *p_parent)
|
|||||||
loadAvailableThemes();
|
loadAvailableThemes();
|
||||||
|
|
||||||
loadCurrentTheme(p_currentThemeName);
|
loadCurrentTheme(p_currentThemeName);
|
||||||
|
|
||||||
IconUtils::setDefaultIconForeground(paletteColor("base#icon#fg"), paletteColor("base#icon#disabled#fg"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString ThemeMgr::getIconFile(const QString &p_icon) const
|
QString ThemeMgr::getIconFile(const QString &p_icon) const
|
||||||
@ -36,7 +35,13 @@ QString ThemeMgr::getIconFile(const QString &p_icon) const
|
|||||||
return p_icon;
|
return p_icon;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ":/vnotex/data/core/icons/" + p_icon;
|
// If there is an ICONS folder in the theme configuration, use the custom ICONS from it.
|
||||||
|
QString customIcon = getFile(Theme::File::Icon) + "/" + p_icon;
|
||||||
|
if (QFile::exists(customIcon)) {
|
||||||
|
return customIcon;
|
||||||
|
} else {
|
||||||
|
return ":/vnotex/data/core/icons/" + p_icon;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ThemeMgr::loadAvailableThemes()
|
void ThemeMgr::loadAvailableThemes()
|
||||||
@ -49,7 +54,7 @@ void ThemeMgr::loadAvailableThemes()
|
|||||||
|
|
||||||
if (m_themes.isEmpty()) {
|
if (m_themes.isEmpty()) {
|
||||||
Exception::throwOne(Exception::Type::EssentialFileMissing,
|
Exception::throwOne(Exception::Type::EssentialFileMissing,
|
||||||
QString("no available themes found in paths: %1").arg(s_searchPaths.join(QLatin1Char(';'))));
|
QStringLiteral("no available themes found in paths: %1").arg(s_searchPaths.join(QLatin1Char(';'))));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,6 +89,7 @@ const Theme &ThemeMgr::getCurrentTheme() const
|
|||||||
|
|
||||||
void ThemeMgr::loadCurrentTheme(const QString &p_themeName)
|
void ThemeMgr::loadCurrentTheme(const QString &p_themeName)
|
||||||
{
|
{
|
||||||
|
m_currentTheme.reset();
|
||||||
auto themeFolder = findThemeFolder(p_themeName);
|
auto themeFolder = findThemeFolder(p_themeName);
|
||||||
if (themeFolder.isNull()) {
|
if (themeFolder.isNull()) {
|
||||||
qWarning() << "failed to locate theme" << p_themeName;
|
qWarning() << "failed to locate theme" << p_themeName;
|
||||||
@ -97,6 +103,8 @@ void ThemeMgr::loadCurrentTheme(const QString &p_themeName)
|
|||||||
qWarning() << "fall back to default theme" << defaultTheme;
|
qWarning() << "fall back to default theme" << defaultTheme;
|
||||||
m_currentTheme.reset(loadTheme(findThemeFolder(defaultTheme)));
|
m_currentTheme.reset(loadTheme(findThemeFolder(defaultTheme)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IconUtils::setDefaultIconForeground(paletteColor("base#icon#fg"), paletteColor("base#icon#disabled#fg"));
|
||||||
}
|
}
|
||||||
|
|
||||||
Theme *ThemeMgr::loadTheme(const QString &p_themeFolder)
|
Theme *ThemeMgr::loadTheme(const QString &p_themeFolder)
|
||||||
@ -204,6 +212,14 @@ QPixmap ThemeMgr::getThemePreview(const QString &p_name) const
|
|||||||
void ThemeMgr::refresh()
|
void ThemeMgr::refresh()
|
||||||
{
|
{
|
||||||
loadAvailableThemes();
|
loadAvailableThemes();
|
||||||
|
refreshCurrentTheme();
|
||||||
|
}
|
||||||
|
|
||||||
|
void vnotex::ThemeMgr::refreshCurrentTheme()
|
||||||
|
{
|
||||||
|
if (m_currentTheme) {
|
||||||
|
loadCurrentTheme(m_currentTheme->name());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ThemeMgr::addWebStylesSearchPath(const QString &p_path)
|
void ThemeMgr::addWebStylesSearchPath(const QString &p_path)
|
||||||
|
@ -60,10 +60,11 @@ namespace vnotex
|
|||||||
|
|
||||||
const ThemeInfo *findTheme(const QString &p_name) const;
|
const ThemeInfo *findTheme(const QString &p_name) const;
|
||||||
|
|
||||||
// Refresh the themes list.
|
// Refresh the themes list and reload current theme.
|
||||||
// Won't affect current theme since we do not support changing theme real time for now.
|
|
||||||
void refresh();
|
void refresh();
|
||||||
|
|
||||||
|
void refreshCurrentTheme();
|
||||||
|
|
||||||
// Return all web stylesheets available, including those from themes and web styles search paths.
|
// Return all web stylesheets available, including those from themes and web styles search paths.
|
||||||
// <DisplayName, FilePath>.
|
// <DisplayName, FilePath>.
|
||||||
QVector<QPair<QString, QString>> getWebStyles() const;
|
QVector<QPair<QString, QString>> getWebStyles() const;
|
||||||
|
@ -1,11 +0,0 @@
|
|||||||
SOURCES += \
|
|
||||||
$$PWD/dummyversioncontroller.cpp \
|
|
||||||
$$PWD/versioncontrollerserver.cpp \
|
|
||||||
$$PWD/dummyversioncontrollerfactory.cpp
|
|
||||||
|
|
||||||
HEADERS += \
|
|
||||||
$$PWD/iversioncontroller.h \
|
|
||||||
$$PWD/dummyversioncontroller.h \
|
|
||||||
$$PWD/versioncontrollerserver.h \
|
|
||||||
$$PWD/iversioncontrollerfactory.h \
|
|
||||||
$$PWD/dummyversioncontrollerfactory.h
|
|
@ -79,6 +79,9 @@ namespace vnotex
|
|||||||
// The handler should determine in which folder this note belongs to.
|
// The handler should determine in which folder this note belongs to.
|
||||||
void newNoteRequested();
|
void newNoteRequested();
|
||||||
|
|
||||||
|
// Requested to new a quick note (maybe in current folder).
|
||||||
|
void newQuickNoteRequested();
|
||||||
|
|
||||||
// Requested to new a folder in current notebook.
|
// Requested to new a folder in current notebook.
|
||||||
void newFolderRequested();
|
void newFolderRequested();
|
||||||
|
|
||||||
|
@ -29,6 +29,8 @@ void WidgetConfig::init(const QJsonObject &p_app,
|
|||||||
|
|
||||||
m_findAndReplaceOptions = static_cast<FindOptions>(READINT(QStringLiteral("find_and_replace_options")));
|
m_findAndReplaceOptions = static_cast<FindOptions>(READINT(QStringLiteral("find_and_replace_options")));
|
||||||
|
|
||||||
|
m_notebookSelectorViewOrder = READINT(QStringLiteral("notebook_selector_view_order"));
|
||||||
|
|
||||||
{
|
{
|
||||||
m_nodeExplorerViewOrder = READINT(QStringLiteral("node_explorer_view_order"));
|
m_nodeExplorerViewOrder = READINT(QStringLiteral("node_explorer_view_order"));
|
||||||
m_nodeExplorerExploreMode = READINT(QStringLiteral("node_explorer_explore_mode"));
|
m_nodeExplorerExploreMode = READINT(QStringLiteral("node_explorer_explore_mode"));
|
||||||
@ -58,6 +60,8 @@ QJsonObject WidgetConfig::toJson() const
|
|||||||
|
|
||||||
obj[QStringLiteral("find_and_replace_options")] = static_cast<int>(m_findAndReplaceOptions);
|
obj[QStringLiteral("find_and_replace_options")] = static_cast<int>(m_findAndReplaceOptions);
|
||||||
|
|
||||||
|
obj[QStringLiteral("notebook_selector_view_order")] = m_notebookSelectorViewOrder;
|
||||||
|
|
||||||
obj[QStringLiteral("node_explorer_view_order")] = m_nodeExplorerViewOrder;
|
obj[QStringLiteral("node_explorer_view_order")] = m_nodeExplorerViewOrder;
|
||||||
obj[QStringLiteral("node_explorer_explore_mode")] = m_nodeExplorerExploreMode;
|
obj[QStringLiteral("node_explorer_explore_mode")] = m_nodeExplorerExploreMode;
|
||||||
obj[QStringLiteral("node_explorer_external_files_visible")] = m_nodeExplorerExternalFilesVisible;
|
obj[QStringLiteral("node_explorer_external_files_visible")] = m_nodeExplorerExternalFilesVisible;
|
||||||
@ -65,6 +69,7 @@ QJsonObject WidgetConfig::toJson() const
|
|||||||
obj[QStringLiteral("node_explorer_close_before_open_with_enabled")] = m_nodeExplorerCloseBeforeOpenWithEnabled;
|
obj[QStringLiteral("node_explorer_close_before_open_with_enabled")] = m_nodeExplorerCloseBeforeOpenWithEnabled;
|
||||||
|
|
||||||
obj[QStringLiteral("search_panel_advanced_settings_visible")] = m_searchPanelAdvancedSettingsVisible;
|
obj[QStringLiteral("search_panel_advanced_settings_visible")] = m_searchPanelAdvancedSettingsVisible;
|
||||||
|
obj[QStringLiteral("snippet_panel_builtin_snippets_visible")] = m_snippetPanelBuiltInSnippetsVisible;
|
||||||
obj[QStringLiteral("tag_explorer_two_columns_enabled")] = m_tagExplorerTwoColumnsEnabled;
|
obj[QStringLiteral("tag_explorer_two_columns_enabled")] = m_tagExplorerTwoColumnsEnabled;
|
||||||
writeStringList(obj,
|
writeStringList(obj,
|
||||||
QStringLiteral("main_window_keep_docks_expanding_content_area"),
|
QStringLiteral("main_window_keep_docks_expanding_content_area"),
|
||||||
@ -114,6 +119,16 @@ void WidgetConfig::setNodeExplorerViewOrder(int p_viewOrder)
|
|||||||
updateConfig(m_nodeExplorerViewOrder, p_viewOrder, this);
|
updateConfig(m_nodeExplorerViewOrder, p_viewOrder, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int WidgetConfig::getNotebookSelectorViewOrder() const
|
||||||
|
{
|
||||||
|
return m_notebookSelectorViewOrder;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WidgetConfig::setNotebookSelectorViewOrder(int p_viewOrder)
|
||||||
|
{
|
||||||
|
updateConfig(m_notebookSelectorViewOrder, p_viewOrder, this);
|
||||||
|
}
|
||||||
|
|
||||||
int WidgetConfig::getNodeExplorerExploreMode() const
|
int WidgetConfig::getNodeExplorerExploreMode() const
|
||||||
{
|
{
|
||||||
return m_nodeExplorerExploreMode;
|
return m_nodeExplorerExploreMode;
|
||||||
|
@ -27,6 +27,9 @@ namespace vnotex
|
|||||||
FindOptions getFindAndReplaceOptions() const;
|
FindOptions getFindAndReplaceOptions() const;
|
||||||
void setFindAndReplaceOptions(FindOptions p_options);
|
void setFindAndReplaceOptions(FindOptions p_options);
|
||||||
|
|
||||||
|
int getNotebookSelectorViewOrder() const;
|
||||||
|
void setNotebookSelectorViewOrder(int p_viewOrder);
|
||||||
|
|
||||||
int getNodeExplorerViewOrder() const;
|
int getNodeExplorerViewOrder() const;
|
||||||
void setNodeExplorerViewOrder(int p_viewOrder);
|
void setNodeExplorerViewOrder(int p_viewOrder);
|
||||||
|
|
||||||
@ -67,6 +70,8 @@ namespace vnotex
|
|||||||
|
|
||||||
FindOptions m_findAndReplaceOptions = FindOption::FindNone;
|
FindOptions m_findAndReplaceOptions = FindOption::FindNone;
|
||||||
|
|
||||||
|
int m_notebookSelectorViewOrder = 0;
|
||||||
|
|
||||||
int m_nodeExplorerViewOrder = 0;
|
int m_nodeExplorerViewOrder = 0;
|
||||||
|
|
||||||
int m_nodeExplorerExploreMode = 1;
|
int m_nodeExplorerExploreMode = 1;
|
||||||
|
@ -16,28 +16,32 @@
|
|||||||
<string>public.plain-text</string>
|
<string>public.plain-text</string>
|
||||||
<string>net.daringfireball.markdown</string>
|
<string>net.daringfireball.markdown</string>
|
||||||
</array>
|
</array>
|
||||||
|
<key>LSHandlerRank</key>
|
||||||
|
<string>Owner</string>
|
||||||
</dict>
|
</dict>
|
||||||
</array>
|
</array>
|
||||||
|
<key>CFBundleName</key>
|
||||||
|
<string>VNote</string>
|
||||||
<key>CFBundleExecutable</key>
|
<key>CFBundleExecutable</key>
|
||||||
<string>vnote</string>
|
<string>VNote</string>
|
||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
<string>3.13.1</string>
|
<string>3.19</string>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>3.13.1.1</string>
|
<string>3.19.2</string>
|
||||||
<key>NSHumanReadableCopyright</key>
|
<key>NSHumanReadableCopyright</key>
|
||||||
<string>Created by VNoteX</string>
|
<string>Distributed under LGPL-3.0 license. Copyright (c) 2025 app.vnote.fun</string>
|
||||||
<key>CFBundleIconFile</key>
|
<key>CFBundleIconFile</key>
|
||||||
<string>vnote.icns</string>
|
<string>vnote.icns</string>
|
||||||
<key>CFBundleIdentifier</key>
|
<key>CFBundleIdentifier</key>
|
||||||
<string>com.vnotex.vnote</string>
|
<string>fun.vnote.vnote</string>
|
||||||
<key>CFBundlePackageType</key>
|
<key>CFBundlePackageType</key>
|
||||||
<string>APPL</string>
|
<string>APPL</string>
|
||||||
<key>CFBundleSignature</key>
|
<key>LSApplicationCategoryType</key>
|
||||||
<string>????</string>
|
<string>public.app-category.productivity</string>
|
||||||
<key>LSMinimumSystemVersion</key>
|
<key>LSMinimumSystemVersion</key>
|
||||||
<string>10.12</string>
|
<string>10.15</string>
|
||||||
<key>NOTE</key>
|
<key>NOTE</key>
|
||||||
<string>Visit [GitHub VNote](https://github.com/vnotex/vnote) for details.</string>
|
<string>A pleasant note-taking platform</string>
|
||||||
<key>NSPrincipalClass</key>
|
<key>NSPrincipalClass</key>
|
||||||
<string>NSApplication</string>
|
<string>NSApplication</string>
|
||||||
<key>NSSupportsAutomaticGraphicsSwitching</key>
|
<key>NSSupportsAutomaticGraphicsSwitching</key>
|
||||||
|
@ -4,15 +4,11 @@
|
|||||||
<file>icons/vnote.icns</file>
|
<file>icons/vnote.icns</file>
|
||||||
<file>icons/vnote.ico</file>
|
<file>icons/vnote.ico</file>
|
||||||
<file>icons/new_note.svg</file>
|
<file>icons/new_note.svg</file>
|
||||||
<file>icons/import_notebook.svg</file>
|
|
||||||
<file>icons/import_notebook_of_vnote2.svg</file>
|
|
||||||
<file>icons/new_notebook.svg</file>
|
|
||||||
<file>icons/notebook_menu.svg</file>
|
<file>icons/notebook_menu.svg</file>
|
||||||
<file>icons/task_menu.svg</file>
|
<file>icons/task_menu.svg</file>
|
||||||
<file>icons/united_entry.svg</file>
|
<file>icons/united_entry.svg</file>
|
||||||
<file>icons/busy.svg</file>
|
<file>icons/busy.svg</file>
|
||||||
<file>icons/advanced_settings.svg</file>
|
<file>icons/advanced_settings.svg</file>
|
||||||
<file>icons/new_notebook_from_folder.svg</file>
|
|
||||||
<file>icons/discard_editor.svg</file>
|
<file>icons/discard_editor.svg</file>
|
||||||
<file>icons/edit_editor.svg</file>
|
<file>icons/edit_editor.svg</file>
|
||||||
<file>icons/read_editor.svg</file>
|
<file>icons/read_editor.svg</file>
|
||||||
@ -22,19 +18,15 @@
|
|||||||
<file>icons/tag_dock.svg</file>
|
<file>icons/tag_dock.svg</file>
|
||||||
<file>icons/tag.svg</file>
|
<file>icons/tag.svg</file>
|
||||||
<file>icons/tag_selected.svg</file>
|
<file>icons/tag_selected.svg</file>
|
||||||
<file>icons/help.svg</file>
|
|
||||||
<file>icons/menu.svg</file>
|
<file>icons/menu.svg</file>
|
||||||
<file>icons/settings.svg</file>
|
<file>icons/settings.svg</file>
|
||||||
<file>icons/view.svg</file>
|
<file>icons/view.svg</file>
|
||||||
<file>icons/inplace_preview_editor.svg</file>
|
<file>icons/inplace_preview_editor.svg</file>
|
||||||
<file>icons/image_host_editor.svg</file>
|
<file>icons/image_host_editor.svg</file>
|
||||||
<file>icons/settings_menu.svg</file>
|
|
||||||
<file>icons/help_menu.svg</file>
|
|
||||||
<file>icons/import_menu.svg</file>
|
<file>icons/import_menu.svg</file>
|
||||||
<file>icons/export_menu.svg</file>
|
<file>icons/export_menu.svg</file>
|
||||||
<file>icons/flash_page_menu.svg</file>
|
<file>icons/flash_page_menu.svg</file>
|
||||||
<file>icons/quick_access_menu.svg</file>
|
<file>icons/quick_access_menu.svg</file>
|
||||||
<file>icons/native_notebook_default.svg</file>
|
|
||||||
<file>icons/notebook_default.svg</file>
|
<file>icons/notebook_default.svg</file>
|
||||||
<file>icons/file_node.svg</file>
|
<file>icons/file_node.svg</file>
|
||||||
<file>icons/folder_node.svg</file>
|
<file>icons/folder_node.svg</file>
|
||||||
@ -50,6 +42,7 @@
|
|||||||
<file>icons/attachment_editor.svg</file>
|
<file>icons/attachment_editor.svg</file>
|
||||||
<file>icons/attachment_full_editor.svg</file>
|
<file>icons/attachment_full_editor.svg</file>
|
||||||
<file>icons/tag_editor.svg</file>
|
<file>icons/tag_editor.svg</file>
|
||||||
|
<file>icons/word_count_editor.svg</file>
|
||||||
<file>icons/split_menu.svg</file>
|
<file>icons/split_menu.svg</file>
|
||||||
<file>icons/split_window_list.svg</file>
|
<file>icons/split_window_list.svg</file>
|
||||||
<file>icons/type_heading_editor.svg</file>
|
<file>icons/type_heading_editor.svg</file>
|
||||||
@ -93,6 +86,7 @@
|
|||||||
<file>icons/navigation_dock.svg</file>
|
<file>icons/navigation_dock.svg</file>
|
||||||
<file>icons/history_dock.svg</file>
|
<file>icons/history_dock.svg</file>
|
||||||
<file>icons/outline_dock.svg</file>
|
<file>icons/outline_dock.svg</file>
|
||||||
|
<file>icons/windows_dock.svg</file>
|
||||||
<file>icons/search_dock.svg</file>
|
<file>icons/search_dock.svg</file>
|
||||||
<file>icons/snippet_dock.svg</file>
|
<file>icons/snippet_dock.svg</file>
|
||||||
<file>icons/location_list_dock.svg</file>
|
<file>icons/location_list_dock.svg</file>
|
||||||
@ -101,15 +95,5 @@
|
|||||||
<file>logo/vnote.png</file>
|
<file>logo/vnote.png</file>
|
||||||
<file>logo/256x256/vnote.png</file>
|
<file>logo/256x256/vnote.png</file>
|
||||||
<file>logo/vnote_mono.png</file>
|
<file>logo/vnote_mono.png</file>
|
||||||
<file>translations/qdialogbuttonbox_zh_CN.qm</file>
|
|
||||||
<file>translations/qwebengine_zh_CN.qm</file>
|
|
||||||
<file>translations/qt_zh_CN.qm</file>
|
|
||||||
<file>translations/vnote_zh_CN.qm</file>
|
|
||||||
<file>translations/qtbase_zh_CN.qm</file>
|
|
||||||
<file>translations/vtextedit_zh_CN.qm</file>
|
|
||||||
<file>translations/qt_ja.qm</file>
|
|
||||||
<file>translations/vnote_ja.qm</file>
|
|
||||||
<file>translations/qtbase_ja.qm</file>
|
|
||||||
<file>translations/vtextedit_ja.qm</file>
|
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user