├── .clang-format
├── .github
├── ISSUE_TEMPLATE
│ ├── bug-report.md
│ ├── feature_request.md
│ └── question.md
└── workflows
│ ├── build.yml
│ ├── check-format.yml
│ ├── cpack-deb.yml
│ └── cpack-nsis.yml
├── .gitignore
├── .gitmodules
├── CHANGELOG.md
├── CMakeLists.txt
├── LICENSE.md
├── README.md
├── assets
├── CREDIT.md
├── notepanda.desktop
└── notepanda.rc
├── images
├── banner.png
├── fluentui-icon
│ ├── LICENSE
│ ├── add.svg
│ ├── clipboard.svg
│ ├── color_background.svg
│ ├── copy.svg
│ ├── cut.svg
│ ├── delete.svg
│ ├── document.svg
│ ├── document_edit.svg
│ ├── info.svg
│ ├── open.svg
│ ├── pin.svg
│ ├── preview.svg
│ ├── print.svg
│ ├── read_only.svg
│ ├── redo.svg
│ ├── save.svg
│ ├── save_as.svg
│ ├── settings.svg
│ ├── sticker.svg
│ └── undo.svg
├── notepanda-sc1.png
├── notepanda-sc2.png
├── notepanda-sc3.png
├── notepanda-sc4.png
├── notepanda.png
└── panda.ico
├── makespec
├── BUILDVERSION
├── VERSION
└── VERSIONSUFFIX
├── resources.qrc
└── src
├── core
├── configmanager.cpp
├── configmanager.h
├── texteditor.cpp
└── texteditor.h
├── main.cpp
└── ui
├── aboutwindow.cpp
├── aboutwindow.h
├── aboutwindow.ui
├── linenumberarea.h
├── mainwindow.cpp
├── mainwindow.h
├── preferenceswindow.cpp
├── preferenceswindow.h
└── preferenceswindow.ui
/.clang-format:
--------------------------------------------------------------------------------
1 | # .clang-format
2 | Language: Cpp
3 | BasedOnStyle: Google
4 | IndentWidth: 4
5 | BreakBeforeBraces: Custom
6 | BraceWrapping:
7 | AfterClass: true
8 | AfterNamespace: true
9 | AfterStruct: true
10 | AfterFunction: true
11 | BeforeCatch: false
12 | BeforeElse: false
13 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug-report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug Report
3 | about: Create a report to help us improve
4 | title: "[BUG]"
5 | labels: ":bug: Bug"
6 | assignees: ChungZH
7 |
8 | ---
9 |
10 | **Describe the bug**
11 | > A clear and concise description of what the bug is.
12 |
13 | **To Reproduce**
14 | Steps to reproduce the behavior:
15 | 1. Go to '...'
16 | 2. Click on '....'
17 | 3. Scroll down to '....'
18 | 4. See error
19 |
20 | **Expected behavior**
21 | > A clear and concise description of what you expected to happen.
22 |
23 | **Screenshots**
24 | > If applicable, add screenshots to help explain your problem.
25 |
26 | **Affected Notepanda installation source**
27 |
28 | - [ ] ArchLinux AUR
29 | - [ ] Compile manually
30 | - [ ] Github Release
31 |
32 |
33 | **Desktop (please complete the following information):**
34 | - OS [e.g. Windows, Linux, MacOS]:
35 | - Version in the AboutWindow [e.g. 0.1.3-alpha1]:
36 |
37 |
38 | **Additional context**
39 | > Add any other context about the problem here.
40 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | title: "[Feature request]"
5 | labels: ":tada: Enhancement"
6 | assignees: ChungZH
7 |
8 | ---
9 |
10 | **Is your feature request related to a problem? Please describe.**
11 | > A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
12 |
13 | **Describe the solution you'd like**
14 | > A clear and concise description of what you want to happen.
15 |
16 | **Describe alternatives you've considered**
17 | > A clear and concise description of any alternative solutions or features you've considered.
18 |
19 | **Additional context**
20 | > Add any other context or screenshots about the feature request here.
21 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/question.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Question
3 | about: Ask a question about Notepanda
4 | title: "[Question]"
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Question description**
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.github/workflows/build.yml:
--------------------------------------------------------------------------------
1 | name: Build CI
2 |
3 | on:
4 | push:
5 | release:
6 | types: [published]
7 |
8 | jobs:
9 | build:
10 | strategy:
11 | matrix:
12 | qt_version: [5.14.2]
13 | platform: [ubuntu-16.04, macos-latest, windows-latest]
14 | arch: [x86, x64]
15 | include:
16 | - platform: windows-latest
17 | arch: x86
18 | qtarch: win32_msvc2017
19 | cmakearch: Win32
20 | - platform: windows-latest
21 | arch: x64
22 | qtarch: win64_msvc2017_64
23 | cmakearch: x64
24 | exclude:
25 | - platform: ubuntu-16.04
26 | arch: x86
27 | - platform: macos-latest
28 | arch: x86
29 | fail-fast: false
30 | runs-on: ${{ matrix.platform }}
31 | steps:
32 | - name: Checking out sources
33 | uses: actions/checkout@v2
34 | with:
35 | submodules: "recursive"
36 | - name: Install MSVC compiler
37 | uses: ilammy/msvc-dev-cmd@v1
38 | with:
39 | # 14.1 is for vs2017, 14.2 is vs2019, following the upstream vcpkg build from Qv2ray-deps repo
40 | toolset: 14.2
41 | arch: ${{ matrix.arch }}
42 | - name: Cache Qt
43 | id: cache-qt
44 | uses: actions/cache@v1
45 | with:
46 | path: ../Qt
47 | key: QtCache-${{ matrix.platform }}-${{ matrix.arch }}-${{ matrix.qt_version }}
48 | - name: Installing Qt - ${{ matrix.arch }}
49 | uses: jurplel/install-qt-action@v2
50 | with:
51 | version: ${{ matrix.qt_version }}
52 | arch: ${{ matrix.qtarch }}
53 | mirror: "http://mirrors.ocf.berkeley.edu/qt/"
54 | cached: ${{ steps.cache-qt.outputs.cache-hit }}
55 | - name: Install Python 3.7 version
56 | if: matrix.platform == 'windows-latest'
57 | uses: actions/setup-python@v1
58 | with:
59 | python-version: "3.7"
60 | architecture: ${{ matrix.arch }}
61 | - name: Get the version
62 | id: get_version
63 | shell: bash
64 | run: echo ::set-output name=VERSION::$(echo $GITHUB_REF | cut -d / -f 3)
65 | # Linux------------------------------------------
66 | - name: Linux - Install packages
67 | if: matrix.platform == 'ubuntu-16.04'
68 | shell: bash
69 | env:
70 | CC: /usr/bin/gcc-9
71 | CXX: /usr/bin/g++-9
72 | run: |
73 | sudo apt install libgl-dev libx11-dev libxkbcommon-x11-dev ninja-build
74 | - name: Linux - Build ecm
75 | if: matrix.platform == 'ubuntu-16.04'
76 | shell: bash
77 | env:
78 | CC: /usr/bin/gcc-9
79 | CXX: /usr/bin/g++-9
80 | run: |
81 | cd src/3rdparty/extra-cmake-modules
82 | mkdir build
83 | cd build
84 | cmake .. -GNinja -DCMAKE_BUILD_TYPE=Release -DBUILD_HTML_DOCS=OFF -DBUILD_MAN_DOCS=OFF -DBUILD_QTHELP_DOCS=OFF -DBUILD_TESTING=OFF -DCMAKE_INSTALL_PREFIX=/usr
85 | cmake --build . --parallel $(nproc)
86 | sudo cmake --build . --target install
87 | - name: Linux - Build SyntaxHighlighting
88 | if: matrix.platform == 'ubuntu-16.04'
89 | shell: bash
90 | env:
91 | CC: /usr/bin/gcc-9
92 | CXX: /usr/bin/g++-9
93 | run: |
94 | cd src/3rdparty/syntax-highlighting
95 | mkdir build
96 | cd build
97 | cmake .. -GNinja -DCMAKE_BUILD_TYPE=Release -DBUILD_HTML_DOCS=OFF -DBUILD_MAN_DOCS=OFF -DBUILD_QTHELP_DOCS=OFF -DBUILD_TESTING=OFF -DCMAKE_INSTALL_PREFIX=/usr
98 | cmake --build . --parallel $(nproc)
99 | sudo cmake --build . --target install
100 | - name: Linux - ${{ matrix.qt_version }} - Generate Dependencies and Build
101 | if: matrix.platform == 'ubuntu-16.04'
102 | shell: bash
103 | env:
104 | CC: /usr/bin/gcc-9
105 | CXX: /usr/bin/g++-9
106 | run: |
107 | mkdir build
108 | cd build
109 | cmake .. -GNinja -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=./AppDir/usr
110 | cmake --build . --parallel $(nproc)
111 | cmake --install .
112 | - name: Linux - ${{ matrix.qt_version }} - Generating AppImage
113 | if: matrix.platform == 'ubuntu-16.04'
114 | shell: bash
115 | env:
116 | CC: /usr/bin/gcc-9
117 | CXX: /usr/bin/g++-9
118 | run: |
119 | cd build
120 | wget https://github.com/probonopd/linuxdeployqt/releases/download/6/linuxdeployqt-6-x86_64.AppImage
121 | chmod +x ./linuxdeployqt-6-x86_64.AppImage
122 | ./linuxdeployqt-6-x86_64.AppImage --appimage-extract
123 | cd AppDir
124 | wget -c https://github.com/darealshinji/AppImageKit-checkrt/releases/download/continuous/AppRun-patched-x86_64 -O AppRun
125 | chmod a+x AppRun
126 | mkdir -p ./usr/{lib,optional}/
127 | wget -c https://github.com/darealshinji/AppImageKit-checkrt/releases/download/continuous/exec-x86_64.so -O ./usr/optional/exec.so
128 | mkdir -p ./usr/optional/libstdc++/
129 | cp -fv /usr/lib/x86_64-linux-gnu/libstdc++.so.6 ./usr/optional/libstdc++/
130 | mkdir -p ./usr/optional/libgcc_s/
131 | cp -fv /lib/x86_64-linux-gnu/libgcc_s.so.1 ./usr/optional/libgcc_s/
132 | cp -fv /usr/lib/x86_64-linux-gnu/{libssl.so.1.1,libcrypto.so.1.1} ./usr/lib/
133 | cd ..
134 | squashfs-root/AppRun AppDir/usr/share/applications/notepanda.desktop -appimage -no-strip -always-overwrite
135 | mv ./Notepanda*.AppImage ./Notepanda.AppImage
136 | - name: Linux - ${{ matrix.qt_version }} - Uploading artifact
137 | if: matrix.platform == 'ubuntu-16.04'
138 | uses: actions/upload-artifact@master
139 | with:
140 | name: Notepanda-${{ github.sha }}.Linux-${{ matrix.arch }}.qt${{ matrix.qt_version }}.AppImage
141 | path: build/Notepanda.AppImage
142 | - name: Linux - ${{ matrix.qt_version }} - Upload binaries to release
143 | uses: svenstaro/upload-release-action@v1-release
144 | if: github.event_name == 'release' && matrix.platform == 'ubuntu-16.04' && matrix.qt_version == '5.14.2'
145 | with:
146 | repo_token: ${{ secrets.GITHUB_TOKEN }}
147 | file: build/Notepanda.AppImage
148 | asset_name: Notepanda.${{ steps.get_version.outputs.VERSION }}.Linux-${{ matrix.arch }}.AppImage
149 | tag: ${{ github.ref }}
150 | overwrite: true
151 | # Windows----------------------------------------------------------------------
152 | # - name: Win-${{ matrix.arch }} - ${{ matrix.qt_version }} - Build preparation - Download Dependencies
153 | # if: matrix.platform == 'windows-latest'
154 | # run: |
155 | # choco install -y ninja
156 | - name: Setup Ninja
157 | if: matrix.platform == 'windows-latest'
158 | uses: ashutoshvarma/setup-ninja@master
159 | with:
160 | # ninja version to download. Default: 1.10.0
161 | version: 1.10.0
162 | - name: Win - Build ecm
163 | if: matrix.platform == 'windows-latest'
164 | env:
165 | CC: cl.exe
166 | CXX: cl.exe
167 | run: |
168 | set VCINSTALLDIR="C:\Program Files (x86)\Microsoft Visual Studio 16.0\VC"
169 | cd src/3rdparty/extra-cmake-modules
170 | mkdir build
171 | cd build
172 | cmake .. -GNinja -DCMAKE_BUILD_TYPE=Release -DBUILD_HTML_DOCS=OFF -DBUILD_MAN_DOCS=OFF -DBUILD_QTHELP_DOCS=OFF -DBUILD_TESTING=OFF
173 | cmake --build . --parallel $(nproc)
174 | cmake --build . --target install
175 | - name: Win - Build syntax highlight
176 | if: matrix.platform == 'windows-latest'
177 | env:
178 | CC: cl.exe
179 | CXX: cl.exe
180 | run: |
181 | cd src/3rdparty/syntax-highlighting
182 | mkdir build
183 | cd build
184 | cmake .. -GNinja -DCMAKE_BUILD_TYPE=Release -DBUILD_HTML_DOCS=OFF -DBUILD_MAN_DOCS=OFF -DBUILD_QTHELP_DOCS=OFF -DBUILD_TESTING=OFF
185 | cmake --build . --parallel $(nproc)
186 | cmake --build . --target install
187 | - name: Windows - ${{ matrix.qt_version }} - Generate Dependencies and Build
188 | if: matrix.platform == 'windows-latest'
189 | env:
190 | CC: cl.exe
191 | CXX: cl.exe
192 | run: |
193 | mkdir build
194 | cd build
195 | cmake .. -GNinja -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=Release -DKF5SyntaxHighlighting_DIR="C:/Program Files (x86)/ECM/lib/cmake/KF5SyntaxHighlighting"
196 | cmake --build . --parallel $(nproc)
197 | cmake --install .
198 | cd Release
199 | windeployqt notepanda.exe --no-translations
200 | - name: Win - ${{ matrix.arch }} - ${{ matrix.qt_version }} - Create 7z Release
201 | if: matrix.platform == 'windows-latest'
202 | uses: DuckSoft/create-7z-action@v1.0
203 | with:
204 | pathSource: ./build/Release
205 | pathTarget: ./release.7z
206 | - name: Win - ${{ matrix.arch }} - ${{ matrix.qt_version }} - Uploading artifact
207 | if: matrix.platform == 'windows-latest'
208 | uses: actions/upload-artifact@master
209 | with:
210 | name: Notepanda-${{ github.sha }}.Windows-${{ matrix.arch }}.qt${{ matrix.qt_version }}.7z
211 | path: release.7z
212 | - name: Win - ${{ matrix.arch }} - ${{ matrix.qt_version }} - Upload binaries to release
213 | uses: svenstaro/upload-release-action@v1-release
214 | if: github.event_name == 'release' && matrix.platform == 'windows-latest' && matrix.qt_version == '5.14.2'
215 | with:
216 | repo_token: ${{ secrets.GITHUB_TOKEN }}
217 | file: release.7z
218 | asset_name: Notepanda.${{ steps.get_version.outputs.VERSION }}.Windows-${{ matrix.arch }}.7z
219 | tag: ${{ github.ref }}
220 | overwrite: true
221 | # MacOS ---------------------------------------------------------
222 | - name: MacOS - Build ecm
223 | if: matrix.platform == 'macos-latest'
224 | shell: bash
225 | run: |
226 | brew install ninja
227 | cd src/3rdparty/extra-cmake-modules
228 | mkdir build
229 | cd build
230 | cmake .. -GNinja -DBUILD_HTML_DOCS=OFF -DBUILD_MAN_DOCS=OFF -DBUILD_QTHELP_DOCS=OFF -DBUILD_TESTING=OFF
231 | cmake --build .
232 | cmake --build . --target install
233 | - name: MacOS - Build syntax highlight
234 | if: matrix.platform == 'macos-latest'
235 | run: |
236 | cd src/3rdparty/syntax-highlighting
237 | mkdir build
238 | cd build
239 | cmake .. -GNinja -DBUILD_HTML_DOCS=OFF -DBUILD_MAN_DOCS=OFF -DBUILD_QTHELP_DOCS=OFF -DBUILD_TESTING=OFF
240 | cmake --build .
241 | sudo cmake --build . --target install
242 | - name: macOS - ${{ matrix.qt_version }} - Generate Dependencies and Build
243 | if: matrix.platform == 'macos-latest'
244 | run: |
245 | mkdir build
246 | cd build
247 | cmake .. -GNinja -DCMAKE_BUILD_TYPE=Release -DCMAKE_OSX_DEPLOYMENT_TARGET=10.13 -DDS_STORE_SCRIPT=ON
248 | cmake --build .
249 | sudo cmake --install .
250 | macdeployqt notepanda.app -dmg
251 | - name: macOS - ${{ matrix.qt_version }} - Uploading Artifact
252 | if: matrix.platform == 'macos-latest'
253 | uses: actions/upload-artifact@master
254 | with:
255 | name: Notepanda-${{ github.sha }}.macOS-${{ matrix.arch }}.qt${{ matrix.qt_version }}.dmg
256 | path: build/notepanda.dmg
257 | - name: macOS - ${{ matrix.qt_version }} - Upload binaries to release
258 | uses: svenstaro/upload-release-action@v1-release
259 | if: github.event_name == 'release' && matrix.platform == 'macos-latest' && matrix.qt_version == '5.14.2'
260 | with:
261 | repo_token: ${{ secrets.GITHUB_TOKEN }}
262 | file: build/notepanda.dmg
263 | asset_name: Notepanda-${{ steps.get_version.outputs.VERSION }}.macOS-${{ matrix.arch }}.dmg
264 | tag: ${{ github.ref }}
265 | overwrite: true
266 | # END
--------------------------------------------------------------------------------
/.github/workflows/check-format.yml:
--------------------------------------------------------------------------------
1 | name: "Check Clang Format"
2 |
3 | on: [push, pull_request]
4 |
5 | jobs:
6 | format:
7 | name: "Check Clang Format"
8 | runs-on: ubuntu-latest
9 | steps:
10 | - uses: actions/checkout@v2
11 | - name: "Install clang-format-9"
12 | run: |
13 | sudo apt-get update
14 | sudo apt-get install clang-format-9
15 | - name: "Format Codes"
16 | run: clang-format-9 -i src/*.cpp src/*/*.cpp src/*/*.h
17 | - name: Check diff
18 | run: git diff --exit-code HEAD
19 | - name: Create Pull Request
20 | if: failure()
21 | uses: peter-evans/create-pull-request@v2
22 | with:
23 | commit-message: "style: format codes"
24 | title: "style: format codes for ${{ github.ref }}"
25 | labels: "auto-pr/style"
26 | assignees: "${{ github.actor }}"
27 | reviewers: "${{ github.actor }}"
28 | branch: "auto-pr/clang-format/${{ github.ref }}"
29 |
--------------------------------------------------------------------------------
/.github/workflows/cpack-deb.yml:
--------------------------------------------------------------------------------
1 | name: CPack - DEB
2 |
3 | on:
4 | push:
5 | release:
6 | types: [published]
7 |
8 | jobs:
9 | check_commit_msg:
10 | outputs:
11 | commit_message: ${{ steps.get_message.outputs.message }}
12 | name: Check if the workflow has been disabled.
13 | runs-on: ubuntu-latest
14 | steps:
15 | - uses: actions/checkout@v1
16 | - name: Get commit message
17 | id: get_message
18 | run: |
19 | echo "::set-output name=message::$(git log --format=%B -n 1 ${{ github.event.after }})"
20 | echo "::set-env name=message::$(git log --format=%B -n 1 ${{ github.event.after }})"
21 | linux:
22 | strategy:
23 | matrix:
24 | distro: [stable]
25 | needs: check_commit_msg
26 | if: ${{ !contains( needs.check_commit_msg.outputs.commit_message, 'NO_DEB') }}
27 | name: Debian ${{ matrix.distro }}
28 | runs-on: ubuntu-latest
29 | container: debian:${{ matrix.distro }}
30 |
31 | steps:
32 | - name: Install git
33 | run: |
34 | apt-get update
35 | apt-get install -y git
36 | - name: Checking out sources
37 | uses: actions/checkout@v2
38 | with:
39 | submodules: 'recursive'
40 | - name: Install build dependencies
41 | run: |
42 | apt-get install -y build-essential ninja-build qtbase5-dev qttools5-dev cmake libkf5syntaxhighlighting-dev
43 | - name: Build
44 | run: |
45 | mkdir build
46 | cd build
47 | cmake .. -GNinja -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=./AppDir/usr -DBUILD_DEB=ON
48 | cmake --build . --target package --parallel $(nproc)
49 | - name: Get package name
50 | shell: bash
51 | id: get_package
52 | run: |
53 | echo ::set-output name=NAME::$(basename build/Notepanda-*.deb)
54 | - name: Get the version
55 | id: get_version
56 | shell: bash
57 | run: echo ::set-output name=VERSION::$(echo $GITHUB_REF | cut -d / -f 3)
58 | - name: Upload artifact
59 | uses: actions/upload-artifact@v2-preview
60 | with:
61 | name: ${{ steps.get_package.outputs.NAME }}
62 | path: build/${{ steps.get_package.outputs.NAME }}
63 | - name: Upload binaries to release
64 | uses: svenstaro/upload-release-action@v1-release
65 | if: github.event_name == 'release' && matrix.distro == 'stable'
66 | with:
67 | repo_token: ${{ secrets.GITHUB_TOKEN }}
68 | file: build/${{ steps.get_package.outputs.NAME }}
69 | asset_name: Notepanda.${{ steps.get_version.outputs.VERSION }}-${{ matrix.distro }}.deb
70 | tag: ${{ github.ref }}
71 | overwrite: true
72 |
--------------------------------------------------------------------------------
/.github/workflows/cpack-nsis.yml:
--------------------------------------------------------------------------------
1 | name: CPack - NSIS
2 |
3 | on:
4 | push:
5 | release:
6 | types: [published]
7 |
8 | jobs:
9 | build:
10 | strategy:
11 | matrix:
12 | qt_version: [5.14.2]
13 | platform: [windows-latest]
14 | arch: [x86, x64]
15 | include:
16 | - platform: windows-latest
17 | arch: x86
18 | qtarch: win32_msvc2017
19 | cmakearch: Win32
20 | - platform: windows-latest
21 | arch: x64
22 | qtarch: win64_msvc2017_64
23 | cmakearch: x64
24 | fail-fast: false
25 |
26 | runs-on: ${{ matrix.platform }}
27 |
28 | steps:
29 | - name: Get the version
30 | id: get_version
31 | shell: bash
32 | run: echo ::set-output name=VERSION::$(echo $GITHUB_REF | cut -d / -f 3)
33 | - name: Checking out sources
34 | uses: actions/checkout@v2
35 | with:
36 | submodules: 'recursive'
37 | - name: Install Python 3.7 version
38 | uses: actions/setup-python@v1
39 | with:
40 | python-version: '3.7'
41 | architecture: ${{ matrix.arch }}
42 | # =========================================================================================================
43 | - name: Install MSVC compiler
44 | uses: ilammy/msvc-dev-cmd@v1
45 | with:
46 | toolset: 14.2
47 | arch: ${{ matrix.arch }}
48 | - name: Cache Qt
49 | id: cache-qt
50 | uses: actions/cache@v1
51 | with:
52 | path: ../Qt
53 | key: QtCache-${{ matrix.platform }}-${{ matrix.arch }}-${{ matrix.qt_version }}
54 | - name: Installing Qt - ${{ matrix.arch }}
55 | uses: jurplel/install-qt-action@v2.5.0
56 | with:
57 | version: ${{ matrix.qt_version }}
58 | arch: ${{ matrix.qtarch }}
59 | mirror: 'http://mirrors.ocf.berkeley.edu/qt/'
60 | cached: ${{ steps.cache-qt.outputs.cache-hit }}
61 | # Windows----------------------------------------------------------------------
62 | # - name: Win-${{ matrix.arch }} - ${{ matrix.qt_version }} - Build preparation - Download Dependencies
63 | # if: matrix.platform == 'windows-latest'
64 | # run: |
65 | # choco install -y ninja
66 | - name: Setup Ninja
67 | if: matrix.platform == 'windows-latest'
68 | uses: ashutoshvarma/setup-ninja@master
69 | with:
70 | # ninja version to download. Default: 1.10.0
71 | version: 1.10.0
72 | - name: Win - Build ecm
73 | if: matrix.platform == 'windows-latest'
74 | env:
75 | CC: cl.exe
76 | CXX: cl.exe
77 | run: |
78 | set VCINSTALLDIR="C:\Program Files (x86)\Microsoft Visual Studio 16.0\VC"
79 | cd src/3rdparty/extra-cmake-modules
80 | mkdir build
81 | cd build
82 | cmake .. -GNinja -DCMAKE_BUILD_TYPE=Release -DBUILD_HTML_DOCS=OFF -DBUILD_MAN_DOCS=OFF -DBUILD_QTHELP_DOCS=OFF -DBUILD_TESTING=OFF
83 | cmake --build .
84 | cmake --build . --target install
85 | - name: Win - Build syntax highlight
86 | if: matrix.platform == 'windows-latest'
87 | env:
88 | CC: cl.exe
89 | CXX: cl.exe
90 | run: |
91 | cd src/3rdparty/syntax-highlighting
92 | mkdir build
93 | cd build
94 | cmake .. -GNinja -DCMAKE_BUILD_TYPE=Release -DBUILD_HTML_DOCS=OFF -DBUILD_MAN_DOCS=OFF -DBUILD_QTHELP_DOCS=OFF -DBUILD_TESTING=OFF
95 | cmake --build .
96 | cmake --build . --target install
97 | - name: Windows - ${{ matrix.qt_version }} - Generate Dependencies and Build
98 | if: matrix.platform == 'windows-latest'
99 | env:
100 | CC: cl.exe
101 | CXX: cl.exe
102 | run: |
103 | mkdir build
104 | cd build
105 | cmake .. -GNinja -DCMAKE_BUILD_TYPE=Release -DKF5SyntaxHighlighting_DIR="C:/Program Files (x86)/ECM/lib/cmake/KF5SyntaxHighlighting" -DBUILD_NSIS=ON
106 | cmake --build . --target package --parallel $(nproc)
107 | - name: Windows - Get package name
108 | shell: bash
109 | id: get_package
110 | run: |
111 | echo ::set-output name=NAME::$(basename build/Notepanda-*.exe)
112 | - name: Win-${{ matrix.arch }} - ${{ matrix.qt_version }} - uploading artifact
113 | uses: actions/upload-artifact@master
114 | with:
115 | name: ${{ steps.get_package.outputs.NAME }}
116 | path: build/${{ steps.get_package.outputs.NAME }}
117 | - name: Win-${{ matrix.arch }} - ${{ matrix.qt_version }} - Upload binaries to release
118 | uses: svenstaro/upload-release-action@v1-release
119 | if: github.event_name == 'release'
120 | with:
121 | repo_token: ${{ secrets.GITHUB_TOKEN }}
122 | file: build/${{ steps.get_package.outputs.NAME }}
123 | asset_name: Notepanda.${{ steps.get_version.outputs.VERSION }}.Windows-${{ matrix.arch }}.exe
124 | tag: ${{ github.ref }}
125 | overwrite: true
126 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Prerequisites
2 | *.d
3 |
4 | # Compiled Object files
5 | *.slo
6 | *.lo
7 | *.o
8 | *.obj
9 |
10 | # Precompiled Headers
11 | *.gch
12 | *.pch
13 |
14 | # Compiled Dynamic libraries
15 | *.so
16 | *.dylib
17 | *.dll
18 |
19 | # Fortran module files
20 | *.mod
21 | *.smod
22 |
23 | # Compiled Static libraries
24 | *.lai
25 | *.la
26 | *.a
27 | *.lib
28 |
29 | # Executables
30 | *.exe
31 | *.out
32 | *.app
33 |
34 | # Some files
35 | .DS_Store
36 | *.autosave
37 | *.user
38 | .vs/
39 | *.qm
40 | .vscode/
41 | CMakeSettings.json
42 | /makespec/qv2ray.spec
43 |
44 | build/
45 |
46 |
47 | ## Ignore Visual Studio temporary files, build results, and
48 | ## files generated by popular Visual Studio add-ons.
49 | ##
50 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
51 |
52 | # User-specific files
53 | *.rsuser
54 | *.suo
55 | *.user
56 | *.userosscache
57 | *.sln.docstates
58 |
59 | # User-specific files (MonoDevelop/Xamarin Studio)
60 | *.userprefs
61 |
62 | # Mono auto generated files
63 | mono_crash.*
64 |
65 | # Build results
66 | [Dd]ebug/
67 | [Dd]ebugPublic/
68 | [Rr]elease/
69 | [Rr]eleases/
70 | x64/
71 | x86/
72 | [Ww][Ii][Nn]32/
73 | [Aa][Rr][Mm]/
74 | [Aa][Rr][Mm]64/
75 | bld/
76 | [Bb]in/
77 | [Oo]bj/
78 | [Ll]og/
79 | [Ll]ogs/
80 |
81 | # Visual Studio 2015/2017 cache/options directory
82 | .vs/
83 | # Uncomment if you have tasks that create the project's static files in wwwroot
84 | #wwwroot/
85 |
86 | # Visual Studio 2017 auto generated files
87 | Generated\ Files/
88 |
89 | # MSTest test Results
90 | [Tt]est[Rr]esult*/
91 | [Bb]uild[Ll]og.*
92 |
93 | # NUnit
94 | *.VisualState.xml
95 | TestResult.xml
96 | nunit-*.xml
97 |
98 | # Build Results of an ATL Project
99 | [Dd]ebugPS/
100 | [Rr]eleasePS/
101 | dlldata.c
102 |
103 | # Benchmark Results
104 | BenchmarkDotNet.Artifacts/
105 |
106 | # .NET Core
107 | project.lock.json
108 | project.fragment.lock.json
109 | artifacts/
110 |
111 | # ASP.NET Scaffolding
112 | ScaffoldingReadMe.txt
113 |
114 | # StyleCop
115 | StyleCopReport.xml
116 |
117 | # Files built by Visual Studio
118 | *_i.c
119 | *_p.c
120 | *_h.h
121 | *.ilk
122 | *.meta
123 | *.obj
124 | *.iobj
125 | *.pch
126 | *.pdb
127 | *.ipdb
128 | *.pgc
129 | *.pgd
130 | *.rsp
131 | *.sbr
132 | *.tlb
133 | *.tli
134 | *.tlh
135 | *.tmp
136 | *.tmp_proj
137 | *_wpftmp.csproj
138 | *.log
139 | *.vspscc
140 | *.vssscc
141 | .builds
142 | *.pidb
143 | *.svclog
144 | *.scc
145 |
146 | # Chutzpah Test files
147 | _Chutzpah*
148 |
149 | # Visual C++ cache files
150 | ipch/
151 | *.aps
152 | *.ncb
153 | *.opendb
154 | *.opensdf
155 | *.sdf
156 | *.cachefile
157 | *.VC.db
158 | *.VC.VC.opendb
159 |
160 | # Visual Studio profiler
161 | *.psess
162 | *.vsp
163 | *.vspx
164 | *.sap
165 |
166 | # Visual Studio Trace Files
167 | *.e2e
168 |
169 | # TFS 2012 Local Workspace
170 | $tf/
171 |
172 | # Guidance Automation Toolkit
173 | *.gpState
174 |
175 | # ReSharper is a .NET coding add-in
176 | _ReSharper*/
177 | *.[Rr]e[Ss]harper
178 | *.DotSettings.user
179 |
180 | # TeamCity is a build add-in
181 | _TeamCity*
182 |
183 | # DotCover is a Code Coverage Tool
184 | *.dotCover
185 |
186 | # AxoCover is a Code Coverage Tool
187 | .axoCover/*
188 | !.axoCover/settings.json
189 |
190 | # Coverlet is a free, cross platform Code Coverage Tool
191 | coverage*[.json, .xml, .info]
192 |
193 | # Visual Studio code coverage results
194 | *.coverage
195 | *.coveragexml
196 |
197 | # NCrunch
198 | _NCrunch_*
199 | .*crunch*.local.xml
200 | nCrunchTemp_*
201 |
202 | # MightyMoose
203 | *.mm.*
204 | AutoTest.Net/
205 |
206 | # Web workbench (sass)
207 | .sass-cache/
208 |
209 | # Installshield output folder
210 | [Ee]xpress/
211 |
212 | # DocProject is a documentation generator add-in
213 | DocProject/buildhelp/
214 | DocProject/Help/*.HxT
215 | DocProject/Help/*.HxC
216 | DocProject/Help/*.hhc
217 | DocProject/Help/*.hhk
218 | DocProject/Help/*.hhp
219 | DocProject/Help/Html2
220 | DocProject/Help/html
221 |
222 | # Click-Once directory
223 | publish/
224 |
225 | # Publish Web Output
226 | *.[Pp]ublish.xml
227 | *.azurePubxml
228 | # Note: Comment the next line if you want to checkin your web deploy settings,
229 | # but database connection strings (with potential passwords) will be unencrypted
230 | *.pubxml
231 | *.publishproj
232 |
233 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
234 | # checkin your Azure Web App publish settings, but sensitive information contained
235 | # in these scripts will be unencrypted
236 | PublishScripts/
237 |
238 | # NuGet Packages
239 | *.nupkg
240 | # NuGet Symbol Packages
241 | *.snupkg
242 | # The packages folder can be ignored because of Package Restore
243 | **/[Pp]ackages/*
244 | # except build/, which is used as an MSBuild target.
245 | !**/[Pp]ackages/build/
246 | # Uncomment if necessary however generally it will be regenerated when needed
247 | #!**/[Pp]ackages/repositories.config
248 | # NuGet v3's project.json files produces more ignorable files
249 | *.nuget.props
250 | *.nuget.targets
251 |
252 | # Microsoft Azure Build Output
253 | csx/
254 | *.build.csdef
255 |
256 | # Microsoft Azure Emulator
257 | ecf/
258 | rcf/
259 |
260 | # Windows Store app package directories and files
261 | AppPackages/
262 | BundleArtifacts/
263 | Package.StoreAssociation.xml
264 | _pkginfo.txt
265 | *.appx
266 | *.appxbundle
267 | *.appxupload
268 |
269 | # Visual Studio cache files
270 | # files ending in .cache can be ignored
271 | *.[Cc]ache
272 | # but keep track of directories ending in .cache
273 | !?*.[Cc]ache/
274 |
275 | # Others
276 | ClientBin/
277 | ~$*
278 | *~
279 | *.dbmdl
280 | *.dbproj.schemaview
281 | *.jfm
282 | *.pfx
283 | *.publishsettings
284 | orleans.codegen.cs
285 |
286 | # Including strong name files can present a security risk
287 | # (https://github.com/github/gitignore/pull/2483#issue-259490424)
288 | #*.snk
289 |
290 | # Since there are multiple workflows, uncomment next line to ignore bower_components
291 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
292 | #bower_components/
293 |
294 | # RIA/Silverlight projects
295 | Generated_Code/
296 |
297 | # Backup & report files from converting an old project file
298 | # to a newer Visual Studio version. Backup files are not needed,
299 | # because we have git ;-)
300 | _UpgradeReport_Files/
301 | Backup*/
302 | UpgradeLog*.XML
303 | UpgradeLog*.htm
304 | ServiceFabricBackup/
305 | *.rptproj.bak
306 |
307 | # SQL Server files
308 | *.mdf
309 | *.ldf
310 | *.ndf
311 |
312 | # Business Intelligence projects
313 | *.rdl.data
314 | *.bim.layout
315 | *.bim_*.settings
316 | *.rptproj.rsuser
317 | *- [Bb]ackup.rdl
318 | *- [Bb]ackup ([0-9]).rdl
319 | *- [Bb]ackup ([0-9][0-9]).rdl
320 |
321 | # Microsoft Fakes
322 | FakesAssemblies/
323 |
324 | # GhostDoc plugin setting file
325 | *.GhostDoc.xml
326 |
327 | # Node.js Tools for Visual Studio
328 | .ntvs_analysis.dat
329 | node_modules/
330 |
331 | # Visual Studio 6 build log
332 | *.plg
333 |
334 | # Visual Studio 6 workspace options file
335 | *.opt
336 |
337 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
338 | *.vbw
339 |
340 | # Visual Studio LightSwitch build output
341 | **/*.HTMLClient/GeneratedArtifacts
342 | **/*.DesktopClient/GeneratedArtifacts
343 | **/*.DesktopClient/ModelManifest.xml
344 | **/*.Server/GeneratedArtifacts
345 | **/*.Server/ModelManifest.xml
346 | _Pvt_Extensions
347 |
348 | # Paket dependency manager
349 | .paket/paket.exe
350 | paket-files/
351 |
352 | # FAKE - F# Make
353 | .fake/
354 |
355 | # CodeRush personal settings
356 | .cr/personal
357 |
358 | # Python Tools for Visual Studio (PTVS)
359 | __pycache__/
360 | *.pyc
361 |
362 | # Cake - Uncomment if you are using it
363 | # tools/**
364 | # !tools/packages.config
365 |
366 | # Tabs Studio
367 | *.tss
368 |
369 | # Telerik's JustMock configuration file
370 | *.jmconfig
371 |
372 | # BizTalk build output
373 | *.btp.cs
374 | *.btm.cs
375 | *.odx.cs
376 | *.xsd.cs
377 |
378 | # OpenCover UI analysis results
379 | OpenCover/
380 |
381 | # Azure Stream Analytics local run output
382 | ASALocalRun/
383 |
384 | # MSBuild Binary and Structured Log
385 | *.binlog
386 |
387 | # NVidia Nsight GPU debugger configuration file
388 | *.nvuser
389 |
390 | # MFractors (Xamarin productivity tool) working folder
391 | .mfractor/
392 |
393 | # Local History for Visual Studio
394 | .localhistory/
395 |
396 | # BeatPulse healthcheck temp database
397 | healthchecksdb
398 |
399 | # Backup folder for Package Reference Convert tool in Visual Studio 2017
400 | MigrationBackup/
401 |
402 | # Ionide (cross platform F# VS Code tools) working folder
403 | .ionide/
404 |
405 | # Fody - auto-generated XML schema
406 | FodyWeavers.xsd
407 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "src/3rdparty/syntax-highlighting"]
2 | path = src/3rdparty/syntax-highlighting
3 | url = git@github.com:KDE/syntax-highlighting.git
4 | [submodule "src/3rdparty/extra-cmake-modules"]
5 | path = src/3rdparty/extra-cmake-modules
6 | url = git@github.com:KDE/extra-cmake-modules.git
7 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | All notable changes to this project will be documented in this file.
4 |
5 | ## [UNRELEASED]
6 |
7 | ### 🌵 Features
8 |
9 | - Use `Segoe UI` font on Microsoft Windows
10 | - Opening files with Drag and Drop.
11 | - Auto complete brackets
12 |
13 | ### 🦋 Optimization
14 |
15 | - Disable PreviewPanel when not in use
16 |
17 | ### 🐞 Bug fix
18 |
19 | - PreviewPanel didn't work
20 |
21 | ## 0.1.4
22 |
23 | ### 🌵 Features
24 |
25 | - Right click menu
26 | - Syntax selection menu
27 | - Clear
28 | - Read-Only mode
29 | - Folding
30 | - Ctrl + Wheel to zoom the text
31 | - Fluent System Icons
32 | - Tab / Spaces indent
33 | - Multi-tab
34 |
35 | ## 0.1.3
36 |
37 | > If you want to track the latest news of Notepanda, welcome to our [📰 Telegram channel](https://t.me/notepanda)!
38 |
39 | ### 🌵 Features
40 |
41 | - Preview panel
42 | - JSON format settings
43 | - Pin to top
44 | - Set window modified
45 | - New logo
46 | - More available syntax highlight themes: `Breeze Dark`, `Default`, `Printing`, `Solarized Dark` and `Solarized Light`
47 | - Add normal mode icon
48 | - Sticky mode
49 | - Hide sidebar
50 | - Hide line number area
51 | - Hide statusbar
52 | - Use general font (not monospace)
53 | - Smaller window
54 | - Custom background color
55 |
56 | ### 🐞 Bug fix
57 |
58 | - Fix font settings cannot take effect
59 | - Fix file content lost on save (#30)
60 | - NSIS installer cannot found dll
61 |
62 | ### ! BREAKING CHANGE !
63 |
64 | - The `Style` setting has been renamed to `StyleTheme`
65 | - The `ColorTheme` setting has been renamed to `EditorColorTheme`
66 |
67 | A deb package has also been added.
68 |
69 | ## 0.1.3-alpha2
70 |
71 | The main purpose of this release is to fix some bugs in the previous alpha version.
72 |
73 | > Are you confused when you see this version number? That's right, we've turned 0.0.3 into the more standardized 0.1.3.
74 |
75 | ### 🌵 Features
76 |
77 | - Pin to top
78 |
79 | ## 🐞 Bug fix
80 |
81 | - NSIS installer cannot found dll
82 |
83 | A deb package has also been added.
84 |
85 | > If you want to track the latest news of Notepanda, welcome to our [📰 Telegram channel](https://t.me/notepanda)!
86 |
87 | ## 0.0.3-alpha1
88 |
89 | ### 🌵 Features
90 |
91 | - Set window modified
92 | - New logo
93 | - More available syntax highlight themes: `Breeze Dark`, `Default`, `Printing`, `Solarized Dark` and `Solarized Light`
94 | - Add normal mode icon
95 | - Sticky mode
96 | - Hide sidebar
97 | - Hide line number area
98 | - Hide statusbar
99 | - Use general font (not monospace)
100 | - Smaller window
101 | - Custom background color
102 |
103 | ### 🐞 Bug fix
104 |
105 | - Fix font settings cannot take effect
106 |
107 | ## 0.0.2
108 |
109 | ### 🌵 Features
110 |
111 | - Custom font in Preferences Window
112 | - Change the default font to `monospace` (Different on different systems)
113 | - Syntax Highlighting
114 | - Custom theme
115 | - Launch from the shell
116 | - Persistent application settings
117 |
118 | ### 🦋 Optimization
119 |
120 | - Refactor code structure.
121 |
122 | ## 0.0.1
123 |
124 | The following is this version of changelog (including the beta/rc version):
125 |
126 | ### 🌵 Features
127 |
128 | - Basic operation
129 | - New
130 | - Open
131 | - Save
132 | - Save as
133 | - Print
134 | - Undo
135 | - Redo
136 | - Copy
137 | - Paste
138 | - Cut
139 | - Quit
140 | - Icons (from [Remix Icon - Open source icon library](https://remixicon.com/))
141 | - Toolbar
142 | - Line numbers
143 | - Highlight current line
144 | - Beautify the interface
145 | - Show characters & line numbers on status bar
146 | - Preferences Window
147 |
148 | ### 🦋 Optimization
149 |
150 | - Refactor
151 | - Use Lambda to set action undo&redo©&cut's state.
152 | - Move all sources to `src/` dir
153 | - Move core sources to `src/core` dir, ui sources to `src/ui` dir
154 | - Rename the `notepanda` class to `MainWindow`
155 |
156 | ### 🐞 Bug fix
157 |
158 | - Fix cannot load SVG files.
159 |
160 | ## 0.0.1-rc.1
161 |
162 | ### 🌵 Features
163 |
164 | - More basic operation
165 | - Undo
166 | - Redo
167 | - Copy
168 | - Paste
169 | - Cut
170 | - Quit
171 | - Icons (from [Remix Icon - Open source icon library](https://remixicon.com/))
172 | - Toolbar
173 | - Line numbers
174 | - Highlight current line
175 |
176 | ### 🦋 Optimization
177 |
178 | - Refactor
179 | - Move all sources to `src/` dir
180 | - Move core sources to `src/core` dir, ui sources to `src/ui` dir
181 | - Rename the `notepanda` class to `MainWindow`
182 |
183 | ## 0.0.1-alpha
184 |
185 | > First release. :beers:
186 |
187 | [GitHub Release](https://github.com/ChungZH/notepanda/releases/tag/v0.0.1-alpha)
188 |
189 | ### 🌵 Features
190 |
191 | - Basic operation
192 | - New
193 | - Open
194 | - Save
195 | - Save as
196 |
--------------------------------------------------------------------------------
/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # CMakeLists.txt
2 |
3 | cmake_minimum_required(VERSION 3.1.0)
4 |
5 | file(STRINGS "${CMAKE_SOURCE_DIR}/makespec/VERSION" VERSION)
6 | file(STRINGS "${CMAKE_SOURCE_DIR}/makespec/BUILDVERSION" BUILD_VERSION)
7 | file(STRINGS "${CMAKE_SOURCE_DIR}/makespec/VERSIONSUFFIX" VERSION_SUFFIX)
8 |
9 | set(CMAKE_CXX_STANDARD 11)
10 | set(CMAKE_CXX_STANDARD_REQUIRED ON)
11 |
12 | project(notepanda)
13 |
14 | set(VERSION_STRING "${VERSION}${VERSION_SUFFIX}")
15 | set(VERSION_LIST ${VERSION})
16 | string(REPLACE "." ";" VERSION_LIST ${VERSION_LIST})
17 | separate_arguments(VERSION_LIST)
18 |
19 | list(GET VERSION_LIST 0 CMAKE_PROJECT_VERSION_MAJOR)
20 | list(GET VERSION_LIST 1 CMAKE_PROJECT_VERSION_MINOR)
21 | list(GET VERSION_LIST 2 CPACK_PACKAGE_VERSION_PATCH)
22 |
23 | add_definitions(-DVERSION_STRING="${VERSION_STRING}")
24 | add_definitions(-DXTOSTRUCT_QT)
25 |
26 | set(CMAKE_AUTOMOC ON)
27 | set(CMAKE_AUTORCC ON)
28 | set(CMAKE_AUTOUIC ON)
29 |
30 | if(CMAKE_VERSION VERSION_LESS "3.7.0")
31 | set(CMAKE_INCLUDE_CURRENT_DIR ON)
32 | endif()
33 |
34 | # =======================
35 | # Notepanda Build Message
36 | # =======================
37 |
38 | message(" ")
39 | message("Notepanda Version: ${VERSION_STRING}")
40 | message("Notepanda Build Version: ${BUILD_VERSION}")
41 | message("Notepanda Build Type: ${CMAKE_BUILD_TYPE}")
42 | message("|-------------------------------------------------|")
43 | message("| Notepanda, A Cross Platform Notepad. |")
44 | message("| Based on C++ & Qt. |")
45 | message("| Licenced under MIT |")
46 | message("| |")
47 | message("| You may only use this program to the extent |")
48 | message("| permitted by local law. |")
49 | message("| |")
50 | message("| See: https://opensource.org/licenses/MIT |")
51 | message("|-------------------------------------------------|")
52 | message("| GitHub: https://github.com/ChungZH/notepanda |")
53 | message("| Welcome to contribute! |")
54 | message("|-------------------------------------------------|")
55 | message(" ")
56 |
57 | find_package(Qt5 COMPONENTS Core Gui Widgets REQUIRED)
58 | find_package(KF5SyntaxHighlighting REQUIRED)
59 |
60 | if(WIN32)
61 | set(GUI_TYPE WIN32)
62 | elseif(APPLE)
63 | set(GUI_TYPE MACOSX_BUNDLE)
64 | endif()
65 |
66 | # =============================
67 | # Notepanda Sources and Headers
68 | # =============================
69 |
70 | set(SOURCES
71 | src/main.cpp
72 | src/ui/aboutwindow.cpp
73 | src/ui/aboutwindow.h
74 | src/ui/aboutwindow.ui
75 | src/ui/mainwindow.cpp
76 | src/ui/mainwindow.h
77 | src/ui/linenumberarea.h
78 | src/ui/preferenceswindow.cpp
79 | src/ui/preferenceswindow.h
80 | src/ui/preferenceswindow.ui
81 | src/core/configmanager.cpp
82 | src/core/configmanager.h
83 | src/core/texteditor.cpp
84 | src/core/texteditor.h
85 | assets/notepanda.rc
86 | ${CMAKE_SOURCE_DIR}/resources.qrc
87 | )
88 |
89 | add_executable(notepanda
90 | ${GUI_TYPE}
91 | ${SOURCES}
92 | )
93 |
94 | if(UNIX AND NOT APPLE AND NOT WIN32)
95 | install(TARGETS notepanda RUNTIME DESTINATION bin)
96 | install(FILES assets/notepanda.desktop DESTINATION share/applications)
97 | install(FILES images/notepanda.png DESTINATION share/icons/hicolor/256x256/apps)
98 | endif()
99 |
100 | # Directories to look for dependencies
101 | set(DIRS "${CMAKE_BINARY_DIR}")
102 |
103 | # Path used for searching by FIND_XXX(), with appropriate suffixes added
104 | if(CMAKE_PREFIX_PATH)
105 | foreach(dir ${CMAKE_PREFIX_PATH})
106 | list(APPEND DIRS "${dir}/bin" "${dir}/lib")
107 | endforeach()
108 | endif()
109 |
110 | # =========
111 | # Packaging
112 | # =========
113 |
114 | set(CPACK_PACKAGE_NAME "Notepanda")
115 | set(CPACK_PACKAGE_VENDOR "ChungZH")
116 | set(CPACK_PACKAGE_VERSION ${VERSION_STRING})
117 | set(CPACK_PACKAGE_DESCRIPTION "A simple cross-platform notepad.")
118 | set(CPACK_PACKAGE_HOMEPAGE_URL "https://github.com/ChungZH/notepanda")
119 | set(CPACK_PACKAGE_ICON "${CMAKE_SOURCE_DIR}/images/panda.ico")
120 | set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/LICENSE.md")
121 |
122 | if(MSVC)
123 | set(CMAKE_INSTALL_SYSTEM_RUNTIME_DESTINATION .)
124 | endif()
125 |
126 | include(InstallRequiredSystemLibraries)
127 |
128 | if(WIN32)
129 | install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION .)
130 | if (BUILD_NSIS)
131 | add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
132 | COMMAND windeployqt ${CMAKE_BINARY_DIR}/${PROJECT_NAME}.exe --compiler-runtime --no-translations --verbose 2 --dir ${CMAKE_BINARY_DIR}/winqt/
133 | )
134 | install(DIRECTORY ${CMAKE_BINARY_DIR}/winqt/ DESTINATION .)
135 | endif()
136 | set(APPS "\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${PROJECT_NAME}.exe")
137 | endif()
138 |
139 | if(WIN32)
140 | if(BUILD_NSIS)
141 | set(CPACK_GENERATOR "NSIS")
142 | set(CPACK_PACKAGE_ICON "${CMAKE_SOURCE_DIR}/images\\\\panda.ico")
143 | set(CPACK_NSIS_MUI_ICON "${CMAKE_SOURCE_DIR}/images/panda.ico")
144 | set(CPACK_NSIS_MUI_UNIICON "${CMAKE_SOURCE_DIR}/images/panda.ico")
145 | set(CPACK_NSIS_DISPLAY_NAME "Notepanda")
146 | set(CPACK_NSIS_PACKAGE_NAME "Notepanda")
147 | set(CPACK_NSIS_EXTRA_INSTALL_COMMANDS "
148 | CreateShortCut \\\"$DESKTOP\\\\Notepanda.lnk\\\" \\\"$INSTDIR\\\\notepanda.exe\\\"
149 | CreateDirectory \\\"$SMPROGRAMS\\\\$STARTMENU_FOLDER\\\\Notepanda\\\"
150 | CreateShortCut \\\"$SMPROGRAMS\\\\$STARTMENU_FOLDER\\\\Notepanda\\\\Notepanda.lnk\\\" \\\"$INSTDIR\\\\notepanda.exe\\\"
151 | WriteRegStr HKLM \\\"Software\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Uninstall\\\\notepanda\\\" \\\"DisplayIcon\\\" \\\"$INSTDIR\\\\notepanda.exe\\\"
152 | WriteRegStr HKLM \\\"Software\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Uninstall\\\\notepanda\\\" \\\"HelpLink\\\" \\\"https://github.com/ChungZH/notepanda\\\"
153 | WriteRegStr HKLM \\\"Software\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Uninstall\\\\notepanda\\\" \\\"InstallLocation\\\" \\\"$INSTDIR\\\"
154 | WriteRegStr HKLM \\\"Software\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Uninstall\\\\notepanda\\\" \\\"URLUpdateInfo\\\" \\\"https://github.com/ChungZH/notepanda/releases\\\"
155 | WriteRegStr HKLM \\\"Software\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Uninstall\\\\notepanda\\\" \\\"URLInfoAbout\\\" \\\"https://github.com/ChungZH/notepanda\\\"
156 | ")
157 | set(CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS "
158 | Delete \\\"$DESKTOP\\\\Notepanda.lnk\\\"
159 | Delete \\\"$SMPROGRAMS\\\\$STARTMENU_FOLDER\\\\Notepanda\\\\Notepanda.lnk\\\"
160 | RMDir \\\"$SMPROGRAMS\\\\$STARTMENU_FOLDER\\\\Notepanda\\\"
161 | DeleteRegKey HKLM \\\"Software\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Uninstall\\\\notepanda\\\"
162 | ")
163 | set(CPACK_PACKAGE_INSTALL_DIRECTORY "notepanda")
164 | endif()
165 | endif()
166 |
167 | if(UNIX)
168 | if(BUILD_DEB)
169 | set(CPACK_GENERATOR "DEB")
170 | set(CPACK_DEBIAN_PACKAGE_NAME "Notepanda")
171 | set(CPACK_PACKAGE_CONTACT "chungzh07@gmail.com")
172 | set(CPACK_DEBIAN_PACKAGE_MAINTAINER "ChungZH")
173 | set(CPACK_DEBIAN_PACKAGE_DEPENDS "qtbase5-dev, qttools5-dev, libkf5syntaxhighlighting-dev")
174 | endif()
175 |
176 | #if(BUILD_RPM)
177 | # set(CPACK_GENERATOR "RPM")
178 | # set(CPACK_RPM_PACKAGE_LICENSE "MIT")
179 | #endif()
180 | endif()
181 |
182 | if(WIN32)
183 | list(APPEND DIRS "${KF5SyntaxHighlighting_DIR}/../../../bin/")
184 | install(CODE "include(BundleUtilities)
185 | fixup_bundle(\"${APPS}\" \"\" \"${DIRS}\")")
186 | endif()
187 |
188 | include(CPack)
189 |
190 | target_link_libraries(notepanda Qt5::Core Qt5::Gui Qt5::Widgets KF5::SyntaxHighlighting)
191 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Haoshen Zhong
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 
2 |
3 | ###### Notepanda's icon is owned by ChungZH, any unanthorized usage will be blamed.
4 |
5 | # Notepanda
6 |
7 | [](https://app.codacy.com/manual/ChungZH/notepanda?utm_source=github.com&utm_medium=referral&utm_content=ChungZH/notepanda&utm_campaign=Badge_Grade_Dashboard)
8 |  [](https://app.fossa.io/projects/git%2Bgithub.com%2FChungZH%2Fnotepanda?ref=badge_shield)
9 |
10 | 
11 | 
12 | 
13 |
14 |
15 | > **A simple cross-platform notepad. Based on Qt and C++.**
16 |
17 | If you want to track the latest news of Notepanda, welcome to our [📰 Telegram channel](https://t.me/notepanda)!
18 |
19 | BTW you can read this post in my blog: [Notepanda 开发小结](https://blog.chungzh.cn/articles/notepanda/)
20 |
21 | ## Why write this text editor?
22 |
23 | I recently started getting started with Qt, this is my first Qt project, the first C++ project, and the first project in my life. I hope to develop my skills through this project.
24 |
25 | I'm not going to use this as a replacement for my other text editors because it's too simple and I am too poor :)
26 |
27 | So enjoy this toy 🍵️
28 |
29 | ## Screenshots
30 |
31 | | Light | Dark |
32 | | :----------------------------------: | :---------------------------------: |
33 | |  |  |
34 | |  |  |
35 |
36 | ## Feature
37 |
38 | - Basic operation
39 | - Line numbers
40 | - Syntax highlight
41 | - Launch from the shell by typing: `notepanda` or `notepanda CMakeLists.txt`
42 | - Preview panel (Support Markdown & HTML)
43 | - Opening files with Drag and Drop.
44 |
45 | ## Install
46 |
47 | If you are Windows / MacOS / Linux user, you can go to [Releases](https://github.com/ChungZH/notepanda/releases) page.
48 |
49 | If you are using [Scoop](https://scoop.sh), you can get Notepanda from my sweet scoop bucket [🍑 peach](https://github.com/ChungZH/peach):
50 |
51 | ```powershell
52 | scoop bucket add peach https://github.com/ChungZH/peach
53 | scoop install notepanda
54 | ```
55 |
56 | If you are Arch Linux (or Arch-based distros) user, you can get Notepanda from AUR. 
57 |
58 | You may use an AUR helper such as `yay` to automatically handle the build process of AUR packages:
59 |
60 | ```sh
61 | yay -S notepanda
62 | ```
63 |
64 | The latest version is `v0.1.4` now.
65 |
66 | ## Build
67 |
68 | For more information, go to [How to build - GitHub Wiki](https://github.com/ChungZH/notepanda/wiki/How-to-build---%E5%A6%82%E4%BD%95%E6%9E%84%E5%BB%BA).
69 |
70 | ### Required Tools
71 |
72 | - [CMake](https://cmake.org/) >= 3.1.0
73 | - [Ninja](https://ninja-build.org/)
74 |
75 | ### Required Dependencies
76 |
77 | - [Qt](https://www.qt.io/) >= 5.11 (recommendation 5.14)
78 | - [KSyntaxHighlighting](https://api.kde.org/frameworks/syntax-highlighting/html/index.html)
79 | - [Extra CMake Modules](https://api.kde.org/ecm/)
80 |
81 | ## Roadmap
82 |
83 | See [Projects](https://github.com/ChungZH/notepanda/projects/).
84 |
85 |
86 | ## Contributions / Bugs
87 |
88 | 
89 |
90 | You want to contribute to Notepanda? Awesome! ~~Please read the contribution guidelines for details and useful hints.~~ There is **no rules** now!
91 |
92 | If you found a bug or have a feature request, you can report it [GitHub Issue](https://github.com/ChungZH/notepanda/issues).
93 |
94 | 🙇♂️️ Thank you very much!
95 |
96 | ## Special Thanks
97 |
98 | - [Qv2ray](https://github.com/qv2ray/qv2ray)
99 |
100 | ## Copyright
101 |
102 | Copyright (c) ChungZH.
103 |
104 | **Libraries that have been used in Notepanda are listed below (Sorted by date added):**
105 |
106 | - Please see: [assets/CREDIT.md](assets/CREDIT.md)
107 |
108 | ## LICENSE
109 |
110 | ⚖ Released under the [MIT license](/LICENSE.Md).
111 |
112 | [](https://app.fossa.com/projects/git%2Bgithub.com%2FChungZH%2Fnotepanda?ref=badge_large)
113 |
114 | ------
115 |
116 | 🗒️ Notepanda © ChungZH.
117 |
118 | > [Blog](https://blog.chungzh.cn/) · [Portfolio](https://chungzh.cn/) · [GitHub](https://github.com/ChungZH)
119 |
--------------------------------------------------------------------------------
/assets/CREDIT.md:
--------------------------------------------------------------------------------
1 | # Credit
2 |
3 | Copyright (c) 2020 ChungZH.
4 |
5 | **Libraries that have been used in Notepanda are listed below (Sorted by date added):**
6 |
7 | - Copyright (c) 2018 KDE : syntax-highlighting (MIT)
8 | - Copyright (c) 2020 Microsoft : Fluent System Icons (MIT)
9 |
--------------------------------------------------------------------------------
/assets/notepanda.desktop:
--------------------------------------------------------------------------------
1 | [Desktop Entry]
2 | Name=Notepanda
3 | Type=Application
4 | Comment=A simple cross-platform notepad. Based on Qt and C++.
5 | Keywords=Notepad;Editor;Text;
6 | Terminal=false
7 | Icon=notepanda
8 | Exec=notepanda
9 | Categories=Qt;
--------------------------------------------------------------------------------
/assets/notepanda.rc:
--------------------------------------------------------------------------------
1 | IDI_ICON1 ICON "../images/panda.ico"
--------------------------------------------------------------------------------
/images/banner.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChungZH/notepanda/c3322084a1392af2c5055c5bd5b25fe5a19bd34b/images/banner.png
--------------------------------------------------------------------------------
/images/fluentui-icon/LICENSE:
--------------------------------------------------------------------------------
1 | Fluent Mobile Icons
2 | Copyright (c) Microsoft Corporation.
3 |
4 | MIT License
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | SOFTWARE.
23 |
--------------------------------------------------------------------------------
/images/fluentui-icon/add.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/images/fluentui-icon/clipboard.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/images/fluentui-icon/color_background.svg:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/images/fluentui-icon/copy.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/images/fluentui-icon/cut.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/images/fluentui-icon/delete.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/images/fluentui-icon/document.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/images/fluentui-icon/document_edit.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/images/fluentui-icon/info.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/images/fluentui-icon/open.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/images/fluentui-icon/pin.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/images/fluentui-icon/preview.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/images/fluentui-icon/print.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/images/fluentui-icon/read_only.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/images/fluentui-icon/redo.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/images/fluentui-icon/save.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/images/fluentui-icon/save_as.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/images/fluentui-icon/settings.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/images/fluentui-icon/sticker.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/images/fluentui-icon/undo.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/images/notepanda-sc1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChungZH/notepanda/c3322084a1392af2c5055c5bd5b25fe5a19bd34b/images/notepanda-sc1.png
--------------------------------------------------------------------------------
/images/notepanda-sc2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChungZH/notepanda/c3322084a1392af2c5055c5bd5b25fe5a19bd34b/images/notepanda-sc2.png
--------------------------------------------------------------------------------
/images/notepanda-sc3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChungZH/notepanda/c3322084a1392af2c5055c5bd5b25fe5a19bd34b/images/notepanda-sc3.png
--------------------------------------------------------------------------------
/images/notepanda-sc4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChungZH/notepanda/c3322084a1392af2c5055c5bd5b25fe5a19bd34b/images/notepanda-sc4.png
--------------------------------------------------------------------------------
/images/notepanda.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChungZH/notepanda/c3322084a1392af2c5055c5bd5b25fe5a19bd34b/images/notepanda.png
--------------------------------------------------------------------------------
/images/panda.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChungZH/notepanda/c3322084a1392af2c5055c5bd5b25fe5a19bd34b/images/panda.ico
--------------------------------------------------------------------------------
/makespec/BUILDVERSION:
--------------------------------------------------------------------------------
1 | 3300
2 |
--------------------------------------------------------------------------------
/makespec/VERSION:
--------------------------------------------------------------------------------
1 | 0.1.4
2 |
--------------------------------------------------------------------------------
/makespec/VERSIONSUFFIX:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources.qrc:
--------------------------------------------------------------------------------
1 |
2 |
3 | assets/CREDIT.md
4 | makespec/VERSION
5 | makespec/VERSIONSUFFIX
6 | makespec/BUILDVERSION
7 | images/panda.ico
8 | images/notepanda.png
9 |
10 |
11 | images/fluentui-icon/open.svg
12 | images/fluentui-icon/add.svg
13 | images/fluentui-icon/clipboard.svg
14 | images/fluentui-icon/info.svg
15 | images/fluentui-icon/redo.svg
16 | images/fluentui-icon/print.svg
17 | images/fluentui-icon/preview.svg
18 | images/fluentui-icon/pin.svg
19 | images/fluentui-icon/save_as.svg
20 | images/fluentui-icon/save.svg
21 | images/fluentui-icon/settings.svg
22 | images/fluentui-icon/sticker.svg
23 | images/fluentui-icon/undo.svg
24 | images/fluentui-icon/document.svg
25 | images/fluentui-icon/cut.svg
26 | images/fluentui-icon/copy.svg
27 | images/fluentui-icon/document_edit.svg
28 | images/fluentui-icon/delete.svg
29 | images/fluentui-icon/read_only.svg
30 | images/fluentui-icon/color_background.svg
31 |
32 |
33 |
--------------------------------------------------------------------------------
/src/core/configmanager.cpp:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2020 ChungZH. ALl Rights Reserved.
3 | * Licensed under the MIT license.
4 | * See file LICENSE for detail or copy at
5 | *
6 | * This file is a part of Notepanda.
7 | *
8 | * @file configmanager.cpp
9 | * @brief This file implements the ConfigManager class.
10 | *
11 | */
12 | #include "configmanager.h"
13 |
14 | #include
15 | #include
16 | #include
17 |
18 | ConfigManager::ConfigManager(const QString &configuration, QObject *parent)
19 | : QObject(parent), configFile(configuration)
20 | {
21 | const QSettings::Format JsonFormat =
22 | QSettings::registerFormat("json", readJsonFile, writeJsonFile);
23 | settings = new QSettings(configFile, JsonFormat, this);
24 |
25 | readGeneralSettings();
26 |
27 | // print all settings
28 | qDebug() << ""
29 | << "All settings:";
30 | for (auto i : settings->allKeys()) {
31 | qDebug() << i << ":" << settings->value(i);
32 | }
33 | qDebug() << "";
34 | }
35 |
36 | bool ConfigManager::readJsonFile(QIODevice &device, QSettings::SettingsMap &map)
37 | {
38 | QJsonParseError error;
39 | map = QJsonDocument::fromJson(device.readAll(), &error).toVariant().toMap();
40 | return error.error == QJsonParseError::NoError;
41 | }
42 |
43 | bool ConfigManager::writeJsonFile(QIODevice &device,
44 | const QSettings::SettingsMap &map)
45 | {
46 | const auto json = QJsonDocument::fromVariant(map).toJson();
47 | return device.write(json) == json.size();
48 | }
49 |
50 | /**
51 | * @brief Save the settings.
52 | */
53 | void ConfigManager::save()
54 | {
55 | settings->beginGroup("Editor");
56 | settings->setValue("FontFamily", QVariant(editorFontFamily));
57 | settings->setValue("FontSize", QVariant(editorFontSize));
58 | settings->setValue("ColorTheme", QVariant(editorColorTheme));
59 | settings->setValue("TabSize", QVariant(editorTabSize));
60 | settings->setValue("IndentMode", QVariant(editorIndentMode));
61 | settings->endGroup();
62 | settings->setValue("StyleTheme", QVariant(styleTheme));
63 | }
64 |
65 | /**
66 | * @brief Read general settings from `settings`.
67 | */
68 | void ConfigManager::readGeneralSettings()
69 | {
70 | if (settings->contains("Editor/FontFamily")) {
71 | editorFontFamily = settings->value("Editor/FontFamily").toString();
72 | } else {
73 | editorFontFamily =
74 | QFontDatabase::systemFont(QFontDatabase::FixedFont).toString();
75 | }
76 | styleTheme = settings->value("StyleTheme", "Fusion").toString();
77 | editorFontSize = settings->value("Editor/FontSize", 16).toInt();
78 | editorColorTheme =
79 | settings->value("Editor/ColorTheme", "Default").toString();
80 | editorTabSize = settings->value("Editor/TabSize", 4).toInt();
81 | editorIndentMode =
82 | settings->value("Editor/IndentMode", "Spaces").toString();
83 | }
84 |
85 | QString ConfigManager::getEditorFontFamily() const { return editorFontFamily; }
86 | void ConfigManager::setEditorFontFamily(const QString &fontname)
87 | {
88 | editorFontFamily = fontname;
89 | }
90 |
91 | QString ConfigManager::getStyleTheme() const { return styleTheme; }
92 | void ConfigManager::setStyleTheme(const QString &stylename)
93 | {
94 | styleTheme = stylename;
95 | }
96 |
97 | int ConfigManager::getEditorFontSize() const { return editorFontSize; }
98 | void ConfigManager::setEditorFontSize(const int &fontsize)
99 | {
100 | editorFontSize = fontsize;
101 | }
102 |
103 | QString ConfigManager::getEditorColorTheme() const { return editorColorTheme; }
104 | void ConfigManager::setEditorColorTheme(const QString &ctname)
105 | {
106 | editorColorTheme = ctname;
107 | }
108 |
109 | int ConfigManager::getEditorTabSize() const { return editorTabSize; }
110 | void ConfigManager::setEditorTabSize(const int &tabsize)
111 | {
112 | editorTabSize = tabsize;
113 | }
114 |
115 | QString ConfigManager::getEditorIndentMode() const { return editorIndentMode; }
116 | void ConfigManager::setEditorIndentMode(const QString &indentmode)
117 | {
118 | editorIndentMode = indentmode;
119 | }
--------------------------------------------------------------------------------
/src/core/configmanager.h:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2020 ChungZH. ALl Rights Reserved.
3 | * Licensed under the MIT license.
4 | * See file LICENSE for detail or copy at
5 | *
6 | * This file is a part of Notepanda.
7 | *
8 | * @file configmanager.h
9 | * @brief This file declares the ConfigManager class for management
10 | * configuration.
11 | */
12 | #ifndef CONFIGMANAGER_H
13 | #define CONFIGMANAGER_H
14 |
15 | #include
16 | #include
17 | #include
18 | #include
19 |
20 | /**
21 | * @brief The ConfigManager class
22 | */
23 | class ConfigManager : public QObject
24 | {
25 | Q_OBJECT
26 | public:
27 | explicit ConfigManager(const QString &configuration,
28 | QObject *parent = nullptr);
29 | void save();
30 | void readGeneralSettings();
31 |
32 | static bool readJsonFile(QIODevice &device, QSettings::SettingsMap &map);
33 | static bool writeJsonFile(QIODevice &device,
34 | const QSettings::SettingsMap &map);
35 |
36 | //
37 | QString getEditorFontFamily() const;
38 | void setEditorFontFamily(const QString &fontname);
39 | QString getStyleTheme() const;
40 | void setStyleTheme(const QString &stylename);
41 | int getEditorFontSize() const;
42 | void setEditorFontSize(const int &fontsize);
43 | QString getEditorColorTheme() const;
44 | void setEditorColorTheme(const QString &ctname);
45 | int getEditorTabSize() const;
46 | void setEditorTabSize(const int &tabsize);
47 | QString getEditorIndentMode() const;
48 | void setEditorIndentMode(const QString &indentmode);
49 |
50 | private:
51 | QSettings *settings;
52 | QString configFile;
53 | QString editorFontFamily;
54 | QString styleTheme;
55 | int editorFontSize;
56 | QString editorColorTheme;
57 | int editorTabSize;
58 | QString editorIndentMode;
59 | };
60 |
61 | #endif // CONFIGMANAGER_H
62 |
--------------------------------------------------------------------------------
/src/core/texteditor.cpp:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2020 ChungZH. ALl Rights Reserved.
3 | * Licensed under the MIT license.
4 | * See file LICENSE for detail or copy at
5 | *
6 | * This file is a part of Notepanda.
7 | *
8 | * @file texteditor.cpp
9 | * @brief This file implements the TextEditor class.
10 | *
11 | */
12 | #include "texteditor.h"
13 |
14 | #include
15 | #include
16 | #include
17 | #include
18 | #include
19 | #include
20 | #include
21 | #include
22 | #include
23 | #include
24 | #include
25 | #include
26 | #include
27 | #include
28 | #include
29 | #include
30 | #include
31 | #include
32 |
33 | // KSyntaxHighlighting
34 | #include
35 | #include
36 | #include
37 | #include
38 |
39 | #include "../ui/linenumberarea.h"
40 |
41 | TextEditor::TextEditor(ConfigManager *cfManager, QWidget *parent)
42 | : QPlainTextEdit(parent),
43 | configManager(cfManager),
44 | m_highlighter(new KSyntaxHighlighting::SyntaxHighlighter(document()))
45 |
46 | {
47 | const auto theme = m_repository.theme(configManager->getEditorColorTheme());
48 | setTheme(theme);
49 |
50 | setTabStopDistance(QFontMetricsF(QFont(configManager->getEditorFontFamily(),
51 | configManager->getEditorFontSize()))
52 | .horizontalAdvance(' ') *
53 | configManager->getEditorTabSize());
54 |
55 | // Line number area
56 | lineNumberArea = new LineNumberArea(this);
57 |
58 | connect(this, &TextEditor::blockCountChanged, this,
59 | &TextEditor::updateLineNumberAreaWidth);
60 | connect(this, &TextEditor::updateRequest, this,
61 | &TextEditor::updateLineNumberArea);
62 | connect(this, &TextEditor::cursorPositionChanged, this,
63 | &TextEditor::highlightCurrentLine);
64 |
65 | updateLineNumberAreaWidth(0);
66 | highlightCurrentLine();
67 |
68 | currentMode = 0;
69 |
70 | TextEditor::setFont(QFont(configManager->getEditorFontFamily(),
71 | configManager->getEditorFontSize()));
72 | setCurrentFile(QString());
73 | lineNumberArea->resize(0, 0);
74 | }
75 |
76 | bool TextEditor::maybeSave()
77 | {
78 | if (!QPlainTextEdit::document()->isModified()) return true;
79 | const QMessageBox::StandardButton ret = QMessageBox::warning(
80 | this, tr("Application"),
81 | tr("The document has been modified.\n"
82 | "Do you want to save your changes?"),
83 | QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel);
84 | switch (ret) {
85 | case QMessageBox::Save:
86 | save();
87 | return true;
88 | case QMessageBox::Cancel:
89 | return false;
90 | default:
91 | break;
92 | }
93 | return true;
94 | }
95 |
96 | bool TextEditor::newDocument()
97 | {
98 | clear();
99 | setCurrentFile(QString());
100 | emit changeTitle();
101 | return true;
102 | }
103 |
104 | bool TextEditor::open()
105 | {
106 | if (maybeSave()) {
107 | QString fileName =
108 | QFileDialog::getOpenFileName(this, tr("Open the file"));
109 | QFile file(fileName);
110 | if (!file.open(QFile::ReadOnly | QFile::Text)) {
111 | QMessageBox::warning(this, tr("Warning"),
112 | tr("Cannot open file: ") + file.errorString());
113 | qWarning() << "[WARN 1] Failed to open" << fileName << ":"
114 | << file.errorString();
115 | return false;
116 | }
117 |
118 | clear();
119 |
120 | auto def = m_repository.definitionForFileName(fileName);
121 | if (currentMode == 1) def = m_repository.definitionForName("Markdown");
122 | m_highlighter->setDefinition(def);
123 |
124 | QTextStream in(&file);
125 |
126 | #ifndef QT_NO_CURSOR
127 | QGuiApplication::setOverrideCursor(Qt::WaitCursor);
128 | #endif
129 |
130 | setPlainText(in.readAll());
131 |
132 | #ifndef QT_NO_CURSOR
133 | QGuiApplication::restoreOverrideCursor();
134 | #endif
135 | file.close();
136 |
137 | setCurrentFile(fileName);
138 | emit changeTitle();
139 | return true;
140 | }
141 | return false;
142 | }
143 |
144 | /**
145 | * @brief Open from command line like `notepanda texteditor.cpp`.
146 | * It doesn't need `maybeSave()` because at this time notepanda opens for
147 | * the first time.
148 | */
149 | void TextEditor::openFile(const QString &fileName)
150 | {
151 | QFile file(fileName);
152 | if (!file.open(QIODevice::ReadOnly | QFile::Text)) {
153 | QMessageBox::warning(this, tr("Warning"),
154 | tr("Cannot open file: ") + file.errorString());
155 | qWarning() << "[WARN 2] Failed to open" << fileName << ":"
156 | << file.errorString();
157 | return;
158 | }
159 |
160 | const auto def = m_repository.definitionForFileName(fileName);
161 | m_highlighter->setDefinition(def);
162 |
163 | QTextStream in(&file);
164 |
165 | #ifndef QT_NO_CURSOR
166 | QGuiApplication::setOverrideCursor(Qt::WaitCursor);
167 | #endif
168 | setPlainText(in.readAll());
169 | #ifndef QT_NO_CURSOR
170 | QGuiApplication::restoreOverrideCursor();
171 | #endif
172 | setCurrentFile(fileName);
173 | emit changeTitle();
174 | }
175 |
176 | void TextEditor::save()
177 | {
178 | QGuiApplication::setOverrideCursor(Qt::WaitCursor);
179 | QString fileName, errorMessage;
180 | if (currentFile.isEmpty())
181 | fileName = QFileDialog::getSaveFileName(this, tr("Save"));
182 | else
183 | fileName = currentFile;
184 |
185 | QSaveFile file(fileName);
186 |
187 | if (file.open(QFile::WriteOnly | QFile::Text)) {
188 | setCurrentFile(fileName);
189 | emit changeTitle();
190 |
191 | QTextStream out(&file);
192 | out << toPlainText();
193 |
194 | if (!file.commit())
195 | errorMessage = "[WARN 5] Cannot save file: " + file.errorString();
196 | } else {
197 | errorMessage = "[WARN 3] Cannot save file: " + file.errorString();
198 | }
199 |
200 | if (!errorMessage.isEmpty()) {
201 | qWarning() << errorMessage;
202 | QMessageBox::warning(this, tr("Warning"),
203 | tr("Cannot save file: ") + file.errorString());
204 | }
205 |
206 | QGuiApplication::restoreOverrideCursor();
207 | }
208 |
209 | void TextEditor::saveAs()
210 | {
211 | QGuiApplication::setOverrideCursor(Qt::WaitCursor);
212 | QString fileName = QFileDialog::getSaveFileName(this, tr("Save as"));
213 | QSaveFile file(fileName);
214 |
215 | if (!file.open(QFile::WriteOnly | QFile::Text)) {
216 | QMessageBox::warning(this, tr("Warning"),
217 | tr("Cannot save file: ") + file.errorString());
218 | qWarning() << "[WARN 4] Failed to save" << fileName << ":"
219 | << file.errorString();
220 | return;
221 | }
222 |
223 | setCurrentFile(fileName);
224 |
225 | emit changeTitle();
226 | QTextStream out(&file);
227 | out << toPlainText();
228 |
229 | QGuiApplication::restoreOverrideCursor();
230 |
231 | if (!file.commit()) {
232 | QMessageBox::warning(
233 | this, tr("Warning"),
234 | tr("Cannot save file: ") + fileName + file.errorString());
235 | qWarning() << "[WARN 6] Failed to save" << fileName << ":"
236 | << file.errorString();
237 | }
238 | }
239 |
240 | void TextEditor::print()
241 | {
242 | #if defined(QT_PRINTSUPPORT_LIB) && QT_CONFIG(printer)
243 | QPrinter printDev;
244 | #if QT_CONFIG(printdialog)
245 | QPrintDialog dialog(&printDev, this);
246 | if (dialog.exec() == QDialog::Rejected) return;
247 | #endif // QT_CONFIG(printdialog)
248 | QPlainTextEdit:
249 | print(&printDev);
250 | #endif // QT_CONFIG(printer)
251 | }
252 |
253 | void TextEditor::undo() { QPlainTextEdit::undo(); }
254 |
255 | void TextEditor::redo() { QPlainTextEdit::redo(); }
256 |
257 | void TextEditor::copy()
258 | {
259 | #if QT_CONFIG(clipboard)
260 | QPlainTextEdit::copy();
261 | #endif
262 | }
263 |
264 | void TextEditor::paste()
265 | {
266 | #if QT_CONFIG(clipboard)
267 | QPlainTextEdit::paste();
268 | #endif
269 | }
270 |
271 | void TextEditor::cut()
272 | {
273 | #if QT_CONFIG(clipboard)
274 | QPlainTextEdit::cut();
275 | #endif
276 | }
277 |
278 | int TextEditor::lineNumberAreaWidth()
279 | {
280 | int digits = 1;
281 | int max = qMax(1, blockCount());
282 | while (max >= 10) {
283 | max /= 10;
284 | ++digits;
285 | }
286 |
287 | return 15 + fontMetrics().horizontalAdvance(QLatin1Char('9')) * digits +
288 | fontMetrics().lineSpacing();
289 | }
290 |
291 | void TextEditor::updateLineNumberAreaWidth(int /* newBlockCount */)
292 | {
293 | if (currentMode == 1)
294 | setViewportMargins(0, 0, 0, 0);
295 | else
296 | setViewportMargins(lineNumberAreaWidth(), 0, 0, 0);
297 | }
298 |
299 | void TextEditor::updateLineNumberArea(const QRect &rect, int dy)
300 | {
301 | if (dy)
302 | lineNumberArea->scroll(0, dy);
303 | else
304 | lineNumberArea->update(0, rect.y(), lineNumberArea->sizeHint().width(),
305 | rect.height());
306 | if (rect.contains(viewport()->rect())) updateLineNumberAreaWidth(0);
307 | }
308 |
309 | void TextEditor::resizeEvent(QResizeEvent *e)
310 | {
311 | QPlainTextEdit::resizeEvent(e);
312 |
313 | QRect cr = contentsRect();
314 | lineNumberArea->setGeometry(
315 | QRect(cr.left(), cr.top(), lineNumberAreaWidth(), cr.height()));
316 | }
317 |
318 | void TextEditor::contextMenuEvent(QContextMenuEvent *event)
319 | {
320 | // if you want to **extend** the standard context menu, use
321 | // auto menu = createStandardContextMenu(event->pos());
322 |
323 | // if you want to customize the context menu, use
324 | QMenu *menu = new QMenu;
325 |
326 | // Read only
327 | QAction *readOnlyAct =
328 | new QAction(QIcon(":/icons/read_only.svg"), tr("Read-Only mode"), this);
329 | readOnlyAct->setCheckable(true);
330 | readOnlyAct->setChecked(isReadOnly());
331 | menu->addAction(readOnlyAct);
332 | connect(readOnlyAct, &QAction::triggered, [&]() {
333 | setReadOnly(!isReadOnly());
334 | readOnlyAct->setChecked(isReadOnly());
335 | emit readOnlyChanged();
336 | });
337 |
338 | // syntax selection
339 | auto hlActionGroup = new QActionGroup(menu);
340 | hlActionGroup->setExclusive(true);
341 | auto hlGroupMenu = menu->addMenu(QStringLiteral("Syntax"));
342 | QMenu *hlSubMenu = hlGroupMenu;
343 | QString currentGroup;
344 | for (const auto &def : m_repository.definitions()) {
345 | if (def.isHidden()) continue;
346 | if (currentGroup != def.section()) {
347 | currentGroup = def.section();
348 | hlSubMenu = hlGroupMenu->addMenu(def.translatedSection());
349 | }
350 |
351 | auto action = hlSubMenu->addAction(def.translatedName());
352 | action->setCheckable(true);
353 | action->setData(def.name());
354 | hlActionGroup->addAction(action);
355 | if (def.name() == m_highlighter->definition().name())
356 | action->setChecked(true);
357 | }
358 | connect(hlActionGroup, &QActionGroup::triggered, this,
359 | [this](QAction *action) {
360 | const auto defName = action->data().toString();
361 | const auto def = m_repository.definitionForName(defName);
362 | m_highlighter->setDefinition(def);
363 | });
364 |
365 | // clear
366 | QAction *clearAct = new QAction(tr("Clear"), this);
367 | menu->addAction(clearAct);
368 | connect(clearAct, &QAction::triggered, [&]() { newDocument(); });
369 |
370 | menu->exec(event->globalPos());
371 | delete menu;
372 | }
373 |
374 | void TextEditor::keyPressEvent(QKeyEvent *e)
375 | {
376 | if (e->key() == Qt::Key_Tab) {
377 | if (this->textCursor().hasSelection()) {
378 | qDebug() << "wtf";
379 | addInEachLineOfSelection(
380 | QRegularExpression("^"),
381 | configManager->getEditorIndentMode() == "Spaces"
382 | ? QString(configManager->getEditorTabSize(), ' ')
383 | : "\t");
384 | return;
385 | } else if (configManager->getEditorIndentMode() == "Spaces") {
386 | this->insertPlainText(
387 | QString(configManager->getEditorTabSize(), ' '));
388 | e->accept();
389 | }
390 | } else if (e->key() == '(') {
391 | this->insertPlainText("()");
392 | this->moveCursor(QTextCursor::MoveOperation::Left,
393 | QTextCursor::MoveAnchor);
394 | e->accept();
395 | } else if (e->key() == '{') {
396 | this->insertPlainText("{}");
397 | this->moveCursor(QTextCursor::MoveOperation::Left,
398 | QTextCursor::MoveAnchor);
399 | e->accept();
400 | } else if (e->key() == '[') {
401 | this->insertPlainText("[]");
402 | this->moveCursor(QTextCursor::MoveOperation::Left,
403 | QTextCursor::MoveAnchor);
404 | e->accept();
405 | }
406 | QPlainTextEdit::keyPressEvent(e);
407 | }
408 |
409 | void TextEditor::addInEachLineOfSelection(const QRegularExpression ®ex,
410 | const QString &str)
411 | {
412 | auto cursor = textCursor();
413 | auto lines = toPlainText().remove('\r').split('\n');
414 | int selectionStart = cursor.selectionStart();
415 | int selectionEnd = cursor.selectionEnd();
416 | bool cursorAtEnd = cursor.position() == selectionEnd;
417 | cursor.setPosition(selectionStart);
418 | int lineStart = cursor.blockNumber();
419 | cursor.setPosition(selectionEnd);
420 | int lineEnd = cursor.blockNumber();
421 | QString newText;
422 | QTextStream stream(&newText);
423 | for (int i = lineStart; i <= lineEnd; ++i) {
424 | auto line = lines[i];
425 | stream << line.insert(line.indexOf(regex), str);
426 | if (i != lineEnd)
427 | #if QT_VERSION >= 0x50E00
428 | stream << Qt::endl;
429 | #else
430 | stream << endl;
431 | #endif
432 | }
433 | cursor.movePosition(QTextCursor::Start);
434 | cursor.movePosition(QTextCursor::NextBlock, QTextCursor::MoveAnchor,
435 | lineStart);
436 | cursor.movePosition(QTextCursor::NextBlock, QTextCursor::KeepAnchor,
437 | lineEnd - lineStart);
438 | cursor.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor);
439 | cursor.insertText(newText);
440 | int pos = selectionStart + str.length();
441 | int pos2 = selectionEnd + str.length() * (lineEnd - lineStart + 1);
442 | if (cursorAtEnd) {
443 | cursor.setPosition(pos);
444 | cursor.setPosition(pos2, QTextCursor::KeepAnchor);
445 | } else {
446 | cursor.setPosition(pos2);
447 | cursor.setPosition(pos, QTextCursor::KeepAnchor);
448 | }
449 | setTextCursor(cursor);
450 | }
451 |
452 | void TextEditor::highlightCurrentLine()
453 | {
454 | QList extraSelections;
455 |
456 | if (!isReadOnly()) {
457 | QTextEdit::ExtraSelection selection;
458 |
459 | selection.format.setBackground(
460 | QColor(m_highlighter->theme().editorColor(
461 | KSyntaxHighlighting::Theme::CurrentLine)));
462 | selection.format.setProperty(QTextFormat::FullWidthSelection, true);
463 | selection.cursor = textCursor();
464 | selection.cursor.clearSelection();
465 | extraSelections.append(selection);
466 | }
467 |
468 | if (currentMode == 1) extraSelections.clear();
469 |
470 | setExtraSelections(extraSelections);
471 | }
472 |
473 | void TextEditor::lineNumberAreaPaintEvent(QPaintEvent *event)
474 | {
475 | QPainter painter(lineNumberArea);
476 | painter.fillRect(event->rect(),
477 | m_highlighter->theme().editorColor(
478 | KSyntaxHighlighting::Theme::IconBorder));
479 |
480 | auto block = firstVisibleBlock();
481 | auto blockNumber = block.blockNumber();
482 | int top = blockBoundingGeometry(block).translated(contentOffset()).top();
483 | int bottom = top + blockBoundingRect(block).height();
484 | const int currentBlockNumber = textCursor().blockNumber();
485 |
486 | const auto foldingMarkerSize = fontMetrics().lineSpacing();
487 |
488 | while (block.isValid() && top <= event->rect().bottom()) {
489 | if (block.isVisible() && bottom >= event->rect().top()) {
490 | const auto number = QString::number(blockNumber + 1);
491 | painter.setPen(m_highlighter->theme().editorColor(
492 | (blockNumber == currentBlockNumber)
493 | ? KSyntaxHighlighting::Theme::CurrentLineNumber
494 | : KSyntaxHighlighting::Theme::LineNumbers));
495 | painter.drawText(0, top,
496 | lineNumberArea->width() - foldingMarkerSize + 3,
497 | fontMetrics().height(), Qt::AlignRight, number);
498 | }
499 |
500 | // folding marker
501 | if (block.isVisible() && isFoldable(block)) {
502 | QPolygonF polygon;
503 | if (isFolded(block)) {
504 | polygon << QPointF(foldingMarkerSize * 0.4,
505 | foldingMarkerSize * 0.25);
506 | polygon << QPointF(foldingMarkerSize * 0.4,
507 | foldingMarkerSize * 0.75);
508 | polygon << QPointF(foldingMarkerSize * 0.8,
509 | foldingMarkerSize * 0.5);
510 | } else {
511 | polygon << QPointF(foldingMarkerSize * 0.25,
512 | foldingMarkerSize * 0.4);
513 | polygon << QPointF(foldingMarkerSize * 0.75,
514 | foldingMarkerSize * 0.4);
515 | polygon << QPointF(foldingMarkerSize * 0.5,
516 | foldingMarkerSize * 0.8);
517 | }
518 | painter.save();
519 | painter.setRenderHint(QPainter::Antialiasing);
520 | painter.setPen(Qt::NoPen);
521 | painter.setBrush(QColor(m_highlighter->theme().editorColor(
522 | KSyntaxHighlighting::Theme::CodeFolding)));
523 | painter.translate(lineNumberArea->width() - foldingMarkerSize + 3,
524 | top);
525 | painter.drawPolygon(polygon);
526 | painter.restore();
527 | }
528 |
529 | block = block.next();
530 | top = bottom;
531 | bottom = top + blockBoundingRect(block).height();
532 | ++blockNumber;
533 | }
534 | }
535 |
536 | void TextEditor::dropEvent(QDropEvent *e)
537 | {
538 | QList urls = e->mimeData()->urls();
539 |
540 | for (auto iUrl : urls) {
541 | QString filename = iUrl.toLocalFile();
542 | qDebug() << filename;
543 | emit openFileInNewTab(filename);
544 | }
545 |
546 | e->accept();
547 | }
548 |
549 | void LineNumberArea::mouseReleaseEvent(QMouseEvent *event)
550 | {
551 | if (event->x() >= width() - textEditor->fontMetrics().lineSpacing()) {
552 | auto block = textEditor->blockAtPosition(event->y());
553 | if (!block.isValid() || !textEditor->isFoldable(block)) return;
554 | textEditor->toggleFold(block);
555 | }
556 | QWidget::mouseReleaseEvent(event);
557 | }
558 |
559 | QTextBlock TextEditor::blockAtPosition(int y) const
560 | {
561 | auto block = firstVisibleBlock();
562 | if (!block.isValid()) return QTextBlock();
563 |
564 | int top = blockBoundingGeometry(block).translated(contentOffset()).top();
565 | int bottom = top + blockBoundingRect(block).height();
566 | do {
567 | if (top <= y && y <= bottom) return block;
568 | block = block.next();
569 | top = bottom;
570 | bottom = top + blockBoundingRect(block).height();
571 | } while (block.isValid());
572 | return QTextBlock();
573 | }
574 |
575 | bool TextEditor::isFoldable(const QTextBlock &block) const
576 | {
577 | return m_highlighter->startsFoldingRegion(block);
578 | }
579 |
580 | bool TextEditor::isFolded(const QTextBlock &block) const
581 | {
582 | if (!block.isValid()) return false;
583 | const auto nextBlock = block.next();
584 | if (!nextBlock.isValid()) return false;
585 | return !nextBlock.isVisible();
586 | }
587 |
588 | void TextEditor::toggleFold(const QTextBlock &startBlock)
589 | {
590 | // we also want to fold the last line of the region, therefore the ".next()"
591 | const auto endBlock =
592 | m_highlighter->findFoldingRegionEnd(startBlock).next();
593 |
594 | if (isFolded(startBlock)) {
595 | // unfold
596 | auto block = startBlock.next();
597 | while (block.isValid() && !block.isVisible()) {
598 | block.setVisible(true);
599 | block.setLineCount(block.layout()->lineCount());
600 | block = block.next();
601 | }
602 |
603 | } else {
604 | // fold
605 | auto block = startBlock.next();
606 | while (block.isValid() && block != endBlock) {
607 | block.setVisible(false);
608 | block.setLineCount(0);
609 | block = block.next();
610 | }
611 | }
612 |
613 | // redraw document
614 | document()->markContentsDirty(
615 | startBlock.position(), endBlock.position() - startBlock.position() + 1);
616 |
617 | // update scrollbars
618 | emit document()->documentLayout()->documentSizeChanged(
619 | document()->documentLayout()->documentSize());
620 | }
621 |
622 | void TextEditor::setTheme(const KSyntaxHighlighting::Theme &theme)
623 | {
624 | auto pal = qApp->palette();
625 | if (theme.isValid()) {
626 | pal.setColor(
627 | QPalette::Base,
628 | theme.editorColor(KSyntaxHighlighting::Theme::BackgroundColor));
629 | pal.setColor(
630 | QPalette::Highlight,
631 | theme.editorColor(KSyntaxHighlighting::Theme::TextSelection));
632 | }
633 |
634 | setPalette(pal);
635 |
636 | m_highlighter->setTheme(theme);
637 | m_highlighter->rehighlight();
638 | highlightCurrentLine();
639 | }
640 |
641 | void TextEditor::setEditorFont(const QFont &font)
642 | {
643 | QFont f = QFont(font.family(), configManager->getEditorFontSize());
644 | QPlainTextEdit::setFont(f);
645 | configManager->setEditorFontFamily(font.family());
646 | lineNumberArea->setFont(f);
647 | }
648 |
649 | void TextEditor::setEditorFontSize(const int &size)
650 | {
651 | QFont font = configManager->getEditorFontFamily();
652 | font.setPointSize(size);
653 | QPlainTextEdit::setFont(font);
654 | configManager->setEditorFontSize(size);
655 | }
656 |
657 | void TextEditor::setEditorColorTheme(const QString &ctname)
658 | {
659 | const auto theme = m_repository.theme(ctname);
660 | setTheme(theme);
661 | }
662 |
663 | void TextEditor::setCurrentFile(const QString &fileName)
664 | {
665 | currentFile = fileName;
666 | if (!fileName.isEmpty()) currentFileName = QFileInfo(fileName).fileName();
667 | document()->setModified(false);
668 | setWindowModified(false);
669 | emit modifiedFalse();
670 | }
671 |
672 | void TextEditor::switchMode(const int &mode)
673 | {
674 | if (mode == 0) {
675 | lineNumberArea->show();
676 | currentMode = mode;
677 | QPlainTextEdit::setFont(QFont(configManager->getEditorFontFamily(),
678 | configManager->getEditorFontSize()));
679 | setStyleSheet("background: " +
680 | QString::number(m_highlighter->theme().editorColor(
681 | KSyntaxHighlighting::Theme::BackgroundColor)));
682 | setEditorFont(configManager->getEditorFontFamily());
683 | } else if (mode == 1) {
684 | lineNumberArea->hide();
685 | setViewportMargins(0, 0, 0, 0);
686 | currentMode = mode;
687 | setFont(QFont(
688 | QFontDatabase::systemFont(QFontDatabase::GeneralFont).toString(),
689 | configManager->getEditorFontSize()));
690 | auto def = m_repository.definitionForName("Markdown");
691 | m_highlighter->setDefinition(def);
692 | }
693 | }
694 |
695 | // QPlainTextEdit can only zoomIn in Read-Only mode
696 | void TextEditor::wheelEvent(QWheelEvent *e)
697 | {
698 | // Qt: if (!(d->control->textInteractionFlags() & Qt::TextEditable))
699 | if (e->modifiers() & Qt::ControlModifier) {
700 | float delta = e->angleDelta().y() / 120.f;
701 | zoomInF(delta);
702 | return;
703 | }
704 |
705 | QAbstractScrollArea::wheelEvent(e);
706 | updateMicroFocus();
707 | }
708 |
709 | void TextEditor::updateSyntaxHighlight()
710 | {
711 | const auto def = m_repository.definitionForFileName(currentFile);
712 | m_highlighter->setDefinition(def);
713 | }
714 |
--------------------------------------------------------------------------------
/src/core/texteditor.h:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2020 ChungZH. ALl Rights Reserved.
3 | * Licensed under the MIT license.
4 | * See file LICENSE for detail or copy at
5 | *
6 | * This file is a part of Notepanda.
7 | *
8 | * @file texteditor.h
9 | * @brief This file declares the TextEditor class.
10 | *
11 | */
12 | #ifndef TEXTEDITOR_H
13 | #define TEXTEDITOR_H
14 |
15 | #include
16 |
17 | #include
18 |
19 | #include "configmanager.h"
20 |
21 | QT_BEGIN_NAMESPACE
22 | class QPaintEvent;
23 | class QResizeEvent;
24 | class QSize;
25 | class QWidget;
26 | class QFileDialog;
27 | QT_END_NAMESPACE
28 |
29 | namespace KSyntaxHighlighting
30 | {
31 | class SyntaxHighlighter;
32 | }
33 |
34 | class TextEditor : public QPlainTextEdit
35 | {
36 | Q_OBJECT
37 |
38 | public:
39 | TextEditor(ConfigManager *cfManager, QWidget *parent = nullptr);
40 | QString currentFile, currentFileName;
41 | void openFile(const QString &fileName);
42 |
43 | void lineNumberAreaPaintEvent(QPaintEvent *event);
44 | int lineNumberAreaWidth();
45 | QTextBlock blockAtPosition(int y) const;
46 | bool isFoldable(const QTextBlock &block) const;
47 | bool isFolded(const QTextBlock &block) const;
48 | void toggleFold(const QTextBlock &block);
49 |
50 | protected:
51 | void resizeEvent(QResizeEvent *event) override;
52 | void contextMenuEvent(QContextMenuEvent *event) override;
53 | void wheelEvent(QWheelEvent *e) override;
54 | void keyPressEvent(QKeyEvent *e) override;
55 | void dropEvent(QDropEvent *e) override;
56 |
57 | public slots:
58 | bool maybeSave();
59 | bool newDocument();
60 | bool open();
61 | void save();
62 | void saveAs();
63 | void print();
64 | void undo();
65 | void redo();
66 | void copy();
67 | void paste();
68 | void cut();
69 | void updateLineNumberAreaWidth(int newBlockCount);
70 | void highlightCurrentLine();
71 | void updateLineNumberArea(const QRect &rect, int dy);
72 | void setEditorFont(const QFont &font);
73 | void setEditorFontSize(const int &size);
74 | void setEditorColorTheme(const QString &ctname);
75 | void setCurrentFile(const QString &fileName);
76 | void updateSyntaxHighlight();
77 |
78 | /**
79 | * @brief switchMode
80 | * @param mode
81 | * 0: normal mode
82 | * 1: sticky mode
83 | */
84 | void switchMode(const int &mode);
85 |
86 | private:
87 | ConfigManager *configManager;
88 |
89 | KSyntaxHighlighting::Repository m_repository;
90 | KSyntaxHighlighting::SyntaxHighlighter *m_highlighter;
91 | void setTheme(const KSyntaxHighlighting::Theme &theme);
92 |
93 | QWidget *lineNumberArea;
94 | int currentMode;
95 |
96 | void addInEachLineOfSelection(const QRegularExpression ®ex,
97 | const QString &str);
98 |
99 | signals:
100 | void changeTitle();
101 | void modifiedFalse();
102 | void readOnlyChanged();
103 | void openFileInNewTab(const QString &file);
104 | };
105 |
106 | #endif // TEXTEDITOR_H
107 |
--------------------------------------------------------------------------------
/src/main.cpp:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2020 ChungZH. ALl Rights Reserved.
3 | * Licensed under the MIT license.
4 | * See file LICENSE for detail or copy at
5 | *
6 | * This file is a part of Notepanda.
7 | *
8 | * @file main.cpp
9 | * @brief This file is main of the project.
10 | *
11 | */
12 |
13 | #include
14 | #include
15 | #include
16 | #include
17 | #include
18 | #include
19 | #include
20 |
21 | #include "./core/configmanager.h"
22 | #include "./ui/mainwindow.h"
23 |
24 | int main(int argc, char *argv[])
25 | {
26 | QApplication App(argc, argv);
27 |
28 | App.setOrganizationName("ChungZH");
29 | App.setApplicationName("Notepanda");
30 | App.setApplicationVersion("0.1.4");
31 |
32 | QCommandLineParser parser;
33 | parser.addHelpOption();
34 | parser.addVersionOption();
35 | parser.addPositionalArgument("source", "The source file to open.");
36 | QCommandLineOption configFileOption("c", "specify configuration file.",
37 | "config.json");
38 | parser.addOption(configFileOption);
39 | parser.process(App);
40 |
41 | QString configFile = parser.value(configFileOption);
42 | if (configFile.isEmpty()) {
43 | #ifdef Q_OS_WIN
44 |
45 | /*
46 | if (QLocale::system().country() == QLocale::China ||
47 | QLocale::system().language() == QLocale::Chinese)
48 | App.setFont(QFont("Microsoft Yahei", 9, QFont::Normal, false));
49 | else */
50 | App.setFont(QFont("Segoe UI", 9, QFont::Normal, false));
51 |
52 | if (QDir(App.applicationDirPath() + "/config").exists()) {
53 | configFile = App.applicationDirPath() + "/config/notepanda.json";
54 | } else {
55 | QDir configDir = QStandardPaths::writableLocation(
56 | QStandardPaths::StandardLocation::AppConfigLocation);
57 | configFile = configDir.absolutePath() + "/config.json";
58 | }
59 | #else
60 | QDir configDir = QDir::homePath() + "/.config/notepanda";
61 | configFile = configDir.absolutePath() + "/config.json";
62 | if (!configDir.exists()) {
63 | configDir.mkpath(configDir.absolutePath());
64 | }
65 | #endif
66 | }
67 | qDebug() << configFile;
68 |
69 | ConfigManager *configManager;
70 | configManager = new ConfigManager(configFile);
71 |
72 | App.setStyle(QStyleFactory::create(configManager->getStyleTheme()));
73 |
74 | MainWindow notepanda(configManager);
75 | notepanda.show();
76 | if (parser.positionalArguments().size() == 1)
77 | notepanda.plainTextEdit->openFile(parser.positionalArguments().at(0));
78 |
79 | qInfo() << QStringLiteral("Welcome to Notepanda!") << "";
80 |
81 | return App.exec();
82 | }
83 |
--------------------------------------------------------------------------------
/src/ui/aboutwindow.cpp:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2020 ChungZH. ALl Rights Reserved.
3 | * Licensed under the MIT license.
4 | * See file LICENSE for detail or copy at
5 | *
6 | * This file is a part of Notepanda.
7 | *
8 | * @file aboutwindow.cpp
9 | * @brief This file implements the AboutWindow class.
10 | *
11 | */
12 | #include "aboutwindow.h"
13 |
14 | #include
15 | #include
16 | #include
17 | #include
18 | #include
19 | #include
20 | #include
21 |
22 | #include "ui_aboutwindow.h"
23 |
24 | AboutWindow::AboutWindow(QWidget *parent)
25 | : QDialog(parent), ui(new Ui::AboutWindow)
26 | {
27 | ui->setupUi(this);
28 | setWindowTitle("About - Notepanda");
29 |
30 | QFile ver(":/asset/makespec/VERSION");
31 | QFile verSuf(":/asset/makespec/VERSIONSUFFIX");
32 | QFile buildVer(":/asset/makespec/BUILDVERSION");
33 | ver.open(QFile::ReadOnly);
34 | verSuf.open(QFile::ReadOnly);
35 | buildVer.open(QFile::ReadOnly);
36 |
37 | QTextStream t_ver(&ver);
38 | QTextStream t_vSf(&verSuf);
39 | QTextStream t_bVe(&buildVer);
40 |
41 | QString verString =
42 | t_ver.readAll() + t_vSf.readAll() + " BV" + t_bVe.readAll();
43 | verString.remove("\n");
44 |
45 | ui->label_5->setText(verString);
46 | ui->label_2->setFont(QFont(
47 | QFontDatabase::systemFont(QFontDatabase::FixedFont).toString(), 15));
48 | ui->label_3->setFont(QFont(
49 | QFontDatabase::systemFont(QFontDatabase::FixedFont).toString(), 15));
50 | ui->label_4->setFont(QFont(
51 | QFontDatabase::systemFont(QFontDatabase::FixedFont).toString(), 15));
52 | ui->label_5->setFont(QFont(
53 | QFontDatabase::systemFont(QFontDatabase::FixedFont).toString(), 15));
54 | ui->label_6->setFont(QFont(
55 | QFontDatabase::systemFont(QFontDatabase::FixedFont).toString(), 15));
56 | ui->label_7->setFont(QFont(
57 | QFontDatabase::systemFont(QFontDatabase::FixedFont).toString(), 15));
58 | }
59 |
--------------------------------------------------------------------------------
/src/ui/aboutwindow.h:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2020 ChungZH. ALl Rights Reserved.
3 | * Licensed under the MIT license.
4 | * See file LICENSE for detail or copy at
5 | *
6 | * This file is a part of Notepanda.
7 | *
8 | * @file aboutwindow.h
9 | * @brief This file declares the AboutWindow class.
10 | */
11 | #ifndef ABOUTWINDOW_H
12 | #define ABOUTWINDOW_H
13 |
14 | #include
15 |
16 | #include
17 | #include
18 | #include
19 | #include
20 |
21 | #include "../core/configmanager.h"
22 |
23 | class AboutWindow : public QDialog, private Ui::AboutWindow
24 | {
25 | Q_OBJECT
26 |
27 | public:
28 | explicit AboutWindow(QWidget *parent = nullptr);
29 |
30 | private:
31 | Ui::AboutWindow *ui;
32 | };
33 |
34 | #endif // ABOUTWINDOW_H
35 |
--------------------------------------------------------------------------------
/src/ui/aboutwindow.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | AboutWindow
4 |
5 |
6 |
7 | 0
8 | 0
9 | 827
10 | 472
11 |
12 |
13 |
14 |
15 | Arial
16 |
17 |
18 |
19 | Dialog
20 |
21 |
22 |
23 |
24 |
25 | -
26 |
27 |
-
28 |
29 |
-
30 |
31 |
32 | image: url(:/asset/images/notepanda.png)
33 |
34 |
35 | QFrame::StyledPanel
36 |
37 |
38 | QFrame::Raised
39 |
40 |
41 |
42 | -
43 |
44 |
45 | Qt::Vertical
46 |
47 |
48 |
49 | 20
50 | 40
51 |
52 |
53 |
54 |
55 |
56 |
57 | -
58 |
59 |
-
60 |
61 |
-
62 |
63 |
64 |
65 | 26
66 |
67 |
68 |
69 | Notepanda
70 |
71 |
72 |
73 | -
74 |
75 |
-
76 |
77 |
-
78 |
79 |
80 |
81 | 16
82 |
83 |
84 |
85 | Version:
86 |
87 |
88 | Qt::AutoText
89 |
90 |
91 |
92 | -
93 |
94 |
95 |
96 | 16
97 |
98 |
99 |
100 | <a href="https://github.com/ChungZH/notepanda">ChungZH/notepanda</a>
101 |
102 |
103 | Qt::AutoText
104 |
105 |
106 | true
107 |
108 |
109 |
110 | -
111 |
112 |
113 |
114 | 16
115 |
116 |
117 |
118 | MIT
119 |
120 |
121 |
122 | -
123 |
124 |
125 |
126 | 16
127 |
128 |
129 |
130 | License:
131 |
132 |
133 |
134 | -
135 |
136 |
137 |
138 | 16
139 |
140 |
141 |
142 | GitHub:
143 |
144 |
145 | Qt::AutoText
146 |
147 |
148 | true
149 |
150 |
151 |
152 | -
153 |
154 |
155 |
156 | 16
157 |
158 |
159 |
160 |
161 |
162 |
163 | -
164 |
165 |
166 |
167 | qrc:/asset/assets/CREDIT.md
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
--------------------------------------------------------------------------------
/src/ui/linenumberarea.h:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2020 ChungZH. ALl Rights Reserved.
3 | * Licensed under the MIT license.
4 | * See file LICENSE for detail or copy at
5 | *
6 | * This file is a part of Notepanda.
7 | *
8 | * @file linenumberarea.h
9 | * @brief This file declares the LineNumberArea class.
10 | *
11 | */
12 | #ifndef LINENUMBERAREA_H
13 | #define LINENUMBERAREA_H
14 |
15 | #include
16 |
17 | #include "../core/texteditor.h"
18 |
19 | class LineNumberArea : public QWidget
20 | {
21 | Q_OBJECT
22 |
23 | public:
24 | LineNumberArea(TextEditor *editor) : QWidget(editor), textEditor(editor) {}
25 | QSize sizeHint() const override
26 | {
27 | return QSize(textEditor->lineNumberAreaWidth(), 0);
28 | }
29 |
30 | protected:
31 | void mouseReleaseEvent(QMouseEvent *event) override;
32 | void paintEvent(QPaintEvent *event) override
33 | {
34 | textEditor->lineNumberAreaPaintEvent(event);
35 | }
36 |
37 | private:
38 | TextEditor *textEditor;
39 | };
40 |
41 | #endif // LINENUMBERAREA_H
42 |
--------------------------------------------------------------------------------
/src/ui/mainwindow.cpp:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2020 ChungZH. ALl Rights Reserved.
3 | * Licensed under the MIT license.
4 | * See file LICENSE for detail or copy at
5 | *
6 | * This file is a part of Notepanda.
7 | *
8 | * @file mainwindow.cpp
9 | * @brief This file implements the MainWindow class.
10 | * It is the main window of notepanda.
11 | *
12 | */
13 |
14 | #include "mainwindow.h"
15 |
16 | #include
17 | #include
18 | #include
19 | #include
20 | #include
21 | #include
22 | #include
23 | #include
24 | #include
25 |
26 | #include "aboutwindow.h"
27 | #include "preferenceswindow.h"
28 | #include "ui_preferenceswindow.h"
29 |
30 | MainWindow::MainWindow(ConfigManager *cfManager, QWidget *parent)
31 | : QMainWindow(parent),
32 | TabBar(new QTabBar),
33 | SToolBar(new QToolBar),
34 | ColorDialog(new QColorDialog),
35 | previewPanel(new QTextBrowser),
36 | ToolBar(new QToolBar),
37 | configManager(cfManager),
38 | curTabIndex(0),
39 | prevTabIndex(0),
40 | lastTabRemoveFlag(0),
41 | doNotSaveDataFlag(0)
42 | {
43 | resize(800, 600);
44 | setupUi();
45 | setBaseSize(size());
46 |
47 | ToolBar->setIconSize(QSize(26, 26));
48 |
49 | isPintotop = 0;
50 |
51 | // Sticky note mode
52 | changeBgColor = new QAction(QIcon(":/icons/color_background.svg"),
53 | tr("Change background color"), this);
54 | changeBgColor->setToolTip(tr("Change background color"));
55 | currentColor = "#AAFFFF";
56 |
57 | SToolBar->addAction(changeBgColor);
58 | SToolBar->addAction(actionNormalmode);
59 | SToolBar->addAction(actionPin_to_top);
60 |
61 | addToolBar(Qt::ToolBarArea::BottomToolBarArea, SToolBar);
62 | SToolBar->setVisible(0);
63 |
64 | connect(changeBgColor, &QAction::triggered, [&]() { ColorDialog->open(); });
65 | connect(ColorDialog, &QColorDialog::currentColorChanged,
66 | [&](const QColor &color) {
67 | currentColor = color;
68 | plainTextEdit->setStyleSheet("background-color: " +
69 | currentColor.name());
70 | });
71 |
72 | // Sticky note mode END
73 |
74 | this->addToolBar(Qt::LeftToolBarArea, ToolBar);
75 |
76 | normalMode(1);
77 |
78 | /** TODO: TabBar->setMovable(true);
79 | If move, index will change. So I must adjust `tabData`.
80 | */
81 |
82 | TabBar->setTabsClosable(true);
83 | TabToolBar = new QToolBar;
84 | TabToolBar->addWidget(TabBar);
85 | TabToolBar->setMovable(false);
86 | TabToolBar->setFloatable(false);
87 | this->addToolBar(Qt::TopToolBarArea, TabToolBar);
88 |
89 | plainTextEdit = new TextEditor(configManager);
90 | this->setCentralWidget(plainTextEdit);
91 |
92 | TabBar->addTab("Untitled.txt");
93 | tabData.push_back(TabData{"", "", 0});
94 |
95 | connect(TabBar, &QTabBar::currentChanged, [&](const int index) {
96 | prevTabIndex = curTabIndex;
97 | curTabIndex = index;
98 |
99 | if (curTabIndex == -1) curTabIndex = 0;
100 | if (prevTabIndex == -1) prevTabIndex = 0;
101 |
102 | if (TabBar->count() == 0) {
103 | prevTabIndex = 0;
104 | tabData.push_back(TabData{"", "", 0});
105 | TabBar->addTab("Untitled.txt");
106 | }
107 |
108 | if (lastTabRemoveFlag == true) {
109 | prevTabIndex = curTabIndex = index;
110 | lastTabRemoveFlag = false;
111 | } else if (doNotSaveDataFlag == true) {
112 | doNotSaveDataFlag = false;
113 | } else {
114 | saveTabData(prevTabIndex);
115 | }
116 |
117 | plainTextEdit->clear();
118 | if (index != -1) {
119 | plainTextEdit->setCurrentFile(tabData[index].fileName);
120 | plainTextEdit->setPlainText(tabData[index].plainText);
121 | }
122 |
123 | plainTextEdit->updateSyntaxHighlight();
124 | plainTextEdit->document()->setModified(tabData[index].isModified);
125 | changeWindowTitle();
126 | });
127 |
128 | connect(TabBar, &QTabBar::tabCloseRequested, [&](int index) {
129 | tabData.remove(index);
130 | lastTabRemoveFlag = true;
131 | TabBar->removeTab(index);
132 |
133 | if (TabBar->count() != 0) {
134 | TabData tempTD = tabData[TabBar->currentIndex()];
135 | plainTextEdit->setPlainText(tempTD.plainText);
136 | plainTextEdit->setCurrentFile(tempTD.fileName);
137 | plainTextEdit->document()->setModified(tempTD.isModified);
138 | }
139 | changeWindowTitle();
140 | });
141 |
142 | connect(actionNew, &QAction::triggered, [&]() {
143 | saveTabData(TabBar->currentIndex());
144 |
145 | if (plainTextEdit->newDocument()) {
146 | doNotSaveDataFlag = true;
147 | const int newIndex = TabBar->addTab("Untitled.txt");
148 | tabData.push_back(TabData{"", "", 0});
149 | TabBar->setCurrentIndex(newIndex);
150 | }
151 | });
152 | connect(actionOpen, &QAction::triggered, [&]() {
153 | saveTabData(TabBar->currentIndex());
154 | if (plainTextEdit->open()) {
155 | doNotSaveDataFlag = true;
156 | const int newIndex = TabBar->addTab(plainTextEdit->currentFileName);
157 | tabData.push_back(TabData{plainTextEdit->toPlainText(),
158 | plainTextEdit->currentFileName, 0});
159 | TabBar->setCurrentIndex(newIndex);
160 | }
161 | });
162 | connect(actionSave, &QAction::triggered, plainTextEdit, &TextEditor::save);
163 | connect(actionSave_As, &QAction::triggered, plainTextEdit,
164 | &TextEditor::saveAs);
165 | connect(actionPrint, &QAction::triggered, plainTextEdit,
166 | &TextEditor::print);
167 | connect(actionRedo, &QAction::triggered, plainTextEdit, &TextEditor::redo);
168 | connect(actionUndo, &QAction::triggered, plainTextEdit, &TextEditor::undo);
169 | connect(actionReadOnlyMode, &QAction::triggered, [&]() {
170 | plainTextEdit->setReadOnly(!plainTextEdit->isReadOnly());
171 | updateStatusBar();
172 | });
173 | /**
174 | if user change Read-Only mode in right-click menu of TextEditor
175 | than setChecked in MainWindow::actionReadOnlyMode
176 | */
177 | connect(plainTextEdit, &TextEditor::readOnlyChanged, [&]() {
178 | actionReadOnlyMode->setChecked(plainTextEdit->isReadOnly());
179 | updateStatusBar();
180 | });
181 |
182 | DockWidget = new QDockWidget(tr("Preview panel"), this);
183 | DockWidget->setAllowedAreas(Qt::LeftDockWidgetArea |
184 | Qt::RightDockWidgetArea);
185 | DockWidget->setWidget(previewPanel);
186 | addDockWidget(Qt::RightDockWidgetArea, DockWidget);
187 | DockWidget->setVisible(0);
188 |
189 | previewPanel->setEnabled(0);
190 |
191 | connect(DockWidget, &QDockWidget::visibilityChanged, [&](bool visible) {
192 | actionPreview_panel->setChecked(visible);
193 | previewPanel->setEnabled(visible);
194 | });
195 |
196 | // PreferencesWindow START
197 |
198 | pfWindow = new PreferencesWindow(configManager, this);
199 |
200 | connect(actionPreferences, &QAction::triggered,
201 | [&]() { pfWindow->exec(); });
202 |
203 | connect(pfWindow->ui->themeCombo, &QComboBox::currentTextChanged,
204 | [&](const QString &curTheme) {
205 | QApplication::setStyle(QStyleFactory::create(curTheme));
206 | configManager->setStyleTheme(curTheme);
207 | });
208 | connect(pfWindow->ui->fontComboBox, &QFontComboBox::currentFontChanged,
209 | [&](const QFont font) { plainTextEdit->setEditorFont(font); });
210 | connect(pfWindow->ui->spinBox, QOverload::of(&QSpinBox::valueChanged),
211 | [=](const int &value) { plainTextEdit->setEditorFontSize(value); });
212 | connect(pfWindow->ui->highlightThemeCombo, &QComboBox::currentTextChanged,
213 | [&](const QString &ctname) {
214 | plainTextEdit->setEditorColorTheme(ctname);
215 | configManager->setEditorColorTheme(ctname);
216 | });
217 |
218 | // User accepted, so change the `settings`.
219 | connect(pfWindow->ui->buttonBox, &QDialogButtonBox::accepted,
220 | [&]() { configManager->save(); });
221 |
222 | // User rejected, so read general settings, do not change the `settings` !!!
223 | // Otherwise it will not be restored
224 | connect(pfWindow->ui->buttonBox, &QDialogButtonBox::rejected, [&]() {
225 | // Restore the variables
226 | configManager->readGeneralSettings();
227 |
228 | // Restore TextEditor
229 | plainTextEdit->setEditorFont(configManager->getEditorFontFamily());
230 | plainTextEdit->setEditorFontSize(configManager->getEditorFontSize());
231 | plainTextEdit->setEditorColorTheme(
232 | configManager->getEditorColorTheme());
233 |
234 | // Restore MainWindow
235 | QApplication::setStyle(
236 | QStyleFactory::create(configManager->getStyleTheme()));
237 |
238 | // Restore PreferencesWindow
239 | pfWindow->resetAllValues(0);
240 | });
241 |
242 | // PW END
243 |
244 | connect(plainTextEdit, &TextEditor::changeTitle, this,
245 | &MainWindow::changeWindowTitle);
246 | connect(plainTextEdit->document(), &QTextDocument::contentsChanged, this,
247 | &MainWindow::documentWasModified);
248 | connect(plainTextEdit, &TextEditor::modifiedFalse,
249 | [=]() { setWindowModified(false); });
250 | connect(plainTextEdit, &TextEditor::undoAvailable,
251 | [=](bool undoIsAvailable) {
252 | actionUndo->setDisabled(!undoIsAvailable);
253 | });
254 | connect(plainTextEdit, &TextEditor::redoAvailable,
255 | [=](bool redoIsAvailable) {
256 | actionRedo->setDisabled(!redoIsAvailable);
257 | });
258 |
259 | connect(plainTextEdit, &TextEditor::textChanged, this,
260 | &MainWindow::updateStatusBar);
261 | connect(
262 | plainTextEdit, &TextEditor::openFileInNewTab, [&](const QString &file) {
263 | saveTabData(TabBar->currentIndex());
264 |
265 | const int newIndex = TabBar->addTab(plainTextEdit->currentFileName);
266 | plainTextEdit->openFile(file);
267 | tabData.push_back(TabData{plainTextEdit->toPlainText(),
268 | plainTextEdit->currentFileName, 0});
269 | doNotSaveDataFlag = true;
270 | TabBar->setCurrentIndex(newIndex);
271 | changeWindowTitle();
272 | });
273 |
274 | updateStatusBar();
275 | changeWindowTitle();
276 | actionUndo->setDisabled(1);
277 | actionRedo->setDisabled(1);
278 |
279 | // Disable menu actions for unavailable features
280 | #if !defined(QT_PRINTSUPPORT_LIB) || !QT_CONFIG(printer)
281 | actionPrint->setEnabled(false);
282 | #endif
283 | #if !QT_CONFIG(clipboard)
284 | ui->actionCut->setEnabled(false);
285 | ui->actionCopy->setEnabled(false);
286 | ui->actionPaste->setEnabled(false);
287 | #else
288 | connect(actionCopy, &QAction::triggered, plainTextEdit, &TextEditor::copy);
289 | connect(actionPaste, &QAction::triggered, plainTextEdit,
290 | &TextEditor::paste);
291 | connect(actionCut, &QAction::triggered, plainTextEdit, &TextEditor::cut);
292 | connect(plainTextEdit, &TextEditor::copyAvailable,
293 | [&](bool isCopyAvailable) {
294 | actionCopy->setDisabled(!isCopyAvailable);
295 | });
296 | connect(
297 | plainTextEdit, &TextEditor::copyAvailable,
298 | [&](bool isCutAvailable) { actionCut->setDisabled(!isCutAvailable); });
299 | actionCopy->setDisabled(1);
300 | actionCut->setDisabled(1);
301 | #endif
302 | }
303 |
304 | MainWindow::~MainWindow() { delete plainTextEdit; }
305 |
306 | void MainWindow::setupUi()
307 | {
308 | actionNew = new QAction(QIcon(":/icons/add.svg"), tr("&New"), this);
309 | actionNew->setShortcut(QKeySequence::New);
310 |
311 | actionOpen = new QAction(QIcon(":/icons/open.svg"), tr("&Open"), this);
312 | actionOpen->setShortcut(QKeySequence::Open);
313 |
314 | actionSave = new QAction(QIcon(":/icons/save.svg"), tr("&Save"), this);
315 | actionSave->setShortcut(QKeySequence::Save);
316 |
317 | actionSave_As =
318 | new QAction(QIcon(":/icons/save_as.svg"), tr("&Save as"), this);
319 | actionSave_As->setShortcut(QKeySequence::SaveAs);
320 |
321 | actionUndo = new QAction(QIcon(":/icons/undo.svg"), tr("&Undo"), this);
322 | actionUndo->setShortcut(QKeySequence::Undo);
323 |
324 | actionRedo = new QAction(QIcon(":/icons/redo.svg"), tr("&Redo"), this);
325 | actionRedo->setShortcut(QKeySequence::Redo);
326 |
327 | actionCopy = new QAction(QIcon(":/icons/copy.svg"), tr("&Copy"), this);
328 | actionCopy->setShortcut(QKeySequence::Copy);
329 |
330 | actionPaste =
331 | new QAction(QIcon(":/icons/clipboard.svg"), tr("&Paste"), this);
332 | actionPaste->setShortcut(QKeySequence::Paste);
333 |
334 | actionQuit = new QAction(QIcon(":/icons/delete.svg"), tr("&Quit"), this);
335 | actionQuit->setShortcut(QKeySequence::Quit);
336 | connect(actionQuit, &QAction::triggered, this, &QCoreApplication::quit);
337 |
338 | actionCut = new QAction(QIcon(":/icons/cut.svg"), tr("Cut"), this);
339 | actionCut->setShortcut(QKeySequence::Cut);
340 |
341 | actionPrint = new QAction(QIcon(":/icons/print.svg"), tr("Print"), this);
342 | actionPrint->setShortcut(QKeySequence::Print);
343 |
344 | actionPreferences =
345 | new QAction(QIcon(":/icons/settings.svg"), tr("Preferences"), this);
346 | actionPreferences->setShortcut(QKeySequence::Preferences);
347 |
348 | actionSticky_note_mode =
349 | new QAction(QIcon(":/icons/sticker.svg"), tr("Sticky note mode"), this);
350 | actionSticky_note_mode->setToolTip(tr("Switch to sticky note mode"));
351 | connect(actionSticky_note_mode, &QAction::triggered, [&]() {
352 | stickyNoteMode();
353 | actionSticky_note_mode->setDisabled(1);
354 | actionNormalmode->setEnabled(1);
355 | });
356 |
357 | actionNormalmode = new QAction(QIcon(":/icons/document_edit.svg"),
358 | tr("Normal mode"), this);
359 | actionNormalmode->setToolTip(tr("Switch to normal mode"));
360 | connect(actionNormalmode, &QAction::triggered, [&]() {
361 | normalMode(0);
362 | actionNormalmode->setDisabled(1);
363 | actionSticky_note_mode->setEnabled(1);
364 | });
365 |
366 | actionPin_to_top =
367 | new QAction(QIcon(":/icons/pin.svg"), tr("Pin to top"), this);
368 | connect(actionPin_to_top, &QAction::triggered, [&]() {
369 | Qt::WindowFlags flags = this->windowFlags();
370 | if (!isPintotop) {
371 | this->setWindowFlags(flags | Qt::CustomizeWindowHint |
372 | Qt::WindowStaysOnTopHint);
373 | this->show();
374 | } else {
375 | this->setWindowFlags(
376 | flags ^ (Qt::CustomizeWindowHint | Qt::WindowStaysOnTopHint));
377 | this->show();
378 | }
379 | isPintotop = !isPintotop;
380 | });
381 |
382 | actionPreview_panel =
383 | new QAction(QIcon(":/icons/preview.svg"), tr("Preview panel"), this);
384 | actionPreview_panel->setCheckable(true);
385 | connect(actionPreview_panel, &QAction::triggered, [&]() {
386 | previewPanel->setEnabled(1);
387 | DockWidget->setVisible(!DockWidget->isVisible());
388 | });
389 |
390 | actionAbout = new QAction(QIcon(":/icons/info.svg"), tr("&About"), this);
391 | connect(actionAbout, &QAction::triggered,
392 | [&]() { AboutWindow(this).exec(); });
393 |
394 | actionAboutQt = new QAction(tr("&About Qt"), this);
395 | connect(actionAboutQt, &QAction::triggered, this, &QApplication::aboutQt);
396 |
397 | actionReadOnlyMode =
398 | new QAction(QIcon(":/icons/read_only.svg"), tr("Read-Only mode"), this);
399 | actionReadOnlyMode->setCheckable(true);
400 | actionReadOnlyMode->setChecked(0);
401 |
402 | menuFile = menuBar()->addMenu(tr("&File"));
403 | menuFile->addAction(actionNew);
404 | menuFile->addAction(actionOpen);
405 | menuFile->addAction(actionSave);
406 | menuFile->addAction(actionSave_As);
407 | menuFile->addSeparator();
408 | menuFile->addAction(actionPreferences);
409 | menuFile->addSeparator();
410 | menuFile->addAction(actionPrint);
411 | menuFile->addSeparator();
412 | menuFile->addAction(actionQuit);
413 |
414 | menuEdit = menuBar()->addMenu(tr("&Edit"));
415 | menuEdit->addAction(actionUndo);
416 | menuEdit->addAction(actionRedo);
417 | menuEdit->addSeparator();
418 | menuEdit->addAction(actionCopy);
419 | menuEdit->addAction(actionPaste);
420 | menuEdit->addAction(actionCut);
421 | menuEdit->addSeparator();
422 | menuEdit->addAction(actionReadOnlyMode);
423 |
424 | menuView = menuBar()->addMenu(tr("&View"));
425 | menuView->addAction(actionNormalmode);
426 | menuView->addAction(actionSticky_note_mode);
427 | menuView->addSeparator();
428 | menuView->addAction(actionPin_to_top);
429 | menuView->addSeparator();
430 | menuView->addAction(actionPreview_panel);
431 |
432 | menuHelp = menuBar()->addMenu(tr("&Help"));
433 | menuHelp->addAction(actionAbout);
434 | menuHelp->addAction(actionAboutQt);
435 |
436 | menuBar()->addMenu(menuFile);
437 | menuBar()->addMenu(menuEdit);
438 | menuBar()->addMenu(menuView);
439 | menuBar()->addMenu(menuHelp);
440 | }
441 |
442 | void MainWindow::closeEvent(QCloseEvent *event)
443 | {
444 | if (plainTextEdit->maybeSave()) {
445 | event->accept();
446 | } else {
447 | event->ignore();
448 | }
449 | }
450 |
451 | void MainWindow::changeWindowTitle()
452 | {
453 | QString showName;
454 | if (!plainTextEdit->currentFile.isEmpty())
455 | showName = plainTextEdit->currentFileName;
456 | else
457 | showName = "Untitled";
458 |
459 | for (int i = 0; i < tabData.size(); i++) {
460 | if (tabData[i].fileName.isEmpty())
461 | TabBar->setTabText(i, "Untitled");
462 | else
463 | TabBar->setTabText(i, tabData[i].fileName);
464 | }
465 | setWindowTitle(showName + "[*] - Notepanda");
466 | }
467 |
468 | void MainWindow::updateStatusBar()
469 | {
470 | if (currentMode != 1) {
471 | QString flags;
472 | if (plainTextEdit->isReadOnly() == 1) {
473 | flags += "[Read-Only]";
474 | }
475 |
476 | statusBar()->showMessage(
477 | tr("Characters:") +
478 | QString::number(plainTextEdit->document()->characterCount() - 1) +
479 | tr(" Lines:") +
480 | QString::number(plainTextEdit->document()->lineCount()) + flags);
481 | }
482 | }
483 |
484 | void MainWindow::normalMode(bool isFirst)
485 | {
486 | if (!isFirst) {
487 | resize(baseSize());
488 | plainTextEdit->switchMode(0);
489 | ToolBar->setVisible(1);
490 | SToolBar->setVisible(0);
491 | } else {
492 | ToolBar->addAction(actionNew);
493 | ToolBar->addAction(actionOpen);
494 | ToolBar->addAction(actionSave);
495 | ToolBar->addAction(actionSave_As);
496 | ToolBar->addAction(actionPreferences);
497 | ToolBar->addAction(actionUndo);
498 | ToolBar->addAction(actionRedo);
499 | ToolBar->addAction(actionQuit);
500 | ToolBar->addAction(actionAbout);
501 | ToolBar->addAction(actionSticky_note_mode);
502 | ToolBar->addAction(actionPreview_panel);
503 | actionNormalmode->setDisabled(1);
504 | }
505 | actionPreferences->setEnabled(1);
506 | currentMode = 0;
507 | }
508 |
509 | /**
510 | * @brief Sticky Note Mode, like Microsoft Sticky Notes. For more details, see
511 | *
512 | */
513 | void MainWindow::stickyNoteMode()
514 | {
515 | resize(baseSize() * 0.7);
516 | plainTextEdit->switchMode(1);
517 | plainTextEdit->setStyleSheet("background: " + currentColor.name());
518 | statusBar()->clearMessage();
519 | actionPreferences->setDisabled(1);
520 |
521 | ToolBar->setVisible(0);
522 | SToolBar->setVisible(1);
523 |
524 | currentMode = 1;
525 | }
526 |
527 | void MainWindow::documentWasModified()
528 | {
529 | setWindowModified(plainTextEdit->document()->isModified());
530 |
531 | if (previewPanel->isEnabled()) {
532 | previewPanel->reload();
533 |
534 | #if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
535 | const QString fileSuffix =
536 | plainTextEdit->currentFileName.split('.').last();
537 |
538 | if (fileSuffix == "md" || fileSuffix == "markdown" ||
539 | fileSuffix == "mdown")
540 | previewPanel->setMarkdown(plainTextEdit->toPlainText());
541 | else
542 | #endif
543 | previewPanel->setText(plainTextEdit->toPlainText());
544 | }
545 | }
546 |
547 | void MainWindow::saveTabData(const int index)
548 | {
549 | tabData[index].fileName = plainTextEdit->currentFileName;
550 | tabData[index].isModified = plainTextEdit->document()->isModified();
551 | tabData[index].plainText = plainTextEdit->toPlainText();
552 | }
553 |
--------------------------------------------------------------------------------
/src/ui/mainwindow.h:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2020 ChungZH. ALl Rights Reserved.
3 | * Licensed under the MIT license.
4 | * See file LICENSE for detail or copy at
5 | *
6 | * This file is a part of Notepanda.
7 | *
8 | * @file mainwindow.h
9 | * @brief This file declares the MainWindow class.
10 | * It is the main window of notepanda.
11 | *
12 | */
13 | #ifndef MAINWINDOW_H
14 | #define MAINWINDOW_H
15 |
16 | #include
17 | #include
18 | #include
19 | #include
20 | #include
21 | #include
22 | #include
23 | #include
24 | #include
25 | #include
26 | #include
27 |
28 | #include "../core/configmanager.h"
29 | #include "../core/texteditor.h"
30 | #include "preferenceswindow.h"
31 |
32 | QT_BEGIN_NAMESPACE
33 | class TextEditor;
34 | QT_END_NAMESPACE
35 |
36 | struct TabData
37 | {
38 | QString plainText;
39 | QString fileName;
40 | bool isModified;
41 | };
42 |
43 | class MainWindow : public QMainWindow
44 | {
45 | Q_OBJECT
46 |
47 | public:
48 | MainWindow(ConfigManager *confManager, QWidget *parent = nullptr);
49 | ~MainWindow();
50 | TextEditor *plainTextEdit;
51 |
52 | protected:
53 | void closeEvent(QCloseEvent *event) override;
54 |
55 | private slots:
56 | void changeWindowTitle();
57 | void updateStatusBar();
58 | void normalMode(bool isFirst);
59 | void stickyNoteMode();
60 | void documentWasModified();
61 |
62 | private:
63 | void setupUi();
64 |
65 | // TODO: use QTabBar::tabData
66 | QVector tabData;
67 |
68 | QToolBar *ToolBar;
69 | ConfigManager *configManager;
70 | PreferencesWindow *pfWindow;
71 | QTextBrowser *previewPanel;
72 | QDockWidget *DockWidget;
73 | QTabBar *TabBar;
74 | QToolBar *TabToolBar;
75 |
76 | bool lastTabRemoveFlag, doNotSaveDataFlag;
77 | int curTabIndex, prevTabIndex;
78 | void saveTabData(const int index);
79 |
80 | /**
81 | * @brief currentMode
82 | * 0: normal mode
83 | * 1: sticky mode
84 | */
85 | int currentMode;
86 | bool isPintotop;
87 |
88 | // Sticky note mode
89 |
90 | QToolBar *SToolBar;
91 | QAction *changeBgColor;
92 | QColorDialog *ColorDialog;
93 | QColor currentColor;
94 |
95 | // SNM end
96 |
97 | // UI start
98 | QAction *actionNew;
99 | QAction *actionOpen;
100 | QAction *actionSave;
101 | QAction *actionSave_As;
102 | QAction *actionUndo;
103 | QAction *actionRedo;
104 | QAction *actionCopy;
105 | QAction *actionPaste;
106 | QAction *actionQuit;
107 | QAction *actionCut;
108 | QAction *actionPrint;
109 | QAction *actionPreferences;
110 | QAction *actionSticky_note_mode;
111 | QAction *actionNormalmode;
112 | QAction *actionPin_to_top;
113 | QAction *actionPreview_panel;
114 | QAction *actionReadOnlyMode;
115 | QAction *actionAbout;
116 | QAction *actionAboutQt;
117 | QMenu *menuFile;
118 | QMenu *menuEdit;
119 | QMenu *menuView;
120 | QMenu *menuHelp;
121 | // UI end
122 | };
123 | #endif // MAINWINDOW_H
124 |
--------------------------------------------------------------------------------
/src/ui/preferenceswindow.cpp:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2020 ChungZH. ALl Rights Reserved.
3 | * Licensed under the MIT license.
4 | * See file LICENSE for detail or copy at
5 | *
6 | * This file is a part of Notepanda.
7 | *
8 | * @file preferenceswindow.cpp
9 | * @brief This file implements the PreferencesWindow class.
10 | * All persistent application settings should be in PreferencesWindow.
11 | *
12 | */
13 | #include "preferenceswindow.h"
14 |
15 | #include
16 | #include
17 | #include
18 | #include
19 |
20 | #include "../core/texteditor.h"
21 | #include "ui_preferenceswindow.h"
22 |
23 | PreferencesWindow::PreferencesWindow(ConfigManager *cfManager, QWidget *parent)
24 | : QDialog(parent), ui(new Ui::PreferencesWindow), configManager(cfManager)
25 | {
26 | ui->setupUi(this);
27 | setWindowTitle(tr("Preferences - Notepanda"));
28 |
29 | resetAllValues(1);
30 | }
31 |
32 | void PreferencesWindow::resetAllValues(const bool isFirst)
33 | {
34 | if (isFirst) {
35 | ui->themeCombo->addItems(QStyleFactory::keys());
36 |
37 | /*
38 | * Another implementation (better but harder) :
39 | for (const auto &theme : m_repository.themes()) addItem(...);
40 | * There is currently no plan to customize the theme of highlighting
41 | * So this implementation is temporarily used
42 | */
43 |
44 | ui->highlightThemeCombo->addItem("Breeze Dark");
45 | ui->highlightThemeCombo->addItem("Default");
46 | ui->highlightThemeCombo->addItem("Printing");
47 | ui->highlightThemeCombo->addItem("Solarized Dark");
48 | ui->highlightThemeCombo->addItem("Solarized Light");
49 | }
50 | ui->themeCombo->setCurrentText(configManager->getStyleTheme());
51 | ui->fontComboBox->setCurrentFont(
52 | QFont(configManager->getEditorFontFamily()));
53 | ui->spinBox->setValue(configManager->getEditorFontSize());
54 | ui->highlightThemeCombo->setCurrentText(
55 | configManager->getEditorColorTheme());
56 | }
57 |
--------------------------------------------------------------------------------
/src/ui/preferenceswindow.h:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2020 ChungZH. ALl Rights Reserved.
3 | * Licensed under the MIT license.
4 | * See file LICENSE for detail or copy at
5 | *
6 | * This file is a part of Notepanda.
7 | *
8 | * @file preferenceswindow.h
9 | * @brief This file declares the PreferencesWindow class.
10 | * All persistent application settings should be in PreferencesWindow.
11 | *
12 | */
13 | #ifndef PREFERENCESWINDOW_H
14 | #define PREFERENCESWINDOW_H
15 |
16 | #include
17 | #include
18 | #include
19 |
20 | #include "../core/configmanager.h"
21 | #include "../core/texteditor.h"
22 | #include "ui_preferenceswindow.h"
23 |
24 | class PreferencesWindow : public QDialog, public Ui::PreferencesWindow
25 | {
26 | Q_OBJECT
27 | public:
28 | PreferencesWindow(ConfigManager *cfManager, QWidget *parent = nullptr);
29 | void resetAllValues(const bool isFirst);
30 | Ui::PreferencesWindow *ui;
31 |
32 | private:
33 | ConfigManager *configManager;
34 | };
35 |
36 | #endif // PREFERENCESWINDOW_H
37 |
--------------------------------------------------------------------------------
/src/ui/preferenceswindow.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | PreferencesWindow
4 |
5 |
6 |
7 | 0
8 | 0
9 | 678
10 | 335
11 |
12 |
13 |
14 | Dialog
15 |
16 |
17 | -
18 |
19 |
20 | Qt::Horizontal
21 |
22 |
23 | QDialogButtonBox::Cancel|QDialogButtonBox::Ok
24 |
25 |
26 |
27 | -
28 |
29 |
30 | 0
31 |
32 |
33 |
34 | General Settings
35 |
36 |
37 |
38 |
39 | 10
40 | 10
41 | 169
42 | 129
43 |
44 |
45 |
46 |
-
47 |
48 |
49 | Appearance
50 |
51 |
52 |
-
53 |
54 |
-
55 |
56 |
-
57 |
58 |
59 |
60 | 61
61 | 76
62 |
63 |
64 |
65 | UI Theme
66 |
67 |
68 |
69 | -
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 | Editor Settings
85 |
86 |
87 |
88 |
89 | 10
90 | 10
91 | 580
92 | 129
93 |
94 |
95 |
96 | -
97 |
98 |
99 | Font and Color
100 |
101 |
102 |
-
103 |
104 |
-
105 |
106 |
107 | 6
108 |
109 |
-
110 |
111 |
112 | Font Family
113 |
114 |
115 |
116 | -
117 |
118 |
119 |
120 | 144
121 | 16777215
122 |
123 |
124 |
125 |
126 |
127 |
128 | -
129 |
130 |
-
131 |
132 |
133 |
134 | 110
135 | 0
136 |
137 |
138 |
139 | Font Size
140 |
141 |
142 |
143 | -
144 |
145 |
146 |
147 |
148 | -
149 |
150 |
151 | 6
152 |
153 |
-
154 |
155 |
156 |
157 | 78
158 | 76
159 |
160 |
161 |
162 | Theme
163 |
164 |
165 |
166 | -
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 | buttonBox
187 | accepted()
188 | PreferencesWindow
189 | accept()
190 |
191 |
192 | 248
193 | 254
194 |
195 |
196 | 157
197 | 274
198 |
199 |
200 |
201 |
202 | buttonBox
203 | rejected()
204 | PreferencesWindow
205 | reject()
206 |
207 |
208 | 316
209 | 260
210 |
211 |
212 | 286
213 | 274
214 |
215 |
216 |
217 |
218 |
219 |
--------------------------------------------------------------------------------