From 91828a1c4069e63ee449609f9bfbda5100165f78 Mon Sep 17 00:00:00 2001 From: Sunyuxuan <3107278279@qq.com> Date: Wed, 20 Nov 2024 22:56:46 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=94=B9=E6=BA=90=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E4=B8=BANotes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source/.clang-format | 108 + source/.clang-tidy | 28 + source/.cmake-format | 241 + source/.github/FUNDING.yml | 13 + source/.github/workflows/ci.yml | 37 + source/.github/workflows/format-lint.yml | 31 + source/.github/workflows/linux.yml | 391 ++ source/.github/workflows/macos.yml | 228 + source/.github/workflows/windows.yml | 248 + source/.gitignore | 46 +- source/.gitmodules | 9 + source/3rdParty/qxt/.gitattributes | 2 + source/3rdParty/qxt/AUTHORS | 27 + source/3rdParty/qxt/COPYING | 30 + source/3rdParty/qxt/qxt.pri | 26 + source/3rdParty/qxt/qxtglobal.cpp | 251 + source/3rdParty/qxt/qxtglobal.h | 233 + source/3rdParty/qxt/qxtglobalshortcut.cpp | 234 + source/3rdParty/qxt/qxtglobalshortcut.h | 66 + source/3rdParty/qxt/qxtglobalshortcut_mac.cpp | 274 ++ source/3rdParty/qxt/qxtglobalshortcut_p.h | 83 + source/3rdParty/qxt/qxtglobalshortcut_win.cpp | 212 + source/3rdParty/qxt/qxtglobalshortcut_x11.cpp | 230 + source/AndroidManifest.xml | 150 - source/CMakeLists.txt | 543 +++ source/Dockerfiles/README.md | 17 + source/Dockerfiles/fedora | 5 + source/Dockerfiles/opensuse | 5 + source/Dockerfiles/ubuntu-20_04 | 10 + source/Dockerfiles/ubuntu-22_04 | 10 + source/Dockerfiles/ubuntu-23_10 | 10 + source/Dockerfiles/ubuntu-aqtinstall-5 | 37 + source/Dockerfiles/ubuntu-aqtinstall-6 | 40 + source/LICENSE | 373 ++ source/NOTICE | 190 - source/README | 23 - source/README.md | 103 + source/UPDATES.json | 22 + source/docs/build_on_linux.md | 75 + source/docs/build_on_macos.md | 58 + source/docs/build_on_windows.md | 86 + source/docs/build_options.md | 33 + source/docs/keyboard_shortcuts.md | 52 + source/notes_purchase_data.json | 7 + .../linux/common/icons/128x128/notes.png | Bin 0 -> 12450 bytes .../linux/common/icons/256x256/notes.png | Bin 0 -> 32653 bytes .../linux/common/icons/512x512/notes.png | Bin 0 -> 90911 bytes .../linux/common/notes.appdata.xml.in | 139 + .../packaging/linux/common/notes.desktop.in | 9 + source/packaging/linux/debian/changelog.in | 72 + source/packaging/linux/debian/copyright.in | 17 + source/packaging/linux/make_snap.sh | 41 + source/packaging/linux/package.sh | 13 + source/packaging/macos/dmg-background.png | Bin 0 -> 914 bytes .../windows/Notes_Inno_Script_Github.iss | 237 + source/res/color/primary_text_dark.xml | 22 - source/res/color/secondary_text_dark.xml | 20 - source/res/drawable-hdpi/bg_btn_set_color.png | Bin 3588 -> 0 bytes .../res/drawable-hdpi/bg_color_btn_mask.png | Bin 245 -> 0 bytes source/res/drawable-hdpi/call_record.png | Bin 3533 -> 0 bytes source/res/drawable-hdpi/clock.png | Bin 3958 -> 0 bytes source/res/drawable-hdpi/delete.png | Bin 3490 -> 0 bytes source/res/drawable-hdpi/dropdown_icon.9.png | Bin 443 -> 0 bytes source/res/drawable-hdpi/edit_blue.9.png | Bin 3524 -> 0 bytes source/res/drawable-hdpi/edit_green.9.png | Bin 3565 -> 0 bytes source/res/drawable-hdpi/edit_red.9.png | Bin 3458 -> 0 bytes .../res/drawable-hdpi/edit_title_blue.9.png | Bin 5100 -> 0 bytes .../res/drawable-hdpi/edit_title_green.9.png | Bin 5627 -> 0 bytes source/res/drawable-hdpi/edit_title_red.9.png | Bin 5061 -> 0 bytes .../res/drawable-hdpi/edit_title_white.9.png | Bin 3866 -> 0 bytes .../res/drawable-hdpi/edit_title_yellow.9.png | Bin 6000 -> 0 bytes source/res/drawable-hdpi/edit_white.9.png | Bin 3441 -> 0 bytes source/res/drawable-hdpi/edit_yellow.9.png | Bin 3634 -> 0 bytes source/res/drawable-hdpi/font_large.png | Bin 3161 -> 0 bytes source/res/drawable-hdpi/font_normal.png | Bin 3097 -> 0 bytes .../drawable-hdpi/font_size_selector_bg.9.png | Bin 4101 -> 0 bytes source/res/drawable-hdpi/font_small.png | Bin 3099 -> 0 bytes source/res/drawable-hdpi/font_super.png | Bin 3188 -> 0 bytes source/res/drawable-hdpi/icon_app.png | Bin 6887 -> 0 bytes source/res/drawable-hdpi/list_background.png | Bin 567323 -> 0 bytes source/res/drawable-hdpi/list_blue_down.9.png | Bin 4361 -> 0 bytes .../res/drawable-hdpi/list_blue_middle.9.png | Bin 3099 -> 0 bytes .../res/drawable-hdpi/list_blue_single.9.png | Bin 4618 -> 0 bytes source/res/drawable-hdpi/list_blue_up.9.png | Bin 3301 -> 0 bytes source/res/drawable-hdpi/list_folder.9.png | Bin 5608 -> 0 bytes source/res/drawable-hdpi/list_footer_bg.9.png | Bin 2837 -> 0 bytes .../res/drawable-hdpi/list_green_down.9.png | Bin 4488 -> 0 bytes .../res/drawable-hdpi/list_green_middle.9.png | Bin 3179 -> 0 bytes .../res/drawable-hdpi/list_green_single.9.png | Bin 4728 -> 0 bytes source/res/drawable-hdpi/list_green_up.9.png | Bin 3351 -> 0 bytes source/res/drawable-hdpi/list_red_down.9.png | Bin 4307 -> 0 bytes .../res/drawable-hdpi/list_red_middle.9.png | Bin 3075 -> 0 bytes .../res/drawable-hdpi/list_red_single.9.png | Bin 4565 -> 0 bytes source/res/drawable-hdpi/list_red_up.9.png | Bin 3277 -> 0 bytes .../res/drawable-hdpi/list_white_down.9.png | Bin 4305 -> 0 bytes .../res/drawable-hdpi/list_white_middle.9.png | Bin 3042 -> 0 bytes .../res/drawable-hdpi/list_white_single.9.png | Bin 4546 -> 0 bytes source/res/drawable-hdpi/list_white_up.9.png | Bin 3220 -> 0 bytes .../res/drawable-hdpi/list_yellow_down.9.png | Bin 4420 -> 0 bytes .../drawable-hdpi/list_yellow_middle.9.png | Bin 3150 -> 0 bytes .../drawable-hdpi/list_yellow_single.9.png | Bin 4670 -> 0 bytes source/res/drawable-hdpi/list_yellow_up.9.png | Bin 3335 -> 0 bytes source/res/drawable-hdpi/menu_delete.png | Bin 3426 -> 0 bytes source/res/drawable-hdpi/menu_move.png | Bin 3294 -> 0 bytes source/res/drawable-hdpi/new_note_normal.png | Bin 89221 -> 0 bytes source/res/drawable-hdpi/new_note_pressed.png | Bin 90126 -> 0 bytes .../note_edit_color_selector_panel.png | Bin 7030 -> 0 bytes source/res/drawable-hdpi/notification.png | Bin 3107 -> 0 bytes source/res/drawable-hdpi/search_result.png | Bin 3030 -> 0 bytes source/res/drawable-hdpi/selected.png | Bin 4959 -> 0 bytes source/res/drawable-hdpi/title_alert.png | Bin 3696 -> 0 bytes source/res/drawable-hdpi/title_bar_bg.9.png | Bin 5970 -> 0 bytes source/res/drawable-hdpi/widget_2x_blue.png | Bin 1946 -> 0 bytes source/res/drawable-hdpi/widget_2x_green.png | Bin 1954 -> 0 bytes source/res/drawable-hdpi/widget_2x_red.png | Bin 1892 -> 0 bytes source/res/drawable-hdpi/widget_2x_white.png | Bin 1901 -> 0 bytes source/res/drawable-hdpi/widget_2x_yellow.png | Bin 1978 -> 0 bytes source/res/drawable-hdpi/widget_4x_blue.png | Bin 4165 -> 0 bytes source/res/drawable-hdpi/widget_4x_green.png | Bin 4192 -> 0 bytes source/res/drawable-hdpi/widget_4x_red.png | Bin 4223 -> 0 bytes source/res/drawable-hdpi/widget_4x_white.png | Bin 4106 -> 0 bytes source/res/drawable-hdpi/widget_4x_yellow.png | Bin 4199 -> 0 bytes source/res/drawable/new_note.xml | 23 - source/res/layout/account_dialog_title.xml | 43 - source/res/layout/add_account_text.xml | 32 - source/res/layout/datetime_picker.xml | 56 - source/res/layout/dialog_edit_text.xml | 23 - source/res/layout/folder_list_item.xml | 29 - source/res/layout/note_edit.xml | 400 -- source/res/layout/note_edit_list_item.xml | 39 - source/res/layout/note_item.xml | 78 - source/res/layout/note_list.xml | 58 - source/res/layout/note_list_dropdown_menu.xml | 32 - source/res/layout/note_list_footer.xml | 24 - source/res/layout/settings_header.xml | 41 - source/res/layout/widget_2x.xml | 37 - source/res/layout/widget_4x.xml | 39 - source/res/menu/call_note_edit.xml | 48 - source/res/menu/call_record_folder.xml | 23 - source/res/menu/note_edit.xml | 52 - source/res/menu/note_list.xml | 39 - source/res/menu/note_list_dropdown.xml | 20 - source/res/menu/note_list_options.xml | 31 - source/res/menu/sub_folder.xml | 24 - source/res/raw-zh-rCN/introduction | 7 - source/res/raw/introduction | 1 - source/res/values-zh-rCN/arrays.xml | 23 - source/res/values-zh-rCN/strings.xml | 126 - source/res/values-zh-rTW/arrays.xml | 23 - source/res/values-zh-rTW/strings.xml | 127 - source/res/values/arrays.xml | 31 - source/res/values/colors.xml | 20 - source/res/values/dimens.xml | 24 - source/res/values/strings.xml | 135 - source/res/values/styles.xml | 69 - source/res/xml/preferences.xml | 30 - source/res/xml/searchable.xml | 27 - source/res/xml/widget_2x_info.xml | 23 - source/res/xml/widget_4x_info.xml | 23 - source/snap/snapcraft.yaml | 152 + source/src/aboutwindow.cpp | 102 + source/src/aboutwindow.h | 34 + source/src/aboutwindow.ui | 56 + .../src/allnotebuttontreedelegateeditor.cpp | 129 + source/src/allnotebuttontreedelegateeditor.h | 43 + source/src/customDocument.h | 36 + source/src/customMarkdownHighlighter.cpp | 77 + source/src/customMarkdownHighlighter.h | 18 + source/src/customapplicationstyle.cpp | 35 + source/src/customapplicationstyle.h | 20 + source/src/customdocument.cpp | 373 ++ source/src/dbmanager.cpp | 2371 +++++++++ source/src/dbmanager.h | 117 + .../src/defaultnotefolderdelegateeditor.cpp | 135 + source/src/defaultnotefolderdelegateeditor.h | 43 + source/src/editorsettingsoptions.cpp | 70 + source/src/editorsettingsoptions.h | 33 + source/src/elidedlabel.cpp | 52 + source/src/elidedlabel.h | 28 + source/src/foldertreedelegateeditor.cpp | 251 + source/src/foldertreedelegateeditor.h | 52 + source/src/fontloader.cpp | 14 + source/src/fontloader.h | 26 + source/src/fonts.qrc | 42 + .../fontawesome/fa-brands-400-original.ttf | Bin 0 -> 187208 bytes .../src/fonts/fontawesome/fa-brands-400.ttf | Bin 0 -> 2164 bytes .../fontawesome/fa-regular-400-original.ttf | Bin 0 -> 63952 bytes .../src/fonts/fontawesome/fa-regular-400.ttf | Bin 0 -> 1480 bytes .../fontawesome/fa-solid-900-original.ttf | Bin 0 -> 394628 bytes source/src/fonts/fontawesome/fa-solid-900.ttf | Bin 0 -> 3732 bytes source/src/fonts/iaduo/LICENSE.txt | 100 + source/src/fonts/iaduo/iAWriterDuoS-Bold.ttf | Bin 0 -> 121460 bytes .../fonts/iaduo/iAWriterDuoS-BoldItalic.ttf | Bin 0 -> 105252 bytes .../src/fonts/iaduo/iAWriterDuoS-Italic.ttf | Bin 0 -> 105824 bytes .../src/fonts/iaduo/iAWriterDuoS-Regular.ttf | Bin 0 -> 120696 bytes source/src/fonts/iamono/LICENSE.txt | 100 + .../src/fonts/iamono/iAWriterMonoS-Bold.ttf | Bin 0 -> 96168 bytes .../fonts/iamono/iAWriterMonoS-BoldItalic.ttf | Bin 0 -> 103400 bytes .../src/fonts/iamono/iAWriterMonoS-Italic.ttf | Bin 0 -> 104120 bytes .../fonts/iamono/iAWriterMonoS-Regular.ttf | Bin 0 -> 97044 bytes source/src/fonts/iaquattro/LICENSE.txt | 100 + .../fonts/iaquattro/iAWriterQuattroS-Bold.ttf | Bin 0 -> 120404 bytes .../iaquattro/iAWriterQuattroS-BoldItalic.ttf | Bin 0 -> 104520 bytes .../iaquattro/iAWriterQuattroS-Italic.ttf | Bin 0 -> 105028 bytes .../iaquattro/iAWriterQuattroS-Regular.ttf | Bin 0 -> 119772 bytes source/src/fonts/mate/Mate-Italic.ttf | Bin 0 -> 25772 bytes source/src/fonts/mate/Mate-Regular.ttf | Bin 0 -> 26240 bytes .../material-symbols-outlined-original.ttf | Bin 0 -> 7538576 bytes .../material/material-symbols-outlined.ttf | Bin 0 -> 9252 bytes source/src/fonts/ptserif/PTSerif-Bold.ttf | Bin 0 -> 195776 bytes .../src/fonts/ptserif/PTSerif-BoldItalic.ttf | Bin 0 -> 193272 bytes source/src/fonts/ptserif/PTSerif-Italic.ttf | Bin 0 -> 231828 bytes source/src/fonts/ptserif/PTSerif-Regular.ttf | Bin 0 -> 215096 bytes .../src/fonts/roboto-hinted/Roboto-Black.ttf | Bin 0 -> 533852 bytes .../roboto-hinted/Roboto-BlackItalic.ttf | Bin 0 -> 551496 bytes .../src/fonts/roboto-hinted/Roboto-Bold.ttf | Bin 0 -> 539952 bytes .../fonts/roboto-hinted/Roboto-BoldItalic.ttf | Bin 0 -> 558388 bytes .../src/fonts/roboto-hinted/Roboto-Italic.ttf | Bin 0 -> 558572 bytes .../src/fonts/roboto-hinted/Roboto-Light.ttf | Bin 0 -> 543992 bytes .../roboto-hinted/Roboto-LightItalic.ttf | Bin 0 -> 564648 bytes .../src/fonts/roboto-hinted/Roboto-Medium.ttf | Bin 0 -> 537252 bytes .../roboto-hinted/Roboto-MediumItalic.ttf | Bin 0 -> 559404 bytes .../fonts/roboto-hinted/Roboto-Regular.ttf | Bin 0 -> 540224 bytes .../src/fonts/roboto-hinted/Roboto-Thin.ttf | Bin 0 -> 543060 bytes .../fonts/roboto-hinted/Roboto-ThinItalic.ttf | Bin 0 -> 559056 bytes .../sourcesanspro/SourceSansPro-Black.ttf | Bin 0 -> 265612 bytes .../SourceSansPro-BlackItalic.ttf | Bin 0 -> 93924 bytes .../sourcesanspro/SourceSansPro-Bold.ttf | Bin 0 -> 267388 bytes .../SourceSansPro-BoldItalic.ttf | Bin 0 -> 94132 bytes .../SourceSansPro-ExtraLight.ttf | Bin 0 -> 267368 bytes .../SourceSansPro-ExtraLightItalic.ttf | Bin 0 -> 95256 bytes .../sourcesanspro/SourceSansPro-Italic.ttf | Bin 0 -> 94816 bytes .../sourcesanspro/SourceSansPro-Light.ttf | Bin 0 -> 268588 bytes .../SourceSansPro-LightItalic.ttf | Bin 0 -> 95128 bytes .../sourcesanspro/SourceSansPro-Regular.ttf | Bin 0 -> 269108 bytes .../sourcesanspro/SourceSansPro-SemiBold.ttf | Bin 0 -> 268280 bytes .../SourceSansPro-SemiBoldItalic.ttf | Bin 0 -> 94512 bytes source/src/fonts/trykker/Trykker-Regular.ttf | Bin 0 -> 36292 bytes source/src/framelesswindow.cpp | 295 ++ source/src/framelesswindow.h | 180 + source/src/framelesswindow.mm | 366 ++ source/src/images.qrc | 36 + source/src/images/confetti.png | Bin 0 -> 2696 bytes source/src/images/folder.png | Bin 0 -> 3773 bytes source/src/images/green.png | Bin 0 -> 405 bytes source/src/images/greenHovered.png | Bin 0 -> 457 bytes source/src/images/greenInHovered.png | Bin 0 -> 449 bytes source/src/images/greenInPressed.png | Bin 0 -> 454 bytes source/src/images/greenPressed.png | Bin 0 -> 443 bytes source/src/images/notepad.icns | Bin 0 -> 34751 bytes source/src/images/notepad.ico | Bin 0 -> 117789 bytes source/src/images/notes.rc | 1 + source/src/images/notes_icon.icns | Bin 0 -> 570077 bytes source/src/images/notes_icon.ico | Bin 0 -> 194292 bytes source/src/images/notes_system_tray_icon.png | Bin 0 -> 316400 bytes source/src/images/red.png | Bin 0 -> 389 bytes source/src/images/redHovered.png | Bin 0 -> 438 bytes source/src/images/redPressed.png | Bin 0 -> 459 bytes source/src/images/unfocusedButton.png | Bin 0 -> 308 bytes source/src/images/windows_close_hovered.png | Bin 0 -> 285 bytes source/src/images/windows_close_pressed.png | Bin 0 -> 353 bytes source/src/images/windows_close_regular.png | Bin 0 -> 324 bytes .../images/windows_de-maximize_hovered.png | Bin 0 -> 160 bytes .../images/windows_de-maximize_pressed.png | Bin 0 -> 158 bytes .../images/windows_de-maximize_regular.png | Bin 0 -> 128 bytes .../src/images/windows_maximize_hovered.png | Bin 0 -> 125 bytes .../src/images/windows_maximize_pressed.png | Bin 0 -> 125 bytes .../src/images/windows_maximize_regular.png | Bin 0 -> 105 bytes .../src/images/windows_minimize_hovered.png | Bin 0 -> 164 bytes .../src/images/windows_minimize_pressed.png | Bin 0 -> 164 bytes .../src/images/windows_minimize_regular.png | Bin 0 -> 87 bytes source/src/images/yellow.png | Bin 0 -> 345 bytes source/src/images/yellowHovered.png | Bin 0 -> 361 bytes source/src/images/yellowPressed.png | Bin 0 -> 414 bytes source/src/labeledittype.cpp | 35 + source/src/labeledittype.h | 27 + source/src/listviewlogic.cpp | 777 +++ source/src/listviewlogic.h | 98 + source/src/lqtutils_enum.h | 54 + source/src/main.cpp | 108 + source/src/mainwindow.cpp | 4242 +++++++++++++++++ source/src/mainwindow.h | 404 ++ source/src/mainwindow.ui | 1144 +++++ source/src/net/micode/notes/data/Contact.java | 73 - source/src/net/micode/notes/data/Notes.java | 279 -- .../notes/data/NotesDatabaseHelper.java | 362 -- .../net/micode/notes/data/NotesProvider.java | 305 -- .../net/micode/notes/gtask/data/MetaData.java | 82 - .../src/net/micode/notes/gtask/data/Node.java | 101 - .../net/micode/notes/gtask/data/SqlData.java | 189 - .../net/micode/notes/gtask/data/SqlNote.java | 505 -- .../src/net/micode/notes/gtask/data/Task.java | 351 -- .../net/micode/notes/gtask/data/TaskList.java | 343 -- .../exception/ActionFailureException.java | 33 - .../exception/NetworkFailureException.java | 33 - .../notes/gtask/remote/GTaskASyncTask.java | 123 - .../notes/gtask/remote/GTaskClient.java | 585 --- .../notes/gtask/remote/GTaskManager.java | 800 ---- .../notes/gtask/remote/GTaskSyncService.java | 128 - source/src/net/micode/notes/model/Note.java | 253 - .../net/micode/notes/model/WorkingNote.java | 368 -- .../net/micode/notes/tool/BackupUtils.java | 344 -- .../src/net/micode/notes/tool/DataUtils.java | 295 -- .../micode/notes/tool/GTaskStringUtils.java | 113 - .../net/micode/notes/tool/ResourceParser.java | 181 - .../micode/notes/ui/AlarmAlertActivity.java | 158 - .../micode/notes/ui/AlarmInitReceiver.java | 65 - .../net/micode/notes/ui/AlarmReceiver.java | 30 - .../net/micode/notes/ui/DateTimePicker.java | 485 -- .../micode/notes/ui/DateTimePickerDialog.java | 90 - .../src/net/micode/notes/ui/DropdownMenu.java | 61 - .../micode/notes/ui/FoldersListAdapter.java | 80 - .../net/micode/notes/ui/NoteEditActivity.java | 873 ---- .../src/net/micode/notes/ui/NoteEditText.java | 217 - .../src/net/micode/notes/ui/NoteItemData.java | 224 - .../micode/notes/ui/NotesListActivity.java | 954 ---- .../net/micode/notes/ui/NotesListAdapter.java | 184 - .../net/micode/notes/ui/NotesListItem.java | 122 - .../notes/ui/NotesPreferenceActivity.java | 388 -- .../notes/widget/NoteWidgetProvider.java | 132 - .../notes/widget/NoteWidgetProvider_2x.java | 47 - .../notes/widget/NoteWidgetProvider_4x.java | 46 - source/src/nodedata.cpp | 248 + source/src/nodedata.h | 112 + source/src/nodepath.cpp | 36 + source/src/nodepath.h | 27 + source/src/nodetreedelegate.cpp | 457 ++ source/src/nodetreedelegate.h | 63 + source/src/nodetreemodel.cpp | 903 ++++ source/src/nodetreemodel.h | 130 + source/src/nodetreeview.cpp | 622 +++ source/src/nodetreeview.h | 124 + source/src/nodetreeview_p.h | 15 + source/src/noteeditorlogic.cpp | 879 ++++ source/src/noteeditorlogic.h | 136 + source/src/notelistdelegate.cpp | 1065 +++++ source/src/notelistdelegate.h | 99 + source/src/notelistdelegateeditor.cpp | 665 +++ source/src/notelistdelegateeditor.h | 111 + source/src/notelistmodel.cpp | 636 +++ source/src/notelistmodel.h | 89 + source/src/notelistview.cpp | 929 ++++ source/src/notelistview.h | 126 + source/src/notelistview_p.h | 17 + source/src/pushbuttontype.cpp | 42 + source/src/pushbuttontype.h | 25 + source/src/qml.qrc | 25 + source/src/qml/CheckBoxMaterial.qml | 31 + source/src/qml/CustomHorizontalScrollBar.qml | 38 + source/src/qml/CustomTextArea.qml | 94 + source/src/qml/CustomTextField.qml | 83 + source/src/qml/CustomVerticalScrollBar.qml | 38 + source/src/qml/EditorSettings.qml | 951 ++++ source/src/qml/EditorSettingsQt512.qml | 945 ++++ source/src/qml/FontChooserButton.qml | 238 + source/src/qml/FontIconLoader.qml | 32 + source/src/qml/FontIconsCodes.qml | 30 + source/src/qml/IconButton.qml | 84 + source/src/qml/OptionItemButton.qml | 122 + source/src/qml/SubscriptionWindow.qml | 1832 +++++++ source/src/qml/SwitchButton.qml | 14 + source/src/qml/TextButton.qml | 122 + source/src/qml/ThemeChooserButton.qml | 124 + source/src/qml/TodoColumnDelegate.qml | 556 +++ source/src/qml/TodoTaskDelegate.qml | 799 ++++ source/src/qml/Utilities.js | 37 + source/src/qml/ViewChooserButton.qml | 293 ++ source/src/qml/kanbanMain.qml | 927 ++++ source/src/singleinstance.cpp | 20 + source/src/singleinstance.h | 25 + source/src/splitterstyle.cpp | 11 + source/src/splitterstyle.h | 17 + source/src/styles.qrc | 11 + source/src/styles/about-window.css | 14 + .../styles/components/custom-scrollbar.css | 38 + source/src/styles/main-window.css | 179 + source/src/styles/nodetreeview.css | 24 + source/src/styles/notelistview.css | 11 + source/src/styles/taglistview.css | 15 + source/src/styles/updater-window.css | 48 + source/src/tagdata.cpp | 56 + source/src/tagdata.h | 43 + source/src/taglistdelegate.cpp | 93 + source/src/taglistdelegate.h | 30 + source/src/taglistmodel.cpp | 79 + source/src/taglistmodel.h | 29 + source/src/taglistview.cpp | 86 + source/src/taglistview.h | 28 + source/src/tagpool.cpp | 67 + source/src/tagpool.h | 37 + source/src/tagtreedelegateeditor.cpp | 206 + source/src/tagtreedelegateeditor.h | 47 + source/src/trashbuttondelegateeditor.cpp | 127 + source/src/trashbuttondelegateeditor.h | 43 + source/src/treeviewlogic.cpp | 410 ++ source/src/treeviewlogic.h | 63 + source/src/updaterwindow.cpp | 601 +++ source/src/updaterwindow.h | 82 + source/src/updaterwindow.ui | 531 +++ source/tests/main.cpp | 16 + source/tests/tests.pro | 34 + source/tests/tst_mainwindow.cpp | 17 + source/tests/tst_mainwindow.h | 21 + source/tests/tst_notedata.cpp | 16 + source/tests/tst_notedata.h | 20 + source/tests/tst_notemodel.cpp | 16 + source/tests/tst_notemodel.h | 18 + source/tests/tst_noteview.cpp | 16 + source/tests/tst_noteview.h | 17 + 409 files changed, 35663 insertions(+), 12295 deletions(-) create mode 100644 source/.clang-format create mode 100644 source/.clang-tidy create mode 100644 source/.cmake-format create mode 100644 source/.github/FUNDING.yml create mode 100644 source/.github/workflows/ci.yml create mode 100644 source/.github/workflows/format-lint.yml create mode 100644 source/.github/workflows/linux.yml create mode 100644 source/.github/workflows/macos.yml create mode 100644 source/.github/workflows/windows.yml create mode 100644 source/.gitmodules create mode 100644 source/3rdParty/qxt/.gitattributes create mode 100644 source/3rdParty/qxt/AUTHORS create mode 100644 source/3rdParty/qxt/COPYING create mode 100644 source/3rdParty/qxt/qxt.pri create mode 100644 source/3rdParty/qxt/qxtglobal.cpp create mode 100644 source/3rdParty/qxt/qxtglobal.h create mode 100644 source/3rdParty/qxt/qxtglobalshortcut.cpp create mode 100644 source/3rdParty/qxt/qxtglobalshortcut.h create mode 100644 source/3rdParty/qxt/qxtglobalshortcut_mac.cpp create mode 100644 source/3rdParty/qxt/qxtglobalshortcut_p.h create mode 100644 source/3rdParty/qxt/qxtglobalshortcut_win.cpp create mode 100644 source/3rdParty/qxt/qxtglobalshortcut_x11.cpp delete mode 100644 source/AndroidManifest.xml create mode 100644 source/CMakeLists.txt create mode 100644 source/Dockerfiles/README.md create mode 100644 source/Dockerfiles/fedora create mode 100644 source/Dockerfiles/opensuse create mode 100644 source/Dockerfiles/ubuntu-20_04 create mode 100644 source/Dockerfiles/ubuntu-22_04 create mode 100644 source/Dockerfiles/ubuntu-23_10 create mode 100644 source/Dockerfiles/ubuntu-aqtinstall-5 create mode 100644 source/Dockerfiles/ubuntu-aqtinstall-6 create mode 100644 source/LICENSE delete mode 100644 source/NOTICE delete mode 100644 source/README create mode 100644 source/README.md create mode 100644 source/UPDATES.json create mode 100644 source/docs/build_on_linux.md create mode 100644 source/docs/build_on_macos.md create mode 100644 source/docs/build_on_windows.md create mode 100644 source/docs/build_options.md create mode 100644 source/docs/keyboard_shortcuts.md create mode 100644 source/notes_purchase_data.json create mode 100644 source/packaging/linux/common/icons/128x128/notes.png create mode 100644 source/packaging/linux/common/icons/256x256/notes.png create mode 100644 source/packaging/linux/common/icons/512x512/notes.png create mode 100644 source/packaging/linux/common/notes.appdata.xml.in create mode 100644 source/packaging/linux/common/notes.desktop.in create mode 100644 source/packaging/linux/debian/changelog.in create mode 100644 source/packaging/linux/debian/copyright.in create mode 100644 source/packaging/linux/make_snap.sh create mode 100644 source/packaging/linux/package.sh create mode 100644 source/packaging/macos/dmg-background.png create mode 100644 source/packaging/windows/Notes_Inno_Script_Github.iss delete mode 100644 source/res/color/primary_text_dark.xml delete mode 100644 source/res/color/secondary_text_dark.xml delete mode 100644 source/res/drawable-hdpi/bg_btn_set_color.png delete mode 100644 source/res/drawable-hdpi/bg_color_btn_mask.png delete mode 100644 source/res/drawable-hdpi/call_record.png delete mode 100644 source/res/drawable-hdpi/clock.png delete mode 100644 source/res/drawable-hdpi/delete.png delete mode 100644 source/res/drawable-hdpi/dropdown_icon.9.png delete mode 100644 source/res/drawable-hdpi/edit_blue.9.png delete mode 100644 source/res/drawable-hdpi/edit_green.9.png delete mode 100644 source/res/drawable-hdpi/edit_red.9.png delete mode 100644 source/res/drawable-hdpi/edit_title_blue.9.png delete mode 100644 source/res/drawable-hdpi/edit_title_green.9.png delete mode 100644 source/res/drawable-hdpi/edit_title_red.9.png delete mode 100644 source/res/drawable-hdpi/edit_title_white.9.png delete mode 100644 source/res/drawable-hdpi/edit_title_yellow.9.png delete mode 100644 source/res/drawable-hdpi/edit_white.9.png delete mode 100644 source/res/drawable-hdpi/edit_yellow.9.png delete mode 100644 source/res/drawable-hdpi/font_large.png delete mode 100644 source/res/drawable-hdpi/font_normal.png delete mode 100644 source/res/drawable-hdpi/font_size_selector_bg.9.png delete mode 100644 source/res/drawable-hdpi/font_small.png delete mode 100644 source/res/drawable-hdpi/font_super.png delete mode 100644 source/res/drawable-hdpi/icon_app.png delete mode 100644 source/res/drawable-hdpi/list_background.png delete mode 100644 source/res/drawable-hdpi/list_blue_down.9.png delete mode 100644 source/res/drawable-hdpi/list_blue_middle.9.png delete mode 100644 source/res/drawable-hdpi/list_blue_single.9.png delete mode 100644 source/res/drawable-hdpi/list_blue_up.9.png delete mode 100644 source/res/drawable-hdpi/list_folder.9.png delete mode 100644 source/res/drawable-hdpi/list_footer_bg.9.png delete mode 100644 source/res/drawable-hdpi/list_green_down.9.png delete mode 100644 source/res/drawable-hdpi/list_green_middle.9.png delete mode 100644 source/res/drawable-hdpi/list_green_single.9.png delete mode 100644 source/res/drawable-hdpi/list_green_up.9.png delete mode 100644 source/res/drawable-hdpi/list_red_down.9.png delete mode 100644 source/res/drawable-hdpi/list_red_middle.9.png delete mode 100644 source/res/drawable-hdpi/list_red_single.9.png delete mode 100644 source/res/drawable-hdpi/list_red_up.9.png delete mode 100644 source/res/drawable-hdpi/list_white_down.9.png delete mode 100644 source/res/drawable-hdpi/list_white_middle.9.png delete mode 100644 source/res/drawable-hdpi/list_white_single.9.png delete mode 100644 source/res/drawable-hdpi/list_white_up.9.png delete mode 100644 source/res/drawable-hdpi/list_yellow_down.9.png delete mode 100644 source/res/drawable-hdpi/list_yellow_middle.9.png delete mode 100644 source/res/drawable-hdpi/list_yellow_single.9.png delete mode 100644 source/res/drawable-hdpi/list_yellow_up.9.png delete mode 100644 source/res/drawable-hdpi/menu_delete.png delete mode 100644 source/res/drawable-hdpi/menu_move.png delete mode 100644 source/res/drawable-hdpi/new_note_normal.png delete mode 100644 source/res/drawable-hdpi/new_note_pressed.png delete mode 100644 source/res/drawable-hdpi/note_edit_color_selector_panel.png delete mode 100644 source/res/drawable-hdpi/notification.png delete mode 100644 source/res/drawable-hdpi/search_result.png delete mode 100644 source/res/drawable-hdpi/selected.png delete mode 100644 source/res/drawable-hdpi/title_alert.png delete mode 100644 source/res/drawable-hdpi/title_bar_bg.9.png delete mode 100644 source/res/drawable-hdpi/widget_2x_blue.png delete mode 100644 source/res/drawable-hdpi/widget_2x_green.png delete mode 100644 source/res/drawable-hdpi/widget_2x_red.png delete mode 100644 source/res/drawable-hdpi/widget_2x_white.png delete mode 100644 source/res/drawable-hdpi/widget_2x_yellow.png delete mode 100644 source/res/drawable-hdpi/widget_4x_blue.png delete mode 100644 source/res/drawable-hdpi/widget_4x_green.png delete mode 100644 source/res/drawable-hdpi/widget_4x_red.png delete mode 100644 source/res/drawable-hdpi/widget_4x_white.png delete mode 100644 source/res/drawable-hdpi/widget_4x_yellow.png delete mode 100644 source/res/drawable/new_note.xml delete mode 100644 source/res/layout/account_dialog_title.xml delete mode 100644 source/res/layout/add_account_text.xml delete mode 100644 source/res/layout/datetime_picker.xml delete mode 100644 source/res/layout/dialog_edit_text.xml delete mode 100644 source/res/layout/folder_list_item.xml delete mode 100644 source/res/layout/note_edit.xml delete mode 100644 source/res/layout/note_edit_list_item.xml delete mode 100644 source/res/layout/note_item.xml delete mode 100644 source/res/layout/note_list.xml delete mode 100644 source/res/layout/note_list_dropdown_menu.xml delete mode 100644 source/res/layout/note_list_footer.xml delete mode 100644 source/res/layout/settings_header.xml delete mode 100644 source/res/layout/widget_2x.xml delete mode 100644 source/res/layout/widget_4x.xml delete mode 100644 source/res/menu/call_note_edit.xml delete mode 100644 source/res/menu/call_record_folder.xml delete mode 100644 source/res/menu/note_edit.xml delete mode 100644 source/res/menu/note_list.xml delete mode 100644 source/res/menu/note_list_dropdown.xml delete mode 100644 source/res/menu/note_list_options.xml delete mode 100644 source/res/menu/sub_folder.xml delete mode 100644 source/res/raw-zh-rCN/introduction delete mode 100644 source/res/raw/introduction delete mode 100644 source/res/values-zh-rCN/arrays.xml delete mode 100644 source/res/values-zh-rCN/strings.xml delete mode 100644 source/res/values-zh-rTW/arrays.xml delete mode 100644 source/res/values-zh-rTW/strings.xml delete mode 100644 source/res/values/arrays.xml delete mode 100644 source/res/values/colors.xml delete mode 100644 source/res/values/dimens.xml delete mode 100644 source/res/values/strings.xml delete mode 100644 source/res/values/styles.xml delete mode 100644 source/res/xml/preferences.xml delete mode 100644 source/res/xml/searchable.xml delete mode 100644 source/res/xml/widget_2x_info.xml delete mode 100644 source/res/xml/widget_4x_info.xml create mode 100644 source/snap/snapcraft.yaml create mode 100644 source/src/aboutwindow.cpp create mode 100644 source/src/aboutwindow.h create mode 100644 source/src/aboutwindow.ui create mode 100644 source/src/allnotebuttontreedelegateeditor.cpp create mode 100644 source/src/allnotebuttontreedelegateeditor.h create mode 100644 source/src/customDocument.h create mode 100644 source/src/customMarkdownHighlighter.cpp create mode 100644 source/src/customMarkdownHighlighter.h create mode 100644 source/src/customapplicationstyle.cpp create mode 100644 source/src/customapplicationstyle.h create mode 100644 source/src/customdocument.cpp create mode 100644 source/src/dbmanager.cpp create mode 100644 source/src/dbmanager.h create mode 100644 source/src/defaultnotefolderdelegateeditor.cpp create mode 100644 source/src/defaultnotefolderdelegateeditor.h create mode 100644 source/src/editorsettingsoptions.cpp create mode 100644 source/src/editorsettingsoptions.h create mode 100644 source/src/elidedlabel.cpp create mode 100644 source/src/elidedlabel.h create mode 100644 source/src/foldertreedelegateeditor.cpp create mode 100644 source/src/foldertreedelegateeditor.h create mode 100644 source/src/fontloader.cpp create mode 100644 source/src/fontloader.h create mode 100644 source/src/fonts.qrc create mode 100644 source/src/fonts/fontawesome/fa-brands-400-original.ttf create mode 100644 source/src/fonts/fontawesome/fa-brands-400.ttf create mode 100644 source/src/fonts/fontawesome/fa-regular-400-original.ttf create mode 100644 source/src/fonts/fontawesome/fa-regular-400.ttf create mode 100644 source/src/fonts/fontawesome/fa-solid-900-original.ttf create mode 100644 source/src/fonts/fontawesome/fa-solid-900.ttf create mode 100644 source/src/fonts/iaduo/LICENSE.txt create mode 100644 source/src/fonts/iaduo/iAWriterDuoS-Bold.ttf create mode 100644 source/src/fonts/iaduo/iAWriterDuoS-BoldItalic.ttf create mode 100644 source/src/fonts/iaduo/iAWriterDuoS-Italic.ttf create mode 100644 source/src/fonts/iaduo/iAWriterDuoS-Regular.ttf create mode 100644 source/src/fonts/iamono/LICENSE.txt create mode 100644 source/src/fonts/iamono/iAWriterMonoS-Bold.ttf create mode 100644 source/src/fonts/iamono/iAWriterMonoS-BoldItalic.ttf create mode 100644 source/src/fonts/iamono/iAWriterMonoS-Italic.ttf create mode 100644 source/src/fonts/iamono/iAWriterMonoS-Regular.ttf create mode 100644 source/src/fonts/iaquattro/LICENSE.txt create mode 100644 source/src/fonts/iaquattro/iAWriterQuattroS-Bold.ttf create mode 100644 source/src/fonts/iaquattro/iAWriterQuattroS-BoldItalic.ttf create mode 100644 source/src/fonts/iaquattro/iAWriterQuattroS-Italic.ttf create mode 100644 source/src/fonts/iaquattro/iAWriterQuattroS-Regular.ttf create mode 100644 source/src/fonts/mate/Mate-Italic.ttf create mode 100644 source/src/fonts/mate/Mate-Regular.ttf create mode 100644 source/src/fonts/material/material-symbols-outlined-original.ttf create mode 100644 source/src/fonts/material/material-symbols-outlined.ttf create mode 100644 source/src/fonts/ptserif/PTSerif-Bold.ttf create mode 100644 source/src/fonts/ptserif/PTSerif-BoldItalic.ttf create mode 100644 source/src/fonts/ptserif/PTSerif-Italic.ttf create mode 100644 source/src/fonts/ptserif/PTSerif-Regular.ttf create mode 100644 source/src/fonts/roboto-hinted/Roboto-Black.ttf create mode 100644 source/src/fonts/roboto-hinted/Roboto-BlackItalic.ttf create mode 100644 source/src/fonts/roboto-hinted/Roboto-Bold.ttf create mode 100644 source/src/fonts/roboto-hinted/Roboto-BoldItalic.ttf create mode 100644 source/src/fonts/roboto-hinted/Roboto-Italic.ttf create mode 100644 source/src/fonts/roboto-hinted/Roboto-Light.ttf create mode 100644 source/src/fonts/roboto-hinted/Roboto-LightItalic.ttf create mode 100644 source/src/fonts/roboto-hinted/Roboto-Medium.ttf create mode 100644 source/src/fonts/roboto-hinted/Roboto-MediumItalic.ttf create mode 100644 source/src/fonts/roboto-hinted/Roboto-Regular.ttf create mode 100644 source/src/fonts/roboto-hinted/Roboto-Thin.ttf create mode 100644 source/src/fonts/roboto-hinted/Roboto-ThinItalic.ttf create mode 100644 source/src/fonts/sourcesanspro/SourceSansPro-Black.ttf create mode 100644 source/src/fonts/sourcesanspro/SourceSansPro-BlackItalic.ttf create mode 100644 source/src/fonts/sourcesanspro/SourceSansPro-Bold.ttf create mode 100644 source/src/fonts/sourcesanspro/SourceSansPro-BoldItalic.ttf create mode 100644 source/src/fonts/sourcesanspro/SourceSansPro-ExtraLight.ttf create mode 100644 source/src/fonts/sourcesanspro/SourceSansPro-ExtraLightItalic.ttf create mode 100644 source/src/fonts/sourcesanspro/SourceSansPro-Italic.ttf create mode 100644 source/src/fonts/sourcesanspro/SourceSansPro-Light.ttf create mode 100644 source/src/fonts/sourcesanspro/SourceSansPro-LightItalic.ttf create mode 100644 source/src/fonts/sourcesanspro/SourceSansPro-Regular.ttf create mode 100644 source/src/fonts/sourcesanspro/SourceSansPro-SemiBold.ttf create mode 100644 source/src/fonts/sourcesanspro/SourceSansPro-SemiBoldItalic.ttf create mode 100644 source/src/fonts/trykker/Trykker-Regular.ttf create mode 100644 source/src/framelesswindow.cpp create mode 100644 source/src/framelesswindow.h create mode 100644 source/src/framelesswindow.mm create mode 100644 source/src/images.qrc create mode 100644 source/src/images/confetti.png create mode 100644 source/src/images/folder.png create mode 100644 source/src/images/green.png create mode 100644 source/src/images/greenHovered.png create mode 100644 source/src/images/greenInHovered.png create mode 100644 source/src/images/greenInPressed.png create mode 100644 source/src/images/greenPressed.png create mode 100644 source/src/images/notepad.icns create mode 100644 source/src/images/notepad.ico create mode 100644 source/src/images/notes.rc create mode 100644 source/src/images/notes_icon.icns create mode 100644 source/src/images/notes_icon.ico create mode 100644 source/src/images/notes_system_tray_icon.png create mode 100644 source/src/images/red.png create mode 100644 source/src/images/redHovered.png create mode 100644 source/src/images/redPressed.png create mode 100644 source/src/images/unfocusedButton.png create mode 100644 source/src/images/windows_close_hovered.png create mode 100644 source/src/images/windows_close_pressed.png create mode 100644 source/src/images/windows_close_regular.png create mode 100644 source/src/images/windows_de-maximize_hovered.png create mode 100644 source/src/images/windows_de-maximize_pressed.png create mode 100644 source/src/images/windows_de-maximize_regular.png create mode 100644 source/src/images/windows_maximize_hovered.png create mode 100644 source/src/images/windows_maximize_pressed.png create mode 100644 source/src/images/windows_maximize_regular.png create mode 100644 source/src/images/windows_minimize_hovered.png create mode 100644 source/src/images/windows_minimize_pressed.png create mode 100644 source/src/images/windows_minimize_regular.png create mode 100644 source/src/images/yellow.png create mode 100644 source/src/images/yellowHovered.png create mode 100644 source/src/images/yellowPressed.png create mode 100644 source/src/labeledittype.cpp create mode 100644 source/src/labeledittype.h create mode 100644 source/src/listviewlogic.cpp create mode 100644 source/src/listviewlogic.h create mode 100644 source/src/lqtutils_enum.h create mode 100644 source/src/main.cpp create mode 100644 source/src/mainwindow.cpp create mode 100644 source/src/mainwindow.h create mode 100644 source/src/mainwindow.ui delete mode 100644 source/src/net/micode/notes/data/Contact.java delete mode 100644 source/src/net/micode/notes/data/Notes.java delete mode 100644 source/src/net/micode/notes/data/NotesDatabaseHelper.java delete mode 100644 source/src/net/micode/notes/data/NotesProvider.java delete mode 100644 source/src/net/micode/notes/gtask/data/MetaData.java delete mode 100644 source/src/net/micode/notes/gtask/data/Node.java delete mode 100644 source/src/net/micode/notes/gtask/data/SqlData.java delete mode 100644 source/src/net/micode/notes/gtask/data/SqlNote.java delete mode 100644 source/src/net/micode/notes/gtask/data/Task.java delete mode 100644 source/src/net/micode/notes/gtask/data/TaskList.java delete mode 100644 source/src/net/micode/notes/gtask/exception/ActionFailureException.java delete mode 100644 source/src/net/micode/notes/gtask/exception/NetworkFailureException.java delete mode 100644 source/src/net/micode/notes/gtask/remote/GTaskASyncTask.java delete mode 100644 source/src/net/micode/notes/gtask/remote/GTaskClient.java delete mode 100644 source/src/net/micode/notes/gtask/remote/GTaskManager.java delete mode 100644 source/src/net/micode/notes/gtask/remote/GTaskSyncService.java delete mode 100644 source/src/net/micode/notes/model/Note.java delete mode 100644 source/src/net/micode/notes/model/WorkingNote.java delete mode 100644 source/src/net/micode/notes/tool/BackupUtils.java delete mode 100644 source/src/net/micode/notes/tool/DataUtils.java delete mode 100644 source/src/net/micode/notes/tool/GTaskStringUtils.java delete mode 100644 source/src/net/micode/notes/tool/ResourceParser.java delete mode 100644 source/src/net/micode/notes/ui/AlarmAlertActivity.java delete mode 100644 source/src/net/micode/notes/ui/AlarmInitReceiver.java delete mode 100644 source/src/net/micode/notes/ui/AlarmReceiver.java delete mode 100644 source/src/net/micode/notes/ui/DateTimePicker.java delete mode 100644 source/src/net/micode/notes/ui/DateTimePickerDialog.java delete mode 100644 source/src/net/micode/notes/ui/DropdownMenu.java delete mode 100644 source/src/net/micode/notes/ui/FoldersListAdapter.java delete mode 100644 source/src/net/micode/notes/ui/NoteEditActivity.java delete mode 100644 source/src/net/micode/notes/ui/NoteEditText.java delete mode 100644 source/src/net/micode/notes/ui/NoteItemData.java delete mode 100644 source/src/net/micode/notes/ui/NotesListActivity.java delete mode 100644 source/src/net/micode/notes/ui/NotesListAdapter.java delete mode 100644 source/src/net/micode/notes/ui/NotesListItem.java delete mode 100644 source/src/net/micode/notes/ui/NotesPreferenceActivity.java delete mode 100644 source/src/net/micode/notes/widget/NoteWidgetProvider.java delete mode 100644 source/src/net/micode/notes/widget/NoteWidgetProvider_2x.java delete mode 100644 source/src/net/micode/notes/widget/NoteWidgetProvider_4x.java create mode 100644 source/src/nodedata.cpp create mode 100644 source/src/nodedata.h create mode 100644 source/src/nodepath.cpp create mode 100644 source/src/nodepath.h create mode 100644 source/src/nodetreedelegate.cpp create mode 100644 source/src/nodetreedelegate.h create mode 100644 source/src/nodetreemodel.cpp create mode 100644 source/src/nodetreemodel.h create mode 100644 source/src/nodetreeview.cpp create mode 100644 source/src/nodetreeview.h create mode 100644 source/src/nodetreeview_p.h create mode 100644 source/src/noteeditorlogic.cpp create mode 100644 source/src/noteeditorlogic.h create mode 100644 source/src/notelistdelegate.cpp create mode 100644 source/src/notelistdelegate.h create mode 100644 source/src/notelistdelegateeditor.cpp create mode 100644 source/src/notelistdelegateeditor.h create mode 100644 source/src/notelistmodel.cpp create mode 100644 source/src/notelistmodel.h create mode 100644 source/src/notelistview.cpp create mode 100644 source/src/notelistview.h create mode 100644 source/src/notelistview_p.h create mode 100644 source/src/pushbuttontype.cpp create mode 100644 source/src/pushbuttontype.h create mode 100644 source/src/qml.qrc create mode 100644 source/src/qml/CheckBoxMaterial.qml create mode 100644 source/src/qml/CustomHorizontalScrollBar.qml create mode 100644 source/src/qml/CustomTextArea.qml create mode 100644 source/src/qml/CustomTextField.qml create mode 100644 source/src/qml/CustomVerticalScrollBar.qml create mode 100644 source/src/qml/EditorSettings.qml create mode 100644 source/src/qml/EditorSettingsQt512.qml create mode 100644 source/src/qml/FontChooserButton.qml create mode 100644 source/src/qml/FontIconLoader.qml create mode 100644 source/src/qml/FontIconsCodes.qml create mode 100644 source/src/qml/IconButton.qml create mode 100644 source/src/qml/OptionItemButton.qml create mode 100644 source/src/qml/SubscriptionWindow.qml create mode 100644 source/src/qml/SwitchButton.qml create mode 100644 source/src/qml/TextButton.qml create mode 100644 source/src/qml/ThemeChooserButton.qml create mode 100644 source/src/qml/TodoColumnDelegate.qml create mode 100644 source/src/qml/TodoTaskDelegate.qml create mode 100644 source/src/qml/Utilities.js create mode 100644 source/src/qml/ViewChooserButton.qml create mode 100644 source/src/qml/kanbanMain.qml create mode 100644 source/src/singleinstance.cpp create mode 100644 source/src/singleinstance.h create mode 100644 source/src/splitterstyle.cpp create mode 100644 source/src/splitterstyle.h create mode 100644 source/src/styles.qrc create mode 100644 source/src/styles/about-window.css create mode 100644 source/src/styles/components/custom-scrollbar.css create mode 100644 source/src/styles/main-window.css create mode 100644 source/src/styles/nodetreeview.css create mode 100644 source/src/styles/notelistview.css create mode 100644 source/src/styles/taglistview.css create mode 100644 source/src/styles/updater-window.css create mode 100644 source/src/tagdata.cpp create mode 100644 source/src/tagdata.h create mode 100644 source/src/taglistdelegate.cpp create mode 100644 source/src/taglistdelegate.h create mode 100644 source/src/taglistmodel.cpp create mode 100644 source/src/taglistmodel.h create mode 100644 source/src/taglistview.cpp create mode 100644 source/src/taglistview.h create mode 100644 source/src/tagpool.cpp create mode 100644 source/src/tagpool.h create mode 100644 source/src/tagtreedelegateeditor.cpp create mode 100644 source/src/tagtreedelegateeditor.h create mode 100644 source/src/trashbuttondelegateeditor.cpp create mode 100644 source/src/trashbuttondelegateeditor.h create mode 100644 source/src/treeviewlogic.cpp create mode 100644 source/src/treeviewlogic.h create mode 100644 source/src/updaterwindow.cpp create mode 100644 source/src/updaterwindow.h create mode 100644 source/src/updaterwindow.ui create mode 100644 source/tests/main.cpp create mode 100644 source/tests/tests.pro create mode 100644 source/tests/tst_mainwindow.cpp create mode 100644 source/tests/tst_mainwindow.h create mode 100644 source/tests/tst_notedata.cpp create mode 100644 source/tests/tst_notedata.h create mode 100644 source/tests/tst_notemodel.cpp create mode 100644 source/tests/tst_notemodel.h create mode 100644 source/tests/tst_noteview.cpp create mode 100644 source/tests/tst_noteview.h diff --git a/source/.clang-format b/source/.clang-format new file mode 100644 index 0000000..e7e30d2 --- /dev/null +++ b/source/.clang-format @@ -0,0 +1,108 @@ +# Copyright (C) 2016 Olivier Goffart +# +# You may use this file under the terms of the 3-clause BSD license. +# See the file LICENSE from this package for details. + +# This is the clang-format configuration style to be used by Qt, +# based on the rules from https://wiki.qt.io/Qt_Coding_Style and +# https://wiki.qt.io/Coding_Conventions + +--- +# Webkit style was loosely based on the Qt style +BasedOnStyle: WebKit + +Standard: c++14 + +# Column width is limited to 100 in accordance with Qt Coding Style. +# https://wiki.qt.io/Qt_Coding_Style +# Note that this may be changed at some point in the future. +ColumnLimit: 100 +# How much weight do extra characters after the line length limit have. +# PenaltyExcessCharacter: 4 + +# Disable reflow of some specific comments +# qdoc comments: indentation rules are different. +# Translation comments and SPDX license identifiers are also excluded. +CommentPragmas: "^!|^:|^ SPDX-License-Identifier:" + +# We want a space between the type and the star for pointer types. +PointerBindsToType: false + +# We use template< without space. +SpaceAfterTemplateKeyword: false + +# We want to break before the operators, but not before a '='. +BreakBeforeBinaryOperators: NonAssignment + +# Braces are usually attached, but not after functions or class declarations. +BreakBeforeBraces: Custom +BraceWrapping: + AfterClass: true + AfterControlStatement: false + AfterEnum: false + AfterFunction: true + AfterNamespace: false + AfterObjCDeclaration: false + AfterStruct: true + AfterUnion: false + BeforeCatch: false + BeforeElse: false + IndentBraces: false + +# When constructor initializers do not fit on one line, put them each on a new line. +ConstructorInitializerAllOnOneLineOrOnePerLine: true +# Indent initializers by 4 spaces +ConstructorInitializerIndentWidth: 4 + +# Indent width for line continuations. +ContinuationIndentWidth: 8 + +# No indentation for namespaces. +NamespaceIndentation: None + +# Allow indentation for preprocessing directives (if/ifdef/endif). https://reviews.llvm.org/rL312125 +IndentPPDirectives: AfterHash +# We only indent with 2 spaces for preprocessor directives +PPIndentWidth: 2 + +# Horizontally align arguments after an open bracket. +# The coding style does not specify the following, but this is what gives +# results closest to the existing code. +AlignAfterOpenBracket: true +AlwaysBreakTemplateDeclarations: true + +# Ideally we should also allow less short function in a single line, but +# clang-format does not handle that. +AllowShortFunctionsOnASingleLine: Inline + +# The coding style specifies some include order categories, but also tells to +# separate categories with an empty line. It does not specify the order within +# the categories. Since the SortInclude feature of clang-format does not +# re-order includes separated by empty lines, the feature is not used. +SortIncludes: false + +# macros for which the opening brace stays attached. +ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH, forever, Q_FOREVER, QBENCHMARK, QBENCHMARK_ONCE ] + +# Break constructor initializers before the colon and after the commas. +BreakConstructorInitializers: BeforeColon + +# Add "// namespace " comments on closing brace for a namespace +# Ignored for namespaces that qualify as a short namespace, +# see 'ShortNamespaceLines' +FixNamespaceComments: true + +# Definition of how short a short namespace is, default 1 +ShortNamespaceLines: 1 + +# When escaping newlines in a macro attach the '\' as far left as possible, e.g. +##define a \ +# something; \ +# other; \ +# thelastlineislong; +AlignEscapedNewlines: Left + +# Avoids the addition of a space between an identifier and the +# initializer list in list-initialization. +SpaceBeforeCpp11BracedList: false + diff --git a/source/.clang-tidy b/source/.clang-tidy new file mode 100644 index 0000000..04c3836 --- /dev/null +++ b/source/.clang-tidy @@ -0,0 +1,28 @@ +Checks: > + -*, + bugprone-* + misc-*, + modernize-*, + performance-*, + portability-*, + readability-*, + -fuchsia-trailing-return, + -readability-magic-numbers, + -modernize-use-nodiscard, + -modernize-use-trailing-return-type, + -readability-braces-around-statements, + -readability-redundant-access-specifiers, + -readability-redundant-member-init, + -readability-redundant-string-init, + -readability-identifier-length, +CheckOptions: + - { key: readability-identifier-naming.NamespaceCase, value: lower_case } + - { key: readability-identifier-naming.ClassCase, value: CamelCase } + - { key: readability-identifier-naming.StructCase, value: CamelCase } + - { key: readability-identifier-naming.FunctionCase, value: camelBack } + - { key: readability-identifier-naming.VariableCase, value: camelBack } + - { key: readability-identifier-naming.PrivateMemberCase, value: camelBack } + - { key: readability-identifier-naming.PrivateMemberPrefix, value: m_ } + - { key: readability-identifier-naming.EnumCase, value: CamelCase } + - { key: readability-identifier-naming.EnumConstantCase, value: CamelCase } + - { key: readability-identifier-naming.GlobalConstantCase, value: UPPER_CASE } diff --git a/source/.cmake-format b/source/.cmake-format new file mode 100644 index 0000000..9e40c67 --- /dev/null +++ b/source/.cmake-format @@ -0,0 +1,241 @@ +# ---------------------------------- +# Options affecting listfile parsing +# ---------------------------------- +with section("parse"): + + # Specify structure for custom cmake functions + additional_commands = { 'foo': { 'flags': ['BAR', 'BAZ'], + 'kwargs': {'DEPENDS': '*', 'HEADERS': '*', 'SOURCES': '*'}}} + + # Override configurations per-command where available + override_spec = {} + + # Specify variable tags. + vartags = [] + + # Specify property tags. + proptags = [] + +# ----------------------------- +# Options affecting formatting. +# ----------------------------- +with section("format"): + + # Disable formatting entirely, making cmake-format a no-op + disable = False + + # How wide to allow formatted cmake files + line_width = 80 + + # How many spaces to tab for indent + tab_size = 2 + + # If true, lines are indented using tab characters (utf-8 0x09) instead of + # space characters (utf-8 0x20). In cases where the layout would + # require a fractional tab character, the behavior of the fractional + # indentation is governed by + use_tabchars = False + + # If is True, then the value of this variable indicates how + # fractional indentions are handled during whitespace replacement. If set to + # 'use-space', fractional indentation is left as spaces (utf-8 0x20). If set + # to `round-up` fractional indentation is replaced with a single tab character + # (utf-8 0x09) effectively shifting the column to the next tabstop + fractional_tab_policy = 'use-space' + + # If an argument group contains more than this many sub-groups (parg or kwarg + # groups) then force it to a vertical layout. + max_subgroups_hwrap = 2 + + # If a positional argument group contains more than this many arguments, then + # force it to a vertical layout. + max_pargs_hwrap = 6 + + # If a cmdline positional group consumes more than this many lines without + # nesting, then invalidate the layout (and nest) + max_rows_cmdline = 2 + + # If true, separate flow control names from their parentheses with a space + separate_ctrl_name_with_space = False + + # If true, separate function names from parentheses with a space + separate_fn_name_with_space = False + + # If a statement is wrapped to more than one line, than dangle the closing + # parenthesis on its own line. + dangle_parens = False + + # If the trailing parenthesis must be 'dangled' on its on line, then align it + # to this reference: `prefix`: the start of the statement, `prefix-indent`: + # the start of the statement, plus one indentation level, `child`: align to + # the column of the arguments + dangle_align = 'prefix' + + # If the statement spelling length (including space and parenthesis) is + # smaller than this amount, then force reject nested layouts. + min_prefix_chars = 4 + + # If the statement spelling length (including space and parenthesis) is larger + # than the tab width by more than this amount, then force reject un-nested + # layouts. + max_prefix_chars = 10 + + # If a candidate layout is wrapped horizontally but it exceeds this many + # lines, then reject the layout. + max_lines_hwrap = 2 + + # What style line endings to use in the output. + line_ending = 'unix' + + # Format command names consistently as 'lower' or 'upper' case + command_case = 'canonical' + + # Format keywords consistently as 'lower' or 'upper' case + keyword_case = 'unchanged' + + # A list of command names which should always be wrapped + always_wrap = [] + + # If true, the argument lists which are known to be sortable will be sorted + # lexicographicall + enable_sort = True + + # If true, the parsers may infer whether or not an argument list is sortable + # (without annotation). + autosort = False + + # By default, if cmake-format cannot successfully fit everything into the + # desired linewidth it will apply the last, most agressive attempt that it + # made. If this flag is True, however, cmake-format will print error, exit + # with non-zero status code, and write-out nothing + require_valid_layout = False + + # A dictionary mapping layout nodes to a list of wrap decisions. See the + # documentation for more information. + layout_passes = {} + +# ------------------------------------------------ +# Options affecting comment reflow and formatting. +# ------------------------------------------------ +with section("markup"): + + # What character to use for bulleted lists + bullet_char = '*' + + # What character to use as punctuation after numerals in an enumerated list + enum_char = '.' + + # If comment markup is enabled, don't reflow the first comment block in each + # listfile. Use this to preserve formatting of your copyright/license + # statements. + first_comment_is_literal = False + + # If comment markup is enabled, don't reflow any comment block which matches + # this (regex) pattern. Default is `None` (disabled). + literal_comment_pattern = None + + # Regular expression to match preformat fences in comments default= + # ``r'^\s*([`~]{3}[`~]*)(.*)$'`` + fence_pattern = '^\\s*([`~]{3}[`~]*)(.*)$' + + # Regular expression to match rulers in comments default= + # ``r'^\s*[^\w\s]{3}.*[^\w\s]{3}$'`` + ruler_pattern = '^\\s*[^\\w\\s]{3}.*[^\\w\\s]{3}$' + + # If a comment line matches starts with this pattern then it is explicitly a + # trailing comment for the preceeding argument. Default is '#<' + explicit_trailing_pattern = '#<' + + # If a comment line starts with at least this many consecutive hash + # characters, then don't lstrip() them off. This allows for lazy hash rulers + # where the first hash char is not separated by space + hashruler_min_length = 10 + + # If true, then insert a space between the first hash char and remaining hash + # chars in a hash ruler, and normalize its length to fill the column + canonicalize_hashrulers = True + + # enable comment markup parsing and reflow + enable_markup = False + +# ---------------------------- +# Options affecting the linter +# ---------------------------- +with section("lint"): + + # a list of lint codes to disable + disabled_codes = [] + + # regular expression pattern describing valid function names + function_pattern = '[0-9a-z_]+' + + # regular expression pattern describing valid macro names + macro_pattern = '[0-9A-Z_]+' + + # regular expression pattern describing valid names for variables with global + # (cache) scope + global_var_pattern = '[A-Z][0-9A-Z_]+' + + # regular expression pattern describing valid names for variables with global + # scope (but internal semantic) + internal_var_pattern = '_[A-Z][0-9A-Z_]+' + + # regular expression pattern describing valid names for variables with local + # scope + local_var_pattern = '[a-z][a-z0-9_]+' + + # regular expression pattern describing valid names for privatedirectory + # variables + private_var_pattern = '_[0-9a-z_]+' + + # regular expression pattern describing valid names for public directory + # variables + public_var_pattern = '[A-Z][0-9A-Z_]+' + + # regular expression pattern describing valid names for function/macro + # arguments and loop variables. + argument_var_pattern = '[a-z][a-z0-9_]+' + + # regular expression pattern describing valid names for keywords used in + # functions or macros + keyword_pattern = '[A-Z][0-9A-Z_]+' + + # In the heuristic for C0201, how many conditionals to match within a loop in + # before considering the loop a parser. + max_conditionals_custom_parser = 2 + + # Require at least this many newlines between statements + min_statement_spacing = 1 + + # Require no more than this many newlines between statements + max_statement_spacing = 2 + max_returns = 6 + max_branches = 12 + max_arguments = 5 + max_localvars = 15 + max_statements = 50 + +# ------------------------------- +# Options affecting file encoding +# ------------------------------- +with section("encode"): + + # If true, emit the unicode byte-order mark (BOM) at the start of the file + emit_byteorder_mark = False + + # Specify the encoding of the input file. Defaults to utf-8 + input_encoding = 'utf-8' + + # Specify the encoding of the output file. Defaults to utf-8. Note that cmake + # only claims to support utf-8 so be careful when using anything else + output_encoding = 'utf-8' + +# ------------------------------------- +# Miscellaneous configurations options. +# ------------------------------------- +with section("misc"): + + # A dictionary containing any per-command configuration overrides. Currently + # only `command_case` is supported. + per_command = {} + diff --git a/source/.github/FUNDING.yml b/source/.github/FUNDING.yml new file mode 100644 index 0000000..3f35b50 --- /dev/null +++ b/source/.github/FUNDING.yml @@ -0,0 +1,13 @@ +# These are supported funding model platforms + +github: nuttyartist # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] +patreon: rubymamis # Replace with a single Patreon username +open_collective: # Replace with a single Open Collective username +ko_fi: # Replace with a single Ko-fi username +tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel +community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry +liberapay: # Replace with a single Liberapay username +issuehunt: # Replace with a single IssueHunt username +otechie: # Replace with a single Otechie username +lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry +custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] diff --git a/source/.github/workflows/ci.yml b/source/.github/workflows/ci.yml new file mode 100644 index 0000000..cdb658d --- /dev/null +++ b/source/.github/workflows/ci.yml @@ -0,0 +1,37 @@ +name: CI + +on: + push: + branches: + - master + tags: + - v* + pull_request: + workflow_dispatch: + +jobs: + format-lint: + name: Code Linting + uses: ./.github/workflows/format-lint.yml + secrets: inherit + + linux: + name: Linux + needs: + - format-lint + uses: ./.github/workflows/linux.yml + secrets: inherit + + macos: + name: macOS + needs: + - format-lint + uses: ./.github/workflows/macos.yml + secrets: inherit + + windows: + name: Windows + needs: + - format-lint + uses: ./.github/workflows/windows.yml + secrets: inherit diff --git a/source/.github/workflows/format-lint.yml b/source/.github/workflows/format-lint.yml new file mode 100644 index 0000000..862f29e --- /dev/null +++ b/source/.github/workflows/format-lint.yml @@ -0,0 +1,31 @@ +name: Code Linting + +on: + workflow_call: + workflow_dispatch: + +jobs: + lint: + name: Format / Lint + runs-on: ubuntu-latest + strategy: + fail-fast: false + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up cmake-format + run: pip install cmakelang + + - name: Run clang-format + run: find src/ -iregex '.*\.\(cpp\|h\|mm\)$' -print0 | xargs -n 1 -0 clang-format -style=file --dry-run --Werror --color=true + + - name: Run cmake-format + run: | + cmake-format CMakeLists.txt > CMakeLists-new.txt + if ! cmp -s CMakeLists.txt CMakeLists-new.txt + then + echo 'Please format CMakeLists.txt using cmake-format: https://github.com/cheshirekow/cmake_format' + echo 'For example: cmake-format CMakeLists.txt | sponge CMakeLists.txt' + exit 1 + fi diff --git a/source/.github/workflows/linux.yml b/source/.github/workflows/linux.yml new file mode 100644 index 0000000..6fce733 --- /dev/null +++ b/source/.github/workflows/linux.yml @@ -0,0 +1,391 @@ +name: Linux + +on: + workflow_call: + workflow_dispatch: + +env: + APP_ID: io.github.nuttyartist.notes + +jobs: + deb: + name: deb (${{ matrix.build-type }}, Qt ${{ matrix.qt-version-major }}, ${{ matrix.image }}) + runs-on: ubuntu-latest + container: + image: zjeffer/notes:${{ matrix.image }} + strategy: + fail-fast: false + matrix: + include: + # Ubuntu's release cycle: https://wiki.ubuntu.com/Releases + - image: ubuntu-20_04 + qt-version-major: 5 + build-type: release + + - image: ubuntu-22_04 + qt-version-major: 6 + build-type: release + + - image: ubuntu-23_10 + qt-version-major: 6 + build-type: release + steps: + - name: Setup git configuration + # workaround for "detected dubious ownership in repository" git error: https://github.com/actions/checkout/issues/1169 + run: git config --global --add safe.directory "${PWD}" + + - name: Checkout code + uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Set up variables + shell: bash + id: vars + run: | + set -x + distro_id=$(grep -oPm1 '^ID="?\K[^"]+' /etc/os-release) + if [ -z "${distro_id}" ] + then + echo 'Fatal: Failed to extract distro ID from /etc/os-release' + exit 1 + fi + distro_codename=$(grep -oPm1 '^VERSION_CODENAME="?\K[^"]+' /etc/os-release) + if [ -z "${distro_codename}" ] + then + echo 'Fatal: Failed to extract distro codename from /etc/os-release' + exit 1 + fi + echo "distro_name=${distro_id}-${distro_codename}" >> "${GITHUB_OUTPUT}" + + - name: Setup GCC problem matcher + uses: ammaraskar/gcc-problem-matcher@0.3.0 + + - name: Build (${{ matrix.build-type }}) + env: + VERBOSE: 1 + run: | + cmake --warn-uninitialized --warn-unused-vars \ + -B build \ + -DCMAKE_BUILD_TYPE=${{ matrix.build-type }} \ + -DGIT_REVISION=${{ github.ref_type != 'tag' && 'ON' || 'OFF' }} \ + -DCMAKE_INSTALL_PREFIX=/usr \ + -DPRO_VERSION=OFF + cmake --build build --parallel $(nproc) + + - name: Create deb package + run: | + cd build + cpack -G DEB + + - name: Grab deb package name + id: deb + shell: bash + run: | + set -x + if ! path=$(find build/ -maxdepth 1 -name '*.deb' -print -quit) + then + echo 'Fatal: Unable to find deb package' + exit 1; + fi + echo "name=$(basename "${path%.*}")" >> "${GITHUB_OUTPUT}" + echo "path=${path}" >> "${GITHUB_OUTPUT}" + + - name: Run lintian + run: | + lintian '${{ steps.deb.outputs.path }}' + + - name: Upload deb package + uses: actions/upload-artifact@v4 + with: + if-no-files-found: error + name: ${{ steps.deb.outputs.name }}-qt${{ matrix.qt-version-major }}-${{ steps.vars.outputs.distro_name }}-${{ matrix.build-type }} + path: ${{ steps.deb.outputs.path }} + + rpm: + name: rpm (${{ matrix.build-type }}, Qt ${{ matrix.qt-version-major }}, ${{ matrix.image }}) + runs-on: ubuntu-latest + container: zjeffer/notes:${{ matrix.image }} + strategy: + fail-fast: false + matrix: + include: + - # Fedora's release cycle: https://docs.fedoraproject.org/en-US/releases/lifecycle/ + image: fedora + qt-version-major: 6 + build-type: release + + - image: opensuse + qt-version-major: 6 + build-type: release + steps: + - name: Setup git configuration + # workaround for "detected dubious ownership in repository" git error: https://github.com/actions/checkout/issues/1169 + run: git config --global --add safe.directory "${PWD}" + + - name: Checkout code + uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Set up variables + shell: bash + id: vars + run: | + set -x + distro_id=$(grep -oPm1 '^ID="?\K[^"]+' /etc/os-release) + if [ -z "${distro_id}" ] + then + echo 'Failed to extract distro ID from /etc/os-release.' + exit 1 + fi + version_id=$(grep -oPm1 '^VERSION_ID="?\K[^"]+' /etc/os-release) + if [ -z "${version_id}" ] + then + echo 'Failed to extract version id from /etc/os-release.' + exit 1 + fi + echo "distro_name=${distro_id}-${version_id}" >> "${GITHUB_OUTPUT}" + + - name: Setup GCC problem matcher + uses: ammaraskar/gcc-problem-matcher@0.3.0 + + - name: Build (${{ matrix.build-type }}) + env: + VERBOSE: 1 + # openSUSE defaults to GCC 7, which doesn't support the filesystem library from C++17, + # and causes trouble compiling for Qt 6. So we have to manully specify GCC 10 instead. + CXX: ${{ startsWith(matrix.image, 'opensuse') && 'g++-10' || 'g++' }} + run: | + cmake --warn-uninitialized --warn-unused-vars \ + -B build \ + -DCMAKE_BUILD_TYPE=${{ matrix.build-type }} \ + -DGIT_REVISION=${{ github.ref_type != 'tag' && 'ON' || 'OFF' }} \ + -DCMAKE_POSITION_INDEPENDENT_CODE=TRUE \ + -DUPDATE_CHECKER=OFF \ + -DUSE_QT_VERSION=${{ matrix.qt-version-major }} \ + -DPRO_VERSION=OFF + cmake --build build --parallel $(nproc) + + - name: Create rpm package + run: | + cd build + cpack -G RPM + + - name: Grab rpm package name + id: rpm + shell: bash + run: | + set -x + if ! path=$(find build/ -maxdepth 1 -name '*.rpm' -print -quit) + then + echo 'Fatal: Unable to find rpm package!' + exit 1; + fi + echo "name=$(basename "${path%.*}")" >> "${GITHUB_OUTPUT}" + echo "path=${path}" >> "${GITHUB_OUTPUT}" + + - name: Run rpmlint + run: | + rpmlint '${{ steps.rpm.outputs.path }}' + + - name: Upload rpm package + uses: actions/upload-artifact@v4 + with: + if-no-files-found: error + name: ${{ steps.rpm.outputs.name }}-qt${{ matrix.qt-version-major }}-${{ steps.vars.outputs.distro_name }}-${{ matrix.build-type }} + path: ${{ steps.rpm.outputs.path }} + + # Build the AppImage using official Qt releases, downloaded by aqtinstall. + # This is also done for macOS and Windows, just to make sure we use the exact same Qt version across all three OSes. + # + # NOTE: This job uses a fixed Qt version (set in the 'qt-version' key below)! + # So, remember to keep it updated whenever a new Qt version is available on aqtinstall. + appimage-aqtinstall: + name: AppImage (${{ matrix.build-type }}, Qt ${{ matrix.qt-version }}, ${{ matrix.image }}) + runs-on: ${{ matrix.os }} + container: + image: zjeffer/notes:${{ matrix.image }} + strategy: + fail-fast: false + matrix: + include: + - os: ubuntu-22.04 + build-type: release + qt-version: 5.15.2 + image: ubuntu-aqtinstall-5 + + - os: ubuntu-22.04 + build-type: release + qt-version: 6.4.3 + image: ubuntu-aqtinstall-6 + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Setup variables + shell: bash + id: vars + run: | + set -x + version=$(grep -oPm1 '\bAPP_VERSION +\K[^)]+' CMakeLists.txt) + if [ -z "${version}" ] + then + echo 'Failed to extract app version from CMakeLists.txt.' + exit 1 + fi + if [ '${{ github.ref_type }}' != 'tag' ] + then + version="${version}+g${GITHUB_SHA::7}" + fi + artifact_name="Notes_${version}-Qt${{ matrix.qt-version }}-x86_64" + if [ '${{ matrix.build-type }}' == 'debug' ] + then + file_name="${artifact_name}-debug.AppImage" + else + file_name="${artifact_name}.AppImage" + fi + echo "version=${version}" >> "${GITHUB_OUTPUT}" + echo "artifact_name=${artifact_name}" >> "${GITHUB_OUTPUT}" + echo "file_name=${file_name}" >> "${GITHUB_OUTPUT}" + + # TODO: Figure out why this error only occurs on the Linux container when building with -DGIT_REVISION=ON + # The error: fatal: detected dubious ownership in repository + - name: Prevent git's dubious ownership message + if: github.ref_type != 'tag' + run: | + git config --global --add safe.directory "${PWD}" + + - name: Build (${{ matrix.build-type }}) + env: + VERBOSE: 1 + run: | + cmake --warn-uninitialized --warn-unused-vars \ + -B build \ + -DCMAKE_BUILD_TYPE=${{ matrix.build-type }} \ + -DGIT_REVISION=${{ github.ref_type != 'tag' && 'ON' || 'OFF' }} \ + -DCMAKE_INSTALL_PREFIX=/usr \ + -DPRO_VERSION=OFF + cmake --build build --parallel $(nproc) + + - name: (FIXME) Run qmllint + if: startsWith(matrix.qt-version, '6.') + run: | + cmake --build build --target all_qmllint || true + + - name: Install (${{ matrix.build-type }}) + run: | + make -C build DESTDIR=Notes install + + - name: Setup linuxdeploy + run: | + cd build + curl -fLO --retry 10 https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage + chmod +x linuxdeploy-x86_64.AppImage + + - name: Setup Qt plugin for linuxdeploy + run: | + cd build + curl -fLO --retry 10 https://github.com/linuxdeploy/linuxdeploy-plugin-qt/releases/download/continuous/linuxdeploy-plugin-qt-x86_64.AppImage + chmod +x linuxdeploy-plugin-qt-x86_64.AppImage + + - name: Deploy (${{ matrix.build-type }}) + env: + APPIMAGE_EXTRACT_AND_RUN: 1 + run: | + export QML_SOURCES_PATHS="${PWD}/src/qml" + cd build + ./linuxdeploy-x86_64.AppImage --appdir Notes --plugin qt + + - name: Remove unnecessary Qt plugins and libraries + shell: bash + run: | + set -x + set -e + cd build/Notes + if [[ '${{ matrix.qt-version }}' == 5.* ]] + then + # The bearer plugin has caused problems for us in the past. Plus, it was removed altogether in Qt 6. + rm -rv usr/plugins/bearer + fi + # We only use the SQLite Qt driver, so it's fine to delete others. + rm -v usr/plugins/sqldrivers/libqsqlodbc.so + rm -v usr/plugins/sqldrivers/libqsqlpsql.so + if [[ '${{ matrix.qt-version }}' == 6.* ]] + then + # The Qt 6 build also has a MySQL Qt driver we don't use. + rm -v usr/plugins/sqldrivers/libqsqlmysql.so + rm -v usr/lib/libmysqlclient.so.* + fi + + - name: Validate AppStream metadata + if: matrix.image != 'ubuntu:20.04' + run: | + cd build/Notes + appstreamcli validate --verbose 'usr/share/metainfo/${{ env.APP_ID }}.metainfo.xml' + + - name: Validate desktop file + run: | + cd build/Notes + desktop-file-validate 'usr/share/applications/${{ env.APP_ID }}.desktop' + + - name: Build AppImage (${{ matrix.build-type }}) + env: + APPIMAGE_EXTRACT_AND_RUN: 1 + run: | + cd build + export VERSION='${{ steps.vars.outputs.version }}' + ./linuxdeploy-x86_64.AppImage --appdir Notes --output appimage + mv -v Notes*.AppImage '${{ steps.vars.outputs.file_name }}' + + - name: Upload AppImage artifact (${{ matrix.build-type }}) + uses: actions/upload-artifact@v4 + with: + if-no-files-found: error + name: ${{ steps.vars.outputs.artifact_name }}-${{ runner.os }}-${{ matrix.build-type }} + path: build/${{ steps.vars.outputs.file_name }} + + snap: + name: snap + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Install snapcraft + run: | + sudo snap install snapcraft --classic + + - name: Set up LXD + run: | + sudo usermod -a -G lxd "${USER}" + sudo lxd init --auto + sudo iptables -P FORWARD ACCEPT + + - name: Build + run: | + sg lxd -c 'snap run snapcraft -v' + + - name: Grab snap package name + id: snap + shell: bash + run: | + set -x + if ! path=$(find . -maxdepth 1 -name '*.snap' -print -quit) + then + echo 'Fatal: Unable to find snap package' + exit 1 + fi + echo "name=$(basename "${path%.*}")" >> "${GITHUB_OUTPUT}" + echo "path=${path}" >> "${GITHUB_OUTPUT}" + + - name: Upload snap package + uses: actions/upload-artifact@v4 + with: + if-no-files-found: error + name: ${{ steps.snap.outputs.name }}.snap + path: ${{ steps.snap.outputs.path }} diff --git a/source/.github/workflows/macos.yml b/source/.github/workflows/macos.yml new file mode 100644 index 0000000..4a1ef07 --- /dev/null +++ b/source/.github/workflows/macos.yml @@ -0,0 +1,228 @@ +name: macOS + +on: + workflow_call: + workflow_dispatch: + +jobs: + # This job is mainly to make sure Notes will compile with Qt from homebrew's repository. + # So it doesn't make much sense to have different build types other than 'debug' here. + # The release dmg is built using aqtinstall instead (the job below this one). + build-homebrew: + name: Build (${{ matrix.build-type }}, homebrew (qt${{ matrix.qt-version-major }}), ${{ matrix.os }}) + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + include: + - os: macos-12 + qt-version-major: 5 + build-type: debug + + - os: macos-12 + qt-version-major: 6 + build-type: debug + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Install Qt ${{ matrix.qt-version-major }} (homebrew) + env: + # TODO: remove once https://github.com/actions/setup-python/issues/577 gets fixed. + HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK: 1 + run: | + brew update + brew install ninja qt@${{ matrix.qt-version-major }} + + - name: Configure Qt ${{ matrix.qt-version-major }} (homebrew) + run: | + brew link qt@${{ matrix.qt-version-major }} + cat << EOF + LDFLAGS="-L/usr/local/opt/qt@${{ matrix.qt-version-major }}/lib" + export CPPFLAGS="-I/usr/local/opt/qt@${{ matrix.qt-version-major }}/include" + export PATH="/usr/local/opt/qt@${{ matrix.qt-version-major }}/bin:$PATH" + EOF >> ~/.bashrc + + - name: Setup CLang problem matcher + # Technically, this action only supports GCC, but it seems to work well for Clang too. + if: matrix.build-type == 'debug' + uses: ammaraskar/gcc-problem-matcher@0.3.0 + + - name: Build (${{ matrix.build-type }}) + env: + VERBOSE: 1 + run: | + export CMAKE_BUILD_PARALLEL_LEVEL=$(sysctl -n hw.logicalcpu) + cmake . --warn-uninitialized --warn-unused-vars \ + -G Ninja -B build \ + -DCMAKE_BUILD_TYPE=${{ matrix.build-type }} \ + -DCMAKE_PREFIX_PATH="$(brew --prefix qt@${{ matrix.qt-version-major }})" \ + -DPRO_VERSION=OFF + cmake --build build + + # Build the dmg disk image using the official Qt 5 release downloaded by aqtinstall. + # This is also done for Linux and Windows, just to make sure we use the exact same Qt version across all three OSes. + # + # NOTE: This job uses a fixed Qt version (set in the 'qt-version' key below)! + # So, remember to keep it updated whenever a new Qt version is available on aqtinstall. + dmg-aqtinstall: + name: dmg (${{ matrix.build-type }}, Qt ${{ matrix.qt-version }}, ${{ matrix.os }}) + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + include: + - os: macos-11 + qt-version: 5.15.2 + build-type: release + + - os: macos-11 + qt-version: 6.5.2 + build-type: release + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Setup variables + id: vars + run: | + set -x + version=$(grep -Em1 '\bAPP_VERSION' CMakeLists.txt | sed -r 's/.*APP_VERSION +//; s/ *)//') + if [ -z "${version}" ] + then + echo 'Failed to extract app version from CMakeLists.txt.' + exit 1 + fi + if [ '${{ github.ref_type }}' != 'tag' ] + then + version="${version}+g${GITHUB_SHA::7}" + fi + arches='x86_64' + if [[ '${{ matrix.qt-version }}' == 6.* ]] + then + arches+='-arm64' + fi + artifact_name="Notes_${version}-Qt${{ matrix.qt-version }}-${arches}" + if [ '${{ matrix.build-type }}' == 'debug' ] + then + file_name="${artifact_name}-debug.dmg" + else + file_name="${artifact_name}.dmg" + fi + echo "version=${version}" >> "${GITHUB_OUTPUT}" + echo "artifact_name=${artifact_name}" >> "${GITHUB_OUTPUT}" + echo "file_name=${file_name}" >> "${GITHUB_OUTPUT}" + + - name: Install Qt ${{ matrix.qt-version }} (aqtinstall) + uses: jurplel/install-qt-action@v3 + with: + version: ${{ matrix.qt-version }} + cache: true + + - name: Install dependencies + run: | + brew update + brew install create-dmg ninja + + - name: Build (${{ matrix.build-type }}) + env: + # Only commercial Qt 5 supports targeting Apple Silicon at the moment: + # https://www.qt.io/blog/qt-on-apple-silicon + TARGET_ARCH: ${{ startsWith(matrix.qt-version, '6.') && 'x86_64;arm64' || 'x86_64' }} + VERBOSE: 1 + run: | + export CMAKE_BUILD_PARALLEL_LEVEL=$(sysctl -n hw.logicalcpu) + cmake . --warn-uninitialized --warn-unused-vars \ + -B build -G Ninja \ + -DCMAKE_BUILD_TYPE=${{ matrix.build-type }} \ + -DGIT_REVISION=${{ github.ref_type != 'tag' && 'ON' || 'OFF' }} \ + -DCMAKE_OSX_ARCHITECTURES="${{ env.TARGET_ARCH }}" \ + -DPRO_VERSION=OFF + cmake --build build + + - name: (FIXME) Run qmllint + if: startsWith(matrix.qt-version, '6.') + run: | + cmake --build build --target all_qmllint || true + + - name: Install (${{ matrix.build-type }}) + run: | + cmake --install build --prefix . + + - name: Deploy (${{ matrix.build-type }}) + run: | + cd build + plutil -insert NSRequiresAquaSystemAppearance -bool true Notes.app/Contents/Info.plist + # Rename the app folder to "Notes Better", so it doesn't conflict with macOS' "Notes" app. + mv Notes.app 'Notes Better.app' + macdeployqt 'Notes Better.app' -qmldir=../src/qml -appstore-compliant + + - name: Remove unnecessary Qt plugins and libraries + run: | + set -x + set -e + cd 'build/Notes Better.app' + if [[ '${{ matrix.qt-version }}' == 5.* ]] + then + # The bearer plugin has caused problems for us in the past. Plus, it was removed altogether in Qt 6. + rm -rv Contents/PlugIns/bearer + fi + + - name: Import signing certificate + if: github.repository == 'nuttyartist/notes' && github.event_name != 'pull_request' + run: | + openssl base64 -d -out cert.p12 <<< '${{ secrets.MACOS_CERTIFICATE }}' + security create-keychain -p '${{ secrets.KEYCHAIN_PWD }}' nuttyartist/notes + security default-keychain -s nuttyartist/notes + security unlock-keychain -p '${{ secrets.KEYCHAIN_PWD }}' nuttyartist/notes + security -q import cert.p12 -f pkcs12 -k nuttyartist/notes -P '${{ secrets.MACOS_CERTIFICATE_PWD }}' -T /usr/bin/codesign -x + security set-key-partition-list -S 'apple-tool:,apple:' -s -k '${{ secrets.KEYCHAIN_PWD }}' nuttyartist/notes + + - name: Sign + if: github.repository == 'nuttyartist/notes' && github.event_name != 'pull_request' + run: | + codesign --deep --force --verify --verbose --sign Mamistvalove --options runtime 'build/Notes Better.app' + + - name: Build dmg (${{ matrix.build-type }}) + run: | + cd build + create-dmg \ + --no-internet-enable \ + --format ULFO \ + --background ../packaging/macos/dmg-background.png \ + --hide-extension 'Notes Better.app' \ + --icon 'Notes Better.app' 180 170 \ + --icon-size 160 \ + --text-size 12 \ + --volname Notes \ + --volicon ../src/images/notes_icon.icns \ + --window-size 660 400 \ + --app-drop-link 480 170 \ + '${{ steps.vars.outputs.file_name }}' \ + 'Notes Better.app' + + - name: Notarize + if: github.repository == 'nuttyartist/notes' && github.event_name != 'pull_request' + run: | + xcrun notarytool submit \ + --apple-id '${{ secrets.NOTARIZATION_USERNAME }}' \ + --password '${{ secrets.NOTARIZATION_PASSWORD }}' \ + --team-id '${{ secrets.NOTARIZATION_TEAM }}' \ + --wait \ + 'build/${{ steps.vars.outputs.file_name }}' + + - name: Staple + if: github.repository == 'nuttyartist/notes' && github.event_name != 'pull_request' + run: | + xcrun stapler staple 'build/${{ steps.vars.outputs.file_name }}' + + - name: Upload dmg artifact (${{ matrix.build-type }}) + uses: actions/upload-artifact@v4 + with: + if-no-files-found: error + name: ${{ steps.vars.outputs.artifact_name }}-${{ runner.os }}-${{ matrix.build-type }} + path: build/${{ steps.vars.outputs.file_name }} diff --git a/source/.github/workflows/windows.yml b/source/.github/workflows/windows.yml new file mode 100644 index 0000000..e527164 --- /dev/null +++ b/source/.github/workflows/windows.yml @@ -0,0 +1,248 @@ +name: Windows + +on: + workflow_call: + workflow_dispatch: + +jobs: + # NOTE: This job uses a fixed Qt version (set in the 'qt-version' key below)! + # So, remember to keep it updated whenever a new Qt version is available on aqtinstall. + build-aqtinstall: + name: Build (${{ matrix.arch }}, ${{ matrix.build-type }}, Qt ${{ matrix.qt-version }}, ${{ matrix.os }}) + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + include: + - os: windows-2019 + arch: x64 + qt-version: 5.15.2 + build-type: release + + - os: windows-2019 + arch: x86 + qt-version: 5.15.2 + build-type: release + + - os: windows-2019 + arch: x64 + qt-version: 6.4.3 + build-type: release + outputs: + version: ${{ steps.vars.outputs.version }} + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Setup variables + id: vars + run: | + $version = Select-String -Path CMakeLists.txt -CaseSensitive -Pattern '\bAPP_VERSION +([^)]+)' | Select-Object -First 1 | %{$_.Matches.Groups[1].value} + if (!$version) { + throw "Failed to extract app version from CMakeLists.txt." + } + if ('${{ github.ref_type }}' -ne 'tag') { + $version += "+g$($env:GITHUB_SHA.Substring(0,7))" + } + $artifact_name = "Notes_$version-Qt${{ matrix.qt-version }}-${{ matrix.arch }}" + Write-Output "version=$version" >> $env:GITHUB_OUTPUT + Write-Output "artifact_name=$artifact_name" >> $env:GITHUB_OUTPUT + + - name: Setup MSVC (${{ matrix.arch }}) + uses: ilammy/msvc-dev-cmd@v1 + with: + arch: ${{ matrix.arch }} + + - name: Install Qt ${{ matrix.qt-version }} (aqtinstall, ${{ matrix.arch }}) + uses: jurplel/install-qt-action@v3 + with: + version: ${{ matrix.qt-version }} + cache: true + arch: ${{ matrix.arch == 'x86' && 'win32_msvc2019' || 'win64_msvc2019_64' }} + + # Details about this OpenSSL build: https://kb.firedaemon.com/support/solutions/articles/4000121705 + # TODO: Remove/tweak this step if/when we get rid of the x86 build or upgrade to Qt 6.5+. + - name: Download OpenSSL 1.x binaries from FireDaemon + if: ${{ startsWith(matrix.qt-version, '5.') || startsWith(matrix.qt-version, '6.4.') }} + run: | + $out_file = "openssl-1.1.1w.zip" + Invoke-WebRequest -Uri https://download.firedaemon.com/FireDaemon-OpenSSL/openssl-1.1.1w.zip -OutFile $env:Temp\$out_file + Expand-Archive -Path $env:Temp\$out_file -DestinationPath $env:Temp + Rename-Item $env:Temp\openssl-1.1 $env:Temp\OpenSSL + + - name: Setup MSVC problem matcher + uses: ammaraskar/msvc-problem-matcher@0.3.0 + + - name: Build (${{ matrix.build-type }}, ${{ matrix.arch }}) + env: + VERBOSE: 1 + run: | + $env:CMAKE_BUILD_PARALLEL_LEVEL = $env:NUMBER_OF_PROCESSORS + cmake . --warn-uninitialized --warn-unused-vars ` + -B build -G Ninja ` + -DCMAKE_BUILD_TYPE=${{ matrix.build-type }} ` + -DGIT_REVISION=${{ github.ref_type != 'tag' && 'ON' || 'OFF' }} ` + -DPRO_VERSION=OFF + cmake --build build + + - name: (FIXME) Run qmllint + if: startsWith(matrix.qt-version, '6.') + run: | + cmake --build build --target all_qmllint || $(exit 0) + + - name: Install (${{ matrix.build-type }}, ${{ matrix.arch }}) + run: | + cmake --install build --prefix build + + - name: Deploy (${{ matrix.build-type }}, ${{ matrix.arch }}) + run: | + windeployqt ${{ startsWith(matrix.qt-version, '5.') && '--no-qmltooling' || ' ' }} --qmldir src\qml build\bin + + - name: Remove unnecessary Qt plugins and libraries + run: | + Set-Location build\bin + # We ship all required runtime DLLs individually. + Remove-Item -Verbose vc_redist.*.exe + if ('${{ matrix.qt-version }}'.StartsWith('5.')) { + # The bearer plugin has caused problems for us in the past. Plus, it was removed altogether in Qt 6. + Remove-Item -Verbose -Recurse bearer + } + # We only use the SQLite Qt driver, so it's fine to delete others. + Remove-Item -Verbose sqldrivers\qsqlodbc.dll + Remove-Item -Verbose sqldrivers\qsqlpsql.dll + + - name: Include required runtime libraries (${{ matrix.build-type }}, ${{ matrix.arch }}) + run: | + Set-Location build\bin + + if ('${{ matrix.arch }}' -ieq 'x64') { + $openssl_lib_suffix = '-x64' + } else { + $openssl_lib_suffix = '' + } + + # Include OpenSSL libraries. + Copy-Item $env:Temp\OpenSSL\${{ matrix.arch }}\bin\libcrypto-1_1$openssl_lib_suffix.dll + Copy-Item $env:Temp\OpenSSL\${{ matrix.arch }}\bin\libssl-1_1$openssl_lib_suffix.dll + + # Also include OpenSSL debug symbols (when building Notes in debug mode). + if ('${{ matrix.build-type }}' -ieq 'debug') { + Copy-Item $env:Temp\OpenSSL\${{ matrix.arch }}\bin\libcrypto-1_1$openssl_lib_suffix.pdb + Copy-Item $env:Temp\OpenSSL\${{ matrix.arch }}\bin\libssl-1_1$openssl_lib_suffix.pdb + } + + # Include MSVC 2019 runtime libraries. + if ('${{ matrix.build-type }}' -ieq 'release') { + Copy-Item $env:VCToolsRedistDir\${{ matrix.arch }}\Microsoft.VC142.CRT\msvcp140.dll + Copy-Item $env:VCToolsRedistDir\${{ matrix.arch }}\Microsoft.VC142.CRT\msvcp140_1.dll + + # Only Qt 6 builds also need msvcp140_2.dll + if ('${{ matrix.qt-version }}'.StartsWith('6')) { + Copy-Item $env:VCToolsRedistDir\${{ matrix.arch }}\Microsoft.VC142.CRT\msvcp140_2.dll + } + + Copy-Item $env:VCToolsRedistDir\${{ matrix.arch }}\Microsoft.VC142.CRT\vcruntime140.dll + if ('${{ matrix.arch }}' -ieq 'x64') { + # Only 64-bit builds also need 'vcruntime140_1.dll' (tested on Windows 7) + Copy-Item $env:VCToolsRedistDir\${{ matrix.arch }}\Microsoft.VC142.CRT\vcruntime140_1.dll + } + } else { + # On debug builds, the libraries above are included automatically, so we only need 'urtcbased.dll'. + Copy-Item $env:WindowsSdkBinPath\${{ matrix.arch }}\ucrt\ucrtbased.dll + } + + - name: Upload artifacts (${{ matrix.build-type }}, ${{ matrix.arch }}) + uses: actions/upload-artifact@v4 + with: + if-no-files-found: error + name: ${{ steps.vars.outputs.artifact_name }}-${{ runner.os }}-${{ matrix.build-type }} + path: build\bin + + unified-installer: + name: Unified x64-x86 Installer + needs: build-aqtinstall + runs-on: windows-2019 + steps: + - name: Checkout code to grab the ISS script + uses: actions/checkout@v4 + + - name: Download build artifacts from previous job + uses: actions/download-artifact@v4 + with: + path: artifacts + pattern: '*Windows*' + + - name: Ensure a 64-bit Qt 6 build is present + run: | + Set-Location artifacts + $x64_build = Get-ChildItem -Filter '*Qt6*-x64-Windows-release' -Attributes Directory | + Sort-Object -Property @{Expression = "Name"; Descending = $true} | + Select-Object -First 1 + if (!$x64_build) { + Throw 'Could not find a 64-bit Qt 6 build.' + } + Move-Item $x64_build Notes64 + + - name: Ensure a 32-bit Qt 5 build is present + run: | + Set-Location artifacts + $x86_build = Get-ChildItem -Filter '*Qt5*-x86-Windows-release' -Attributes Directory | + Sort-Object -Property @{Expression = "Name"; Descending = $true} | + Select-Object -First 1 + if (!$x86_build) { + Throw 'Could not find a 32-bit Qt 5 build.' + } + Move-Item $x86_build Notes32 + + - name: Create unified installer + run: | + Set-Location artifacts + Copy-Item ..\packaging\windows\Notes_Inno_Script_Github.iss + $env:APP_VERSION = '${{ needs.build-aqtinstall.outputs.version }}' + iscc /Oinstaller Notes_Inno_Script_Github.iss + + # This step makes sure that all files copied by windeployqt are also included in the final installer. + # This is done by parsing the 'Set-Manifest.txt' file, which is generated by Inno Setup: + # https://jrsoftware.org/ishelp/index.php?topic=setup_outputmanifestfile + - name: Verify installer files + run: | + Set-Location artifacts + $inno_setup_manifest = ".\installer\Setup-Manifest.txt" + $windeployqt_paths = @(".\Notes32", ".\Notes64") + + $inno_setup_files = @() + Get-Content -LiteralPath $inno_setup_manifest -ErrorAction Stop | Select-Object -Skip 1 | Foreach-Object { + $path = ($_ -Split "\t")[1] # We only need the second column, which refers to the absolute path of the file. + $inno_setup_files += (Resolve-Path $path).ToString() + } + + $missing_files = 0 + Get-ChildItem -File -LiteralPath $windeployqt_paths -Recurse -ErrorAction Stop | Foreach-Object { + $path = (Resolve-Path $_).ToString() + if ($path -NotIn $inno_setup_files) { + Write-Host "File '$path' was not included in Inno Setup's list of files." -ForegroundColor Yellow + $missing_files++ + } + } + + if ($missing_files -gt 0) { + $is_plural = $missing_files -gt 1 + Write-Host "" + Write-Host ("ERROR: {0} {1} previously copied by windeployqt {2} missing from Inno Setup's list of files." ` + -F $missing_files, ($is_plural ? "files" : "file"), ($is_plural ? "are" : "is")) ` + -ForegroundColor DarkRed + Write-Host (" Did you forget to include {0} in '.\packaging\windows\Notes_Inno_Script_Github.iss'?" ` + -F ($is_plural ? "them" : "it")) ` + -ForegroundColor DarkRed + Exit 1 + } + Write-Host "SUCCESS: List of files in the installer matches the ones copied by windeployqt." + + - name: Upload unified installer artifact + uses: actions/upload-artifact@v4 + with: + if-no-files-found: error + name: NotesSetup_${{ needs.build-aqtinstall.outputs.version }}-${{ runner.os }}-release + path: artifacts\installer diff --git a/source/.gitignore b/source/.gitignore index 7df8dff..71f3b3e 100644 --- a/source/.gitignore +++ b/source/.gitignore @@ -1,9 +1,39 @@ -# generated files -bin/ -gen/ +# Build dirs and files # +######################## +*.pro.user +build-Notes-* +build-* +bin* +CMakeLists.txt.user -# Local configuration file (sdk path, etc) -project.properties -.settings/ -.classpath -.project +# OS generated files # +###################### +.DS_Store* +.vscode/ +.cache/ +ehthumbs.db +Thumbs.db +Makefile +Notes +qrc_images.cpp +*.autosave +*~ +*.snap +*.swp +__pycache__ +packaging/linux/deb_build/ +packaging/linux/snap/stage +packaging/linux/snap/snap +packaging/linux/snap/parts/notes +packaging/linux/snap/parts/desktop +prime/ +squashfs-root/ +build/ +install/ +src/moc +src/obj +src/qrc +src/snap +src/uic +src/notes +.qmake.stash diff --git a/source/.gitmodules b/source/.gitmodules new file mode 100644 index 0000000..1e0e7d5 --- /dev/null +++ b/source/.gitmodules @@ -0,0 +1,9 @@ +[submodule "3rdParty/qautostart"] + path = 3rdParty/qautostart + url = https://github.com/b00f/qautostart.git +[submodule "3rdParty/qmarkdowntextedit"] + path = 3rdParty/qmarkdowntextedit + url = https://github.com/pbek/qmarkdowntextedit +[submodule "3rdParty/QSimpleUpdater"] + path = 3rdParty/QSimpleUpdater + url = https://github.com/alex-spataru/QSimpleUpdater diff --git a/source/3rdParty/qxt/.gitattributes b/source/3rdParty/qxt/.gitattributes new file mode 100644 index 0000000..3924138 --- /dev/null +++ b/source/3rdParty/qxt/.gitattributes @@ -0,0 +1,2 @@ +*.h whitespace=cr-at-eol +*.cpp whitespace=cr-at-eol diff --git a/source/3rdParty/qxt/AUTHORS b/source/3rdParty/qxt/AUTHORS new file mode 100644 index 0000000..182a7d8 --- /dev/null +++ b/source/3rdParty/qxt/AUTHORS @@ -0,0 +1,27 @@ +== main developers == + +Arvid Picciani +Adam Higerd +J-P Nurmi +Benjamin Zeller + +== contributors == + +Gabriel Assis Bezerra +Scott Aron Bloom +Lawrence Holtsclaw +Marcin Jakubowski +Dominique Leducq +Marcus Lindblom +Konstantin Molchanov +Thomas Mueller +Bjørn Erik Nilsen +Kaleb Pederson +Matthew Schnee +André Somers +Alex Unden +Chris Vickery +Benjamin Wohlwend + +thanks everyone not named for all the patches, bug reports, +beta tests, and the free beer :-) diff --git a/source/3rdParty/qxt/COPYING b/source/3rdParty/qxt/COPYING new file mode 100644 index 0000000..1b80aa7 --- /dev/null +++ b/source/3rdParty/qxt/COPYING @@ -0,0 +1,30 @@ +/**************************************************************************** +** Copyright (c) 2006 - 2011, the LibQxt project. +** See the Qxt AUTHORS file for a list of authors and copyright holders. +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** * Neither the name of the LibQxt project nor the +** names of its contributors may be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +** DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +** +** +*****************************************************************************/ + diff --git a/source/3rdParty/qxt/qxt.pri b/source/3rdParty/qxt/qxt.pri new file mode 100644 index 0000000..96621e5 --- /dev/null +++ b/source/3rdParty/qxt/qxt.pri @@ -0,0 +1,26 @@ +INCLUDEPATH += $$PWD + +HEADERS += \ + $$PWD/qxtglobal.h \ + $$PWD/qxtglobalshortcut_p.h \ + $$PWD/qxtglobalshortcut.h + +SOURCES += \ + $$PWD/qxtglobal.cpp \ + $$PWD/qxtglobalshortcut.cpp + +win32 { + LIBS+= -luser32 + DEFINES += QXT_STATIC + SOURCES += $$PWD/qxtglobalshortcut_win.cpp +} + +macx { + LIBS += -framework Carbon + SOURCES += $$PWD/qxtglobalshortcut_mac.cpp +} + +unix:!macx { + LIBS += -lX11 + SOURCES += $$PWD/qxtglobalshortcut_x11.cpp +} diff --git a/source/3rdParty/qxt/qxtglobal.cpp b/source/3rdParty/qxt/qxtglobal.cpp new file mode 100644 index 0000000..3da47c1 --- /dev/null +++ b/source/3rdParty/qxt/qxtglobal.cpp @@ -0,0 +1,251 @@ + +/**************************************************************************** +** Copyright (c) 2006 - 2011, the LibQxt project. +** See the Qxt AUTHORS file for a list of authors and copyright holders. +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** * Neither the name of the LibQxt project nor the +** names of its contributors may be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +** DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +** +** +*****************************************************************************/ + +#include "qxtglobal.h" + +/*! + \headerfile + \title Global Qxt Declarations + \inmodule QxtCore + + \brief The header provides basic declarations and + is included by all other Qxt headers. + */ + +/*! + \macro QXT_VERSION + \relates + + This macro expands a numeric value of the form 0xMMNNPP (MM = + major, NN = minor, PP = patch) that specifies Qxt's version + number. For example, if you compile your application against Qxt + 0.4.0, the QXT_VERSION macro will expand to 0x000400. + + You can use QXT_VERSION to use the latest Qt features where + available. For example: + \code + #if QXT_VERSION >= 0x000400 + qxtTabWidget->setTabMovementMode(QxtTabWidget::InPlaceMovement); + #endif + \endcode + + \sa QXT_VERSION_STR, qxtVersion() + */ + +/*! + \macro QXT_VERSION_STR + \relates + + This macro expands to a string that specifies Qxt's version number + (for example, "0.4.0"). This is the version against which the + application is compiled. + + \sa qxtVersion(), QXT_VERSION + */ + +/*! + \relates + + Returns the version number of Qxt at run-time as a string (for + example, "0.4.0"). This may be a different version than the + version the application was compiled against. + + \sa QXT_VERSION_STR + */ +const char * qxtVersion() +{ + return QXT_VERSION_STR; +} + +/*! +\headerfile +\title The Qxt private implementation +\inmodule QxtCore + +\brief The header provides tools for hiding +details of a class. + +Application code generally doesn't have to be concerned about hiding its +implementation details, but when writing library code it is important to +maintain a constant interface, both source and binary. Maintaining a constant +source interface is easy enough, but keeping the binary interface constant +means moving implementation details into a private class. The PIMPL, or +d-pointer, idiom is a common method of implementing this separation. QxtPimpl +offers a convenient way to connect the public and private sides of your class. + +\section1 Getting Started +Before you declare the public class, you need to make a forward declaration +of the private class. The private class must have the same name as the public +class, followed by the word Private. For example, a class named MyTest would +declare the private class with: +\code +class MyTestPrivate; +\endcode + +\section1 The Public Class +Generally, you shouldn't keep any data members in the public class without a +good reason. Functions that are part of the public interface should be declared +in the public class, and functions that need to be available to subclasses (for +calling or overriding) should be in the protected section of the public class. +To connect the private class to the public class, include the +QXT_DECLARE_PRIVATE macro in the private section of the public class. In the +example above, the private class is connected as follows: +\code +private: + QXT_DECLARE_PRIVATE(MyTest) +\endcode + +Additionally, you must include the QXT_INIT_PRIVATE macro in the public class's +constructor. Continuing with the MyTest example, your constructor might look +like this: +\code +MyTest::MyTest() { + // initialization + QXT_INIT_PRIVATE(MyTest); +} +\endcode + +\section1 The Private Class +As mentioned above, data members should usually be kept in the private class. +This allows the memory layout of the private class to change without breaking +binary compatibility for the public class. Functions that exist only as +implementation details, or functions that need access to private data members, +should be implemented here. + +To define the private class, inherit from the template QxtPrivate class, and +include the QXT_DECLARE_PUBLIC macro in its public section. The template +parameter should be the name of the public class. For example: +\code +class MyTestPrivate : public QxtPrivate { +public: + MyTestPrivate(); + QXT_DECLARE_PUBLIC(MyTest) +}; +\endcode + +\section1 Accessing Private Members +Use the qxt_d() function (actually a function-like object) from functions in +the public class to access the private class. Similarly, functions in the +private class can invoke functions in the public class by using the qxt_p() +function (this one's actually a function). + +For example, assume that MyTest has methods named getFoobar and doBaz(), +and MyTestPrivate has a member named foobar and a method named doQuux(). +The code might resemble this example: +\code +int MyTest::getFoobar() { + return qxt_d().foobar; +} + +void MyTestPrivate::doQuux() { + qxt_p().doBaz(foobar); +} +\endcode +*/ + +/*! + * \macro QXT_DECLARE_PRIVATE(PUB) + * \relates + * Declares that a public class has a related private class. + * + * This shuold be put in the private section of the public class. The + * parameter \a PUB must be the name of the public class. + */ + +/*! + * \macro QXT_DECLARE_PUBLIC(PUB) + * \relates + * Declares that a private class has a related public class named \a PUB. + * + * This may be put anywhere in the declaration of the private class. The parameter is the name of the public class. + */ + +/*! + * \macro QXT_INIT_PRIVATE(PUB) + * \relates + * Initializes resources owned by the private class. + * + * This should be called from the public class's constructor, + * before qxt_d() is used for the first time. The parameter \a PUB must be + * the name of the public class. + */ + +/*! + * \macro QXT_D(PUB) + * \relates + * Returns a reference in the current scope named "d" to the private class + * associated with the public class \a PUB. + * + * This function is only available in a class using QXT_DECLARE_PRIVATE(). + */ + +/*! + * \macro QXT_P(PUB) + * \relates + * Creates a reference in the current scope named "q" to the public class + * named \a PUB. + * + * This macro only works in a class using QXT_DECLARE_PUBLIC(). + */ + +/*! + * \fn QxtPrivate& PUB::qxt_d() + * \relates + * Returns a reference to the private class. + * + * This function is only available in a class using \a QXT_DECLARE_PRIVATE. + */ + +/*! + * \fn const QxtPrivate& PUB::qxt_d() const + * \relates + * Returns a const reference to the private class. + * + * This function is only available in a class using \a QXT_DECLARE_PRIVATE. + * This overload will be automatically used in const functions. + */ + +/*! + * \fn PUB& QxtPrivate::qxt_p() + * \relates + * Returns a reference to the public class. + * + * This function is only available in a class using QXT_DECLARE_PUBLIC(). + */ + +/*! + * \fn const PUB& QxtPrivate::qxt_p() const + * \relates + * Returns a const reference to the public class. + * + * This function is only available in a class using QXT_DECLARE_PUBLIC(). + * This overload will be automatically used in const functions. + */ diff --git a/source/3rdParty/qxt/qxtglobal.h b/source/3rdParty/qxt/qxtglobal.h new file mode 100644 index 0000000..7d5abfb --- /dev/null +++ b/source/3rdParty/qxt/qxtglobal.h @@ -0,0 +1,233 @@ + +/**************************************************************************** +** Copyright (c) 2006 - 2011, the LibQxt project. +** See the Qxt AUTHORS file for a list of authors and copyright holders. +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** * Neither the name of the LibQxt project nor the +** names of its contributors may be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +** DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +** +** +*****************************************************************************/ + +#ifndef QXTGLOBAL_H +#define QXTGLOBAL_H + +#include + +#define QXT_VERSION 0x000700 +#define QXT_VERSION_STR "0.7.0" + +//--------------------------global macros------------------------------ + +#ifndef QXT_NO_MACROS + +#ifndef _countof +#define _countof(x) (sizeof(x)/sizeof(*x)) +#endif + +#endif // QXT_NO_MACROS + +//--------------------------export macros------------------------------ + +#define QXT_DLLEXPORT DO_NOT_USE_THIS_ANYMORE + +#if !defined(QXT_STATIC) && !defined(QXT_DOXYGEN_RUN) +# if defined(BUILD_QXT_CORE) +# define QXT_CORE_EXPORT Q_DECL_EXPORT +# else +# define QXT_CORE_EXPORT Q_DECL_IMPORT +# endif +#else +# define QXT_CORE_EXPORT +#endif // BUILD_QXT_CORE + +#if !defined(QXT_STATIC) && !defined(QXT_DOXYGEN_RUN) +# if defined(BUILD_QXT_GUI) +# define QXT_GUI_EXPORT Q_DECL_EXPORT +# else +# define QXT_GUI_EXPORT Q_DECL_IMPORT +# endif +#else +# define QXT_GUI_EXPORT +#endif // BUILD_QXT_GUI + +#if !defined(QXT_STATIC) && !defined(QXT_DOXYGEN_RUN) +# if defined(BUILD_QXT_NETWORK) +# define QXT_NETWORK_EXPORT Q_DECL_EXPORT +# else +# define QXT_NETWORK_EXPORT Q_DECL_IMPORT +# endif +#else +# define QXT_NETWORK_EXPORT +#endif // BUILD_QXT_NETWORK + +#if !defined(QXT_STATIC) && !defined(QXT_DOXYGEN_RUN) +# if defined(BUILD_QXT_SQL) +# define QXT_SQL_EXPORT Q_DECL_EXPORT +# else +# define QXT_SQL_EXPORT Q_DECL_IMPORT +# endif +#else +# define QXT_SQL_EXPORT +#endif // BUILD_QXT_SQL + +#if !defined(QXT_STATIC) && !defined(QXT_DOXYGEN_RUN) +# if defined(BUILD_QXT_WEB) +# define QXT_WEB_EXPORT Q_DECL_EXPORT +# else +# define QXT_WEB_EXPORT Q_DECL_IMPORT +# endif +#else +# define QXT_WEB_EXPORT +#endif // BUILD_QXT_WEB + +#if !defined(QXT_STATIC) && !defined(QXT_DOXYGEN_RUN) +# if defined(BUILD_QXT_BERKELEY) +# define QXT_BERKELEY_EXPORT Q_DECL_EXPORT +# else +# define QXT_BERKELEY_EXPORT Q_DECL_IMPORT +# endif +#else +# define QXT_BERKELEY_EXPORT +#endif // BUILD_QXT_BERKELEY + +#if !defined(QXT_STATIC) && !defined(QXT_DOXYGEN_RUN) +# if defined(BUILD_QXT_ZEROCONF) +# define QXT_ZEROCONF_EXPORT Q_DECL_EXPORT +# else +# define QXT_ZEROCONF_EXPORT Q_DECL_IMPORT +# endif +#else +# define QXT_ZEROCONF_EXPORT +#endif // QXT_ZEROCONF_EXPORT + +#if defined(BUILD_QXT_CORE) || defined(BUILD_QXT_GUI) || defined(BUILD_QXT_SQL) || defined(BUILD_QXT_NETWORK) || defined(BUILD_QXT_WEB) || defined(BUILD_QXT_BERKELEY) || defined(BUILD_QXT_ZEROCONF) +# define BUILD_QXT +#endif + +QXT_CORE_EXPORT const char* qxtVersion(); + +#ifndef QT_BEGIN_NAMESPACE +#define QT_BEGIN_NAMESPACE +#endif + +#ifndef QT_END_NAMESPACE +#define QT_END_NAMESPACE +#endif + +#ifndef QT_FORWARD_DECLARE_CLASS +#define QT_FORWARD_DECLARE_CLASS(Class) class Class; +#endif + +/**************************************************************************** +** This file is derived from code bearing the following notice: +** The sole author of this file, Adam Higerd, has explicitly disclaimed all +** copyright interest and protection for the content within. This file has +** been placed in the public domain according to United States copyright +** statute and case law. In jurisdictions where this public domain dedication +** is not legally recognized, anyone who receives a copy of this file is +** permitted to use, modify, duplicate, and redistribute this file, in whole +** or in part, with no restrictions or conditions. In these jurisdictions, +** this file shall be copyright (C) 2006-2008 by Adam Higerd. +****************************************************************************/ + +#define QXT_DECLARE_PRIVATE(PUB) friend class PUB##Private; QxtPrivateInterface qxt_d; +#define QXT_DECLARE_PUBLIC(PUB) friend class PUB; +#define QXT_INIT_PRIVATE(PUB) qxt_d.setPublic(this); +#define QXT_D(PUB) PUB##Private& d = qxt_d() +#define QXT_P(PUB) PUB& p = qxt_p() + +template +class QxtPrivate +{ +public: + virtual ~QxtPrivate() + {} + inline void QXT_setPublic(PUB* pub) + { + qxt_p_ptr = pub; + } + +protected: + inline PUB& qxt_p() + { + return *qxt_p_ptr; + } + inline const PUB& qxt_p() const + { + return *qxt_p_ptr; + } + inline PUB* qxt_ptr() + { + return qxt_p_ptr; + } + inline const PUB* qxt_ptr() const + { + return qxt_p_ptr; + } + +private: + PUB* qxt_p_ptr; +}; + +template +class QxtPrivateInterface +{ + friend class QxtPrivate; +public: + QxtPrivateInterface() + { + pvt = new PVT; + } + ~QxtPrivateInterface() + { + delete pvt; + } + + inline void setPublic(PUB* pub) + { + pvt->QXT_setPublic(pub); + } + inline PVT& operator()() + { + return *static_cast(pvt); + } + inline const PVT& operator()() const + { + return *static_cast(pvt); + } + inline PVT * operator->() + { + return static_cast(pvt); + } + inline const PVT * operator->() const + { + return static_cast(pvt); + } +private: + QxtPrivateInterface(const QxtPrivateInterface&) { } + QxtPrivateInterface& operator=(const QxtPrivateInterface&) { } + QxtPrivate* pvt; +}; + +#endif // QXT_GLOBAL diff --git a/source/3rdParty/qxt/qxtglobalshortcut.cpp b/source/3rdParty/qxt/qxtglobalshortcut.cpp new file mode 100644 index 0000000..d2f2e51 --- /dev/null +++ b/source/3rdParty/qxt/qxtglobalshortcut.cpp @@ -0,0 +1,234 @@ +#include "qxtglobalshortcut.h" +/**************************************************************************** +** Copyright (c) 2006 - 2011, the LibQxt project. +** See the Qxt AUTHORS file for a list of authors and copyright holders. +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** * Neither the name of the LibQxt project nor the +** names of its contributors may be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +** DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +** +** +*****************************************************************************/ + +#include "qxtglobalshortcut_p.h" +#include +#include + +#ifndef Q_OS_MAC +int QxtGlobalShortcutPrivate::ref = 0; +#endif // Q_OS_MAC +QHash, QxtGlobalShortcut*> QxtGlobalShortcutPrivate::shortcuts; + +QxtGlobalShortcutPrivate::QxtGlobalShortcutPrivate() + : enabled(true) + , key(Qt::Key(0)) + , mods(Qt::NoModifier) + , nativeKey(0) + , nativeMods(0) + , registered(false) +{ +#ifndef Q_OS_MAC + if (ref == 0) { + QAbstractEventDispatcher::instance()->installNativeEventFilter(this); + } + ++ref; +#endif // Q_OS_MAC +} + +QxtGlobalShortcutPrivate::~QxtGlobalShortcutPrivate() +{ + unsetShortcut(); + +#ifndef Q_OS_MAC + --ref; + if (ref == 0) { + QAbstractEventDispatcher *ed = QAbstractEventDispatcher::instance(); + if (ed != 0) { + ed->removeNativeEventFilter(this); + } + } +#endif // Q_OS_MAC +} + +#include + +bool QxtGlobalShortcutPrivate::setShortcut(const QKeySequence& shortcut) +{ + unsetShortcut(); + +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + Qt::Key key = shortcut[0].key(); + Qt::KeyboardModifiers mods = shortcut[0].keyboardModifiers(); +#else + const Qt::KeyboardModifiers allMods = + Qt::ShiftModifier | Qt::ControlModifier | Qt::AltModifier | Qt::MetaModifier; + const uint xkeyCode = shortcut[0]; + // WORKAROUND: Qt has convert some keys to upper case which + // breaks some shortcuts on some keyboard layouts. + const uint keyCode = QChar::toLower(xkeyCode & ~allMods); + + key = Qt::Key(keyCode); + mods = Qt::KeyboardModifiers(xkeyCode & allMods); +#endif + nativeKey = nativeKeycode(key); + nativeMods = nativeModifiers(mods); + + registered = registerShortcut(nativeKey, nativeMods); + if (registered) + shortcuts.insert(qMakePair(nativeKey, nativeMods), &qxt_p()); + + return registered; +} + +bool QxtGlobalShortcutPrivate::unsetShortcut() +{ + if (registered + && shortcuts.value(qMakePair(nativeKey, nativeMods)) == &qxt_p() + && unregisterShortcut(nativeKey, nativeMods)) + { + shortcuts.remove(qMakePair(nativeKey, nativeMods)); + registered = false; + return true; + } + + return false; +} + +void QxtGlobalShortcutPrivate::activateShortcut(quint32 nativeKey, quint32 nativeMods) +{ + QxtGlobalShortcut* shortcut = shortcuts.value(qMakePair(nativeKey, nativeMods)); + if (shortcut && shortcut->isEnabled()) + emit shortcut->activated(shortcut); +} + +/*! + \class QxtGlobalShortcut + \inmodule QxtWidgets + \brief The QxtGlobalShortcut class provides a global shortcut aka "hotkey". + + A global shortcut triggers even if the application is not active. This + makes it easy to implement applications that react to certain shortcuts + still if some other application is active or if the application is for + example minimized to the system tray. + + Example usage: + \code + QxtGlobalShortcut* shortcut = new QxtGlobalShortcut(window); + connect(shortcut, SIGNAL(activated()), window, SLOT(toggleVisibility())); + shortcut->setShortcut(QKeySequence("Ctrl+Shift+F12")); + \endcode + + \bold {Note:} Since Qxt 0.6 QxtGlobalShortcut no more requires QxtApplication. + */ + +/*! + \fn QxtGlobalShortcut::activated() + + This signal is emitted when the user types the shortcut's key sequence. + + \sa shortcut + */ + +/*! + Constructs a new QxtGlobalShortcut with \a parent. + */ +QxtGlobalShortcut::QxtGlobalShortcut(QObject* parent) + : QObject(parent) +{ + QXT_INIT_PRIVATE(QxtGlobalShortcut); +} + +/*! + Constructs a new QxtGlobalShortcut with \a shortcut and \a parent. + */ +QxtGlobalShortcut::QxtGlobalShortcut(const QKeySequence& shortcut, QObject* parent) + : QObject(parent) +{ + QXT_INIT_PRIVATE(QxtGlobalShortcut); + setShortcut(shortcut); +} + +/*! + Destructs the QxtGlobalShortcut. + */ +QxtGlobalShortcut::~QxtGlobalShortcut() +{ +} + +/*! + \property QxtGlobalShortcut::shortcut + \brief the shortcut key sequence + + \bold {Note:} Notice that corresponding key press and release events are not + delivered for registered global shortcuts even if they are disabled. + Also, comma separated key sequences are not supported. + Only the first part is used: + + \code + qxtShortcut->setShortcut(QKeySequence("Ctrl+Alt+A,Ctrl+Alt+B")); + Q_ASSERT(qxtShortcut->shortcut() == QKeySequence("Ctrl+Alt+A")); + \endcode + */ +QKeySequence QxtGlobalShortcut::shortcut() const +{ + return QKeySequence(qxt_d().key | qxt_d().mods); +} + +bool QxtGlobalShortcut::setShortcut(const QKeySequence& shortcut) +{ + return qxt_d().setShortcut(shortcut); +} + +/*! + \property QxtGlobalShortcut::enabled + \brief whether the shortcut is enabled + + A disabled shortcut does not get activated. + + The default value is \c true. + + \sa setDisabled() + */ +bool QxtGlobalShortcut::isEnabled() const +{ + return qxt_d().enabled; +} + +bool QxtGlobalShortcut::isValid() const +{ + return qxt_d().registered; +} + +void QxtGlobalShortcut::setEnabled(bool enabled) +{ + qxt_d().enabled = enabled; +} + +/*! + Sets the shortcut \a disabled. + + \sa enabled + */ +void QxtGlobalShortcut::setDisabled(bool disabled) +{ + qxt_d().enabled = !disabled; +} diff --git a/source/3rdParty/qxt/qxtglobalshortcut.h b/source/3rdParty/qxt/qxtglobalshortcut.h new file mode 100644 index 0000000..3f6f21e --- /dev/null +++ b/source/3rdParty/qxt/qxtglobalshortcut.h @@ -0,0 +1,66 @@ +#ifndef QXTGLOBALSHORTCUT_H +/**************************************************************************** +** Copyright (c) 2006 - 2011, the LibQxt project. +** See the Qxt AUTHORS file for a list of authors and copyright holders. +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** * Neither the name of the LibQxt project nor the +** names of its contributors may be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +** DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +** +** +*****************************************************************************/ + +#define QXTGLOBALSHORTCUT_H + +#include "qxtglobal.h" +#include +#include +class QxtGlobalShortcutPrivate; + +class QXT_GUI_EXPORT QxtGlobalShortcut : public QObject +{ + Q_OBJECT + QXT_DECLARE_PRIVATE(QxtGlobalShortcut) + Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled) + Q_PROPERTY(QKeySequence shortcut READ shortcut WRITE setShortcut) + +public: + explicit QxtGlobalShortcut(QObject* parent = 0); + explicit QxtGlobalShortcut(const QKeySequence& shortcut, QObject* parent = 0); + virtual ~QxtGlobalShortcut(); + + QKeySequence shortcut() const; + bool setShortcut(const QKeySequence& shortcut); + + bool isEnabled() const; + + bool isValid() const; + +public Q_SLOTS: + void setEnabled(bool enabled = true); + void setDisabled(bool disabled = true); + +Q_SIGNALS: + void activated(QxtGlobalShortcut *self); +}; + +#endif // QXTGLOBALSHORTCUT_H diff --git a/source/3rdParty/qxt/qxtglobalshortcut_mac.cpp b/source/3rdParty/qxt/qxtglobalshortcut_mac.cpp new file mode 100644 index 0000000..ec681fe --- /dev/null +++ b/source/3rdParty/qxt/qxtglobalshortcut_mac.cpp @@ -0,0 +1,274 @@ +#include +/**************************************************************************** +** Copyright (c) 2006 - 2011, the LibQxt project. +** See the Qxt AUTHORS file for a list of authors and copyright holders. +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** * Neither the name of the LibQxt project nor the +** names of its contributors may be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +** DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +** +** +*****************************************************************************/ + +#include "qxtglobalshortcut_p.h" +#include +#include +#include +#include + +typedef QPair Identifier; +static QMap keyRefs; +static QHash keyIDs; +static quint32 hotKeySerial = 0; +static bool qxt_mac_handler_installed = false; + +OSStatus qxt_mac_handle_hot_key(EventHandlerCallRef nextHandler, EventRef event, void* data) +{ + Q_UNUSED(nextHandler); + Q_UNUSED(data); + if (GetEventClass(event) == kEventClassKeyboard && GetEventKind(event) == kEventHotKeyPressed) + { + EventHotKeyID keyID; + GetEventParameter(event, kEventParamDirectObject, typeEventHotKeyID, NULL, sizeof(keyID), NULL, &keyID); + Identifier id = keyIDs.key(keyID.id); + QxtGlobalShortcutPrivate::activateShortcut(id.second, id.first); + } + return noErr; +} + +quint32 QxtGlobalShortcutPrivate::nativeModifiers(Qt::KeyboardModifiers modifiers) +{ + quint32 native = 0; + if (modifiers & Qt::ShiftModifier) + native |= shiftKey; + if (modifiers & Qt::ControlModifier) + native |= cmdKey; + if (modifiers & Qt::AltModifier) + native |= optionKey; + if (modifiers & Qt::MetaModifier) + native |= controlKey; + if (modifiers & Qt::KeypadModifier) + native |= kEventKeyModifierNumLockMask; + return native; +} + +// This is only here to get it to compile on OSX +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) +bool QxtGlobalShortcutPrivate::nativeEventFilter(const QByteArray & eventType, + void * message, qintptr * result) +#else +bool QxtGlobalShortcutPrivate::nativeEventFilter(const QByteArray & eventType, + void * message, long * result) +#endif +{ + Q_UNUSED(result); + Q_UNUSED(message); + Q_UNUSED(eventType); + + return false; +} + +quint32 QxtGlobalShortcutPrivate::nativeKeycode(Qt::Key key) +{ + UTF16Char ch; + // Constants found in NSEvent.h from AppKit.framework + switch (key) + { + case Qt::Key_Return: + return kVK_Return; + case Qt::Key_Enter: + return kVK_ANSI_KeypadEnter; + case Qt::Key_Tab: + return kVK_Tab; + case Qt::Key_Space: + return kVK_Space; + case Qt::Key_Backspace: + return kVK_Delete; + case Qt::Key_Control: + return kVK_Command; + case Qt::Key_Shift: + return kVK_Shift; + case Qt::Key_CapsLock: + return kVK_CapsLock; + case Qt::Key_Option: + return kVK_Option; + case Qt::Key_Meta: + return kVK_Control; + case Qt::Key_F17: + return kVK_F17; + case Qt::Key_VolumeUp: + return kVK_VolumeUp; + case Qt::Key_VolumeDown: + return kVK_VolumeDown; + case Qt::Key_F18: + return kVK_F18; + case Qt::Key_F19: + return kVK_F19; + case Qt::Key_F20: + return kVK_F20; + case Qt::Key_F5: + return kVK_F5; + case Qt::Key_F6: + return kVK_F6; + case Qt::Key_F7: + return kVK_F7; + case Qt::Key_F3: + return kVK_F3; + case Qt::Key_F8: + return kVK_F8; + case Qt::Key_F9: + return kVK_F9; + case Qt::Key_F11: + return kVK_F11; + case Qt::Key_F13: + return kVK_F13; + case Qt::Key_F16: + return kVK_F16; + case Qt::Key_F14: + return kVK_F14; + case Qt::Key_F10: + return kVK_F10; + case Qt::Key_F12: + return kVK_F12; + case Qt::Key_F15: + return kVK_F15; + case Qt::Key_Help: + return kVK_Help; + case Qt::Key_Home: + return kVK_Home; + case Qt::Key_PageUp: + return kVK_PageUp; + case Qt::Key_Delete: + return kVK_ForwardDelete; + case Qt::Key_F4: + return kVK_F4; + case Qt::Key_End: + return kVK_End; + case Qt::Key_F2: + return kVK_F2; + case Qt::Key_PageDown: + return kVK_PageDown; + case Qt::Key_F1: + return kVK_F1; + case Qt::Key_Left: + return kVK_LeftArrow; + case Qt::Key_Right: + return kVK_RightArrow; + case Qt::Key_Down: + return kVK_DownArrow; + case Qt::Key_Up: + return kVK_UpArrow; + default: + ; + } + + if (key == Qt::Key_Escape) ch = 27; + else if (key == Qt::Key_Return) ch = 13; + else if (key == Qt::Key_Enter) ch = 3; + else if (key == Qt::Key_Tab) ch = 9; + else ch = key; + + CFDataRef currentLayoutData; + TISInputSourceRef currentKeyboard = TISCopyCurrentKeyboardInputSource(); + + if (currentKeyboard == NULL) + return 0; + + currentLayoutData = (CFDataRef)TISGetInputSourceProperty(currentKeyboard, kTISPropertyUnicodeKeyLayoutData); + CFRelease(currentKeyboard); + if (currentLayoutData == NULL) + return 0; + + UCKeyboardLayout* header = (UCKeyboardLayout*)CFDataGetBytePtr(currentLayoutData); + UCKeyboardTypeHeader* table = header->keyboardTypeList; + + uint8_t *data = (uint8_t*)header; + // God, would a little documentation for this shit kill you... + for (quint32 i=0; i < header->keyboardTypeCount; i++) + { + UCKeyStateRecordsIndex* stateRec = 0; + if (table[i].keyStateRecordsIndexOffset != 0) + { + stateRec = reinterpret_cast(data + table[i].keyStateRecordsIndexOffset); + if (stateRec->keyStateRecordsIndexFormat != kUCKeyStateRecordsIndexFormat) stateRec = 0; + } + + UCKeyToCharTableIndex* charTable = reinterpret_cast(data + table[i].keyToCharTableIndexOffset); + if (charTable->keyToCharTableIndexFormat != kUCKeyToCharTableIndexFormat) continue; + + for (quint32 j=0; j < charTable->keyToCharTableCount; j++) + { + UCKeyOutput* keyToChar = reinterpret_cast(data + charTable->keyToCharTableOffsets[j]); + for (quint32 k=0; k < charTable->keyToCharTableSize; k++) + { + if (keyToChar[k] & kUCKeyOutputTestForIndexMask) + { + long idx = keyToChar[k] & kUCKeyOutputGetIndexMask; + if (stateRec && idx < stateRec->keyStateRecordCount) + { + UCKeyStateRecord* rec = reinterpret_cast(data + stateRec->keyStateRecordOffsets[idx]); + if (rec->stateZeroCharData == ch) return k; + } + } + else if (!(keyToChar[k] & kUCKeyOutputSequenceIndexMask) && keyToChar[k] < 0xFFFE) + { + if (keyToChar[k] == ch) return k; + } + } // for k + } // for j + } // for i + return 0; +} + +bool QxtGlobalShortcutPrivate::registerShortcut(quint32 nativeKey, quint32 nativeMods) +{ + if (!qxt_mac_handler_installed) + { + EventTypeSpec t; + t.eventClass = kEventClassKeyboard; + t.eventKind = kEventHotKeyPressed; + InstallApplicationEventHandler(&qxt_mac_handle_hot_key, 1, &t, NULL, NULL); + } + + EventHotKeyID keyID; + keyID.signature = 'cute'; + keyID.id = ++hotKeySerial; + + EventHotKeyRef ref = 0; + bool rv = !RegisterEventHotKey(nativeKey, nativeMods, keyID, GetApplicationEventTarget(), 0, &ref); + if (rv) + { + keyIDs.insert(Identifier(nativeMods, nativeKey), keyID.id); + keyRefs.insert(keyID.id, ref); + } + return rv; +} + +bool QxtGlobalShortcutPrivate::unregisterShortcut(quint32 nativeKey, quint32 nativeMods) +{ + Identifier id(nativeMods, nativeKey); + if (!keyIDs.contains(id)) return false; + + EventHotKeyRef ref = keyRefs.take(keyIDs[id]); + keyIDs.remove(id); + return !UnregisterEventHotKey(ref); +} diff --git a/source/3rdParty/qxt/qxtglobalshortcut_p.h b/source/3rdParty/qxt/qxtglobalshortcut_p.h new file mode 100644 index 0000000..5c30db2 --- /dev/null +++ b/source/3rdParty/qxt/qxtglobalshortcut_p.h @@ -0,0 +1,83 @@ +#ifndef QXTGLOBALSHORTCUT_P_H +/**************************************************************************** +** Copyright (c) 2006 - 2011, the LibQxt project. +** See the Qxt AUTHORS file for a list of authors and copyright holders. +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** * Neither the name of the LibQxt project nor the +** names of its contributors may be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +** DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +** +** +*****************************************************************************/ + +#define QXTGLOBALSHORTCUT_P_H + +#include "qxtglobalshortcut.h" +#include +#include +#include + +#include + +class QxtGlobalShortcutPrivate + : public QxtPrivate + , public QAbstractNativeEventFilter +{ +public: + QXT_DECLARE_PUBLIC(QxtGlobalShortcut) + QxtGlobalShortcutPrivate(); + ~QxtGlobalShortcutPrivate(); + + bool enabled; + Qt::Key key; + Qt::KeyboardModifiers mods; + quint32 nativeKey; + quint32 nativeMods; + bool registered; + + bool setShortcut(const QKeySequence& shortcut); + bool unsetShortcut(); + +# ifndef Q_OS_MAC + static int ref; +# endif // Q_OS_MAC + +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + virtual bool nativeEventFilter(const QByteArray &eventType, void *message, qintptr *result); +#else + virtual bool nativeEventFilter(const QByteArray &eventType, void *message, long *result); +#endif + + + static void activateShortcut(quint32 nativeKey, quint32 nativeMods); + +private: + static quint32 nativeKeycode(Qt::Key keycode); + static quint32 nativeModifiers(Qt::KeyboardModifiers modifiers); + + static bool registerShortcut(quint32 nativeKey, quint32 nativeMods); + static bool unregisterShortcut(quint32 nativeKey, quint32 nativeMods); + + static QHash, QxtGlobalShortcut*> shortcuts; +}; + +#endif // QXTGLOBALSHORTCUT_P_H diff --git a/source/3rdParty/qxt/qxtglobalshortcut_win.cpp b/source/3rdParty/qxt/qxtglobalshortcut_win.cpp new file mode 100644 index 0000000..5bd6022 --- /dev/null +++ b/source/3rdParty/qxt/qxtglobalshortcut_win.cpp @@ -0,0 +1,212 @@ +#include "qxtglobalshortcut_p.h" +/**************************************************************************** +** Copyright (c) 2006 - 2011, the LibQxt project. +** See the Qxt AUTHORS file for a list of authors and copyright holders. +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** * Neither the name of the LibQxt project nor the +** names of its contributors may be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +** DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +** +** +*****************************************************************************/ + +#include + + + +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) +bool QxtGlobalShortcutPrivate::nativeEventFilter(const QByteArray & eventType, + void * message, qintptr * result) +#else +bool QxtGlobalShortcutPrivate::nativeEventFilter(const QByteArray & eventType, + void * message, long * result) +#endif +{ + Q_UNUSED(eventType); + Q_UNUSED(result); + MSG* msg = static_cast(message); + if (msg->message == WM_HOTKEY) + { + const quint32 keycode = HIWORD(msg->lParam); + const quint32 modifiers = LOWORD(msg->lParam); + activateShortcut(keycode, modifiers); + } + return false; +} + +quint32 QxtGlobalShortcutPrivate::nativeModifiers(Qt::KeyboardModifiers modifiers) +{ + // MOD_ALT, MOD_CONTROL, (MOD_KEYUP), MOD_SHIFT, MOD_WIN + quint32 native = 0; + if (modifiers & Qt::ShiftModifier) + native |= MOD_SHIFT; + if (modifiers & Qt::ControlModifier) + native |= MOD_CONTROL; + if (modifiers & Qt::AltModifier) + native |= MOD_ALT; + if (modifiers & Qt::MetaModifier) + native |= MOD_WIN; + // TODO: resolve these? + //if (modifiers & Qt::KeypadModifier) + //if (modifiers & Qt::GroupSwitchModifier) + return native; +} + +quint32 QxtGlobalShortcutPrivate::nativeKeycode(Qt::Key key) +{ + // Here is list of keys that presumably work on most keyboard layouts. + // Default branch is for keys that can change with keyboard layout. + switch (key) + { + case Qt::Key_Escape: + return VK_ESCAPE; + case Qt::Key_Tab: + case Qt::Key_Backtab: + return VK_TAB; + case Qt::Key_Backspace: + return VK_BACK; + case Qt::Key_Return: + case Qt::Key_Enter: + return VK_RETURN; + case Qt::Key_Insert: + return VK_INSERT; + case Qt::Key_Delete: + return VK_DELETE; + case Qt::Key_Pause: + return VK_PAUSE; + case Qt::Key_Print: + return VK_PRINT; + case Qt::Key_Clear: + return VK_CLEAR; + case Qt::Key_Home: + return VK_HOME; + case Qt::Key_End: + return VK_END; + case Qt::Key_Left: + return VK_LEFT; + case Qt::Key_Up: + return VK_UP; + case Qt::Key_Right: + return VK_RIGHT; + case Qt::Key_Down: + return VK_DOWN; + case Qt::Key_PageUp: + return VK_PRIOR; + case Qt::Key_PageDown: + return VK_NEXT; + case Qt::Key_F1: + return VK_F1; + case Qt::Key_F2: + return VK_F2; + case Qt::Key_F3: + return VK_F3; + case Qt::Key_F4: + return VK_F4; + case Qt::Key_F5: + return VK_F5; + case Qt::Key_F6: + return VK_F6; + case Qt::Key_F7: + return VK_F7; + case Qt::Key_F8: + return VK_F8; + case Qt::Key_F9: + return VK_F9; + case Qt::Key_F10: + return VK_F10; + case Qt::Key_F11: + return VK_F11; + case Qt::Key_F12: + return VK_F12; + case Qt::Key_F13: + return VK_F13; + case Qt::Key_F14: + return VK_F14; + case Qt::Key_F15: + return VK_F15; + case Qt::Key_F16: + return VK_F16; + case Qt::Key_F17: + return VK_F17; + case Qt::Key_F18: + return VK_F18; + case Qt::Key_F19: + return VK_F19; + case Qt::Key_F20: + return VK_F20; + case Qt::Key_F21: + return VK_F21; + case Qt::Key_F22: + return VK_F22; + case Qt::Key_F23: + return VK_F23; + case Qt::Key_F24: + return VK_F24; + case Qt::Key_Space: + return VK_SPACE; + case Qt::Key_Asterisk: + return VK_MULTIPLY; + case Qt::Key_Plus: + return VK_ADD; + case Qt::Key_Minus: + return VK_SUBTRACT; + case Qt::Key_Slash: + return VK_DIVIDE; + case Qt::Key_MediaNext: + return VK_MEDIA_NEXT_TRACK; + case Qt::Key_MediaPrevious: + return VK_MEDIA_PREV_TRACK; + case Qt::Key_MediaPlay: + return VK_MEDIA_PLAY_PAUSE; + case Qt::Key_MediaStop: + return VK_MEDIA_STOP; + // couldn't find those in VK_* + //case Qt::Key_MediaLast: + //case Qt::Key_MediaRecord: + case Qt::Key_VolumeDown: + return VK_VOLUME_DOWN; + case Qt::Key_VolumeUp: + return VK_VOLUME_UP; + case Qt::Key_VolumeMute: + return VK_VOLUME_MUTE; + + default: + // Try to get virtual key from current keyboard layout or US. + const HKL layout = GetKeyboardLayout(0); + int vk = VkKeyScanEx(key, layout); + if (vk == -1) { + const HKL layoutUs = GetKeyboardLayout(0x409); + vk = VkKeyScanEx(key, layoutUs); + } + return vk == -1 ? 0 : vk; + } +} + +bool QxtGlobalShortcutPrivate::registerShortcut(quint32 nativeKey, quint32 nativeMods) +{ + return RegisterHotKey(0, nativeMods ^ nativeKey, nativeMods, nativeKey); +} + +bool QxtGlobalShortcutPrivate::unregisterShortcut(quint32 nativeKey, quint32 nativeMods) +{ + return UnregisterHotKey(0, nativeMods ^ nativeKey); +} diff --git a/source/3rdParty/qxt/qxtglobalshortcut_x11.cpp b/source/3rdParty/qxt/qxtglobalshortcut_x11.cpp new file mode 100644 index 0000000..08ad097 --- /dev/null +++ b/source/3rdParty/qxt/qxtglobalshortcut_x11.cpp @@ -0,0 +1,230 @@ +#include "qxtglobalshortcut_p.h" +/**************************************************************************** +** Copyright (c) 2006 - 2011, the LibQxt project. +** See the Qxt AUTHORS file for a list of authors and copyright holders. +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** * Neither the name of the LibQxt project nor the +** names of its contributors may be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +** DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +** +** +*****************************************************************************/ + +#include +#include +#include +#include +#include + +namespace { + +QVector maskModifiers() +{ + return QVector() << 0 << Mod2Mask << LockMask << (Mod2Mask | LockMask); +} + +typedef int (*X11ErrorHandler)(Display* display, XErrorEvent* event); + +class QxtX11ErrorHandler { +public: + static bool error; + + static int qxtX11ErrorHandler(Display* display, XErrorEvent *event) + { + Q_UNUSED(display); + switch (event->error_code) + { + case BadAccess: + case BadValue: + case BadWindow: + if (event->request_code == 33 /* X_GrabKey */ || + event->request_code == 34 /* X_UngrabKey */) + { + error = true; + //TODO: + //char errstr[256]; + //XGetErrorText(dpy, err->error_code, errstr, 256); + } + } + return 0; + } + + QxtX11ErrorHandler() + : m_previousErrorHandler(0) + { + error = false; + m_previousErrorHandler = XSetErrorHandler(qxtX11ErrorHandler); + } + + ~QxtX11ErrorHandler() + { + XSetErrorHandler(m_previousErrorHandler); + } + +private: + X11ErrorHandler m_previousErrorHandler; +}; + +bool QxtX11ErrorHandler::error = false; + +class QxtX11Data { +public: + QxtX11Data() + : m_display(0) + { + QPlatformNativeInterface *native = qApp->platformNativeInterface(); + void *display = native->nativeResourceForScreen(QByteArray("display"), + QGuiApplication::primaryScreen()); + m_display = reinterpret_cast(display); + } + + bool isValid() + { + return m_display != 0; + } + + Display *display() + { + Q_ASSERT(isValid()); + return m_display; + } + + Window rootWindow() + { + return DefaultRootWindow(display()); + } + + bool grabKey(quint32 keycode, quint32 modifiers, Window window) + { + QxtX11ErrorHandler errorHandler; + + foreach (quint32 maskMods, maskModifiers()) { + XGrabKey(display(), keycode, modifiers | maskMods, window, True, + GrabModeAsync, GrabModeAsync); + if (errorHandler.error) + break; + } + + if (errorHandler.error) { + ungrabKey(keycode, modifiers, window); + return false; + } + + return true; + } + + bool ungrabKey(quint32 keycode, quint32 modifiers, Window window) + { + QxtX11ErrorHandler errorHandler; + + foreach (quint32 maskMods, maskModifiers()) { + XUngrabKey(display(), keycode, modifiers | maskMods, window); + } + + return !errorHandler.error; + } + +private: + Display *m_display; +}; + +} // namespace + +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) +bool QxtGlobalShortcutPrivate::nativeEventFilter(const QByteArray & eventType, + void * message, qintptr * result) +#else +bool QxtGlobalShortcutPrivate::nativeEventFilter(const QByteArray & eventType, + void * message, long * result) +#endif +{ + Q_UNUSED(result); + + xcb_key_press_event_t *kev = 0; + if (eventType == "xcb_generic_event_t") { + xcb_generic_event_t* ev = static_cast(message); + if ((ev->response_type & 127) == XCB_KEY_PRESS) + kev = static_cast(message); + } + + if (kev != 0) { + unsigned int keycode = kev->detail; + unsigned int keystate = 0; + if(kev->state & XCB_MOD_MASK_1) + keystate |= Mod1Mask; + if(kev->state & XCB_MOD_MASK_CONTROL) + keystate |= ControlMask; + if(kev->state & XCB_MOD_MASK_4) + keystate |= Mod4Mask; + if(kev->state & XCB_MOD_MASK_SHIFT) + keystate |= ShiftMask; + activateShortcut(keycode, + // Mod1Mask == Alt, Mod4Mask == Meta + keystate & (ShiftMask | ControlMask | Mod1Mask | Mod4Mask)); + } + return false; +} + +quint32 QxtGlobalShortcutPrivate::nativeModifiers(Qt::KeyboardModifiers modifiers) +{ + // ShiftMask, LockMask, ControlMask, Mod1Mask, Mod2Mask, Mod3Mask, Mod4Mask, and Mod5Mask + quint32 native = 0; + if (modifiers & Qt::ShiftModifier) + native |= ShiftMask; + if (modifiers & Qt::ControlModifier) + native |= ControlMask; + if (modifiers & Qt::AltModifier) + native |= Mod1Mask; + if (modifiers & Qt::MetaModifier) + native |= Mod4Mask; + + // TODO: resolve these? + //if (modifiers & Qt::MetaModifier) + //if (modifiers & Qt::KeypadModifier) + //if (modifiers & Qt::GroupSwitchModifier) + return native; +} + +quint32 QxtGlobalShortcutPrivate::nativeKeycode(Qt::Key key) +{ + QxtX11Data x11; + if (!x11.isValid()) + return 0; + + KeySym keysym = XStringToKeysym(QKeySequence(key).toString().toLatin1().data()); + if (keysym == NoSymbol) + keysym = static_cast(key); + + return XKeysymToKeycode(x11.display(), keysym); +} + +bool QxtGlobalShortcutPrivate::registerShortcut(quint32 nativeKey, quint32 nativeMods) +{ + QxtX11Data x11; + return x11.isValid() && x11.grabKey(nativeKey, nativeMods, x11.rootWindow()); +} + +bool QxtGlobalShortcutPrivate::unregisterShortcut(quint32 nativeKey, quint32 nativeMods) +{ + QxtX11Data x11; + return x11.isValid() && x11.ungrabKey(nativeKey, nativeMods, x11.rootWindow()); +} diff --git a/source/AndroidManifest.xml b/source/AndroidManifest.xml deleted file mode 100644 index e5c7d47..0000000 --- a/source/AndroidManifest.xml +++ /dev/null @@ -1,150 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt new file mode 100644 index 0000000..b19c3d9 --- /dev/null +++ b/source/CMakeLists.txt @@ -0,0 +1,543 @@ +cmake_minimum_required(VERSION 3.10) + +set(APP_VERSION 2.2.1) +set(APP_ID "io.github.nuttyartist.notes") +set(APP_AUTHOR "Ruby Mamistvalove") +set(APP_AUTHOR_EMAIL "ruby.mamistvalove@gmail.com") +set(APP_WEBSITE "https://www.get-notes.com/") +set(APP_REPOSITORY "https://github.com/nuttyartist/notes") +string(TIMESTAMP CURRENT_YEAR "%Y") + +# Any of the options below can be changed by passing -D