├── .codespellrc ├── .github ├── CODEOWNERS ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── dependabot.yml └── workflows │ ├── build-linux.yml │ ├── build-macos.yml │ └── codespell.yml ├── .gitignore ├── .gitlab-ci.yml ├── .pre-commit-config.yaml ├── .readthedocs.yaml ├── .weblate ├── AUTHORS ├── CHANGES.md ├── CMakeLists.txt ├── CMakePresets.json ├── Doxyfile ├── HACKING ├── INSTALL ├── LICENSE ├── README.md ├── RELEASE.md ├── appveyor.yml ├── debian ├── changelog ├── compat ├── control ├── copyq.1 ├── copyq.docs ├── copyright ├── manpages ├── rules ├── source │ └── format └── watch ├── docs ├── Makefile ├── autobuild.sh ├── backup.rst ├── basic-usage.rst ├── build-source-code.rst ├── command-examples.rst ├── command-line.rst ├── commands-display.rst ├── commands-script.rst ├── conf.py ├── customize-and-build-the-windows-installer.rst ├── faq.rst ├── fixing-bugs.rst ├── glossary.rst ├── images.rst ├── images │ ├── copyq-menu.png │ ├── copyq-show.png │ ├── encryption-generate-keys.png │ ├── encryption-install.png │ ├── encryption-password.png │ ├── encryption-reload.png │ ├── encryption-tab.png │ ├── encryption-tabs.png │ ├── image-editor.png │ ├── pin-items-shortcuts.png │ ├── synchronize-config.png │ ├── synchronize-formats.png │ ├── tags-add-command.png │ ├── tags-config.png │ └── tags.png ├── index.rst ├── installation.rst ├── keyboard.rst ├── known-issues.rst ├── make.bat ├── password-protection.rst ├── pin-items.rst ├── requirements.txt ├── scripting-api.rst ├── scripting.rst ├── security.rst ├── sessions.rst ├── source-code-overview.rst ├── synchronize.rst ├── tabs-and-items.rst ├── tags.rst ├── text-encoding.rst ├── theme.rst ├── translations.rst ├── writing-commands-and-adding-functionality.rst └── writing-raw-data.rst ├── gpl.txt ├── plugins ├── CMakeLists.txt ├── itemencrypted │ ├── CMakeLists.txt │ ├── itemencrypted.cpp │ ├── itemencrypted.h │ ├── itemencryptedsettings.ui │ └── tests │ │ ├── itemencryptedtests.cpp │ │ └── itemencryptedtests.h ├── itemfakevim │ ├── CMakeLists.txt │ ├── fakevim │ │ ├── LGPL_EXCEPTION.TXT │ │ ├── LICENSE.LGPL │ │ ├── fakevim.png │ │ ├── fakevimactions.cpp │ │ ├── fakevimactions.h │ │ ├── fakevimhandler.cpp │ │ ├── fakevimhandler.h │ │ ├── fakevimtr.h │ │ └── private │ │ │ └── fakevim_export.h │ ├── itemfakevim.cpp │ ├── itemfakevim.h │ ├── itemfakevim.qrc │ ├── itemfakevimsettings.ui │ └── tests │ │ ├── itemfakevimtests.cpp │ │ └── itemfakevimtests.h ├── itemimage │ ├── CMakeLists.txt │ ├── itemimage.cpp │ ├── itemimage.h │ ├── itemimagesettings.ui │ └── tests │ │ ├── itemimagetests.cpp │ │ └── itemimagetests.h ├── itemnotes │ ├── CMakeLists.txt │ ├── itemnotes.cpp │ ├── itemnotes.h │ └── itemnotessettings.ui ├── itempinned │ ├── CMakeLists.txt │ ├── itempinned.cpp │ ├── itempinned.h │ └── tests │ │ ├── itempinnedtests.cpp │ │ └── itempinnedtests.h ├── itemsync │ ├── CMakeLists.txt │ ├── filewatcher.cpp │ ├── filewatcher.h │ ├── itemsync.cpp │ ├── itemsync.h │ ├── itemsyncsettings.ui │ └── tests │ │ ├── itemsynctests.cpp │ │ └── itemsynctests.h ├── itemtags │ ├── CMakeLists.txt │ ├── itemtags.cpp │ ├── itemtags.h │ ├── itemtagssettings.ui │ └── tests │ │ ├── itemtagstests.cpp │ │ └── itemtagstests.h └── itemtext │ ├── CMakeLists.txt │ ├── itemtext.cpp │ ├── itemtext.h │ └── itemtextsettings.ui ├── qxt ├── AUTHORS ├── COPYING ├── qxtglobalshortcut.cpp ├── qxtglobalshortcut.h ├── qxtglobalshortcut_mac.cpp ├── qxtglobalshortcut_p.h ├── qxtglobalshortcut_win.cpp ├── qxtglobalshortcut_x11.cpp └── xcbkeyboard.h ├── shared ├── Info.plist ├── com.github.hluk.copyq.appdata.xml ├── com.github.hluk.copyq.desktop.in ├── copyq-completion ├── copyq.iss ├── flatpak │ ├── README.md │ └── com.github.hluk.copyq.json ├── logo-small.bmp ├── logo.bmp ├── plugins │ └── example.js └── themes │ ├── black.ini │ ├── dark.ini │ ├── forest.ini │ ├── items.css │ ├── light.ini │ ├── main_window.css │ ├── main_window_simple.css │ ├── menu.css │ ├── notification.css │ ├── paper.ini │ ├── simple.ini │ ├── solarized-dark.ini │ ├── solarized-light.ini │ ├── tooltip.css │ └── wine.ini ├── src ├── CMakeLists.txt ├── app │ ├── app.cpp │ ├── app.h │ ├── applicationexceptionhandler.cpp │ ├── applicationexceptionhandler.h │ ├── clipboardclient.cpp │ ├── clipboardclient.h │ ├── clipboardmonitor.cpp │ ├── clipboardmonitor.h │ ├── clipboardownermonitor.cpp │ ├── clipboardownermonitor.h │ ├── clipboardserver.cpp │ └── clipboardserver.h ├── common │ ├── action.cpp │ ├── action.h │ ├── actionhandlerenums.h │ ├── actionoutput.cpp │ ├── actionoutput.h │ ├── actiontablemodel.cpp │ ├── actiontablemodel.h │ ├── appconfig.cpp │ ├── appconfig.h │ ├── client_server.cpp │ ├── client_server.h │ ├── clientsocket.cpp │ ├── clientsocket.h │ ├── clipboarddataguard.cpp │ ├── clipboarddataguard.h │ ├── clipboardmode.h │ ├── command.cpp │ ├── command.h │ ├── commandstatus.h │ ├── commandstore.cpp │ ├── commandstore.h │ ├── common.cpp │ ├── common.h │ ├── config.cpp │ ├── config.h │ ├── contenttype.h │ ├── display.cpp │ ├── display.h │ ├── globalshortcutcommands.cpp │ ├── globalshortcutcommands.h │ ├── log.cpp │ ├── log.h │ ├── messagehandlerforqt.cpp │ ├── messagehandlerforqt.h │ ├── mimetypes.cpp │ ├── mimetypes.h │ ├── navigationstyle.h │ ├── option.cpp │ ├── option.h │ ├── predefinedcommands.cpp │ ├── predefinedcommands.h │ ├── processsignals.h │ ├── regexp.h │ ├── server.cpp │ ├── server.h │ ├── settings.cpp │ ├── settings.h │ ├── shortcuts.cpp │ ├── shortcuts.h │ ├── sleeptimer.h │ ├── tabs.cpp │ ├── tabs.h │ ├── temporaryfile.cpp │ ├── temporaryfile.h │ ├── temporarysettings.cpp │ ├── temporarysettings.h │ ├── textdata.cpp │ ├── textdata.h │ ├── timer.h │ ├── version.cpp.in │ └── version.h ├── copyq.qrc ├── copyq.rc ├── gui │ ├── aboutdialog.cpp │ ├── aboutdialog.h │ ├── actiondialog.cpp │ ├── actiondialog.h │ ├── actionhandler.cpp │ ├── actionhandler.h │ ├── actionhandlerdialog.cpp │ ├── actionhandlerdialog.h │ ├── addcommanddialog.cpp │ ├── addcommanddialog.h │ ├── clipboardbrowser.cpp │ ├── clipboardbrowser.h │ ├── clipboardbrowserplaceholder.cpp │ ├── clipboardbrowserplaceholder.h │ ├── clipboardbrowsershared.h │ ├── clipboarddialog.cpp │ ├── clipboarddialog.h │ ├── clipboardspy.cpp │ ├── clipboardspy.h │ ├── commandaction.cpp │ ├── commandaction.h │ ├── commandcompleter.cpp │ ├── commandcompleter.h │ ├── commandcompleterdocumentation.h │ ├── commanddialog.cpp │ ├── commanddialog.h │ ├── commandedit.cpp │ ├── commandedit.h │ ├── commandhelpbutton.cpp │ ├── commandhelpbutton.h │ ├── commandsyntaxhighlighter.cpp │ ├── commandsyntaxhighlighter.h │ ├── commandwidget.cpp │ ├── commandwidget.h │ ├── configtabappearance.cpp │ ├── configtabappearance.h │ ├── configtabtabs.cpp │ ├── configtabtabs.h │ ├── configurationmanager.cpp │ ├── configurationmanager.h │ ├── execmenu.cpp │ ├── execmenu.h │ ├── fancylineedit.cpp │ ├── fancylineedit.h │ ├── filedialog.cpp │ ├── filedialog.h │ ├── filtercompleter.cpp │ ├── filtercompleter.h │ ├── filterlineedit.cpp │ ├── filterlineedit.h │ ├── fix_icon_id.h │ ├── fromiconid.h │ ├── icon_list.h │ ├── iconfactory.cpp │ ├── iconfactory.h │ ├── iconfont.cpp │ ├── iconfont.h │ ├── icons.h │ ├── iconselectbutton.cpp │ ├── iconselectbutton.h │ ├── iconselectdialog.cpp │ ├── iconselectdialog.h │ ├── iconwidget.cpp │ ├── iconwidget.h │ ├── importexportdialog.cpp │ ├── importexportdialog.h │ ├── itemorderlist.cpp │ ├── itemorderlist.h │ ├── logdialog.cpp │ ├── logdialog.h │ ├── mainwindow.cpp │ ├── mainwindow.h │ ├── menuitems.cpp │ ├── menuitems.h │ ├── navigation.cpp │ ├── navigation.h │ ├── notification.h │ ├── notificationbasic.cpp │ ├── notificationbasic.h │ ├── notificationbutton.h │ ├── notificationdaemon.cpp │ ├── notificationdaemon.h │ ├── notificationnative │ │ ├── notificationnative.cpp │ │ └── notificationnative.h │ ├── pixelratio.h │ ├── pluginwidget.cpp │ ├── pluginwidget.h │ ├── screen.cpp │ ├── screen.h │ ├── selectiondata.cpp │ ├── selectiondata.h │ ├── shortcutbutton.cpp │ ├── shortcutbutton.h │ ├── shortcutdialog.cpp │ ├── shortcutdialog.h │ ├── shortcutswidget.cpp │ ├── shortcutswidget.h │ ├── tabbar.cpp │ ├── tabbar.h │ ├── tabdialog.cpp │ ├── tabdialog.h │ ├── tabicons.cpp │ ├── tabicons.h │ ├── tabpropertieswidget.cpp │ ├── tabpropertieswidget.h │ ├── tabswidgetinterface.h │ ├── tabtree.cpp │ ├── tabtree.h │ ├── tabwidget.cpp │ ├── tabwidget.h │ ├── theme.cpp │ ├── theme.h │ ├── traymenu.cpp │ ├── traymenu.h │ ├── windowgeometryguard.cpp │ └── windowgeometryguard.h ├── images │ ├── fontawesome.ttf │ ├── icon-busy_128x128.png │ ├── icon-busy_16x16.png │ ├── icon-busy_22x22.png │ ├── icon-busy_24x24.png │ ├── icon-busy_32x32.png │ ├── icon-busy_48x48.png │ ├── icon-busy_64x64.png │ ├── icon.icns │ ├── icon.ico │ ├── icon.svg │ ├── icon_1024x1024.png │ ├── icon_128x128.png │ ├── icon_16x16.png │ ├── icon_22x22.png │ ├── icon_24x24.png │ ├── icon_256x256.png │ ├── icon_32x32.png │ ├── icon_48x48.png │ ├── icon_512x512.png │ ├── icon_64x64.png │ ├── icon_mask.svg │ ├── tab_icon.svg │ ├── tab_new.svg │ ├── tab_remove.svg │ └── tab_rename.svg ├── item │ ├── clipboarditem.cpp │ ├── clipboarditem.h │ ├── clipboardmodel.cpp │ ├── clipboardmodel.h │ ├── indexes.cpp │ ├── indexes.h │ ├── itemdelegate.cpp │ ├── itemdelegate.h │ ├── itemeditor.cpp │ ├── itemeditor.h │ ├── itemeditorwidget.cpp │ ├── itemeditorwidget.h │ ├── itemfactory.cpp │ ├── itemfactory.h │ ├── itemfilter.h │ ├── itemsaverwrapper.cpp │ ├── itemsaverwrapper.h │ ├── itemstore.cpp │ ├── itemstore.h │ ├── itemwidget.cpp │ ├── itemwidget.h │ ├── itemwidgetwrapper.cpp │ ├── itemwidgetwrapper.h │ ├── persistentdisplayitem.cpp │ ├── persistentdisplayitem.h │ ├── serialize.cpp │ └── serialize.h ├── knotifications5 │ └── copyq.notifyrc ├── main.cpp ├── notifications.cmake ├── platform │ ├── dummy │ │ ├── dummyclipboard.cpp │ │ ├── dummyclipboard.h │ │ ├── dummyplatform.cpp │ │ └── dummyplatform.h │ ├── mac │ │ ├── copyqpasteboardmime.h │ │ ├── copyqpasteboardmime.mm │ │ ├── foregroundbackgroundfilter.h │ │ ├── foregroundbackgroundfilter.mm │ │ ├── macactivity.h │ │ ├── macactivity.mm │ │ ├── macclipboard.h │ │ ├── macclipboard.mm │ │ ├── macplatform.cmake │ │ ├── macplatform.h │ │ ├── macplatform.mm │ │ ├── macplatformwindow.h │ │ ├── macplatformwindow.mm │ │ ├── mactimer.h │ │ ├── mactimer.mm │ │ ├── urlpasteboardmime.h │ │ └── urlpasteboardmime.mm │ ├── platform.cmake │ ├── platformclipboard.h │ ├── platformcommon.cpp │ ├── platformcommon.h │ ├── platformnativeinterface.h │ ├── platformwindow.h │ ├── unix │ │ ├── unixsignalhandler.cpp │ │ └── unixsignalhandler.h │ ├── win │ │ ├── winplatform.cmake │ │ ├── winplatform.cpp │ │ ├── winplatform.h │ │ ├── winplatformclipboard.cpp │ │ ├── winplatformclipboard.h │ │ ├── winplatformwindow.cpp │ │ └── winplatformwindow.h │ └── x11 │ │ ├── systemclipboard │ │ ├── CMakeLists.txt │ │ ├── keyboard-shortcuts-inhibit-unstable-v1.xml │ │ ├── waylandclipboard.cpp │ │ ├── waylandclipboard.h │ │ └── wlr-data-control-unstable-v1.xml │ │ ├── x11info.cpp │ │ ├── x11info.h │ │ ├── x11platform.cmake │ │ ├── x11platform.cpp │ │ ├── x11platform.h │ │ ├── x11platformclipboard.cpp │ │ ├── x11platformclipboard.h │ │ ├── x11platformwindow.cpp │ │ └── x11platformwindow.h ├── scriptable │ ├── commandhelp.cpp │ ├── commandhelp.h │ ├── scriptable.cpp │ ├── scriptable.h │ ├── scriptablebytearray.cpp │ ├── scriptablebytearray.h │ ├── scriptabledir.cpp │ ├── scriptabledir.h │ ├── scriptablefile.cpp │ ├── scriptablefile.h │ ├── scriptableitemselection.cpp │ ├── scriptableitemselection.h │ ├── scriptablenetworkreply.cpp │ ├── scriptablenetworkreply.h │ ├── scriptablenetworkrequest.cpp │ ├── scriptablenetworkrequest.h │ ├── scriptableproxy.cpp │ ├── scriptableproxy.h │ ├── scriptablesettings.cpp │ ├── scriptablesettings.h │ ├── scriptabletemporaryfile.cpp │ ├── scriptabletemporaryfile.h │ ├── scriptoverrides.h │ └── scriptvaluefactory.h ├── tests │ ├── test_utils.h │ ├── testinterface.h │ ├── tests.cpp │ ├── tests.h │ ├── tests_classes.cpp │ ├── tests_cli.cpp │ ├── tests_commands.cpp │ ├── tests_common.cpp │ ├── tests_common.h │ ├── tests_dialogs.cpp │ ├── tests_drag_n_drop.cpp │ ├── tests_expire.cpp │ ├── tests_items.cpp │ ├── tests_navigation.cpp │ ├── tests_other.cpp │ ├── tests_script_commands.cpp │ ├── tests_scripts.cpp │ ├── tests_slow_clipboard.cpp │ └── tests_tray.cpp ├── ui │ ├── aboutdialog.ui │ ├── actiondialog.ui │ ├── actionhandlerdialog.ui │ ├── addcommanddialog.ui │ ├── clipboarddialog.ui │ ├── commanddialog.ui │ ├── commandedit.ui │ ├── commandwidget.ui │ ├── configtabappearance.ui │ ├── configtabgeneral.ui │ ├── configtabhistory.ui │ ├── configtablayout.ui │ ├── configtabnotifications.ui │ ├── configtabtray.ui │ ├── configurationmanager.ui │ ├── importexportdialog.ui │ ├── itemorderlist.ui │ ├── logdialog.ui │ ├── mainwindow.ui │ ├── pluginwidget.ui │ ├── shortcutdialog.ui │ ├── shortcutswidget.ui │ ├── tabdialog.ui │ └── tabpropertieswidget.ui ├── version.cmake └── version_file.cmake ├── translations ├── copyq_ar.ts ├── copyq_ca.ts ├── copyq_cs.ts ├── copyq_da.ts ├── copyq_de.ts ├── copyq_el.ts ├── copyq_es.ts ├── copyq_fa.ts ├── copyq_fi.ts ├── copyq_fr.ts ├── copyq_ga.ts ├── copyq_he.ts ├── copyq_hr.ts ├── copyq_hu.ts ├── copyq_id.ts ├── copyq_it.ts ├── copyq_ja.ts ├── copyq_kab.ts ├── copyq_ko.ts ├── copyq_lt.ts ├── copyq_nb.ts ├── copyq_nl.ts ├── copyq_pl.ts ├── copyq_pt_BR.ts ├── copyq_pt_PT.ts ├── copyq_ru.ts ├── copyq_sk.ts ├── copyq_sv.ts ├── copyq_tr.ts ├── copyq_uk.ts ├── copyq_vi.ts ├── copyq_zh_CN.ts └── copyq_zh_TW.ts └── utils ├── appveyor ├── after_build.sh ├── before_build.sh ├── build_script.sh ├── env.sh ├── install.sh ├── kf_build.sh ├── patches │ └── knotifications │ │ └── 0001-Support-updating-Snore-notifications.patch ├── test.sh ├── test_screenshots.sh └── trigger_build.sh ├── bump_version.sh ├── copy_files.sh ├── create_source_package.sh ├── debian ├── create_source_packages.sh └── update_changelog.sh ├── download_obs_packages.sh ├── download_window_builds.sh ├── fedora ├── build_sprm.sh └── copyq.spec ├── fix-translations.py ├── fosshub.py ├── generata-big-data-tab.sh ├── github ├── bundle-macos.sh ├── homebrew │ └── Formula │ │ ├── extra-cmake-modules.rb │ │ ├── kf6-kconfig.rb │ │ ├── kf6-knotifications.rb │ │ ├── kf6-kstatusnotifieritem.rb │ │ └── kf6-kwindowsystem.rb ├── install-macos.sh ├── test-linux-global-shortcuts.sh ├── test-linux-wayland.sh ├── test-linux.sh ├── test-signals.sh └── test-start-server.sh ├── gitlab ├── build-before_script.sh ├── build-script.sh ├── test-before_script.sh ├── test-script.sh ├── test_gui-before_script.sh └── test_gui-script.sh ├── launchpad ├── Dockerfile ├── build.sh ├── entrypoint.sh └── run.sh ├── linux_make_icons.sh ├── lupdate.sh ├── make_icns.sh ├── make_ico.sh ├── sanitize.sh ├── script_docs_to_cpp.py ├── sign_released_files.sh ├── test_window_build.sh ├── update_icon_font.py ├── view_windows_screenshots.sh └── windows_copyq_update.sh /.codespellrc: -------------------------------------------------------------------------------- 1 | # Ref: https://github.com/codespell-project/codespell#using-a-config-file 2 | [codespell] 3 | skip = .git,*.pdf,*.svg,go.sum,*.css,.codespellrc,translations,./plugins/itemfakevim/fakevim/* 4 | check-hidden = true 5 | # ignore translations, names, Some&annotations, etc 6 | ignore-regex = (Comment|GenericName)\[.*|\bSimon Ser\b|DoubleClick|{0xf.*, (true|false),.*|\b\S+&(amp;)?\S+\b|.*codespell-ignore.*|\bonTop\b|readLine\(\)=INE 7 | # ignore-words-list = 8 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @hluk 2 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project. 4 | title: '' 5 | labels: feature 6 | assignees: '' 7 | 8 | --- 9 | 10 | 14 | 15 | **Is your feature request related to a problem? Please describe.** 16 | 17 | 18 | **Describe the solution you'd like** 19 | 20 | 21 | **Describe alternatives you've considered** 22 | 23 | 24 | **Additional context** 25 | 26 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "github-actions" 4 | directory: "/" 5 | schedule: 6 | interval: "monthly" 7 | -------------------------------------------------------------------------------- /.github/workflows/codespell.yml: -------------------------------------------------------------------------------- 1 | # Codespell configuration is within .codespellrc 2 | --- 3 | name: Codespell 4 | 5 | on: 6 | push: 7 | branches: [master] 8 | pull_request: 9 | branches: [master] 10 | 11 | permissions: 12 | contents: read 13 | 14 | jobs: 15 | codespell: 16 | name: Check for spelling errors 17 | runs-on: ubuntu-latest 18 | 19 | steps: 20 | - name: Checkout 21 | uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5 22 | - name: Codespell 23 | uses: codespell-project/actions-codespell@406322ec52dd7b488e48c1c4b82e2a8b3a1bf630 # v2 24 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Generated CMake files 2 | CMakeFiles/ 3 | CMakeCache.txt 4 | cmake_install.cmake 5 | 6 | # Generated Visual Studio files 7 | /plugins/Debug/ 8 | /plugins/Release/ 9 | /plugins/Win*/ 10 | /Debug/ 11 | /Release/ 12 | /Win*/ 13 | *.sln 14 | *.suo 15 | *.*sdf 16 | *.vc?proj* 17 | 18 | # Generated Makefiles 19 | /plugins/Makefile 20 | /plugins/*/Makefile 21 | /src/Makefile 22 | /Makefile 23 | 24 | # Generated Qt files 25 | /plugins/**/*.dir/ 26 | /src/copyqcon.dir/ 27 | /src/copyq.dir/ 28 | /src/copyq_*.qm 29 | /src/copyq_*.qm.rule 30 | /src/qrc_copyq.cxx 31 | /src/translations.qrc 32 | /src/qrc_translations.cxx 33 | 34 | moc_* 35 | ui_* 36 | *.depends 37 | *.o 38 | *.dylib 39 | *.moc 40 | **/qrc_*.cpp 41 | /.qmake.cache 42 | /copyq.app 43 | copyq.pro.user* 44 | CMakeLists.txt.user* 45 | .DS_Store 46 | .qmake.stash 47 | *.pyc 48 | *.dmg 49 | /build 50 | *.qm 51 | 52 | # Generated Sphinx files 53 | /docs/_build 54 | 55 | # Generated Flatpak files 56 | /shared/flatpak/.flatpak-builder 57 | /shared/flatpak/copyq 58 | 59 | # Visual Studio Code 60 | /.vscode 61 | 62 | # Files for utils/launchpad/build.sh 63 | .gitconfig 64 | launchpad.key 65 | -------------------------------------------------------------------------------- /.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | --- 2 | image: ubuntu:24.04 3 | 4 | variables: 5 | BUILD_DIR: "build" 6 | INSTALL_PREFIX: "copyq" 7 | SCREENSHOT_DIR: "screenshots" 8 | TESTS_LOG_DIR: "logs" 9 | DEBIAN_FRONTEND: "noninteractive" 10 | 11 | build: 12 | stage: build 13 | 14 | before_script: 15 | - utils/gitlab/build-before_script.sh 16 | 17 | script: 18 | - utils/gitlab/build-script.sh 19 | 20 | # Upload installed application. 21 | artifacts: 22 | paths: 23 | - "$INSTALL_PREFIX" 24 | 25 | cache: 26 | paths: 27 | - build 28 | 29 | # Run simple tests (doesn't require GUI) 30 | test: 31 | stage: test 32 | 33 | before_script: 34 | - utils/gitlab/test-before_script.sh 35 | 36 | script: 37 | - utils/gitlab/test-script.sh 38 | 39 | dependencies: 40 | - build 41 | 42 | # GUI tests (requires X11) 43 | test_gui: 44 | stage: test 45 | 46 | before_script: 47 | - utils/gitlab/test_gui-before_script.sh 48 | 49 | script: 50 | - utils/gitlab/test_gui-script.sh 51 | 52 | # Upload screenshots on failure. 53 | artifacts: 54 | when: on_failure 55 | paths: 56 | - "$SCREENSHOT_DIR" 57 | - "$TESTS_LOG_DIR" 58 | 59 | dependencies: 60 | - build 61 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | repos: 3 | - repo: https://github.com/pre-commit/pre-commit-hooks 4 | rev: v6.0.0 5 | hooks: 6 | - id: check-executables-have-shebangs 7 | - id: check-merge-conflict 8 | - id: check-xml 9 | - id: check-yaml 10 | - id: end-of-file-fixer 11 | - id: trailing-whitespace 12 | -------------------------------------------------------------------------------- /.readthedocs.yaml: -------------------------------------------------------------------------------- 1 | # Read the Docs configuration file for Sphinx projects 2 | # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details 3 | --- 4 | version: 2 5 | 6 | build: 7 | os: ubuntu-22.04 8 | tools: 9 | python: "3.11" 10 | 11 | sphinx: 12 | configuration: docs/conf.py 13 | 14 | python: 15 | install: 16 | - requirements: docs/requirements.txt 17 | -------------------------------------------------------------------------------- /.weblate: -------------------------------------------------------------------------------- 1 | [weblate] 2 | url = https://hosted.weblate.org/api/ 3 | translation = copyq/master 4 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | Adam Batkin 2 | Giacomo Margarito 3 | Greg Carp 4 | Ilya Plenne 5 | Jörg Thalheim 6 | Kim Jzhone 7 | Kos Ivantsov 8 | lightonflux 9 | Lukas Holecek 10 | Marjolein Hoekstra 11 | Martin Lepadusch 12 | Matt d'Entremont 13 | Michal Čihař 14 | Patricio M. Ros 15 | Robert Orzanna 16 | Ryan Wooden 17 | Scott Kostyshak 18 | Sebastian Schuberth 19 | Tomas Nilzon 20 | Wilfried Caruel 21 | x2357 22 | -------------------------------------------------------------------------------- /HACKING: -------------------------------------------------------------------------------- 1 | https://copyq.readthedocs.io/en/latest/build-source-code.html 2 | -------------------------------------------------------------------------------- /INSTALL: -------------------------------------------------------------------------------- 1 | https://copyq.readthedocs.io/en/latest/build-source-code.html 2 | -------------------------------------------------------------------------------- /debian/changelog: -------------------------------------------------------------------------------- 1 | copyq (3.0.3~debian) unstable; urgency=medium 2 | 3 | * New upstream release. 4 | 5 | -- Boyuan Yang <073plan@gmail.com> Wed, 05 Jul 2017 15:50:16 +0800 6 | 7 | copyq (2.9.0~xenial) xenial; urgency=medium 8 | 9 | * v2.9.0 10 | 11 | -- Lukas Holecek Fri, 10 Mar 2017 10:10:00 +0200 12 | -------------------------------------------------------------------------------- /debian/compat: -------------------------------------------------------------------------------- 1 | 10 2 | -------------------------------------------------------------------------------- /debian/copyq.docs: -------------------------------------------------------------------------------- 1 | AUTHORS 2 | HACKING 3 | README.md 4 | -------------------------------------------------------------------------------- /debian/manpages: -------------------------------------------------------------------------------- 1 | debian/copyq.1 2 | -------------------------------------------------------------------------------- /debian/rules: -------------------------------------------------------------------------------- 1 | #!/usr/bin/make -f 2 | 3 | # Uncomment this to turn on verbose mode. 4 | #export DH_VERBOSE=1 5 | 6 | export DEB_BUILD_MAINT_OPTIONS = hardening=+all 7 | export DEB_LDFLAGS_MAINT_APPEND += -Wl,--as-needed 8 | export QT_SELECT=5 9 | 10 | %: 11 | dh $@ 12 | 13 | override_dh_auto_configure: 14 | dh_auto_configure -- \ 15 | -DCMAKE_VERBOSE_MAKEFILE=ON \ 16 | -DCMAKE_BUILD_TYPE=Release \ 17 | -DWITH_QT6=OFF 18 | -------------------------------------------------------------------------------- /debian/source/format: -------------------------------------------------------------------------------- 1 | 3.0 (quilt) 2 | -------------------------------------------------------------------------------- /debian/watch: -------------------------------------------------------------------------------- 1 | version=4 2 | opts="filenamemangle=s%(?:.*?)?v?(\d[\d.]*)\.tar\.gz%copyq-$1.tar.gz%" \ 3 | https://github.com/hluk/CopyQ/tags \ 4 | (?:.*?/)?v?(\d[\d.]*)\.tar\.gz debian uupdate 5 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = 6 | SPHINXBUILD = python -msphinx 7 | SPHINXPROJ = CopyQ 8 | SOURCEDIR = . 9 | BUILDDIR = _build 10 | 11 | # Put it first so that "make" without argument is like "make help". 12 | help: 13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 14 | 15 | .PHONY: help Makefile 16 | 17 | # Catch-all target: route all unknown targets to Sphinx using the new 18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 19 | %: Makefile 20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 21 | -------------------------------------------------------------------------------- /docs/autobuild.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Automatically re-build the documentation whenever it changes. 3 | # 4 | # Requires sphinx-autobuild script: 5 | # 6 | # pip install --user sphinx-autobuild 7 | # export PATH="$HOME/.local/bin:$PATH" 8 | # 9 | exec sphinx-autobuild \ 10 | --ignore '.*' \ 11 | --ignore "*.swp" \ 12 | --ignore "*~" \ 13 | . _build/html 14 | -------------------------------------------------------------------------------- /docs/command-line.rst: -------------------------------------------------------------------------------- 1 | Command Line 2 | ============ 3 | 4 | Tabs, items, clipboard and configuration can be changed through command 5 | line interface. Run command ``copyq help`` to see complete list of 6 | commands and their description. 7 | 8 | .. warning:: 9 | 10 | On Windows, you may not see any output when executing CopyQ in 11 | terminal/console (PowerShell or cmd). 12 | 13 | See workarounds in :ref:`known-issue-windows-console-output`. 14 | 15 | To add new item to tab with name "notes" run: 16 | 17 | :: 18 | 19 | copyq tab notes add "This is the first note." 20 | 21 | To print the item: 22 | 23 | :: 24 | 25 | copyq tab notes read 0 26 | 27 | Add other item: 28 | 29 | :: 30 | 31 | copyq tab notes add "This is second note." 32 | 33 | and print all items in the tab: 34 | 35 | :: 36 | 37 | copyq eval -- "tab('notes'); for(i=size(); i>0; --i) print(str(read(i-1)) + '\n');" 38 | 39 | This will print: 40 | 41 | :: 42 | 43 | This is the first note. 44 | This is second note. 45 | 46 | Among other things that are possible with CopyQ are: 47 | 48 | * open video player if text copied in clipboard is URL with multimedia 49 | * store text copied from a code editor in "code" tab 50 | * store URLs in different tab 51 | * save screenshots (print-screen) 52 | * load all files from directory to items (create image gallery) 53 | * replace a text in all matching items 54 | * run item as a Python script 55 | -------------------------------------------------------------------------------- /docs/commands-display.rst: -------------------------------------------------------------------------------- 1 | .. _commands-display: 2 | 3 | Display Commands 4 | ================ 5 | 6 | Display command is type of command that modifies item data before displaying. 7 | The modified data are only used for displaying the item and are not stored. 8 | 9 | The command is executed just before an item needs to be displayed. This can 10 | sometimes happen multiple times for the same item if the data or 11 | configuration changes or the tab was unloaded. 12 | 13 | Display commands can be created in Command dialog by setting Type of Action 14 | to :ref:`command-dialog-display`. 15 | 16 | Use ``data()`` to retrieve current item data and ``setData()`` to set the 17 | data to display (these are not stored permanently). 18 | 19 | E.g. use slightly different color for plain text items. 20 | 21 | .. code-block:: js 22 | 23 | copyq: 24 | if ( str(data(mimeText)) && !str(data(mimeHtml)) ) { 25 | html = escapeHtml(data(mimeText)) 26 | setData(mimeHtml, '' + html + '') 27 | } 28 | 29 | E.g. try to interpret text as Markdown (with ``marked`` external utility). 30 | 31 | .. code-block:: js 32 | 33 | copyq: 34 | var text = data(mimeText) 35 | var result = execute('marked', null, text) 36 | if (result && result.exit_code == 0) { 37 | setData(mimeHtml, result.stdout) 38 | } 39 | -------------------------------------------------------------------------------- /docs/customize-and-build-the-windows-installer.rst: -------------------------------------------------------------------------------- 1 | Customize and Build the Windows Installer 2 | ========================================= 3 | 4 | Translations 5 | ------------ 6 | 7 | Most of the translations for the installer are taken directly from the 8 | installer generator Inno Setup (http://www.jrsoftware.org/isinfo.php). 9 | 10 | You can add translations for CopyQ-specific messages in 11 | ``shared/copyq.iss``. Just copy lines starting with ``en.`` from 12 | ``[Custom Messages]`` section and change prefix to ``de.`` (for german 13 | translation). 14 | 15 | Modify and Test Installation 16 | ---------------------------- 17 | 18 | Normally the installation file is generated automatically by Appveyor 19 | which executes 20 | `appveyor-after-build.bat `__ 21 | to generate portable app folder from build files and runs Inno Setup 22 | (the last line). 23 | 24 | You don't have to build the app again, you just need: 25 | 26 | 1. Download the unzipped portable version of the app. 27 | 2. Clone of this repository. 28 | 3. Install `Inno Setup `__. 29 | 4. Open 30 | `shared/copyq.iss `__ 31 | in Inno Setup and add few lines at the beginning of the file. 32 | 33 | :: 34 | 35 | #define AppVersion 2.8.1-beta 36 | #define Source C:\path\to\CopyQ-repository-clone 37 | #define Destination C:\path\to\CopyQ-portable 38 | 39 | You should now be able to modify the file in Inno Setup and run it 40 | easily. 41 | -------------------------------------------------------------------------------- /docs/glossary.rst: -------------------------------------------------------------------------------- 1 | .. _glossary: 2 | 3 | Glossary 4 | ======== 5 | 6 | Here is a list of frequent terms from CopyQ. 7 | 8 | - Action - a command run from Action dialog 9 | - Clipboard - system clipboard that stores and provides copied stuff (``Ctrl+C``) 10 | - Command - user-defined command or script executed by the app 11 | - Item - element stored in a tab, usually automatically created from a new clipboard content 12 | - Main window - main application window shown by selecting "Show" from tray menu 13 | - Plugin - a binary file which adds some functionality when app starts 14 | - Process - an executed command 15 | - Script - simple code written in internal scripting language used by the app 16 | - Tray - tray or notification area in panel, contains small icons for various applications 17 | - Tray menu - menu invoked from app icon in tray (usually by right mouse button click) 18 | - Tab - container for multiple items, similar to tabs in modern web browsers 19 | -------------------------------------------------------------------------------- /docs/images/copyq-menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hluk/CopyQ/d54623cf916577a1bed76353a8e8ac482a71cbc9/docs/images/copyq-menu.png -------------------------------------------------------------------------------- /docs/images/copyq-show.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hluk/CopyQ/d54623cf916577a1bed76353a8e8ac482a71cbc9/docs/images/copyq-show.png -------------------------------------------------------------------------------- /docs/images/encryption-generate-keys.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hluk/CopyQ/d54623cf916577a1bed76353a8e8ac482a71cbc9/docs/images/encryption-generate-keys.png -------------------------------------------------------------------------------- /docs/images/encryption-install.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hluk/CopyQ/d54623cf916577a1bed76353a8e8ac482a71cbc9/docs/images/encryption-install.png -------------------------------------------------------------------------------- /docs/images/encryption-password.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hluk/CopyQ/d54623cf916577a1bed76353a8e8ac482a71cbc9/docs/images/encryption-password.png -------------------------------------------------------------------------------- /docs/images/encryption-reload.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hluk/CopyQ/d54623cf916577a1bed76353a8e8ac482a71cbc9/docs/images/encryption-reload.png -------------------------------------------------------------------------------- /docs/images/encryption-tab.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hluk/CopyQ/d54623cf916577a1bed76353a8e8ac482a71cbc9/docs/images/encryption-tab.png -------------------------------------------------------------------------------- /docs/images/encryption-tabs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hluk/CopyQ/d54623cf916577a1bed76353a8e8ac482a71cbc9/docs/images/encryption-tabs.png -------------------------------------------------------------------------------- /docs/images/image-editor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hluk/CopyQ/d54623cf916577a1bed76353a8e8ac482a71cbc9/docs/images/image-editor.png -------------------------------------------------------------------------------- /docs/images/pin-items-shortcuts.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hluk/CopyQ/d54623cf916577a1bed76353a8e8ac482a71cbc9/docs/images/pin-items-shortcuts.png -------------------------------------------------------------------------------- /docs/images/synchronize-config.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hluk/CopyQ/d54623cf916577a1bed76353a8e8ac482a71cbc9/docs/images/synchronize-config.png -------------------------------------------------------------------------------- /docs/images/synchronize-formats.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hluk/CopyQ/d54623cf916577a1bed76353a8e8ac482a71cbc9/docs/images/synchronize-formats.png -------------------------------------------------------------------------------- /docs/images/tags-add-command.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hluk/CopyQ/d54623cf916577a1bed76353a8e8ac482a71cbc9/docs/images/tags-add-command.png -------------------------------------------------------------------------------- /docs/images/tags-config.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hluk/CopyQ/d54623cf916577a1bed76353a8e8ac482a71cbc9/docs/images/tags-config.png -------------------------------------------------------------------------------- /docs/images/tags.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hluk/CopyQ/d54623cf916577a1bed76353a8e8ac482a71cbc9/docs/images/tags.png -------------------------------------------------------------------------------- /docs/index.rst: -------------------------------------------------------------------------------- 1 | Welcome to CopyQ's documentation! 2 | ================================= 3 | 4 | CopyQ is clipboard manager -- a desktop application which stores content of the 5 | system clipboard whenever it changes and allows to search the history and copy 6 | it back to the system clipboard or paste it directly to other applications. 7 | 8 | This documentation describes some basic concepts and workflows as well as more 9 | advanced topics like scripting and application development process. 10 | 11 | .. toctree:: 12 | :caption: The Basics 13 | :maxdepth: 2 14 | 15 | installation 16 | basic-usage 17 | tabs-and-items 18 | keyboard 19 | images 20 | tags 21 | security 22 | theme 23 | faq 24 | known-issues 25 | glossary 26 | 27 | .. toctree:: 28 | :caption: Advanced Topics 29 | :maxdepth: 2 30 | 31 | command-line 32 | sessions 33 | pin-items 34 | password-protection 35 | synchronize 36 | writing-commands-and-adding-functionality 37 | scripting 38 | command-examples 39 | commands-script 40 | commands-display 41 | backup 42 | writing-raw-data 43 | scripting-api 44 | 45 | .. toctree:: 46 | :caption: Development 47 | :maxdepth: 2 48 | 49 | build-source-code 50 | fixing-bugs 51 | source-code-overview 52 | translations 53 | text-encoding 54 | customize-and-build-the-windows-installer 55 | -------------------------------------------------------------------------------- /docs/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | pushd %~dp0 4 | 5 | REM Command file for Sphinx documentation 6 | 7 | if "%SPHINXBUILD%" == "" ( 8 | set SPHINXBUILD=python -msphinx 9 | ) 10 | set SOURCEDIR=. 11 | set BUILDDIR=_build 12 | set SPHINXPROJ=CopyQ 13 | 14 | if "%1" == "" goto help 15 | 16 | %SPHINXBUILD% >NUL 2>NUL 17 | if errorlevel 9009 ( 18 | echo. 19 | echo.The Sphinx module was not found. Make sure you have Sphinx installed, 20 | echo.then set the SPHINXBUILD environment variable to point to the full 21 | echo.path of the 'sphinx-build' executable. Alternatively you may add the 22 | echo.Sphinx directory to PATH. 23 | echo. 24 | echo.If you don't have Sphinx installed, grab it from 25 | echo.http://sphinx-doc.org/ 26 | exit /b 1 27 | ) 28 | 29 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% 30 | goto end 31 | 32 | :help 33 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% 34 | 35 | :end 36 | popd 37 | -------------------------------------------------------------------------------- /docs/requirements.txt: -------------------------------------------------------------------------------- 1 | sphinx==7.2.6 2 | sphinx-rtd-theme==1.3.0 3 | -------------------------------------------------------------------------------- /docs/text-encoding.rst: -------------------------------------------------------------------------------- 1 | Text Encoding 2 | ============= 3 | 4 | This page serves as concept for adding additional CopyQ command line 5 | switch to print and read texts in UTF-8 (i.e. without using system 6 | encoding). 7 | 8 | Every time the bytes are read from a command (standard output or 9 | arguments from client) the input is expected to be either just series of 10 | bytes or text in system encoding (possibly Latin1 on Windows). But 11 | texts/strings in CopyQ and in clipboard are UTF-8 formatted (except some 12 | MIME types with specified encoding). 13 | 14 | When reading system-encoded text (MIME starts with "text/") CopyQ 15 | re-encodes the data from system encoding to UTF-8. That's not a problem 16 | if the received data is really in system encoding. But if you send data 17 | from Perl with the UTF-8 switch, CopyQ must also know that UTF-8 is used 18 | instead of system encoding. 19 | 20 | The same goes for other way. CopyQ sends texts back to client or to a 21 | command in system encoding so it needs to convert these texts from 22 | UTF-8. 23 | 24 | As for the re-encoding part, Qt does nice job transforming characters 25 | from UTF-8 but of course for lot of characters in UTF-8 there is no 26 | alternative in Latin1 and other encodings. 27 | -------------------------------------------------------------------------------- /docs/writing-raw-data.rst: -------------------------------------------------------------------------------- 1 | Writing Raw Data 2 | ================ 3 | 4 | Application allows you to save any kind of data using *drag and drop* or 5 | scripting interface. 6 | 7 | To add an image to ``Images`` tab you can run: 8 | 9 | :: 10 | 11 | cat image1.png | copyq tab Images write image/png - 12 | 13 | This works for any other MIME data type (though unknown formats won't be 14 | displayed properly). 15 | -------------------------------------------------------------------------------- /plugins/itemencrypted/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(copyq_plugin_itemencrypted_SOURCES 2 | ../../src/common/command.cpp 3 | ../../src/common/config.cpp 4 | ../../src/common/mimetypes.cpp 5 | ../../src/common/shortcuts.cpp 6 | ../../src/common/textdata.cpp 7 | ../../src/gui/iconfont.cpp 8 | ../../src/gui/iconwidget.cpp 9 | ../../src/gui/screen.cpp 10 | ../../src/item/serialize.cpp 11 | ) 12 | 13 | copyq_add_plugin(itemencrypted) 14 | -------------------------------------------------------------------------------- /plugins/itemencrypted/tests/itemencryptedtests.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #pragma once 4 | 5 | 6 | #include "tests/testinterface.h" 7 | 8 | #include 9 | 10 | class ItemEncryptedTests final : public QObject 11 | { 12 | Q_OBJECT 13 | public: 14 | explicit ItemEncryptedTests(const TestInterfacePtr &test, QObject *parent = nullptr); 15 | 16 | private slots: 17 | void initTestCase(); 18 | void cleanupTestCase(); 19 | void init(); 20 | void cleanup(); 21 | 22 | void encryptDecryptData(); 23 | 24 | void encryptDecryptItems(); 25 | 26 | private: 27 | bool isGpgInstalled() const; 28 | 29 | TestInterfacePtr m_test; 30 | }; 31 | -------------------------------------------------------------------------------- /plugins/itemfakevim/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file(GLOB copyq_plugin_itemfakevim_SOURCES 2 | ../../src/item/itemwidgetwrapper.cpp 3 | ) 4 | file(GLOB copyq_plugin_itemfakevim_external_SOURCES 5 | fakevim/*.cpp 6 | ) 7 | 8 | set(copyq_plugin_itemfakevim_DEFINITIONS 9 | QT_NO_CAST_TO_ASCII 10 | QT_RESTRICTED_CAST_FROM_ASCII 11 | DEBUG_KEY=0 12 | DEBUG_UNDO=0 13 | ) 14 | 15 | set(copyq_plugin_itemfakevim_RESOURCES itemfakevim.qrc) 16 | 17 | copyq_add_plugin(itemfakevim) 18 | target_include_directories(itemfakevim SYSTEM PRIVATE fakevim) 19 | -------------------------------------------------------------------------------- /plugins/itemfakevim/fakevim/LGPL_EXCEPTION.TXT: -------------------------------------------------------------------------------- 1 | Digia Qt LGPL Exception version 1.1 2 | 3 | As an additional permission to the GNU Lesser General Public License version 4 | 2.1, the object code form of a "work that uses the Library" may incorporate 5 | material from a header file that is part of the Library. You may distribute 6 | such object code under terms of your choice, provided that: 7 | (i) the header files of the Library have not been modified; and 8 | (ii) the incorporated material is limited to numerical parameters, data 9 | structure layouts, accessors, macros, inline functions and 10 | templates; and 11 | (iii) you comply with the terms of Section 6 of the GNU Lesser General 12 | Public License version 2.1. 13 | 14 | Moreover, you may apply this exception to a modified version of the Library, 15 | provided that such modification does not involve copying material from the 16 | Library into the modified Library's header files unless such material is 17 | limited to (i) numerical parameters; (ii) data structure layouts; 18 | (iii) accessors; and (iv) small macros, templates and inline functions of 19 | five lines or less in length. 20 | 21 | Furthermore, you are not required to apply this additional permission to a 22 | modified version of the Library. 23 | -------------------------------------------------------------------------------- /plugins/itemfakevim/fakevim/fakevim.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hluk/CopyQ/d54623cf916577a1bed76353a8e8ac482a71cbc9/plugins/itemfakevim/fakevim/fakevim.png -------------------------------------------------------------------------------- /plugins/itemfakevim/fakevim/fakevimtr.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2016 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0 3 | 4 | #pragma once 5 | 6 | #include 7 | 8 | namespace FakeVim { 9 | 10 | struct Tr 11 | { 12 | Q_DECLARE_TR_FUNCTIONS(FakeVim) 13 | }; 14 | 15 | } // namespace FakeVim 16 | -------------------------------------------------------------------------------- /plugins/itemfakevim/fakevim/private/fakevim_export.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #define FAKEVIM_EXPORT 3 | -------------------------------------------------------------------------------- /plugins/itemfakevim/itemfakevim.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | fakevim/fakevim.png 4 | 5 | 6 | -------------------------------------------------------------------------------- /plugins/itemfakevim/itemfakevimsettings.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | ItemFakeVimSettings 4 | 5 | 6 | 7 | 0 8 | 0 9 | 400 10 | 300 11 | 12 | 13 | 14 | 15 | 16 | 17 | Enable FakeVim for Editing Items 18 | 19 | 20 | 21 | 22 | 23 | 24 | Path to Configuration File: 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | Qt::Vertical 35 | 36 | 37 | 38 | 20 39 | 40 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /plugins/itemfakevim/tests/itemfakevimtests.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #pragma once 4 | 5 | 6 | #include "tests/testinterface.h" 7 | 8 | #include 9 | 10 | class ItemFakeVimTests final : public QObject 11 | { 12 | Q_OBJECT 13 | public: 14 | explicit ItemFakeVimTests(const TestInterfacePtr &test, QObject *parent = nullptr); 15 | 16 | static QString fileNameToSource(); 17 | 18 | private slots: 19 | void initTestCase(); 20 | void cleanupTestCase(); 21 | void init(); 22 | void cleanup(); 23 | 24 | void createItem(); 25 | 26 | void blockSelection(); 27 | 28 | void search(); 29 | 30 | void incDecNumbers(); 31 | 32 | private: 33 | TestInterfacePtr m_test; 34 | }; 35 | -------------------------------------------------------------------------------- /plugins/itemimage/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(copyq_plugin_itemimage_SOURCES 2 | ../../src/common/action.cpp 3 | ../../src/common/mimetypes.cpp 4 | ../../src/common/temporaryfile.cpp 5 | ../../src/item/itemeditor.cpp 6 | ../../src/item/serialize.cpp 7 | ) 8 | 9 | copyq_add_plugin(itemimage) 10 | -------------------------------------------------------------------------------- /plugins/itemimage/tests/itemimagetests.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | #pragma once 3 | 4 | #include "tests/testinterface.h" 5 | 6 | #include 7 | 8 | class ItemImageTests final : public QObject 9 | { 10 | Q_OBJECT 11 | public: 12 | explicit ItemImageTests(const TestInterfacePtr &test, QObject *parent = nullptr); 13 | 14 | private slots: 15 | void initTestCase(); 16 | void cleanupTestCase(); 17 | void init(); 18 | void cleanup(); 19 | 20 | void supportedFormats(); 21 | void savePng(); 22 | void saveBmp(); 23 | void saveGif(); 24 | void saveWebp(); 25 | 26 | private: 27 | TestInterfacePtr m_test; 28 | }; 29 | -------------------------------------------------------------------------------- /plugins/itemnotes/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(copyq_plugin_itemnotes_SOURCES 2 | ../../src/item/itemwidgetwrapper.cpp 3 | ../../src/gui/iconfont.cpp 4 | ../../src/gui/iconwidget.cpp 5 | ../../src/common/mimetypes.cpp 6 | ../../src/common/textdata.cpp 7 | ) 8 | 9 | copyq_add_plugin(itemnotes) 10 | -------------------------------------------------------------------------------- /plugins/itempinned/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(copyq_plugin_itempinned_SOURCES 2 | ../../src/item/itemwidgetwrapper.cpp 3 | ../../src/item/itemsaverwrapper.cpp 4 | ../../src/common/command.cpp 5 | ../../src/common/display.cpp 6 | ../../src/gui/screen.cpp 7 | ) 8 | 9 | copyq_add_plugin(itempinned) 10 | -------------------------------------------------------------------------------- /plugins/itempinned/tests/itempinnedtests.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #pragma once 4 | 5 | 6 | #include "tests/testinterface.h" 7 | 8 | #include 9 | 10 | class ItemPinnedTests final : public QObject 11 | { 12 | Q_OBJECT 13 | public: 14 | explicit ItemPinnedTests(const TestInterfacePtr &test, QObject *parent = nullptr); 15 | 16 | private slots: 17 | void initTestCase(); 18 | void cleanupTestCase(); 19 | void init(); 20 | void cleanup(); 21 | 22 | void isPinned(); 23 | void pin(); 24 | void pinMultiple(); 25 | void unpin(); 26 | void unpinMultiple(); 27 | 28 | void removePinnedThrows(); 29 | 30 | void pinToRow(); 31 | 32 | void fullTab(); 33 | 34 | void keepPinnedIfMaxItemsChanges(); 35 | 36 | private: 37 | TestInterfacePtr m_test; 38 | }; 39 | -------------------------------------------------------------------------------- /plugins/itemsync/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(copyq_plugin_itemsync_SOURCES 2 | ../../src/item/itemwidgetwrapper.cpp 3 | ../../src/common/config.cpp 4 | ../../src/common/mimetypes.cpp 5 | ../../src/gui/iconfont.cpp 6 | ../../src/gui/iconselectbutton.cpp 7 | ../../src/gui/iconselectdialog.cpp 8 | ../../src/gui/iconwidget.cpp 9 | ../../src/gui/screen.cpp 10 | ../../src/item/serialize.cpp 11 | ) 12 | 13 | copyq_add_plugin(itemsync) 14 | -------------------------------------------------------------------------------- /plugins/itemsync/tests/itemsynctests.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #pragma once 4 | 5 | 6 | #include "tests/testinterface.h" 7 | 8 | #include 9 | 10 | class ItemSyncTests final : public QObject 11 | { 12 | Q_OBJECT 13 | public: 14 | explicit ItemSyncTests(const TestInterfacePtr &test, QObject *parent = nullptr); 15 | 16 | static QString testTab(int i); 17 | 18 | static QString testDir(int i); 19 | 20 | private slots: 21 | void initTestCase(); 22 | void cleanupTestCase(); 23 | void init(); 24 | void cleanup(); 25 | 26 | void createRemoveTestDir(); 27 | 28 | void itemsToFiles(); 29 | void filesToItems(); 30 | 31 | void removeOwnItems(); 32 | void removeNotOwnedItems(); 33 | void removeNotOwnedItemsCancel(); 34 | void removeFiles(); 35 | 36 | void modifyItems(); 37 | void modifyFiles(); 38 | 39 | void itemToClipboard(); 40 | 41 | void notes(); 42 | 43 | void customFormats(); 44 | 45 | void getAbsoluteFilePath(); 46 | 47 | void addItemsWhenFull(); 48 | 49 | void addItemsWhenFullOmitDeletingNotOwned(); 50 | 51 | void moveOwnItemsSortsBaseNames(); 52 | 53 | void avoidDuplicateItemsAddedFromClipboard(); 54 | 55 | void saveLargeItem(); 56 | 57 | void sortItemsSimple(); 58 | void sortItems(); 59 | 60 | void copyFiles(); 61 | 62 | private: 63 | TestInterfacePtr m_test; 64 | }; 65 | -------------------------------------------------------------------------------- /plugins/itemtags/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(copyq_plugin_itemtags_SOURCES 2 | ../../src/item/itemwidgetwrapper.cpp 3 | ../../src/item/itemsaverwrapper.cpp 4 | ../../src/common/command.cpp 5 | ../../src/common/config.cpp 6 | ../../src/common/mimetypes.cpp 7 | ../../src/common/textdata.cpp 8 | ../../src/gui/iconselectbutton.cpp 9 | ../../src/gui/iconselectdialog.cpp 10 | ../../src/gui/iconwidget.cpp 11 | ../../src/gui/iconfont.cpp 12 | ../../src/gui/screen.cpp 13 | ) 14 | 15 | copyq_add_plugin(itemtags) 16 | -------------------------------------------------------------------------------- /plugins/itemtags/tests/itemtagstests.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #pragma once 4 | 5 | 6 | #include "tests/testinterface.h" 7 | 8 | #include 9 | 10 | class ItemTagsTests final : public QObject 11 | { 12 | Q_OBJECT 13 | public: 14 | explicit ItemTagsTests(const TestInterfacePtr &test, QObject *parent = nullptr); 15 | 16 | static QStringList testTags(); 17 | 18 | private slots: 19 | void initTestCase(); 20 | void cleanupTestCase(); 21 | void init(); 22 | void cleanup(); 23 | 24 | void userTags(); 25 | void tag(); 26 | void untag(); 27 | void clearTags(); 28 | void searchTags(); 29 | 30 | void tagSelected(); 31 | void untagSelected(); 32 | 33 | private: 34 | TestInterfacePtr m_test; 35 | }; 36 | -------------------------------------------------------------------------------- /plugins/itemtext/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(copyq_plugin_itemtext_SOURCES 2 | ../../src/common/mimetypes.cpp 3 | ../../src/common/textdata.cpp 4 | ) 5 | 6 | copyq_add_plugin(itemtext) 7 | -------------------------------------------------------------------------------- /qxt/AUTHORS: -------------------------------------------------------------------------------- 1 | == main developers == 2 | 3 | Arvid Picciani 4 | Adam Higerd 5 | J-P Nurmi 6 | Benjamin Zeller 7 | 8 | == contributors == 9 | 10 | Gabriel Assis Bezerra 11 | Scott Aron Bloom 12 | Lawrence Holtsclaw 13 | Marcin Jakubowski 14 | Dominique Leducq 15 | Marcus Lindblom 16 | Konstantin Molchanov 17 | Thomas Mueller 18 | Bjørn Erik Nilsen 19 | Kaleb Pederson 20 | Matthew Schnee 21 | André Somers 22 | Alex Unden 23 | Chris Vickery 24 | Benjamin Wohlwend 25 | 26 | thanks everyone not named for all the patches, bug reports, 27 | beta tests, and the free beer :-) 28 | -------------------------------------------------------------------------------- /shared/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleExecutable 8 | ${COPYQ_EXECUTABLE_NAME} 9 | CFBundleGetInfoString 10 | ${MACOSX_BUNDLE_INFO_STRING} 11 | CFBundleIconFile 12 | ${MACOSX_BUNDLE_ICON_FILE} 13 | CFBundleIdentifier 14 | ${MACOSX_BUNDLE_GUI_IDENTIFIER} 15 | CFBundleInfoDictionaryVersion 16 | 6.0 17 | CFBundleLongVersionString 18 | ${MACOSX_BUNDLE_LONG_VERSION_STRING} 19 | CFBundleName 20 | ${MACOSX_BUNDLE_BUNDLE_NAME} 21 | CFBundlePackageType 22 | APPL 23 | CFBundleShortVersionString 24 | ${MACOSX_BUNDLE_SHORT_VERSION_STRING} 25 | CFBundleSignature 26 | ???? 27 | CFBundleVersion 28 | ${MACOSX_BUNDLE_BUNDLE_VERSION} 29 | CSResourcesFileMapped 30 | 31 | NSHumanReadableCopyright 32 | 33 | NSPrincipalClass 34 | NSApplication 35 | NSHighResolutionCapable 36 | True 37 | 38 | 39 | -------------------------------------------------------------------------------- /shared/flatpak/README.md: -------------------------------------------------------------------------------- 1 | This directory contains source files for building CopyQ Flatpak package. 2 | 3 | # Build 4 | 5 | Install `flatpak-builder`. 6 | 7 | Option `--user` can be omitted. 8 | 9 | ```bash 10 | flatpak install --user flathub org.freedesktop.Platform//1.6 org.freedesktop.Sdk//1.6 11 | flatpak remote-add --user --if-not-exists kdeapps --from https://distribute.kde.org/kdeapps.flatpakrepo 12 | flatpak install --user flathub org.kde.Platform//5.9 13 | flatpak install --user flathub org.kde.Sdk//5.9 14 | ``` 15 | 16 | Build the app. 17 | 18 | ```bash 19 | mkdir copyq repo 20 | flatpak-builder --ccache --force-clean --repo=repo --subject="Build of copyq" copyq com.github.hluk.copyq.json 21 | ``` 22 | 23 | Install the app. 24 | 25 | ```bash 26 | flatpak remote-add --user copyq repo --no-gpg-verify 27 | flatpak install --user --reinstall copyq com.github.hluk.copyq 28 | flatpak run com.github.hluk.copyq 29 | ``` 30 | -------------------------------------------------------------------------------- /shared/flatpak/com.github.hluk.copyq.json: -------------------------------------------------------------------------------- 1 | { 2 | "app-id": "com.github.hluk.copyq", 3 | "runtime": "org.kde.Platform", 4 | "runtime-version": "5.9", 5 | "sdk": "org.kde.Sdk", 6 | "command": "copyq", 7 | 8 | "finish-args": [ 9 | "--socket=x11", 10 | "--socket=wayland", 11 | "--talk-name=org.kde.StatusNotifierWatcher", 12 | "--share=ipc", 13 | "--device=dri" 14 | ], 15 | 16 | "modules": [ 17 | { 18 | "name": "copyq", 19 | "buildsystem": "cmake-ninja", 20 | "sources": [ 21 | { 22 | "type": "git", 23 | "url": "https://github.com/hluk/CopyQ.git", 24 | "tag": "v3.3.0", 25 | "commit": "bc2795594e4e0f50f2cc040be78855f4adcfa7ea" 26 | } 27 | ], 28 | "config-opts": [ 29 | "-DCMAKE_BUILD_TYPE=Release", 30 | "-DICON_NAME=com.github.hluk.copyq" 31 | ] 32 | } 33 | ] 34 | } 35 | -------------------------------------------------------------------------------- /shared/logo-small.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hluk/CopyQ/d54623cf916577a1bed76353a8e8ac482a71cbc9/shared/logo-small.bmp -------------------------------------------------------------------------------- /shared/logo.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hluk/CopyQ/d54623cf916577a1bed76353a8e8ac482a71cbc9/shared/logo.bmp -------------------------------------------------------------------------------- /shared/plugins/example.js: -------------------------------------------------------------------------------- 1 | // This is example plugin script for CopyQ. 2 | // Plugin scripts should be copied to plugins directory 3 | // (usually ~/.config/copyq/plugins/). 4 | 5 | // Override popup() 6 | popup = function(title, message, time) 7 | { 8 | if (!time) 9 | time = 1000 10 | if (!message) 11 | message = "" 12 | execute("notify-send", "--expire-time=" + time, title, message) 13 | } 14 | 15 | function copyq_script() { 16 | popup("Script loaded!") 17 | return { 18 | name: "Test Script", 19 | author: function() { return "author@example.com" }, 20 | description: function() { return "A script for testing" }, 21 | formatsToSave: ["test1", "test2"], 22 | 23 | copyItem: function(data) { 24 | data['copy'] = "copied" 25 | return data 26 | }, 27 | 28 | transformItemData: function(data) { 29 | data[mimeText] = "TEST: " + str(data[mimeText]) 30 | return data; 31 | }, 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /shared/themes/black.ini: -------------------------------------------------------------------------------- 1 | [General] 2 | notes_css= 3 | find_bg=#222222 4 | edit_font="Sans,11,-1,5,50,0,0,0,0,0" 5 | bg=#000000 6 | find_font="Sans,10,-1,5,50,0,0,0,0,0" 7 | alt_item_css= 8 | sel_fg=#ffffff 9 | show_scrollbars=true 10 | find_fg=#ffffff 11 | edit_bg=#000000 12 | num_fg=#888888 13 | font="Sans,10,-1,5,50,0,0,0,0,0" 14 | sel_item_css= 15 | sel_bg=#333333 16 | notes_font="Sans,11,-1,5,50,0,0,0,0,0" 17 | edit_fg=#ffffff 18 | show_number=true 19 | notes_fg=#ffffff 20 | item_css= 21 | alt_bg=#111111 22 | css= 23 | fg=#ffffff 24 | num_font="Sans,7,-1,5,25,0,0,0,0,0" 25 | notes_bg=#000000 26 | -------------------------------------------------------------------------------- /shared/themes/dark.ini: -------------------------------------------------------------------------------- 1 | [General] 2 | notes_css= 3 | find_bg=#00689c 4 | edit_font="Sans,11,-1,5,50,0,0,0,0,0" 5 | bg=#4b4b4b 6 | find_font="Sans,10,-1,5,50,0,0,0,0,0" 7 | alt_item_css= 8 | sel_fg=#ffffff 9 | show_scrollbars=true 10 | find_fg=#ffffff 11 | edit_bg=#ffffff 12 | num_fg=#7f7f7f 13 | font="Sans,10,-1,5,50,0,0,0,0,0" 14 | sel_item_css= 15 | sel_bg=#61819c 16 | notes_font="Sans,11,-1,5,50,0,0,0,0,0" 17 | edit_fg=#1a1a1a 18 | show_number=true 19 | notes_fg=#232323 20 | item_css= 21 | alt_bg=#383838 22 | css= 23 | fg=#dfdfdf 24 | num_font="Sans,7,-1,5,25,0,0,0,0,0" 25 | notes_bg=#ffffff 26 | -------------------------------------------------------------------------------- /shared/themes/forest.ini: -------------------------------------------------------------------------------- 1 | [General] 2 | alt_bg=#f1edcb 3 | alt_item_css=" 4 | ;background: qlineargradient( 5 | x1: 0, y1: 0, 6 | x2: 0, y2: 1, 7 | stop: 0 ${alt_bg}, 8 | stop: 1.0 ${alt_bg - #112} 9 | ) 10 | ;border-radius: 3px 11 | " 12 | bg=#fffaeb 13 | css=ClipboardBrowser::selected:item{outline:0px} 14 | edit_bg=#fdfcfa 15 | edit_fg=#000000 16 | edit_font="Ubuntu Mono,11,-1,5,50,0,0,0,0,0" 17 | fg=#2f2a15 18 | find_bg=#d6ff94 19 | find_fg=#000 20 | find_font="Ubuntu Mono,11,-1,5,50,0,0,0,0,0" 21 | font="Ubuntu Mono,11,-1,5,50,0,0,0,0,0" 22 | item_css= 23 | notes_bg=#d5ff94 24 | notes_css= 25 | notes_fg=#554e18 26 | notes_font="Ubuntu Condensed,11,-1,5,50,0,0,0,0,0" 27 | num_fg=#96865b 28 | num_font="Ubuntu Mono,7,-1,5,50,0,0,0,0,0" 29 | sel_bg=#6eb662 30 | sel_fg=#ffffff 31 | sel_item_css=" 32 | ;background: qlineargradient( 33 | x1: 0, y1: 0, 34 | x2: 0, y2: 1, 35 | stop: 0 ${sel_bg}, 36 | stop: 1.0 ${sel_bg - #222} 37 | ) 38 | ;border: 0px solid transparent 39 | ;border-radius: 3px 40 | ; 41 | " 42 | show_number=true 43 | show_scrollbars=false 44 | -------------------------------------------------------------------------------- /shared/themes/items.css: -------------------------------------------------------------------------------- 1 | #ClipboardBrowser,#item,#item_child{ 2 | ;${font} 3 | ;color: ${fg} 4 | ;background: ${bg} 5 | } 6 | 7 | #ClipboardBrowser::item:alternate:!hover:!selected{ 8 | ;color: ${alt_fg} 9 | ;background: ${alt_bg} 10 | } 11 | 12 | #ClipboardBrowser::item:selected 13 | ,#item[CopyQ_selected="true"] 14 | ,#item[CopyQ_selected="true"] #item_child 15 | { 16 | ;color: ${sel_fg} 17 | ;background: ${sel_bg} 18 | } 19 | 20 | #item #item_child 21 | ,#item[CopyQ_selected="true"] #item_child 22 | { 23 | ;background: transparent 24 | } 25 | 26 | ${hsv_saturation_factor = 0.5} 27 | #ClipboardBrowser::item:selected:!active 28 | { 29 | ;background:${sel_bg} 30 | ;${sel_item_css} 31 | } 32 | ${hsv_saturation_factor = 2} 33 | ${hsv_value_factor = 0.9} 34 | #ClipboardBrowser::item:hover:selected 35 | { 36 | ;background:${sel_bg} 37 | ;${hover_item_css} 38 | } 39 | #ClipboardBrowser::item:hover:!selected 40 | { 41 | ;background:${bg} 42 | ;${hover_item_css} 43 | } 44 | ${hsv_saturation_factor = 1} 45 | ${hsv_value_factor = 1} 46 | 47 | /* Omit showing current item outline. */ 48 | #ClipboardBrowser::focus{outline:0} 49 | 50 | #ClipboardBrowser::item:focus{ ${cur_item_css} } 51 | 52 | /* Allow user to change CSS. */ 53 | #ClipboardBrowser{ ${item_css} } 54 | #ClipboardBrowser::item:alternate:!hover:!selected{ ${alt_item_css} } 55 | #ClipboardBrowser::item:selected{ ${sel_item_css} } 56 | 57 | #editor_status_bar * { 58 | ;background: ${edit_bg} 59 | ;color: ${edit_fg} 60 | ;border: none 61 | } 62 | 63 | ${css:tooltip} 64 | -------------------------------------------------------------------------------- /shared/themes/main_window.css: -------------------------------------------------------------------------------- 1 | #searchBar{${search_bar}} 2 | 3 | #searchBar:focus{${search_bar_focused}} 4 | 5 | #tab_bar{${tab_bar_css}} 6 | #tab_bar::tab:selected{${tab_bar_tab_selected_css}} 7 | #tab_bar::tab:!selected{${tab_bar_tab_unselected_css}} 8 | #tab_bar #tab_item_counter{${tab_bar_item_counter}} 9 | #tab_bar #tab_item_counter[CopyQ_selected="true"]{ 10 | ;${tab_bar_sel_item_counter} 11 | } 12 | 13 | #tab_bar QToolButton{${tab_bar_scroll_buttons_css}} 14 | 15 | #tab_tree, #tab_tree_item{${tab_tree_css}} 16 | 17 | #tab_tree::item:selected 18 | ,#tab_tree_item[CopyQ_selected="true"] 19 | { 20 | ;${tab_tree_sel_item_css} 21 | } 22 | 23 | #tab_tree_item[CopyQ_selected="false"] 24 | ,#tab_tree_item[CopyQ_selected="true"] 25 | { 26 | ;background: transparent 27 | } 28 | 29 | #tab_tree #tab_item_counter{${tab_tree_item_counter}} 30 | #tab_tree #tab_item_counter[CopyQ_selected="true"]{ 31 | ;${tab_tree_sel_item_counter} 32 | } 33 | 34 | #MainWindow>QToolBar QToolButton{ 35 | ;color: ${fg} 36 | ;background: ${bg} 37 | } 38 | #MainWindow>QToolBar{${tool_bar_css}} 39 | #MainWindow>QToolBar QToolButton{${tool_button_css}} 40 | #MainWindow>QToolBar QToolButton:hover{${tool_button_selected_css}} 41 | #MainWindow>QToolBar QToolButton:pressed{${tool_button_pressed_css}} 42 | 43 | ${css:main_window_simple} 44 | 45 | ${css:menu} 46 | 47 | ${css} 48 | -------------------------------------------------------------------------------- /shared/themes/main_window_simple.css: -------------------------------------------------------------------------------- 1 | #plainTextEditCommand { 2 | ;${edit_font} 3 | } 4 | #comboBoxCommands { 5 | ;${edit_font} 6 | } 7 | -------------------------------------------------------------------------------- /shared/themes/menu.css: -------------------------------------------------------------------------------- 1 | /* Remove icon border in menus. */ 2 | #TrayMenu::item:selected, 3 | #MainWindow>QMenu::item:selected, 4 | #menu_bar>QMenu::item:selected 5 | { 6 | border:none 7 | } 8 | 9 | #TrayMenu::item, 10 | #MainWindow>QMenu::item, 11 | #menu_bar>QMenu::item 12 | { 13 | ;padding: 0.2em 1em 0.2em 1em 14 | ;padding-left: ${scale=2}${icon_size}${scale=1}px 15 | } 16 | 17 | #TrayMenu::icon, 18 | #MainWindow>QMenu::icon, 19 | #menu_bar>QMenu::icon 20 | { 21 | ;padding-left: ${scale=0.5}${icon_size}${scale=1}px 22 | } 23 | 24 | /* Keep default item highlighted (removing icon border resets the style). */ 25 | #TrayMenu::item:default, 26 | #MainWindow>QMenu::item:default, 27 | #menu_bar>QMenu::item:default 28 | { 29 | font-weight:bold 30 | } 31 | 32 | #TrayMenu, 33 | #MainWindow>QMenu, 34 | #menu_bar>QMenu 35 | { 36 | ${menu_css} 37 | } 38 | 39 | #TrayMenu::item:selected, 40 | #MainWindow>QMenu::item:selected, 41 | #menu_bar>QMenu::item:selected 42 | { 43 | ${menu_bar_selected_css} 44 | } 45 | 46 | #menu_bar, #menu_bar::item{${menu_bar_css}} 47 | #menu_bar::item:selected{${menu_bar_selected_css}} 48 | #menu_bar::item:disabled{${menu_bar_disabled_css}} 49 | 50 | ${css:tooltip} 51 | -------------------------------------------------------------------------------- /shared/themes/notification.css: -------------------------------------------------------------------------------- 1 | #Notification, #Notification QWidget 2 | { 3 | /* Resets notification opacity. It will be set in NotificationDaemon::setNotificationOpacity(). */ 4 | ;background: ${notification_bg + #000} 5 | } 6 | #Notification QWidget{ 7 | ;color: ${notification_fg} 8 | ;${notification_font} 9 | } 10 | #Notification #NotificationTitle{ 11 | ;${scale=1.2}${notification_font}${scale=1} 12 | } 13 | #Notification #NotificationTip{ 14 | ;font-style: italic 15 | } 16 | -------------------------------------------------------------------------------- /shared/themes/paper.ini: -------------------------------------------------------------------------------- 1 | [General] 2 | alt_bg=bg 3 | alt_item_css="\n " 4 | bg=#f7f7f7 5 | css="\n ClipboardBrowser::selected:item{outline:0px}\n ClipboardBrowser::item{border-bottom:1px solid #cdf}\n " 6 | edit_bg="rgba(247,247,247,0.862745)" 7 | edit_fg=fg - #111 8 | edit_font="Sans,9,-1,5,50,0,0,0,0,0" 9 | fg=#068 10 | find_bg="rgba(157,255,0,0)" 11 | find_fg=#09a 12 | find_font="Ubuntu,9,-1,5,50,0,1,0,0,0" 13 | font="Sans,9,-1,5,50,0,0,0,0,0" 14 | item_css=padding:1.5em 3em 1.5em 3em 15 | notes_bg=bg 16 | notes_css= 17 | notes_fg=fg 18 | notes_font="Sans,10,-1,5,50,0,0,0,0,0" 19 | num_fg=bg - #866 20 | num_font="Sans,7,-1,5,25,0,0,0,0,0" 21 | sel_bg=#97ea6a 22 | sel_fg=#234 23 | sel_item_css="\n ;background: qlineargradient(\n x1: 0, y1: 0.2,\n x2: 0.8, y2: 0,\n stop: 0 ${sel_bg},\n stop: 1 ${bg}\n )\n " 24 | show_number=true 25 | show_scrollbars=false 26 | -------------------------------------------------------------------------------- /shared/themes/simple.ini: -------------------------------------------------------------------------------- 1 | [General] 2 | alt_bg=bg 3 | alt_item_css=" 4 | ;border-radius: 2px 5 | ;background: qlineargradient( 6 | x1: 0, y1: 0, 7 | x2: 1.5, y2: 0, 8 | stop: 0 ${alt_bg - #100c0a}, 9 | stop: 1 ${alt_bg} 10 | ) 11 | " 12 | bg=#f7f7f7 13 | css=ClipboardBrowser::selected:item{outline:0px} 14 | edit_bg=bg 15 | edit_fg=fg - #111 16 | edit_font="Sans,9,-1,5,50,0,0,0,0,0" 17 | fg=#356 18 | find_bg="rgba(0,0,0,0)" 19 | find_fg=#08a 20 | find_font="Sans,9,-1,5,50,0,1,0,0,0" 21 | font="Sans,9,-1,5,50,0,0,0,0,0" 22 | item_css=padding:1em 23 | notes_bg=bg 24 | notes_css= 25 | notes_fg=#222 26 | notes_font="Serif,10,-1,5,50,0,0,0,0,0" 27 | num_fg=#586e75 28 | num_font="Sans,7,-1,5,25,0,0,0,0,0" 29 | sel_bg="bg + #000409 - #100" 30 | sel_fg=#234 31 | sel_item_css=" 32 | ;border: 1px solid ${bg - #940} 33 | ;border-radius: 2px 34 | ;background: qlineargradient( 35 | x1: 0, y1: 0, 36 | x2: 1.5, y2: 0, 37 | stop: 0 ${sel_bg}, 38 | stop: 1 ${bg} 39 | ) 40 | " 41 | show_number=false 42 | show_scrollbars=false 43 | -------------------------------------------------------------------------------- /shared/themes/solarized-dark.ini: -------------------------------------------------------------------------------- 1 | [General] 2 | alt_bg=#073642 3 | alt_item_css= 4 | bg=#002b36 5 | css= 6 | edit_bg=alt_bg 7 | edit_fg=#2aa198 8 | edit_font="Monospace,9,-1,5,50,0,0,0,0,0" 9 | fg=#93a1a1 10 | find_bg="rgba(0,0,0,0)" 11 | find_fg=#b58900 12 | find_font="Monospace,9,-1,5,50,0,0,0,0,0" 13 | font="Monospace,9,-1,5,50,0,0,0,0,0" 14 | item_css= 15 | notes_css= 16 | notes_bg=bg 17 | notes_fg=#ce4d17 18 | notes_font="Serif,10,-1,5,50,0,0,0,0,0" 19 | num_fg=#586e75 20 | num_font="Monospace,7,-1,5,25,0,0,0,0,0" 21 | sel_bg=fg 22 | sel_fg=bg 23 | sel_item_css= 24 | show_number=true 25 | show_scrollbars=false 26 | -------------------------------------------------------------------------------- /shared/themes/solarized-light.ini: -------------------------------------------------------------------------------- 1 | [General] 2 | alt_bg=#eee8d5 3 | alt_item_css= 4 | bg=#fdf6e3 5 | css= 6 | edit_bg=bg 7 | edit_fg=#268bd2 8 | edit_font="Monospace,9,-1,5,50,0,0,0,0,0" 9 | fg=#586e75 10 | find_bg="rgba(0,0,0,0)" 11 | find_fg=#b58900 12 | find_font="Monospace,9,-1,5,50,0,0,0,0,0" 13 | font="Monospace,9,-1,5,50,0,0,0,0,0" 14 | item_css= 15 | notes_css= 16 | notes_bg=bg 17 | notes_fg=#ce4d17 18 | notes_font="Serif,10,-1,5,50,0,0,0,0,0" 19 | num_fg=#586e75 20 | num_font="Monospace,7,-1,5,25,0,0,0,0,0" 21 | sel_bg=fg 22 | sel_fg=bg 23 | sel_item_css= 24 | show_number=true 25 | show_scrollbars=false 26 | -------------------------------------------------------------------------------- /shared/themes/tooltip.css: -------------------------------------------------------------------------------- 1 | #item QToolTip, QMenu QToolTip { 2 | ;${notes_font} 3 | ;background: ${notes_bg} 4 | ;color: ${notes_fg} 5 | /* Resetting border helps in some cases to set correct background color. */ 6 | ;border: 1px solid ${notes_fg} 7 | ;${notes_css} 8 | } 9 | -------------------------------------------------------------------------------- /shared/themes/wine.ini: -------------------------------------------------------------------------------- 1 | [General] 2 | alt_bg=bg-#101a1a 3 | alt_item_css=" 4 | ;border: 0px solid transparent 5 | ;border-radius: 5px 6 | " 7 | bg=#ffffff 8 | css=ClipboardBrowser::selected:item{outline:0px} 9 | edit_bg=#ffffff 10 | edit_fg=#1a1a1a 11 | edit_font="Serif,9,-1,5,50,0,0,0,0,0" 12 | fg=#515151 13 | find_bg=sel_bg 14 | find_fg=#fff 15 | find_font="Serif,9,-1,5,50,0,1,0,0,0" 16 | font="Serif,9,-1,5,50,0,0,0,0,0" 17 | item_css= 18 | notes_bg=#610001 19 | notes_css= 20 | notes_fg=#ffffff 21 | notes_font="Serif,10,-1,5,50,0,0,0,0,0" 22 | num_fg=#a00028 23 | num_font="Ubuntu,7,-1,5,25,0,0,0,0,0" 24 | sel_bg=#a04 25 | sel_fg=#fff 26 | sel_item_css=" 27 | ;background: qlineargradient( 28 | x1: 0, y1: 0, 29 | x2: 0, y2: 1, 30 | stop: 0 ${sel_bg}, 31 | stop: 1 ${sel_bg - #444} 32 | ) 33 | ;border: 1px solid #000 34 | ;border-radius: 5px 35 | " 36 | show_number=true 37 | show_scrollbars=false 38 | -------------------------------------------------------------------------------- /src/app/app.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #pragma once 4 | 5 | 6 | class QCoreApplication; 7 | class QString; 8 | 9 | /** Application class. */ 10 | class App 11 | { 12 | public: 13 | explicit App( 14 | QCoreApplication *application, 15 | const QString &sessionName 16 | ); 17 | 18 | virtual ~App(); 19 | 20 | static void installTranslator(); 21 | 22 | /** 23 | * Execute application. Returns immediately if exit() was called before. 24 | * @return Exit code. 25 | */ 26 | int exec(); 27 | 28 | /** 29 | * Exit application with given exit code. 30 | */ 31 | virtual void exit(int exitCode=0); 32 | 33 | /** 34 | * Return true if exit() was called. 35 | */ 36 | bool wasClosed() const; 37 | 38 | App(const App &) = delete; 39 | App &operator=(const App &) = delete; 40 | 41 | private: 42 | QCoreApplication *m_app; 43 | int m_exitCode; 44 | bool m_started; 45 | bool m_closed; 46 | }; 47 | -------------------------------------------------------------------------------- /src/app/applicationexceptionhandler.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #include "applicationexceptionhandler.h" 4 | 5 | #include "common/log.h" 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | void logException(const char *what) 12 | { 13 | QFile f; 14 | f.open(stderr, QIODevice::WriteOnly); 15 | f.write(what ? what : "Unknown exception"); 16 | f.write("\n"); 17 | f.close(); 18 | 19 | log( QString("Exception: ") + what, LogError ); 20 | } 21 | 22 | void detail::ApplicationExceptionHandlerBase::exit(int exitCode) 23 | { 24 | QMetaObject::invokeMethod(this, "exitSlot", Q_ARG(int, exitCode)); 25 | } 26 | 27 | void detail::ApplicationExceptionHandlerBase::exitSlot(int exitCode) 28 | { 29 | qApp->exit(exitCode); 30 | } 31 | -------------------------------------------------------------------------------- /src/app/applicationexceptionhandler.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #pragma once 4 | 5 | 6 | #include 7 | 8 | #include 9 | 10 | class QCoreApplication; 11 | class QEvent; 12 | 13 | void logException(const char *what = nullptr); 14 | 15 | namespace detail { 16 | 17 | class ApplicationExceptionHandlerBase : public QObject 18 | { 19 | Q_OBJECT 20 | 21 | protected: 22 | /// Exit application (thread-safe). 23 | void exit(int exitCode); 24 | 25 | private slots: 26 | void exitSlot(int exitCode); 27 | }; 28 | 29 | } // namespace detail 30 | 31 | template 32 | class ApplicationExceptionHandler : public detail::ApplicationExceptionHandlerBase, public QtApplication 33 | { 34 | public: 35 | ApplicationExceptionHandler(int &argc, char **argv) 36 | : QtApplication(argc, argv) 37 | { 38 | } 39 | 40 | bool notify(QObject *receiver, QEvent *event) override 41 | { 42 | try { 43 | return QtApplication::notify(receiver, event); 44 | } catch (const std::exception &e) { 45 | logException(e.what()); 46 | } catch (...) { 47 | logException(); 48 | } 49 | 50 | detail::ApplicationExceptionHandlerBase::exit(1); 51 | return true; 52 | } 53 | }; 54 | -------------------------------------------------------------------------------- /src/app/clipboardclient.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #pragma once 4 | 5 | 6 | #include "app.h" 7 | 8 | #include 9 | #include 10 | 11 | /** 12 | * Application client. 13 | * 14 | * Sends a command to the server and exits after the command is executed. 15 | * Exit code is same as exit code send by ClipboardServer::sendMessage(). 16 | * Also the received message is printed on standard output (if exit code is 17 | * zero) or standard error output. 18 | */ 19 | class ClipboardClient final : public QObject, public App 20 | { 21 | Q_OBJECT 22 | 23 | public: 24 | ClipboardClient( 25 | int &argc, char **argv, const QStringList &arguments, const QString &sessionName); 26 | 27 | signals: 28 | void functionCallResultReceived(const QByteArray &returnValue); 29 | void inputDialogFinished(const QByteArray &data); 30 | void dataReceived(const QByteArray &data); 31 | void stop(); 32 | 33 | private: 34 | void onMessageReceived(const QByteArray &data, int messageCode); 35 | void onDisconnected(); 36 | void onConnectionFailed(); 37 | 38 | void start(const QStringList &arguments); 39 | }; 40 | -------------------------------------------------------------------------------- /src/app/clipboardownermonitor.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #pragma once 4 | 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | class ClipboardMonitor; 11 | 12 | #if QT_VERSION >= QT_VERSION_CHECK(6,0,0) 13 | using NativeEventResult = qintptr; 14 | #else 15 | using NativeEventResult = long; 16 | #endif 17 | 18 | class ClipboardOwnerMonitor final : public QAbstractNativeEventFilter 19 | { 20 | public: 21 | explicit ClipboardOwnerMonitor(ClipboardMonitor *monitor); 22 | ~ClipboardOwnerMonitor(); 23 | 24 | bool nativeEventFilter( 25 | const QByteArray &, void *message, NativeEventResult *result) override; 26 | 27 | void setUpdateInterval(int ms) { m_timerSetOwner.setInterval(ms); } 28 | 29 | void update(); 30 | 31 | private: 32 | ClipboardMonitor *m_monitor; 33 | QString m_lastClipboardOwner; 34 | QStringList m_nextClipboardOwners; 35 | QTimer m_timerSetOwner; 36 | QTimer m_timerUpdateAfterEvent; 37 | }; 38 | -------------------------------------------------------------------------------- /src/common/actionhandlerenums.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | 4 | #include 5 | 6 | enum class ActionState { 7 | Starting, 8 | Running, 9 | Finished, 10 | Error, 11 | }; 12 | 13 | namespace ActionHandlerColumn { 14 | enum { 15 | id, 16 | name, 17 | status, 18 | started, 19 | finished, 20 | error, 21 | count 22 | }; 23 | } 24 | 25 | namespace ActionHandlerRole { 26 | enum { 27 | sort = Qt::UserRole, 28 | status, 29 | id 30 | }; 31 | } 32 | -------------------------------------------------------------------------------- /src/common/actionoutput.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #pragma once 4 | 5 | 6 | class Action; 7 | class MainWindow; 8 | class QString; 9 | class QRegularExpression; 10 | class QModelIndex; 11 | 12 | void actionOutput( 13 | MainWindow *wnd, 14 | Action *action, 15 | const QString &outputItemFormat, 16 | const QString &outputTabName, 17 | const QRegularExpression &itemSeparator 18 | ); 19 | 20 | void actionOutput( 21 | MainWindow *wnd, 22 | Action *action, 23 | const QString &outputItemFormat, 24 | const QString &outputTabName 25 | ); 26 | 27 | void actionOutput( 28 | MainWindow *wnd, 29 | Action *action, 30 | const QString &outputItemFormat, 31 | const QModelIndex &index 32 | ); 33 | -------------------------------------------------------------------------------- /src/common/appconfig.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #include "appconfig.h" 4 | 5 | #include "platform/platformnativeinterface.h" 6 | 7 | #include 8 | #include 9 | 10 | Config::Config::Value Config::editor::defaultValue() 11 | { 12 | return platformNativeInterface()->defaultEditorCommand(); 13 | } 14 | 15 | Config::Config::Value Config::autostart::defaultValue() 16 | { 17 | return platformNativeInterface()->isAutostartEnabled(); 18 | } 19 | 20 | QString defaultClipboardTabName() 21 | { 22 | return QObject::tr( 23 | "&clipboard", "Default name of the tab that automatically stores new clipboard content"); 24 | } 25 | 26 | QVariant AppConfig::option(const QString &name) const 27 | { 28 | return m_settings.value(QStringLiteral("Options/") + name); 29 | } 30 | 31 | void AppConfig::setOption(const QString &name, const QVariant &value) 32 | { 33 | if ( option(name) != value ) 34 | m_settings.setValue(QStringLiteral("Options/") + name, value); 35 | } 36 | 37 | void AppConfig::removeOption(const QString &name) 38 | { 39 | m_settings.remove(QStringLiteral("Options/") + name); 40 | } 41 | -------------------------------------------------------------------------------- /src/common/client_server.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #include "common/client_server.h" 4 | #include "common/config.h" 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | QString clipboardServerName() 14 | { 15 | // applicationName changes case depending on whether this is a GUI app 16 | // or a console app on OS X. 17 | const QString appName = QCoreApplication::applicationName().toLower(); 18 | 19 | #ifdef Q_OS_UNIX 20 | const QString socketPath = settingsDirectoryPath(); 21 | QDir(socketPath).mkpath("."); 22 | 23 | // On Unix, files for local socket are created in temporary path which can be 24 | // overridden by environment variable. This can lead to having multiple 25 | // instances that can write simultaneously to same settings and data files. 26 | // It's ugly but creating socket files in settings directory should fix this. 27 | return socketPath + "/." + appName + "_s"; 28 | #else 29 | return appName + "_" + qgetenv("USERNAME") + "_s"; 30 | #endif 31 | } 32 | -------------------------------------------------------------------------------- /src/common/client_server.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #pragma once 4 | 5 | 6 | class QString; 7 | 8 | QString clipboardServerName(); 9 | -------------------------------------------------------------------------------- /src/common/clipboarddataguard.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | #pragma once 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | class QMimeData; 9 | class QImage; 10 | class QUrl; 11 | 12 | // Avoids accessing old clipboard/drag'n'drop data. 13 | class ClipboardDataGuard final { 14 | public: 15 | explicit ClipboardDataGuard( 16 | const QMimeData *data, 17 | const long int *clipboardSequenceNumber = nullptr); 18 | 19 | ~ClipboardDataGuard(); 20 | 21 | QStringList formats(); 22 | bool hasFormat(const QString &mime); 23 | 24 | QByteArray data(const QString &mime); 25 | 26 | QList urls(); 27 | QString text(); 28 | bool hasText(); 29 | QImage getImageData(); 30 | QByteArray getUtf8Data(const QString &format); 31 | bool isExpired(); 32 | const QMimeData *mimeData(); 33 | 34 | private: 35 | const QMimeData *m_data; 36 | QElapsedTimer m_timerExpire; 37 | const long int *m_clipboardSequenceNumber; 38 | long int m_clipboardSequenceNumberOriginal; 39 | QMetaObject::Connection m_connection; 40 | }; 41 | -------------------------------------------------------------------------------- /src/common/clipboardmode.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #pragma once 4 | 5 | 6 | enum class ClipboardMode { 7 | Clipboard, 8 | Selection, 9 | }; 10 | -------------------------------------------------------------------------------- /src/common/commandstatus.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #pragma once 4 | 5 | 6 | /** Command status. */ 7 | enum CommandStatus { 8 | /** Script finished */ 9 | CommandFinished = 0, 10 | /** Script finished with exit code 1 (fail() was called) */ 11 | CommandError = 1, 12 | /** Bad command syntax */ 13 | CommandBadSyntax = 2, 14 | /** Exception thrown */ 15 | CommandException = 4, 16 | 17 | /** Print on stdout */ 18 | CommandPrint = 5, 19 | 20 | CommandFunctionCall = 8, 21 | CommandFunctionCallReturnValue = 9, 22 | 23 | CommandStop = 10, 24 | 25 | CommandInputDialogFinished = 11, 26 | 27 | CommandData = 12, 28 | 29 | CommandReceiveData = 13, 30 | }; 31 | -------------------------------------------------------------------------------- /src/common/commandstore.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #pragma once 4 | 5 | 6 | #include 7 | 8 | class QSettings; 9 | struct Command; 10 | 11 | using Commands = QVector; 12 | 13 | Commands loadAllCommands(); 14 | void saveCommands(const Commands &commands); 15 | 16 | Commands loadCommands(QSettings *settings); 17 | void saveCommands(const Commands &commands, QSettings *settings); 18 | 19 | Commands importCommandsFromFile(const QString &filePath); 20 | Commands importCommandsFromText(const QString &commands); 21 | QString exportCommands(const Commands &commands); 22 | -------------------------------------------------------------------------------- /src/common/config.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #pragma once 4 | 5 | 6 | class QByteArray; 7 | class QPoint; 8 | class QString; 9 | class QVariant; 10 | class QWidget; 11 | 12 | bool ensureSettingsDirectoryExists(); 13 | 14 | const QString &getConfigurationFilePath(); 15 | 16 | QString getConfigurationFilePath(const char *suffix); 17 | 18 | const QString &settingsDirectoryPath(); 19 | 20 | QVariant geometryOptionValue(const QString &optionName); 21 | void setGeometryOptionValue(const QString &optionName, const QVariant &value); 22 | 23 | void restoreWindowGeometry(QWidget *w, bool openOnCurrentScreen); 24 | 25 | void saveWindowGeometry(QWidget *w, bool openOnCurrentScreen); 26 | 27 | QByteArray mainWindowState(const QString &mainWindowObjectName); 28 | 29 | void saveMainWindowState(const QString &mainWindowObjectName, const QByteArray &state); 30 | 31 | void moveToCurrentWorkspace(QWidget *w); 32 | 33 | void moveWindowOnScreen(QWidget *w, QPoint pos); 34 | 35 | void setGeometryGuardBlockedUntilHidden(QWidget *w, bool blocked); 36 | bool isGeometryGuardBlockedUntilHidden(const QWidget *w); 37 | -------------------------------------------------------------------------------- /src/common/contenttype.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #pragma once 4 | 5 | 6 | #include 7 | 8 | /** 9 | * Enum values are used in ClipboardModel class to fetch or set data from ClipboardItem. 10 | * @see ClipboardModel:setData(), ClipboardModel::data() 11 | */ 12 | namespace contentType { 13 | 14 | enum { 15 | /** 16 | * Set/get data as QVarianMap (key is MIME type and value is QByteArray). 17 | */ 18 | data = Qt::UserRole, 19 | 20 | /** 21 | * Update existing data. Clears non-internal data if passed data map contains non-internal data. 22 | */ 23 | updateData, 24 | 25 | /** 26 | * Remove formats (QStringList of MIME types). 27 | */ 28 | removeFormats, 29 | 30 | text, 31 | html, 32 | notes, 33 | 34 | /// Item color (string expression as used in themes). 35 | color, 36 | 37 | /// If true, hide content of item (not notes, tags etc.). 38 | isHidden 39 | }; 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/common/display.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #include "display.h" 4 | 5 | #include "gui/screen.h" 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | namespace { 15 | 16 | QScreen *screenForWidget(QWidget *w) 17 | { 18 | if (w) { 19 | if ( w->screen() ) 20 | return w->screen(); 21 | 22 | const int i = screenNumberAt(w->pos()); 23 | const auto screens = QGuiApplication::screens(); 24 | if (0 <= i && i < screens.size()) 25 | return screens[i]; 26 | } 27 | 28 | return QGuiApplication::primaryScreen(); 29 | } 30 | 31 | } // namespace 32 | 33 | int smallIconSize() 34 | { 35 | return QApplication::style()->pixelMetric(QStyle::PM_SmallIconSize); 36 | } 37 | 38 | QPoint toScreen(QPoint pos, QWidget *w) 39 | { 40 | QWindow *window = w->windowHandle(); 41 | w->move(pos); 42 | 43 | const QRect availableGeometry = screenAvailableGeometry(*w); 44 | if ( !availableGeometry.isValid() ) 45 | return pos; 46 | 47 | const QSize size = window ? window->size() : w->size(); 48 | return QPoint( 49 | qMax(availableGeometry.left(), qMin(pos.x(), availableGeometry.right() - size.width())), 50 | qMax(availableGeometry.top(), qMin(pos.y(), availableGeometry.bottom() - size.height())) 51 | ); 52 | } 53 | 54 | int pointsToPixels(int points, QWidget *w) 55 | { 56 | QScreen *screen = screenForWidget(w); 57 | return static_cast(points * screen->physicalDotsPerInchX() / 72.0); 58 | } 59 | -------------------------------------------------------------------------------- /src/common/display.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #pragma once 4 | 5 | 6 | class QPoint; 7 | class QWidget; 8 | 9 | int smallIconSize(); 10 | 11 | QPoint toScreen(QPoint pos, QWidget *w); 12 | 13 | int pointsToPixels(int points, QWidget *w = nullptr); 14 | -------------------------------------------------------------------------------- /src/common/globalshortcutcommands.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #pragma once 4 | 5 | 6 | #include 7 | 8 | class QString; 9 | struct Command; 10 | 11 | QVector globalShortcutCommands(); 12 | 13 | QString pasteAsPlainTextScript(const QString &what); 14 | -------------------------------------------------------------------------------- /src/common/log.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | #pragma once 3 | 4 | 5 | class QByteArray; 6 | class QString; 7 | 8 | enum LogLevel { 9 | LogAlways, 10 | LogError, 11 | LogWarning, 12 | LogNote, 13 | LogDebug, 14 | LogTrace 15 | }; 16 | 17 | const QString &logFileName(); 18 | 19 | QByteArray readLogFile(int maxReadSize); 20 | 21 | bool dropLogsToFileCountAndSize(int maxFileCount, int keepMaxSize); 22 | 23 | void createSessionMutex(); 24 | 25 | int getLogLevel(); 26 | 27 | bool hasLogLevel(LogLevel level); 28 | 29 | QByteArray logLevelLabel(LogLevel level); 30 | 31 | #define COPYQ_LOG(msg) do { if ( hasLogLevel(LogDebug) ) log(msg, LogDebug); } while (false) 32 | #define COPYQ_LOG_VERBOSE(msg) do { if ( hasLogLevel(LogTrace) ) log(msg, LogTrace); } while (false) 33 | 34 | void log(const char *text, LogLevel level = LogNote); 35 | void log(const QString &text, LogLevel level = LogNote); 36 | void log(const QByteArray &text, LogLevel level = LogNote); 37 | 38 | void setLogLabel(const QByteArray &name); 39 | 40 | QByteArray &logLabel(); 41 | -------------------------------------------------------------------------------- /src/common/messagehandlerforqt.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #pragma once 4 | 5 | 6 | void installMessageHandlerForQt(); 7 | -------------------------------------------------------------------------------- /src/common/mimetypes.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #include "mimetypes.h" 4 | 5 | #include 6 | 7 | const QLatin1String mimePrivatePrefix(COPYQ_MIME_PRIVATE_PREFIX); 8 | const QLatin1String mimeText("text/plain"); 9 | const QLatin1String mimeTextUtf8("text/plain;charset=utf-8"); 10 | const QLatin1String mimeHtml("text/html"); 11 | const QLatin1String mimeUriList("text/uri-list"); 12 | const QLatin1String mimeWindowTitle(COPYQ_MIME_PREFIX "owner-window-title"); 13 | const QLatin1String mimeItems(COPYQ_MIME_PREFIX "item"); 14 | const QLatin1String mimeItemNotes(COPYQ_MIME_PREFIX "item-notes"); 15 | const QLatin1String mimeIcon(COPYQ_MIME_PREFIX "item-icon"); 16 | const QLatin1String mimeOwner(COPYQ_MIME_PREFIX "owner"); 17 | const QLatin1String mimeClipboardMode(COPYQ_MIME_PREFIX "clipboard-mode"); 18 | const QLatin1String mimeCurrentTab(COPYQ_MIME_PREFIX "current-tab"); 19 | const QLatin1String mimeSelectedItems(COPYQ_MIME_PREFIX "selected-items"); 20 | const QLatin1String mimeCurrentItem(COPYQ_MIME_PREFIX "current-item"); 21 | const QLatin1String mimeHidden(COPYQ_MIME_PREFIX "hidden"); 22 | const QLatin1String mimeShortcut(COPYQ_MIME_PREFIX "shortcut"); 23 | const QLatin1String mimeColor(COPYQ_MIME_PREFIX "color"); 24 | const QLatin1String mimeOutputTab(COPYQ_MIME_PREFIX "output-tab"); 25 | const QLatin1String mimeDisplayItemInMenu(COPYQ_MIME_PREFIX "display-item-in-menu"); 26 | const QLatin1String mimeSecret(COPYQ_MIME_PREFIX "secret"); 27 | -------------------------------------------------------------------------------- /src/common/mimetypes.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #pragma once 4 | 5 | class QLatin1String; 6 | 7 | #define COPYQ_MIME_PREFIX "application/x-copyq-" 8 | // Prefix for MIME format not visible to user for data private to plugins. 9 | #define COPYQ_MIME_PRIVATE_PREFIX COPYQ_MIME_PREFIX "private-" 10 | extern const QLatin1String mimePrivatePrefix; 11 | extern const QLatin1String mimeText; 12 | extern const QLatin1String mimeTextUtf8; 13 | extern const QLatin1String mimeHtml; 14 | extern const QLatin1String mimeUriList; 15 | extern const QLatin1String mimeWindowTitle; 16 | extern const QLatin1String mimeItems; 17 | extern const QLatin1String mimeItemNotes; 18 | extern const QLatin1String mimeIcon; 19 | extern const QLatin1String mimeOwner; 20 | extern const QLatin1String mimeClipboardMode; 21 | extern const QLatin1String mimeCurrentTab; 22 | extern const QLatin1String mimeSelectedItems; 23 | extern const QLatin1String mimeCurrentItem; 24 | extern const QLatin1String mimeHidden; 25 | extern const QLatin1String mimeShortcut; 26 | extern const QLatin1String mimeColor; 27 | extern const QLatin1String mimeOutputTab; 28 | extern const QLatin1String mimeDisplayItemInMenu; 29 | extern const QLatin1String mimeSecret; 30 | -------------------------------------------------------------------------------- /src/common/navigationstyle.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | #pragma once 3 | 4 | #include 5 | #if QT_VERSION < QT_VERSION_CHECK(6,0,0) 6 | # include 7 | #endif 8 | 9 | enum class NavigationStyle { 10 | Default, 11 | Vi, 12 | Emacs 13 | }; 14 | 15 | #if QT_VERSION < QT_VERSION_CHECK(6,0,0) 16 | Q_DECLARE_METATYPE(NavigationStyle) 17 | #endif 18 | -------------------------------------------------------------------------------- /src/common/option.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #pragma once 4 | 5 | 6 | #include 7 | 8 | class QObject; 9 | 10 | /** 11 | * Configuration option. 12 | */ 13 | class Option final { 14 | public: 15 | Option(); 16 | 17 | /** 18 | * Create option with a default value. 19 | * Current value is taken from object's property. 20 | */ 21 | explicit Option( 22 | const QVariant &default_value, 23 | const char *property_name, 24 | QObject *obj 25 | ); 26 | 27 | explicit Option( 28 | const QVariant &default_value, 29 | const char *description = nullptr 30 | ); 31 | 32 | /** Return current value. */ 33 | QVariant value() const; 34 | 35 | /** Set current value. */ 36 | bool setValue(const QVariant &value); 37 | 38 | /** Reset option to default value. */ 39 | void reset(); 40 | 41 | /** 42 | * Tooltip for option. 43 | * This text is taken from toolTip property of a QObject which was passed 44 | * to constructor. 45 | */ 46 | QString tooltip() const; 47 | 48 | private: 49 | QVariant m_default_value; 50 | QVariant m_value; 51 | const char *m_property_name = nullptr; 52 | const char *m_description = nullptr; 53 | QObject *m_obj = nullptr; 54 | }; 55 | -------------------------------------------------------------------------------- /src/common/predefinedcommands.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #pragma once 4 | 5 | 6 | #include 7 | 8 | struct Command; 9 | 10 | QVector predefinedCommands(); 11 | -------------------------------------------------------------------------------- /src/common/processsignals.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | 4 | #include 5 | #include 6 | 7 | template 8 | void connectProcessFinished(QProcess *process, Receiver *receiver, void (Receiver::*slot)()) 9 | { 10 | const auto processFinishedSignal = static_cast(&QProcess::finished); 11 | QObject::connect( 12 | process, processFinishedSignal, receiver, 13 | [receiver, slot](int, QProcess::ExitStatus) { 14 | (receiver->*slot)(); 15 | }); 16 | } 17 | 18 | template 19 | void connectProcessFinished(QProcess *process, Receiver *receiver, void (Receiver::*slot)(int, QProcess::ExitStatus)) 20 | { 21 | const auto processFinishedSignal = static_cast(&QProcess::finished); 22 | QObject::connect(process, processFinishedSignal, receiver, slot); 23 | } 24 | 25 | template 26 | void connectProcessError(QProcess *process, Receiver receiver, Slot slot) 27 | { 28 | QObject::connect( process, &QProcess::errorOccurred, receiver, slot ); 29 | } 30 | -------------------------------------------------------------------------------- /src/common/regexp.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | 4 | #include 5 | 6 | static QRegularExpression anchoredRegExp(const QString &pattern) 7 | { 8 | return QRegularExpression(QRegularExpression::anchoredPattern(pattern)); 9 | } 10 | -------------------------------------------------------------------------------- /src/common/server.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #pragma once 4 | 5 | 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | class ClientSocket; 12 | class QEventLoop; 13 | class QLocalServer; 14 | 15 | using ClientSocketPtr = std::shared_ptr; 16 | Q_DECLARE_METATYPE(ClientSocketPtr) 17 | 18 | class Server final : public QObject 19 | { 20 | Q_OBJECT 21 | public: 22 | explicit Server(const QString &name, QObject *parent = nullptr); 23 | 24 | ~Server(); 25 | 26 | void start(); 27 | 28 | bool isListening() const; 29 | 30 | void close(); 31 | 32 | signals: 33 | void newConnection(const ClientSocketPtr &socket); 34 | 35 | private: 36 | void onNewConnection(); 37 | void onSocketDestroyed(); 38 | 39 | struct PrivateData; 40 | std::unique_ptr m_data; 41 | }; 42 | -------------------------------------------------------------------------------- /src/common/settings.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #include "settings.h" 4 | 5 | #include 6 | 7 | Settings::Settings() 8 | : QSettings( 9 | QSettings::defaultFormat(), 10 | QSettings::UserScope, 11 | QCoreApplication::organizationName(), 12 | QCoreApplication::applicationName() ) 13 | { 14 | } 15 | 16 | Settings::Settings(const QString &path) 17 | : QSettings(path, QSettings::IniFormat) 18 | { 19 | } 20 | -------------------------------------------------------------------------------- /src/common/settings.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #pragma once 4 | 5 | #include 6 | 7 | class QString; 8 | 9 | /** 10 | * Simple wrapper class for QSettings. 11 | */ 12 | class Settings final : public QSettings 13 | { 14 | public: 15 | Settings(); 16 | 17 | explicit Settings(const QString &path); 18 | 19 | Settings(const Settings &) = delete; 20 | Settings &operator=(const Settings &) = delete; 21 | }; 22 | -------------------------------------------------------------------------------- /src/common/shortcuts.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #include "shortcuts.h" 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | namespace { 10 | 11 | int indexOfKeyHint(const QString &name) 12 | { 13 | bool amp = false; 14 | int i = 0; 15 | 16 | for (const auto &c : name) { 17 | if (c == '&') 18 | amp = !amp; 19 | else if (amp) 20 | return i - 1; 21 | ++i; 22 | } 23 | 24 | return -1; 25 | } 26 | 27 | } // namespace 28 | 29 | QString shortcutToRemove() 30 | { 31 | #ifdef Q_OS_MAC 32 | return QObject::tr("Backspace", "Key to remove item or MIME on OS X"); 33 | #else 34 | return QObject::tr("Delete", "Key to remove item or MIME"); 35 | #endif 36 | } 37 | 38 | QString portableShortcutText(const QKeySequence &shortcut) 39 | { 40 | // WORKAROUND: Qt has convert some keys to upper case which 41 | // breaks some shortcuts on some keyboard layouts. 42 | return shortcut.toString(QKeySequence::PortableText).toLower(); 43 | } 44 | 45 | QString toPortableShortcutText(const QString &shortcutNativeText) 46 | { 47 | return portableShortcutText( 48 | QKeySequence(shortcutNativeText, QKeySequence::NativeText)); 49 | } 50 | 51 | bool hasKeyHint(const QString &name) 52 | { 53 | return indexOfKeyHint(name) != -1; 54 | } 55 | 56 | QString &removeKeyHint(QString *name) 57 | { 58 | const int i = indexOfKeyHint(*name); 59 | return i == -1 ? *name : name->remove(i, 1); 60 | } 61 | -------------------------------------------------------------------------------- /src/common/shortcuts.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #pragma once 4 | 5 | 6 | class QString; 7 | class QKeySequence; 8 | 9 | /** 10 | * Shortcut to remove items, formats etc. 11 | */ 12 | QString shortcutToRemove(); 13 | 14 | QString portableShortcutText(const QKeySequence &shortcut); 15 | 16 | QString toPortableShortcutText(const QString &shortcutNativeText); 17 | 18 | /// Returns true only if UI name contains key hint (unescaped '&'). 19 | bool hasKeyHint(const QString &name); 20 | 21 | /// Removes key hint (first unescaped '&') from UI name. 22 | QString &removeKeyHint(QString *name); 23 | -------------------------------------------------------------------------------- /src/common/sleeptimer.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #pragma once 4 | 5 | 6 | #include 7 | #include 8 | 9 | class SleepTimer final 10 | { 11 | public: 12 | explicit SleepTimer(int timeoutMs, int minSleepCount = 2) 13 | : m_timeoutMs(timeoutMs) 14 | , m_minSleepCount(minSleepCount) 15 | { 16 | m_timer.start(); 17 | } 18 | 19 | bool sleep() 20 | { 21 | if (m_minSleepCount <= 0 && m_timer.elapsed() >= m_timeoutMs) 22 | return false; 23 | 24 | --m_minSleepCount; 25 | QCoreApplication::processEvents(QEventLoop::AllEvents, 5); 26 | return true; 27 | } 28 | 29 | private: 30 | QElapsedTimer m_timer; 31 | int m_timeoutMs; 32 | int m_minSleepCount = 2; 33 | }; 34 | 35 | inline void waitFor(int ms) 36 | { 37 | SleepTimer t(ms); 38 | while (t.sleep()) {} 39 | } 40 | -------------------------------------------------------------------------------- /src/common/tabs.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #pragma once 4 | 5 | 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | class QSettings; 12 | 13 | struct TabProperties { 14 | QString name; 15 | QString iconName; 16 | int maxItemCount = 0; 17 | bool storeItems = true; 18 | }; 19 | 20 | class Tabs 21 | { 22 | public: 23 | Tabs(); 24 | ~Tabs(); 25 | 26 | Tabs(const Tabs &other); 27 | Tabs &operator=(const Tabs &other); 28 | 29 | TabProperties tabProperties(const QString &name) const; 30 | void setTabProperties(const TabProperties &tabProperties); 31 | 32 | void save(QSettings *settings, const QStringList &tabs); 33 | 34 | private: 35 | struct PrivateData; 36 | std::unique_ptr m_data; 37 | }; 38 | -------------------------------------------------------------------------------- /src/common/temporaryfile.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #include "temporaryfile.h" 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | namespace { 10 | 11 | Q_DECLARE_LOGGING_CATEGORY(tempFileCategory) 12 | Q_LOGGING_CATEGORY(tempFileCategory, "copyq.temporaryfile") 13 | 14 | } // namespace 15 | 16 | bool openTemporaryFile(QTemporaryFile *file, const QString &suffix) 17 | { 18 | const QString tmpFileName = "CopyQ.XXXXXX" + suffix; 19 | const QString tmpPath = QDir( QDir::tempPath() ).absoluteFilePath(tmpFileName); 20 | file->setFileTemplate(tmpPath); 21 | 22 | if ( !file->open() ) { 23 | qCCritical(tempFileCategory) << "Failed to open temporary file" 24 | << file->fileName() << "template" << tmpPath << ":" << file->errorString(); 25 | return false; 26 | } 27 | 28 | if ( !file->setPermissions(QFile::ReadOwner | QFile::WriteOwner | QFile::ExeOwner) ) { 29 | qCCritical(tempFileCategory) << "Failed set permissions to temporary file" 30 | << file->fileName() << ":" << file->errorString(); 31 | return false; 32 | } 33 | 34 | return true; 35 | } 36 | -------------------------------------------------------------------------------- /src/common/temporaryfile.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | #pragma once 3 | 4 | 5 | class QString; 6 | class QTemporaryFile; 7 | 8 | bool openTemporaryFile(QTemporaryFile *file, const QString &suffix); 9 | -------------------------------------------------------------------------------- /src/common/temporarysettings.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #include "temporarysettings.h" 4 | 5 | #include "common/log.h" 6 | #include "common/temporaryfile.h" 7 | 8 | #include 9 | #include 10 | 11 | namespace { 12 | 13 | QString temporaryFileName(const QByteArray &content) 14 | { 15 | QTemporaryFile tmpfile; 16 | if ( !openTemporaryFile(&tmpfile, ".ini") ) 17 | { 18 | log("Failed to create temporary settings file", LogError); 19 | return QString(); 20 | } 21 | 22 | tmpfile.write(content); 23 | tmpfile.setAutoRemove(false); 24 | return tmpfile.fileName(); 25 | } 26 | 27 | } // namespace 28 | 29 | TemporarySettings::TemporarySettings(const QByteArray &content) 30 | : m_settings(new QSettings(temporaryFileName(content), QSettings::IniFormat)) 31 | { 32 | } 33 | 34 | TemporarySettings::~TemporarySettings() 35 | { 36 | const QString fileName = m_settings->fileName(); 37 | delete m_settings; 38 | m_settings = nullptr; 39 | 40 | if (!fileName.isEmpty()) 41 | QFile::remove(fileName); 42 | } 43 | 44 | QSettings *TemporarySettings::settings() 45 | { 46 | return m_settings; 47 | } 48 | 49 | QByteArray TemporarySettings::content() 50 | { 51 | m_settings->sync(); 52 | 53 | QFile file(m_settings->fileName()); 54 | if (!file.open(QIODevice::ReadOnly)) { 55 | log("Failed to open temporary settings file", LogError); 56 | return QByteArray(); 57 | } 58 | 59 | return file.readAll(); 60 | } 61 | -------------------------------------------------------------------------------- /src/common/temporarysettings.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #pragma once 4 | 5 | 6 | class QByteArray; 7 | class QSettings; 8 | 9 | /** 10 | * Temporary ini settings which is removed after destroyed. 11 | * 12 | * Use this to get ini as data instead of saving to a file. 13 | */ 14 | class TemporarySettings final 15 | { 16 | public: 17 | /// Creates temporary settings file. 18 | explicit TemporarySettings(const QByteArray &content); 19 | 20 | /// Destroys underlying settings and removes settings file. 21 | ~TemporarySettings(); 22 | 23 | /// Returns underlying settings. 24 | QSettings *settings(); 25 | 26 | /// Return content of settings file. 27 | QByteArray content(); 28 | 29 | TemporarySettings(const TemporarySettings &) = delete; 30 | TemporarySettings &operator=(const TemporarySettings &) = delete; 31 | 32 | private: 33 | QSettings *m_settings; 34 | }; 35 | -------------------------------------------------------------------------------- /src/common/textdata.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #pragma once 4 | 5 | 6 | #include 7 | #if QT_VERSION < QT_VERSION_CHECK(6,0,0) 8 | #include 9 | #endif 10 | 11 | class QByteArray; 12 | class QString; 13 | 14 | uint hash(const QVariantMap &data); 15 | 16 | QString quoteString(const QString &str); 17 | 18 | QString escapeHtml(const QString &str); 19 | 20 | QString getTextData(const QByteArray &bytes); 21 | 22 | /** 23 | * Get given text format from data; null string if not available. 24 | * Assumes that text data is UTF8 encoded. 25 | */ 26 | QString getTextData(const QVariantMap &data, const QString &mime); 27 | 28 | /** Helper function that calls getTextData(data, "text/plain"). */ 29 | QString getTextData(const QVariantMap &data); 30 | 31 | void setTextData(QVariantMap *data, const QString &text, const QString &mime); 32 | 33 | void setTextData(QVariantMap *data, const QString &text); 34 | 35 | QVariantMap createDataMap(const QString &format, const QVariant &value); 36 | 37 | QVariantMap createDataMap(const QString &format, const QByteArray &value); 38 | 39 | QVariantMap createDataMap(const QString &format, const QString &value); 40 | 41 | /// Returns text without accents/diacritics. 42 | QString accentsRemoved(const QString &text); 43 | -------------------------------------------------------------------------------- /src/common/timer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | template 6 | void initSingleShotTimer(QTimer *timer, int milliseconds, const Receiver *receiver, Slot slot) 7 | { 8 | timer->setSingleShot(true); 9 | timer->setInterval(milliseconds); 10 | 11 | Q_ASSERT(receiver); 12 | if (!receiver) 13 | return; 14 | 15 | // Unique connection only works with member functions. 16 | const auto flags = std::is_invocable() ? Qt::AutoConnection : Qt::UniqueConnection; 17 | QObject::connect(timer, &QTimer::timeout, receiver, slot, flags); 18 | } 19 | -------------------------------------------------------------------------------- /src/common/version.cpp.in: -------------------------------------------------------------------------------- 1 | #include "common/version.h" 2 | #include 3 | const QLatin1String versionString("${copyq_version}"); 4 | -------------------------------------------------------------------------------- /src/common/version.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | class QLatin1String; 3 | extern const QLatin1String versionString; 4 | -------------------------------------------------------------------------------- /src/copyq.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | images/icon.svg 4 | images/icon_mask.svg 5 | images/tab_icon.svg 6 | images/tab_new.svg 7 | images/tab_rename.svg 8 | images/tab_remove.svg 9 | images/icon_512x512.png 10 | images/fontawesome.ttf 11 | knotifications5/copyq.notifyrc 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/copyq.rc: -------------------------------------------------------------------------------- 1 | DI_ICON1 ICON DISCARDABLE "images/icon.ico" 2 | -------------------------------------------------------------------------------- /src/gui/aboutdialog.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #pragma once 4 | 5 | 6 | #include 7 | 8 | namespace Ui { 9 | class AboutDialog; 10 | } 11 | 12 | class AboutDialog final : public QDialog 13 | { 14 | Q_OBJECT 15 | public: 16 | explicit AboutDialog(QWidget *parent = nullptr); 17 | ~AboutDialog(); 18 | 19 | private: 20 | static QString aboutPage(); 21 | 22 | Ui::AboutDialog *ui; 23 | }; 24 | -------------------------------------------------------------------------------- /src/gui/actionhandler.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #pragma once 4 | 5 | 6 | #include 7 | #include 8 | 9 | class Action; 10 | class NotificationDaemon; 11 | class ActionTableModel; 12 | 13 | class ActionHandler final : public QObject 14 | { 15 | Q_OBJECT 16 | public: 17 | explicit ActionHandler(NotificationDaemon *notificationDaemon, QObject *parent); 18 | 19 | void setMaxRowCount(uint rows); 20 | 21 | int runningActionCount() const { return m_actions.size() - m_internalActions.size(); } 22 | 23 | void showProcessManagerDialog(QWidget *parent); 24 | 25 | void addFinishedAction(const QString &name); 26 | 27 | QVariantMap actionData(int id) const; 28 | void setActionData(int id, const QVariantMap &data); 29 | 30 | void internalAction(Action *action); 31 | bool isInternalActionId(int id) const; 32 | 33 | /** Execute action. */ 34 | void action(Action *action); 35 | 36 | void terminateAction(int id); 37 | 38 | private: 39 | /** Delete finished action and its menu item. */ 40 | void closeAction(Action *action); 41 | 42 | void showActionErrors(Action *action, const QString &message, ushort icon); 43 | 44 | NotificationDaemon *m_notificationDaemon; 45 | ActionTableModel *m_actionModel; 46 | QHash m_actions; 47 | QSet m_internalActions; 48 | int m_lastActionId = -1; 49 | }; 50 | -------------------------------------------------------------------------------- /src/gui/actionhandlerdialog.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #pragma once 4 | 5 | 6 | #include 7 | 8 | class ActionHandler; 9 | class QAbstractItemModel; 10 | 11 | namespace Ui { 12 | class ActionHandlerDialog; 13 | } 14 | 15 | class ActionHandlerDialog final : public QDialog 16 | { 17 | public: 18 | explicit ActionHandlerDialog(ActionHandler *actionHandler, QAbstractItemModel *model, QWidget *parent = nullptr); 19 | ~ActionHandlerDialog(); 20 | 21 | private: 22 | Ui::ActionHandlerDialog *ui; 23 | }; 24 | -------------------------------------------------------------------------------- /src/gui/addcommanddialog.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #pragma once 4 | 5 | 6 | #include "common/command.h" 7 | 8 | #include 9 | #include 10 | 11 | namespace Ui { 12 | class AddCommandDialog; 13 | } 14 | 15 | class QSortFilterProxyModel; 16 | 17 | class AddCommandDialog final : public QDialog 18 | { 19 | Q_OBJECT 20 | 21 | public: 22 | explicit AddCommandDialog(const QVector &pluginCommands, QWidget *parent = nullptr); 23 | ~AddCommandDialog(); 24 | 25 | void accept() override; 26 | 27 | signals: 28 | void addCommands(const QVector &commands); 29 | 30 | private: 31 | void onLineEditFilterTextChanged(const QString &text); 32 | void onListViewCommandsActivated(); 33 | 34 | Ui::AddCommandDialog *ui; 35 | QSortFilterProxyModel *m_filterModel; 36 | }; 37 | -------------------------------------------------------------------------------- /src/gui/clipboardbrowsershared.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | #pragma once 3 | 4 | 5 | #include "common/navigationstyle.h" 6 | #include "gui/menuitems.h" 7 | #include "gui/theme.h" 8 | 9 | #include 10 | 11 | #include 12 | 13 | class ActionHandler; 14 | class ItemFactory; 15 | class NotificationDaemon; 16 | 17 | struct ClipboardBrowserShared { 18 | QString editor; 19 | int maxItems = 100; 20 | bool textWrap = true; 21 | NavigationStyle navigationStyle = NavigationStyle::Default; 22 | bool saveOnReturnKey = false; 23 | bool moveItemOnReturnKey = false; 24 | bool showSimpleItems = false; 25 | bool numberSearch = false; 26 | int minutesToExpire = 0; 27 | int saveDelayMsOnItemAdded = 0; 28 | int saveDelayMsOnItemModified = 0; 29 | int saveDelayMsOnItemRemoved = 0; 30 | int saveDelayMsOnItemMoved = 0; 31 | int saveDelayMsOnItemEdited = 0; 32 | bool rowIndexFromOne = true; 33 | ItemFactory *itemFactory = nullptr; 34 | ActionHandler *actions = nullptr; 35 | NotificationDaemon *notifications = nullptr; 36 | Theme theme; 37 | MenuItems menuItems; 38 | }; 39 | 40 | using ClipboardBrowserSharedPtr = std::shared_ptr; 41 | -------------------------------------------------------------------------------- /src/gui/clipboardspy.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #pragma once 4 | 5 | 6 | #include "common/clipboardmode.h" 7 | #include "platform/platformnativeinterface.h" 8 | 9 | #include 10 | 11 | class ClipboardSpy final : public QObject 12 | { 13 | Q_OBJECT 14 | public: 15 | explicit ClipboardSpy(ClipboardMode mode, const QByteArray &owner); 16 | 17 | /// Actively wait for clipboard/selection to change. 18 | void wait(int ms = 2000, int checkIntervalMs = 8000); 19 | 20 | bool setClipboardData(const QVariantMap &data); 21 | 22 | QByteArray currentOwnerData() const; 23 | 24 | void stop(); 25 | 26 | signals: 27 | void changed(); 28 | void stopped(); 29 | 30 | private: 31 | void emitChangeIfChanged(); 32 | 33 | ClipboardMode m_mode; 34 | PlatformClipboardPtr m_clipboard; 35 | QByteArray m_oldOwnerData; 36 | bool m_settingClipboard = false; 37 | }; 38 | -------------------------------------------------------------------------------- /src/gui/commandaction.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #include "commandaction.h" 4 | 5 | #include "common/common.h" 6 | #include "common/mimetypes.h" 7 | #include "common/shortcuts.h" 8 | #include "common/textdata.h" 9 | #include "gui/iconfactory.h" 10 | 11 | #include 12 | #include 13 | 14 | CommandAction::CommandAction( 15 | const Command &command, 16 | const QString &name, 17 | QMenu *parentMenu) 18 | : QAction(parentMenu) 19 | , m_command(command) 20 | { 21 | setText( elideText(name, parentMenu->font(), QString()) ); 22 | 23 | setIcon( iconFromFile(m_command.icon) ); 24 | if (m_command.icon.size() == 1) 25 | setProperty( "CopyQ_icon_id", m_command.icon[0].unicode() ); 26 | 27 | connect(this, &QAction::triggered, this, &CommandAction::onTriggered); 28 | 29 | parentMenu->addAction(this); 30 | } 31 | 32 | const Command &CommandAction::command() const 33 | { 34 | return m_command; 35 | } 36 | 37 | bool CommandAction::event(QEvent *event) 38 | { 39 | if (event->type() == QEvent::Shortcut) { 40 | QShortcutEvent *shortcutEvent = static_cast(event); 41 | m_triggeredShortcut = portableShortcutText(shortcutEvent->key()); 42 | } 43 | 44 | return QAction::event(event); 45 | } 46 | 47 | void CommandAction::onTriggered() 48 | { 49 | const auto triggeredShortcut = m_triggeredShortcut; 50 | m_triggeredShortcut.clear(); 51 | emit triggerCommand(this, triggeredShortcut); 52 | } 53 | -------------------------------------------------------------------------------- /src/gui/commandaction.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #pragma once 4 | 5 | 6 | #include "common/command.h" 7 | 8 | #include 9 | #include 10 | 11 | class CommandAction final : public QAction 12 | { 13 | Q_OBJECT 14 | public: 15 | CommandAction(const Command &command, 16 | const QString &name, 17 | QMenu *parentMenu = nullptr); 18 | 19 | const Command &command() const; 20 | 21 | signals: 22 | void triggerCommand(CommandAction *self, const QString &triggeredShortcut); 23 | 24 | protected: 25 | bool event(QEvent *event) override; 26 | 27 | private: 28 | void onTriggered(); 29 | void onChanged(); 30 | 31 | Command m_command; 32 | QString m_triggeredShortcut; 33 | }; 34 | -------------------------------------------------------------------------------- /src/gui/commandcompleter.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #pragma once 4 | 5 | 6 | #include 7 | 8 | class QCompleter; 9 | class QPlainTextEdit; 10 | 11 | class CommandCompleter final : public QObject { 12 | Q_OBJECT 13 | Q_PROPERTY(QWidget* popup READ popup) 14 | 15 | public: 16 | explicit CommandCompleter(QPlainTextEdit *editor); 17 | 18 | bool eventFilter(QObject *watched, QEvent *event) override; 19 | 20 | QWidget *popup() const; 21 | 22 | private: 23 | void onTextChanged(); 24 | void updateCompletion(bool forceShow); 25 | void insertCompletion(const QString &completion); 26 | void showCompletion(); 27 | 28 | QString textUnderCursor() const; 29 | 30 | QPlainTextEdit *m_editor; 31 | QCompleter *m_completer; 32 | }; 33 | -------------------------------------------------------------------------------- /src/gui/commandedit.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #pragma once 4 | 5 | 6 | #include 7 | 8 | namespace Ui { 9 | class CommandEdit; 10 | } 11 | 12 | class CommandEdit final : public QWidget 13 | { 14 | Q_OBJECT 15 | 16 | public: 17 | explicit CommandEdit(QWidget *parent = nullptr); 18 | ~CommandEdit(); 19 | 20 | void setCommand(const QString &command) const; 21 | QString command() const; 22 | 23 | bool isEmpty() const; 24 | 25 | void setReadOnly(bool readOnly); 26 | 27 | signals: 28 | void changed(); 29 | void commandTextChanged(const QString &command); 30 | 31 | private: 32 | void onPlainTextEditCommandTextChanged(); 33 | 34 | Ui::CommandEdit *ui; 35 | }; 36 | -------------------------------------------------------------------------------- /src/gui/commandhelpbutton.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #pragma once 4 | 5 | 6 | #include 7 | 8 | class QToolButton; 9 | class QDialog; 10 | 11 | class CommandHelpButton final : public QWidget 12 | { 13 | Q_OBJECT 14 | public: 15 | explicit CommandHelpButton(QWidget *parent = nullptr); 16 | 17 | public: 18 | void showHelp(); 19 | 20 | signals: 21 | void hidden(); 22 | 23 | private: 24 | QToolButton *m_button; 25 | QDialog *m_help; 26 | }; 27 | -------------------------------------------------------------------------------- /src/gui/commandsyntaxhighlighter.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #pragma once 4 | 5 | 6 | #include 7 | 8 | class QPlainTextEdit; 9 | class QTextEdit; 10 | 11 | QList scriptableKeywords(); 12 | QList scriptableProperties(); 13 | QList scriptableFunctions(); 14 | /// Constructors and functions from ECMA specification supported by Qt plus ByteArray. 15 | QList scriptableObjects(); 16 | 17 | void installCommandSyntaxHighlighter(QTextEdit *editor); 18 | void installCommandSyntaxHighlighter(QPlainTextEdit *editor); 19 | -------------------------------------------------------------------------------- /src/gui/configtabtabs.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #pragma once 4 | 5 | 6 | #include 7 | 8 | class ItemOrderList; 9 | class QSettings; 10 | 11 | class ConfigTabTabs final : public QWidget 12 | { 13 | Q_OBJECT 14 | public: 15 | explicit ConfigTabTabs(QWidget *parent = nullptr); 16 | 17 | void saveTabs(QSettings *settings); 18 | 19 | private: 20 | ItemOrderList *m_list; 21 | }; 22 | -------------------------------------------------------------------------------- /src/gui/filedialog.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #include "filedialog.h" 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | FileDialog::FileDialog(QWidget *parent, const QString &caption, const QString &fileName) 10 | : QObject(parent) 11 | , m_parent(parent) 12 | , m_caption(caption) 13 | , m_defaultPath(QFileInfo(fileName).absoluteFilePath()) 14 | { 15 | } 16 | 17 | void FileDialog::exec() 18 | { 19 | const QString fileName = 20 | QFileDialog::getSaveFileName( 21 | m_parent, m_caption, m_defaultPath, 22 | /* filter = */ QString(), /* selectedFilter = */ nullptr, 23 | QFileDialog::DontConfirmOverwrite | QFileDialog::ReadOnly); 24 | if (!fileName.isEmpty()) 25 | emit fileSelected(fileName); 26 | } 27 | -------------------------------------------------------------------------------- /src/gui/filedialog.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #pragma once 4 | 5 | 6 | #include 7 | #include 8 | 9 | class QWidget; 10 | 11 | /** 12 | * Opens native file dialog (unlike QFileDialog). 13 | */ 14 | class FileDialog final : public QObject 15 | { 16 | Q_OBJECT 17 | public: 18 | FileDialog(QWidget *parent, const QString &caption, const QString &fileName); 19 | 20 | void exec(); 21 | 22 | signals: 23 | void fileSelected(const QString &fileName); 24 | 25 | private: 26 | QWidget *m_parent; 27 | QString m_caption; 28 | QString m_defaultPath; 29 | }; 30 | -------------------------------------------------------------------------------- /src/gui/filtercompleter.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #pragma once 4 | 5 | 6 | #include 7 | #include 8 | 9 | class QLineEdit; 10 | 11 | class FilterCompleter final : public QCompleter 12 | { 13 | Q_OBJECT 14 | Q_PROPERTY(QStringList history READ history WRITE setHistory) 15 | public: 16 | static void installCompleter(QLineEdit *lineEdit); 17 | static void removeCompleter(QLineEdit *lineEdit); 18 | 19 | QStringList history() const; 20 | void setHistory(const QStringList &history); 21 | 22 | protected: 23 | bool eventFilter(QObject *obj, QEvent *event) override; 24 | 25 | private: 26 | void onTextEdited(const QString &text); 27 | void onEditingFinished(); 28 | void onComplete(); 29 | 30 | explicit FilterCompleter(QLineEdit *lineEdit); 31 | void setUnfiltered(bool unfiltered); 32 | void prependItem(const QString &item); 33 | 34 | QLineEdit *m_lineEdit; 35 | QString m_lastText; 36 | }; 37 | -------------------------------------------------------------------------------- /src/gui/fromiconid.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | #pragma once 3 | 4 | #include 5 | #include 6 | 7 | inline QString fromIconId(int id) { 8 | return QString(QChar(id)); 9 | } 10 | -------------------------------------------------------------------------------- /src/gui/iconfactory.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #pragma once 4 | 5 | 6 | class QColor; 7 | class QIcon; 8 | class QPixmap; 9 | class QPainter; 10 | class QObject; 11 | class QString; 12 | class QVariant; 13 | class QWidget; 14 | 15 | QIcon getIcon(const QString &themeName, unsigned short id); 16 | 17 | QIcon getIcon(const QVariant &iconOrIconId); 18 | 19 | QIcon getIconFromResources(const QString &iconName); 20 | 21 | QIcon iconFromFile(const QString &fileName, const QString &tag, const QColor &color); 22 | QIcon iconFromFile(const QString &fileName, const QString &tag); 23 | QIcon iconFromFile(const QString &fileName); 24 | 25 | unsigned short toIconId(const QString &fileNameOrId); 26 | 27 | QPixmap createPixmap(unsigned short id, const QColor &color, int size); 28 | 29 | /// Return app icon (color is calculated from session name). 30 | QIcon appIcon(); 31 | 32 | void setActivePaintDevice(QObject *device); 33 | 34 | QColor getDefaultIconColor(const QWidget &widget, bool selected = false); 35 | 36 | void setSessionIconColor(QColor color); 37 | 38 | void setSessionIconTag(const QString &tag); 39 | 40 | void setSessionIconTagColor(QColor color); 41 | 42 | void setSessionIconEnabled(bool enabled); 43 | 44 | QColor sessionIconColor(); 45 | 46 | QString sessionIconTag(); 47 | 48 | QColor sessionIconTagColor(); 49 | 50 | void setUseSystemIcons(bool useSystemIcons); 51 | -------------------------------------------------------------------------------- /src/gui/iconfont.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #pragma once 4 | 5 | 6 | class QFont; 7 | class QString; 8 | 9 | const QString &iconFontFamily(); 10 | 11 | bool loadIconFont(); 12 | 13 | int iconFontSizePixels(); 14 | 15 | QFont iconFont(); 16 | 17 | QFont iconFontFitSize(int w, int h); 18 | -------------------------------------------------------------------------------- /src/gui/iconselectbutton.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #pragma once 4 | 5 | 6 | #include 7 | 8 | class IconSelectButton final : public QPushButton 9 | { 10 | Q_OBJECT 11 | Q_PROPERTY(QString currentIcon READ currentIcon WRITE setCurrentIcon NOTIFY currentIconChanged) 12 | public: 13 | explicit IconSelectButton(QWidget *parent = nullptr); 14 | 15 | const QString ¤tIcon() const { return m_currentIcon; } 16 | 17 | QSize sizeHint() const override; 18 | 19 | void setCurrentIcon(const QString &iconString); 20 | 21 | signals: 22 | void currentIconChanged(const QString &icon); 23 | 24 | private: 25 | void onClicked(); 26 | 27 | QString m_currentIcon; 28 | }; 29 | -------------------------------------------------------------------------------- /src/gui/iconselectdialog.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #pragma once 4 | 5 | 6 | #include 7 | 8 | class QModelIndex; 9 | 10 | class IconListWidget; 11 | 12 | class IconSelectDialog final : public QDialog 13 | { 14 | Q_OBJECT 15 | 16 | public: 17 | explicit IconSelectDialog(const QString &defaultIcon, QWidget *parent = nullptr); 18 | 19 | const QString &selectedIcon() const { return m_selectedIcon; } 20 | 21 | void done(int result) override; 22 | 23 | signals: 24 | void iconSelected(const QString &icon); 25 | 26 | private: 27 | void onIconListItemActivated(const QModelIndex &index); 28 | 29 | void onBrowse(); 30 | 31 | void onAcceptCurrent(); 32 | 33 | void addIcons(); 34 | 35 | IconListWidget *m_iconList; 36 | QString m_selectedIcon; 37 | }; 38 | -------------------------------------------------------------------------------- /src/gui/iconwidget.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #include "iconwidget.h" 4 | 5 | #include "gui/icons.h" 6 | #include "gui/iconfont.h" 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | IconWidget::IconWidget(int icon, QWidget *parent) 13 | : QWidget(parent) 14 | , m_icon() 15 | { 16 | QFontMetrics fm(iconFont()); 17 | QChar c(icon); 18 | if ( fm.inFont(c) ) 19 | m_icon = QString(c); 20 | 21 | setFixedSize(sizeHint()); 22 | } 23 | 24 | IconWidget::IconWidget(const QString &icon, QWidget *parent) 25 | : QWidget(parent) 26 | , m_icon(icon) 27 | { 28 | setFixedSize(sizeHint()); 29 | } 30 | 31 | QSize IconWidget::sizeHint() const 32 | { 33 | if ( m_icon.isEmpty() ) 34 | return QSize(0, 0); 35 | 36 | const int side = iconFontSizePixels() + 4; 37 | return QSize(side, side); 38 | } 39 | 40 | void IconWidget::paintEvent(QPaintEvent *) 41 | { 42 | if (m_icon.isEmpty()) 43 | return; 44 | 45 | QPainter p(this); 46 | 47 | if (m_icon.size() == 1) { 48 | p.setFont(iconFont()); 49 | p.setRenderHint(QPainter::TextAntialiasing, true); 50 | 51 | if (parentWidget()) 52 | p.setPen( parentWidget()->palette().color(QPalette::Text) ); 53 | p.drawText( rect(), Qt::AlignCenter, m_icon); 54 | } else { 55 | QPixmap pix(m_icon); 56 | p.drawPixmap( 0, 0, pix.scaled(size(), Qt::KeepAspectRatio) ); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/gui/iconwidget.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #pragma once 4 | 5 | 6 | #include 7 | 8 | class QString; 9 | 10 | class IconWidget final : public QWidget 11 | { 12 | public: 13 | explicit IconWidget(int icon, QWidget *parent = nullptr); 14 | 15 | explicit IconWidget(const QString &icon, QWidget *parent = nullptr); 16 | 17 | QSize sizeHint() const override; 18 | 19 | protected: 20 | void paintEvent(QPaintEvent *event) override; 21 | 22 | private: 23 | QString m_icon; 24 | }; 25 | -------------------------------------------------------------------------------- /src/gui/importexportdialog.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #pragma once 4 | 5 | 6 | #include 7 | 8 | namespace Ui { 9 | class ImportExportDialog; 10 | } 11 | 12 | class ImportExportDialog final : public QDialog 13 | { 14 | public: 15 | explicit ImportExportDialog(QWidget *parent = nullptr); 16 | ~ImportExportDialog(); 17 | 18 | void setTabs(const QStringList &tabs); 19 | void setCurrentTab(const QString &tabName); 20 | 21 | void setHasConfiguration(bool hasConfiguration); 22 | void setHasCommands(bool hasCommands); 23 | 24 | void setConfigurationEnabled(bool enabled); 25 | void setCommandsEnabled(bool enabled); 26 | 27 | QStringList selectedTabs() const; 28 | bool isConfigurationEnabled() const; 29 | bool isCommandsEnabled() const; 30 | 31 | private: 32 | void onCheckBoxAllClicked(bool checked); 33 | 34 | void update(); 35 | 36 | bool canAccept() const; 37 | 38 | Ui::ImportExportDialog *ui; 39 | }; 40 | -------------------------------------------------------------------------------- /src/gui/logdialog.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | #pragma once 3 | 4 | 5 | #include "common/log.h" 6 | 7 | #include 8 | 9 | namespace Ui { 10 | class LogDialog; 11 | } 12 | 13 | class Decorator; 14 | 15 | class LogDialog final : public QDialog 16 | { 17 | public: 18 | explicit LogDialog(QWidget *parent = nullptr); 19 | ~LogDialog(); 20 | 21 | private: 22 | using FilterCheckBoxSlot = void (LogDialog::*)(bool); 23 | 24 | void updateLog(); 25 | 26 | void showError(bool show); 27 | void showWarning(bool show); 28 | void showNote(bool show); 29 | void showDebug(bool show); 30 | void showTrace(bool show); 31 | 32 | void addFilterCheckBox(LogLevel level, FilterCheckBoxSlot slot); 33 | 34 | Ui::LogDialog *ui; 35 | 36 | Decorator *m_logDecorator; 37 | Decorator *m_stringDecorator; 38 | Decorator *m_threadNameDecorator; 39 | 40 | bool m_showError; 41 | bool m_showWarning; 42 | bool m_showNote; 43 | bool m_showDebug; 44 | bool m_showTrace; 45 | }; 46 | -------------------------------------------------------------------------------- /src/gui/navigation.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | #pragma once 3 | 4 | #include 5 | 6 | class QKeyEvent; 7 | class QObject; 8 | 9 | struct KeyMods { 10 | int key; 11 | Qt::KeyboardModifiers mods; 12 | 13 | KeyMods(int key = 0, Qt::KeyboardModifiers mods = Qt::NoModifier) 14 | : key(key), mods(mods) {} 15 | }; 16 | 17 | bool isViEscape(KeyMods keyMods); 18 | bool isEmacsEscape(KeyMods keyMods); 19 | 20 | KeyMods translateToVi(KeyMods keyMods); 21 | KeyMods translateToEmacs(KeyMods keyMods); 22 | -------------------------------------------------------------------------------- /src/gui/notificationbasic.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #pragma once 4 | 5 | class Notification; 6 | class QObject; 7 | 8 | Notification *createNotificationBasic(QObject *parent); 9 | -------------------------------------------------------------------------------- /src/gui/notificationbutton.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #pragma once 4 | 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | struct NotificationButton 12 | { 13 | QString name; 14 | QString script; 15 | QByteArray data; 16 | }; 17 | 18 | Q_DECLARE_METATYPE(NotificationButton) 19 | 20 | using NotificationButtons = QList; 21 | -------------------------------------------------------------------------------- /src/gui/notificationnative/notificationnative.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #pragma once 4 | 5 | class Notification; 6 | class QColor; 7 | class QObject; 8 | 9 | Notification *createNotificationNative(const QColor &iconColor, QObject *parent); 10 | -------------------------------------------------------------------------------- /src/gui/pixelratio.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | 4 | #include 5 | 6 | static qreal pixelRatio(QPaintDevice *pd) 7 | { 8 | return pd->devicePixelRatioF(); 9 | } 10 | -------------------------------------------------------------------------------- /src/gui/pluginwidget.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #include "pluginwidget.h" 4 | #include "ui_pluginwidget.h" 5 | 6 | #include "item/itemwidget.h" 7 | 8 | PluginWidget::PluginWidget(const ItemLoaderPtr &loader, QWidget *parent) 9 | : QWidget(parent) 10 | , ui(new Ui::PluginWidget) 11 | , m_loader(loader) 12 | { 13 | ui->setupUi(this); 14 | 15 | const QString author = m_loader->author(); 16 | if (author.isEmpty()) 17 | ui->labelAuthor->hide(); 18 | else 19 | ui->labelAuthor->setText(author); 20 | 21 | const QString description = m_loader->description(); 22 | if (description.isEmpty()) 23 | ui->labelDescription->hide(); 24 | else 25 | ui->labelDescription->setText(m_loader->description()); 26 | 27 | QWidget *loaderSettings = m_loader->createSettingsWidget(this); 28 | if (loaderSettings) { 29 | ui->verticalLayout->insertWidget(2, loaderSettings); 30 | ui->verticalLayout->setStretch(2, 1); 31 | } 32 | } 33 | 34 | PluginWidget::~PluginWidget() 35 | { 36 | delete ui; 37 | } 38 | -------------------------------------------------------------------------------- /src/gui/pluginwidget.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #pragma once 4 | 5 | 6 | #include "item/itemwidget.h" 7 | 8 | #include 9 | 10 | class QSettings; 11 | 12 | namespace Ui { 13 | class PluginWidget; 14 | } 15 | 16 | class PluginWidget final : public QWidget 17 | { 18 | Q_OBJECT 19 | 20 | public: 21 | explicit PluginWidget(const ItemLoaderPtr &loader, QWidget *parent = nullptr); 22 | ~PluginWidget(); 23 | 24 | const ItemLoaderPtr &loader() const { return m_loader; } 25 | 26 | private: 27 | Ui::PluginWidget *ui; 28 | ItemLoaderPtr m_loader; 29 | }; 30 | -------------------------------------------------------------------------------- /src/gui/screen.cpp: -------------------------------------------------------------------------------- 1 | #include "screen.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | namespace { 9 | 10 | QScreen *screenFromNumber(int i) 11 | { 12 | const auto screens = QGuiApplication::screens(); 13 | if (i < 0 || i >= screens.size()) 14 | return nullptr; 15 | return screens[i]; 16 | } 17 | 18 | } // namespace 19 | 20 | int screenCount() 21 | { 22 | return QGuiApplication::screens().size(); 23 | } 24 | 25 | int screenNumberAt(const QPoint &pos) 26 | { 27 | auto screen = QGuiApplication::screenAt(pos); 28 | if (screen == nullptr) 29 | screen = QGuiApplication::primaryScreen(); 30 | return QGuiApplication::screens().indexOf(screen); 31 | } 32 | 33 | QRect screenGeometry(int i) 34 | { 35 | auto screen = screenFromNumber(i); 36 | return screen ? screen->availableGeometry() : QRect(); 37 | } 38 | 39 | QRect screenAvailableGeometry(const QWidget &w) 40 | { 41 | auto screen = QGuiApplication::screenAt(w.pos()); 42 | return screen ? screen->availableGeometry() : screenGeometry(0); 43 | } 44 | -------------------------------------------------------------------------------- /src/gui/screen.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | 4 | class QPoint; 5 | class QRect; 6 | class QWidget; 7 | 8 | int screenCount(); 9 | 10 | int screenNumberAt(const QPoint &pos); 11 | 12 | QRect screenGeometry(int i); 13 | 14 | QRect screenAvailableGeometry(const QWidget &w); 15 | -------------------------------------------------------------------------------- /src/gui/selectiondata.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | #pragma once 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | class ClipboardBrowser; 9 | 10 | void addSelectionData( 11 | QVariantMap *result, 12 | const QList &selectedIndexes); 13 | 14 | void addSelectionData( 15 | QVariantMap *result, 16 | const QModelIndexList &selectedIndexes); 17 | 18 | /// Adds information about current tab and selection if command is triggered by user. 19 | QVariantMap selectionData( 20 | const ClipboardBrowser &c, 21 | const QModelIndex ¤tIndex, 22 | const QModelIndexList &selectedIndexes); 23 | 24 | QVariantMap selectionData(const ClipboardBrowser &c); 25 | -------------------------------------------------------------------------------- /src/gui/shortcutdialog.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #pragma once 4 | 5 | 6 | #include 7 | 8 | namespace Ui { 9 | class ShortcutDialog; 10 | } 11 | 12 | class ShortcutDialog final : public QDialog 13 | { 14 | Q_OBJECT 15 | public: 16 | explicit ShortcutDialog(QWidget *parent = nullptr); 17 | ~ShortcutDialog(); 18 | 19 | /** Return accepted shortcut or empty one. */ 20 | QKeySequence shortcut() const; 21 | 22 | protected: 23 | bool eventFilter(QObject *object, QEvent *event) override; 24 | 25 | private: 26 | void onResetButtonClicked(); 27 | 28 | Ui::ShortcutDialog *ui; 29 | }; 30 | -------------------------------------------------------------------------------- /src/gui/tabdialog.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #pragma once 4 | 5 | 6 | #include 7 | #include 8 | 9 | namespace Ui { 10 | class TabDialog; 11 | } 12 | 13 | /** 14 | * Dialog for naming and renaming tabs. 15 | */ 16 | class TabDialog final : public QDialog 17 | { 18 | Q_OBJECT 19 | 20 | public: 21 | /** Tab dialog type (new tab or rename existing tab). */ 22 | enum TabDialogType { 23 | TabNew, 24 | TabRename, 25 | TabGroupRename 26 | }; 27 | 28 | explicit TabDialog(TabDialogType type, QWidget *parent = nullptr); 29 | ~TabDialog(); 30 | 31 | /** Set tab index to rename (emitted parameter of accepted()). */ 32 | void setTabIndex(int tabIndex); 33 | 34 | /** Set existing tabs for validation. */ 35 | void setTabs(const QStringList &tabs); 36 | 37 | /** Set current tab name. */ 38 | void setTabName(const QString &tabName); 39 | 40 | /** Set current tab group name. */ 41 | void setTabGroupName(const QString &tabGroupName); 42 | 43 | signals: 44 | void newTabNameAccepted(const QString &newName); 45 | void barTabNameAccepted(const QString &newName, int tabIndex); 46 | void treeTabNameAccepted(const QString &newName, const QString &oldName); 47 | 48 | private: 49 | void onAccepted(); 50 | 51 | /** 52 | * Validate tab name. 53 | * Tab name should be non-empty and should not be in existing tab list 54 | * (see setTabs()). 55 | */ 56 | void validate(); 57 | 58 | Ui::TabDialog *ui; 59 | int m_tabIndex = -1; 60 | QString m_tabGroupName; 61 | QStringList m_tabs; 62 | }; 63 | -------------------------------------------------------------------------------- /src/gui/tabicons.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | #pragma once 3 | 4 | 5 | #include 6 | 7 | class QIcon; 8 | class QComboBox; 9 | class QString; 10 | class QWidget; 11 | 12 | /** Return list of saved tabs (ordered by "tabs" option if possible). */ 13 | QList savedTabs(); 14 | 15 | QString getIconNameForTabName(const QString &tabName); 16 | 17 | void setIconNameForTabName(const QString &tabName, const QString &icon); 18 | 19 | QIcon getIconForTabName(const QString &tabName); 20 | 21 | void initTabComboBox(QComboBox *comboBox); 22 | 23 | void setDefaultTabItemCounterStyle(QWidget *widget); 24 | 25 | void setComboBoxItems(QComboBox *comboBox, const QList &items); 26 | -------------------------------------------------------------------------------- /src/gui/tabpropertieswidget.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #include "gui/tabpropertieswidget.h" 4 | #include "ui_tabpropertieswidget.h" 5 | 6 | TabPropertiesWidget::TabPropertiesWidget(QWidget *parent) : 7 | QWidget(parent), 8 | ui(new Ui::TabPropertiesWidget) 9 | { 10 | ui->setupUi(this); 11 | 12 | connect( ui->iconButton, &IconSelectButton::currentIconChanged, 13 | this, &TabPropertiesWidget::iconNameChanged ); 14 | connect( ui->maxItems, static_cast(&QSpinBox::valueChanged), 15 | this, &TabPropertiesWidget::maxItemCountChanged ); 16 | connect( ui->storeItems, &QCheckBox::toggled, 17 | this, &TabPropertiesWidget::storeItemsChanged ); 18 | } 19 | 20 | TabPropertiesWidget::~TabPropertiesWidget() 21 | { 22 | delete ui; 23 | } 24 | 25 | void TabPropertiesWidget::setTabName(const QString &name) 26 | { 27 | ui->tabName->setText(name); 28 | } 29 | 30 | void TabPropertiesWidget::setIconName(const QString &iconName) 31 | { 32 | ui->iconButton->setCurrentIcon(iconName); 33 | } 34 | 35 | void TabPropertiesWidget::setMaxItemCount(int maxItemCount) 36 | { 37 | ui->maxItems->setValue(maxItemCount); 38 | } 39 | 40 | void TabPropertiesWidget::setStoreItems(bool storeItems) 41 | { 42 | ui->storeItems->setChecked(storeItems); 43 | } 44 | -------------------------------------------------------------------------------- /src/gui/tabpropertieswidget.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #pragma once 4 | 5 | 6 | #include 7 | 8 | namespace Ui { 9 | class TabPropertiesWidget; 10 | } 11 | 12 | class TabPropertiesWidget : public QWidget 13 | { 14 | Q_OBJECT 15 | 16 | public: 17 | explicit TabPropertiesWidget(QWidget *parent = nullptr); 18 | ~TabPropertiesWidget(); 19 | 20 | void setTabName(const QString &name); 21 | void setIconName(const QString &iconName); 22 | void setMaxItemCount(int maxItemCount); 23 | void setStoreItems(bool storeItems); 24 | 25 | signals: 26 | void iconNameChanged(const QString &iconName); 27 | void maxItemCountChanged(int maxItemCount); 28 | void storeItemsChanged(bool storeItems); 29 | 30 | private: 31 | Ui::TabPropertiesWidget *ui; 32 | }; 33 | -------------------------------------------------------------------------------- /src/gui/windowgeometryguard.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | #pragma once 3 | 4 | 5 | #include 6 | #include 7 | 8 | class QWidget; 9 | 10 | void raiseWindow(QWidget *window); 11 | 12 | class WindowGeometryGuard final : public QObject 13 | { 14 | public: 15 | static void create(QWidget *window); 16 | 17 | bool eventFilter(QObject *object, QEvent *event) override; 18 | 19 | private: 20 | explicit WindowGeometryGuard(QWidget *window); 21 | 22 | bool isWindowGeometryLocked() const; 23 | 24 | bool lockWindowGeometry(); 25 | 26 | void saveWindowGeometry(); 27 | void restoreWindowGeometry(); 28 | void unlockWindowGeometry(); 29 | 30 | void onScreenChanged(); 31 | 32 | QWidget *m_window; 33 | 34 | QTimer m_timerSaveGeometry; 35 | QTimer m_timerRestoreGeometry; 36 | QTimer m_timerUnlockGeometry; 37 | }; 38 | -------------------------------------------------------------------------------- /src/images/fontawesome.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hluk/CopyQ/d54623cf916577a1bed76353a8e8ac482a71cbc9/src/images/fontawesome.ttf -------------------------------------------------------------------------------- /src/images/icon-busy_128x128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hluk/CopyQ/d54623cf916577a1bed76353a8e8ac482a71cbc9/src/images/icon-busy_128x128.png -------------------------------------------------------------------------------- /src/images/icon-busy_16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hluk/CopyQ/d54623cf916577a1bed76353a8e8ac482a71cbc9/src/images/icon-busy_16x16.png -------------------------------------------------------------------------------- /src/images/icon-busy_22x22.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hluk/CopyQ/d54623cf916577a1bed76353a8e8ac482a71cbc9/src/images/icon-busy_22x22.png -------------------------------------------------------------------------------- /src/images/icon-busy_24x24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hluk/CopyQ/d54623cf916577a1bed76353a8e8ac482a71cbc9/src/images/icon-busy_24x24.png -------------------------------------------------------------------------------- /src/images/icon-busy_32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hluk/CopyQ/d54623cf916577a1bed76353a8e8ac482a71cbc9/src/images/icon-busy_32x32.png -------------------------------------------------------------------------------- /src/images/icon-busy_48x48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hluk/CopyQ/d54623cf916577a1bed76353a8e8ac482a71cbc9/src/images/icon-busy_48x48.png -------------------------------------------------------------------------------- /src/images/icon-busy_64x64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hluk/CopyQ/d54623cf916577a1bed76353a8e8ac482a71cbc9/src/images/icon-busy_64x64.png -------------------------------------------------------------------------------- /src/images/icon.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hluk/CopyQ/d54623cf916577a1bed76353a8e8ac482a71cbc9/src/images/icon.icns -------------------------------------------------------------------------------- /src/images/icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hluk/CopyQ/d54623cf916577a1bed76353a8e8ac482a71cbc9/src/images/icon.ico -------------------------------------------------------------------------------- /src/images/icon_1024x1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hluk/CopyQ/d54623cf916577a1bed76353a8e8ac482a71cbc9/src/images/icon_1024x1024.png -------------------------------------------------------------------------------- /src/images/icon_128x128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hluk/CopyQ/d54623cf916577a1bed76353a8e8ac482a71cbc9/src/images/icon_128x128.png -------------------------------------------------------------------------------- /src/images/icon_16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hluk/CopyQ/d54623cf916577a1bed76353a8e8ac482a71cbc9/src/images/icon_16x16.png -------------------------------------------------------------------------------- /src/images/icon_22x22.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hluk/CopyQ/d54623cf916577a1bed76353a8e8ac482a71cbc9/src/images/icon_22x22.png -------------------------------------------------------------------------------- /src/images/icon_24x24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hluk/CopyQ/d54623cf916577a1bed76353a8e8ac482a71cbc9/src/images/icon_24x24.png -------------------------------------------------------------------------------- /src/images/icon_256x256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hluk/CopyQ/d54623cf916577a1bed76353a8e8ac482a71cbc9/src/images/icon_256x256.png -------------------------------------------------------------------------------- /src/images/icon_32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hluk/CopyQ/d54623cf916577a1bed76353a8e8ac482a71cbc9/src/images/icon_32x32.png -------------------------------------------------------------------------------- /src/images/icon_48x48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hluk/CopyQ/d54623cf916577a1bed76353a8e8ac482a71cbc9/src/images/icon_48x48.png -------------------------------------------------------------------------------- /src/images/icon_512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hluk/CopyQ/d54623cf916577a1bed76353a8e8ac482a71cbc9/src/images/icon_512x512.png -------------------------------------------------------------------------------- /src/images/icon_64x64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hluk/CopyQ/d54623cf916577a1bed76353a8e8ac482a71cbc9/src/images/icon_64x64.png -------------------------------------------------------------------------------- /src/item/indexes.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #include "indexes.h" 4 | 5 | #include 6 | 7 | QList toPersistentModelIndexList(const QList &indexes) 8 | { 9 | QList result; 10 | result.reserve( indexes.size() ); 11 | 12 | for (const auto &index : indexes) { 13 | if ( index.isValid() ) 14 | result.append(index); 15 | } 16 | 17 | return result; 18 | } 19 | 20 | int dropIndexes(const QModelIndexList &indexes, QAbstractItemModel *model) 21 | { 22 | auto toRemove = toPersistentModelIndexList(indexes); 23 | return dropIndexes(toRemove, model); 24 | } 25 | 26 | int dropIndexes(QList &indexes, QAbstractItemModel *model) 27 | { 28 | const int first = indexes.value(0).row(); 29 | 30 | std::sort( std::begin(indexes), std::end(indexes) ); 31 | 32 | // Remove ranges of rows instead of a single rows. 33 | for (auto it1 = std::begin(indexes); it1 != std::end(indexes); ) { 34 | if ( it1->isValid() ) { 35 | const auto firstRow = it1->row(); 36 | auto rowCount = 0; 37 | 38 | for ( ++it1, ++rowCount; it1 != std::end(indexes) 39 | && it1->isValid() 40 | && it1->row() == firstRow + rowCount; ++it1, ++rowCount ) {} 41 | 42 | model->removeRows(firstRow, rowCount); 43 | } else { 44 | ++it1; 45 | } 46 | } 47 | 48 | return first; 49 | } 50 | -------------------------------------------------------------------------------- /src/item/indexes.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | class QAbstractItemModel; 6 | class QModelIndex; 7 | class QPersistentModelIndex; 8 | typedef QList QModelIndexList; 9 | 10 | QList toPersistentModelIndexList(const QList &indexes); 11 | 12 | int dropIndexes(const QModelIndexList &indexes, QAbstractItemModel *model); 13 | 14 | int dropIndexes(QList &indexes, QAbstractItemModel *model); 15 | -------------------------------------------------------------------------------- /src/item/itemfilter.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | class QModelIndex; 6 | class QString; 7 | class QTextCharFormat; 8 | class QTextEdit; 9 | 10 | class ItemFilter 11 | { 12 | public: 13 | virtual ~ItemFilter() = default; 14 | virtual bool matchesAll() const = 0; 15 | virtual bool matchesNone() const = 0; 16 | virtual bool matches(const QString &text) const = 0; 17 | virtual bool matchesIndex(const QModelIndex &index) const = 0; 18 | virtual void highlight(QTextEdit *edit, const QTextCharFormat &format) const = 0; 19 | virtual void search(QTextEdit *edit, bool backwards) const = 0; 20 | virtual QString searchString() const = 0; 21 | }; 22 | 23 | using ItemFilterPtr = std::shared_ptr; 24 | -------------------------------------------------------------------------------- /src/item/itemsaverwrapper.cpp: -------------------------------------------------------------------------------- 1 | #include "itemsaverwrapper.h" 2 | 3 | #include 4 | 5 | ItemSaverWrapper::ItemSaverWrapper(const ItemSaverPtr &saver) 6 | : m_saver(saver) 7 | { 8 | } 9 | 10 | bool ItemSaverWrapper::saveItems(const QString &tabName, const QAbstractItemModel &model, QIODevice *file) 11 | { 12 | return m_saver->saveItems(tabName, model, file); 13 | } 14 | 15 | bool ItemSaverWrapper::canRemoveItems(const QList &indexList, QString *error) 16 | { 17 | return m_saver->canRemoveItems(indexList, error); 18 | } 19 | 20 | bool ItemSaverWrapper::canDropItem(const QModelIndex &index) 21 | { 22 | return m_saver->canDropItem(index); 23 | } 24 | 25 | bool ItemSaverWrapper::canMoveItems(const QList &indexList) 26 | { 27 | return m_saver->canMoveItems(indexList); 28 | } 29 | 30 | void ItemSaverWrapper::itemsRemovedByUser(const QList &indexList) 31 | { 32 | return m_saver->itemsRemovedByUser(indexList); 33 | } 34 | 35 | QVariantMap ItemSaverWrapper::copyItem(const QAbstractItemModel &model, const QVariantMap &itemData) 36 | { 37 | return m_saver->copyItem(model, itemData); 38 | } 39 | 40 | void ItemSaverWrapper::setFocus(bool focus) 41 | { 42 | return m_saver->setFocus(focus); 43 | } 44 | -------------------------------------------------------------------------------- /src/item/itemsaverwrapper.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "item/itemwidget.h" 4 | 5 | class ItemSaverWrapper : public ItemSaverInterface 6 | { 7 | public: 8 | explicit ItemSaverWrapper(const ItemSaverPtr &saver); 9 | 10 | bool saveItems(const QString &tabName, const QAbstractItemModel &model, QIODevice *file) override; 11 | 12 | bool canRemoveItems(const QList &indexList, QString *error) override; 13 | 14 | bool canDropItem(const QModelIndex &index) override; 15 | 16 | bool canMoveItems(const QList &indexList) override; 17 | 18 | void itemsRemovedByUser(const QList &indexList) override; 19 | 20 | QVariantMap copyItem(const QAbstractItemModel &model, const QVariantMap &itemData) override; 21 | 22 | void setFocus(bool focus) override; 23 | 24 | protected: 25 | ItemSaverInterface *wrapped() const { return m_saver.get(); } 26 | 27 | private: 28 | ItemSaverPtr m_saver; 29 | }; 30 | -------------------------------------------------------------------------------- /src/item/itemstore.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | #pragma once 3 | 4 | #include 5 | #include 6 | 7 | class ItemFactory; 8 | class ItemSaverInterface; 9 | class QAbstractItemModel; 10 | class QString; 11 | using ItemSaverPtr = std::shared_ptr; 12 | 13 | /** Load items from configuration file. */ 14 | ItemSaverPtr loadItems(const QString &tabName, QAbstractItemModel &model //!< Model for items. 15 | , ItemFactory *itemFactory, int maxItems); 16 | 17 | /** Save items to configuration file. */ 18 | bool saveItems(const QString &tabName, const QAbstractItemModel &model //!< Model containing items to save. 19 | , const ItemSaverPtr &saver); 20 | 21 | /** Remove configuration file for items. */ 22 | void removeItems(const QString &tabName //!< See ClipboardBrowser::getID(). 23 | ); 24 | 25 | /** Move configuration file for items. */ 26 | bool moveItems( 27 | const QString &oldId, //!< See ClipboardBrowser::getID(). 28 | const QString &newId //!< See ClipboardBrowser::getID(). 29 | ); 30 | 31 | void cleanDataFiles(const QStringList &tabNames); 32 | -------------------------------------------------------------------------------- /src/item/itemwidgetwrapper.cpp: -------------------------------------------------------------------------------- 1 | #include "itemwidgetwrapper.h" 2 | 3 | #include 4 | 5 | ItemWidgetWrapper::ItemWidgetWrapper(ItemWidget *childItem, QWidget *widget) 6 | : ItemWidget(widget) 7 | , m_childItem(childItem) 8 | { 9 | } 10 | 11 | void ItemWidgetWrapper::updateSize(QSize maximumSize, int idealWidth) 12 | { 13 | childItem()->updateSize(maximumSize, idealWidth); 14 | } 15 | 16 | void ItemWidgetWrapper::setCurrent(bool current) 17 | { 18 | childItem()->setCurrent(current); 19 | } 20 | 21 | void ItemWidgetWrapper::setTagged(bool tagged) 22 | { 23 | childItem()->setTagged(tagged); 24 | } 25 | -------------------------------------------------------------------------------- /src/item/itemwidgetwrapper.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | 4 | #include "itemwidget.h" 5 | 6 | #include 7 | 8 | class ItemWidgetWrapper : public ItemWidget 9 | { 10 | public: 11 | ItemWidgetWrapper(ItemWidget *childItem, QWidget *widget); 12 | 13 | void updateSize(QSize maximumSize, int idealWidth) override; 14 | 15 | void setCurrent(bool current) override; 16 | 17 | void setTagged(bool tagged) override; 18 | 19 | protected: 20 | ItemWidget *childItem() const { return m_childItem.get(); } 21 | 22 | private: 23 | std::unique_ptr m_childItem; 24 | }; 25 | -------------------------------------------------------------------------------- /src/item/persistentdisplayitem.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #pragma once 4 | 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | class ItemDelegate; 12 | class QAction; 13 | class QModelIndex; 14 | class QWidget; 15 | class QString; 16 | 17 | /** 18 | * Holds data for currently displayed item. 19 | * 20 | * Can be used to change the data for displaying without altering the item data itself. 21 | */ 22 | class PersistentDisplayItem final 23 | { 24 | public: 25 | PersistentDisplayItem() = default; 26 | 27 | PersistentDisplayItem( 28 | ItemDelegate *delegate, const QVariantMap &data, QWidget *widget); 29 | 30 | PersistentDisplayItem(QAction *action, const QVariantMap &data); 31 | 32 | /** 33 | * Returns display data of the item. 34 | * 35 | * This method is thread-safe. 36 | */ 37 | const QVariantMap &data() const noexcept { return m_data; } 38 | 39 | /** 40 | * Returns true only if display item widget is still available. 41 | */ 42 | bool isValid(); 43 | 44 | /** 45 | * Sets display data. 46 | * 47 | * If data is empty, the item will be displayed later again. 48 | */ 49 | void setData(const QVariantMap &data); 50 | 51 | private: 52 | QVariantMap m_data; 53 | QPointer m_widget; 54 | QPointer m_action; 55 | QPointer m_delegate; 56 | }; 57 | 58 | Q_DECLARE_METATYPE(PersistentDisplayItem) 59 | -------------------------------------------------------------------------------- /src/item/serialize.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #pragma once 4 | 5 | 6 | #include 7 | #if QT_VERSION < QT_VERSION_CHECK(6,0,0) 8 | #include 9 | #endif 10 | 11 | class QAbstractItemModel; 12 | class QByteArray; 13 | class QDataStream; 14 | class QIODevice; 15 | 16 | class DataFile; 17 | QDataStream &operator<<(QDataStream &out, DataFile value); 18 | QDataStream &operator>>(QDataStream &in, DataFile &value); 19 | void registerDataFileConverter(); 20 | 21 | void serializeData(QDataStream *stream, const QVariantMap &data, int itemDataThreshold = -1); 22 | bool deserializeData(QDataStream *stream, QVariantMap *data); 23 | QByteArray serializeData(const QVariantMap &data); 24 | bool deserializeData(QVariantMap *data, const QByteArray &bytes); 25 | 26 | bool serializeData(const QAbstractItemModel &model, QDataStream *stream, int itemDataThreshold = -1); 27 | bool deserializeData(QAbstractItemModel *model, QDataStream *stream); 28 | bool serializeData(const QAbstractItemModel &model, QIODevice *file, int itemDataThreshold = -1); 29 | bool deserializeData(QAbstractItemModel *model, QIODevice *file); 30 | 31 | QString itemDataPath(); 32 | bool itemDataFiles(QIODevice *file, QStringList *files); 33 | -------------------------------------------------------------------------------- /src/knotifications5/copyq.notifyrc: -------------------------------------------------------------------------------- 1 | [Global] 2 | IconName=copyq 3 | Comment=CopyQ Clipboard Manager 4 | Name=CopyQ 5 | 6 | [Event/generic] 7 | Name=Generic event 8 | Action=Popup 9 | -------------------------------------------------------------------------------- /src/notifications.cmake: -------------------------------------------------------------------------------- 1 | OPTION(WITH_NATIVE_NOTIFICATIONS "Build with native notification support" ON) 2 | 3 | if (WITH_NATIVE_NOTIFICATIONS) 4 | set(KF5_MIN_VERSION "5.18.0") 5 | 6 | find_package(ECM ${KF5_MIN_VERSION} REQUIRED NO_MODULE) 7 | list(APPEND CMAKE_MODULE_PATH ${ECM_MODULE_PATH}) 8 | 9 | if (WITH_QT6) 10 | set(KF6_MIN_VERSION "5.248.0") 11 | find_package(KF6 ${KF6_MIN_VERSION} REQUIRED COMPONENTS Notifications StatusNotifierItem) 12 | list(APPEND copyq_LIBRARIES KF6::Notifications KF6::StatusNotifierItem) 13 | else() 14 | find_package(KF5 ${KF5_MIN_VERSION} REQUIRED COMPONENTS Notifications) 15 | list(APPEND copyq_LIBRARIES KF5::Notifications) 16 | endif() 17 | 18 | list(APPEND copyq_SOURCES gui/notificationnative/notificationnative.cpp) 19 | 20 | list(APPEND copyq_DEFINITIONS WITH_NATIVE_NOTIFICATIONS) 21 | endif() 22 | -------------------------------------------------------------------------------- /src/platform/dummy/dummyclipboard.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #pragma once 4 | 5 | 6 | #include "common/clipboardmode.h" 7 | #include "platform/platformclipboard.h" 8 | 9 | #include 10 | 11 | QClipboard::Mode modeToQClipboardMode(ClipboardMode mode); 12 | 13 | class DummyClipboard : public PlatformClipboard 14 | { 15 | public: 16 | void startMonitoring(const QStringList &) override; 17 | 18 | void setMonitoringEnabled(ClipboardMode, bool) override {} 19 | 20 | QVariantMap data(ClipboardMode mode, const QStringList &formats) const override; 21 | 22 | void setData(ClipboardMode mode, const QVariantMap &dataMap) override; 23 | void setRawData(ClipboardMode mode, QMimeData *mimeData) override; 24 | 25 | const QMimeData *mimeData(ClipboardMode mode) const override; 26 | 27 | bool isSelectionSupported() const override { return false; } 28 | 29 | bool isHidden(const QMimeData &data) const override; 30 | 31 | void setClipboardOwner(const QString &) override {} 32 | 33 | protected: 34 | virtual const QMimeData *rawMimeData(ClipboardMode mode) const; 35 | virtual void onChanged(int mode); 36 | void onClipboardChanged(QClipboard::Mode mode); 37 | virtual const long int *clipboardSequenceNumber(ClipboardMode) const { return nullptr; } 38 | }; 39 | -------------------------------------------------------------------------------- /src/platform/mac/foregroundbackgroundfilter.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #pragma once 4 | 5 | 6 | #include 7 | 8 | /** 9 | * This event filter manages the "activationPolicy" for an OS X app by 10 | * ensuring that it is a "regular" app when there are windows shown, but 11 | * an "accessory" or "prohibited"/"background" app when there are none. 12 | * 13 | * This allows the app to not have a dock icon unless there is an open window. 14 | * 15 | * If only menu or some notifications are visible dock icon is hidden. 16 | */ 17 | class ForegroundBackgroundFilter final : public QObject 18 | { 19 | public: 20 | /** 21 | * Install the filter to parent. 22 | */ 23 | static void installFilter(QObject *parent); 24 | 25 | protected: 26 | bool eventFilter(QObject *obj, QEvent *ev); 27 | ForegroundBackgroundFilter(QObject *parent); 28 | }; 29 | -------------------------------------------------------------------------------- /src/platform/mac/macactivity.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #pragma once 4 | 5 | 6 | class QString; 7 | 8 | /** 9 | * RAII class for using activity blocks on OSX. 10 | */ 11 | class MacActivity 12 | { 13 | public: 14 | explicit MacActivity(const QString &reason); 15 | ~MacActivity(); 16 | private: 17 | void *m_activity; 18 | }; 19 | -------------------------------------------------------------------------------- /src/platform/mac/macactivity.mm: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #include "macactivity.h" 4 | 5 | #include "common/log.h" 6 | 7 | #include 8 | 9 | #include 10 | 11 | MacActivity::MacActivity(const QString &reason) 12 | : m_activity(0) 13 | { 14 | const NSActivityOptions options = NSActivityBackground;; 15 | id act = [[NSProcessInfo processInfo] 16 | beginActivityWithOptions:options 17 | reason:reason.toNSString()]; 18 | if (act) { 19 | m_activity = reinterpret_cast(act); 20 | COPYQ_LOG_VERBOSE(QString("Started Background activity for: %1").arg(reason)); 21 | } else { 22 | ::log("Failed to create activity", LogWarning); 23 | } 24 | } 25 | 26 | MacActivity::~MacActivity() { 27 | id act = reinterpret_cast(m_activity); 28 | if (act) { 29 | [[NSProcessInfo processInfo] endActivity:act]; 30 | COPYQ_LOG_VERBOSE("Ended activity"); 31 | } else { 32 | ::log("Failed to stop activity", LogWarning); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/platform/mac/macclipboard.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #pragma once 4 | 5 | 6 | #include "platform/dummy/dummyclipboard.h" 7 | 8 | class MacClipboard final : public DummyClipboard { 9 | public: 10 | void startMonitoring(const QStringList &) override; 11 | 12 | void setData(ClipboardMode mode, const QVariantMap &dataMap) override; 13 | 14 | bool isHidden(const QMimeData &data) const override; 15 | 16 | protected: 17 | void onChanged(int mode) override; 18 | const long int *clipboardSequenceNumber(ClipboardMode) const override { 19 | return &m_prevChangeCount; 20 | } 21 | 22 | private: 23 | void clipboardTimeout(); 24 | 25 | long int m_prevChangeCount = 0; 26 | }; 27 | -------------------------------------------------------------------------------- /src/platform/mac/macplatform.cmake: -------------------------------------------------------------------------------- 1 | file(GLOB copyq_SOURCES ${copyq_SOURCES} 2 | platform/mac/*.mm 3 | platform/dummy/dummyclipboard.cpp 4 | platform/platformcommon.cpp 5 | ../qxt/qxtglobalshortcut_mac.cpp 6 | ) 7 | 8 | set(USE_QXT TRUE) 9 | 10 | if (NOT WITH_QT6) 11 | list(APPEND copyq_qt_modules MacExtras) 12 | endif() 13 | -------------------------------------------------------------------------------- /src/platform/mac/macplatform.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #pragma once 4 | 5 | 6 | #include "platform/platformnativeinterface.h" 7 | 8 | #include 9 | #include 10 | 11 | class MacPlatform final : public PlatformNativeInterface 12 | { 13 | public: 14 | MacPlatform(); 15 | 16 | PlatformWindowPtr getWindow(WId winId) override; 17 | PlatformWindowPtr getCurrentWindow() override; 18 | 19 | bool canGetWindowTitle() override { return true; } 20 | bool canAutostart() override { return true; } 21 | bool isAutostartEnabled() override; 22 | void setAutostartEnabled(bool) override; 23 | bool setPreventScreenCapture(WId, bool) override { return false; } 24 | bool canPreventScreenCapture() override { return false; } 25 | 26 | QCoreApplication *createConsoleApplication(int &argc, char **argv) override; 27 | 28 | QApplication *createServerApplication(int &argc, char **argv) override; 29 | 30 | QGuiApplication *createClipboardProviderApplication(int &argc, char **argv) override; 31 | 32 | QCoreApplication *createClientApplication(int &argc, char **argv) override; 33 | 34 | QGuiApplication *createTestApplication(int &argc, char **argv) override; 35 | 36 | PlatformClipboardPtr clipboard() override; 37 | 38 | QStringList getCommandLineArguments(int argc, char **argv) override; 39 | 40 | bool findPluginDir(QDir *pluginsDir) override; 41 | 42 | QString defaultEditorCommand() override; 43 | 44 | QString translationPrefix() override; 45 | 46 | QString themePrefix() override; 47 | }; 48 | -------------------------------------------------------------------------------- /src/platform/mac/macplatformwindow.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #pragma once 4 | 5 | 6 | #include "platform/platformwindow.h" 7 | 8 | // For WId 9 | #include 10 | 11 | #ifdef __OBJC__ 12 | @class NSWindow; 13 | @class NSRunningApplication; 14 | #else 15 | using NSWindow = void; 16 | using NSRunningApplication = void; 17 | #endif 18 | 19 | class MacPlatformWindow final : public PlatformWindow 20 | { 21 | public: 22 | MacPlatformWindow(); 23 | explicit MacPlatformWindow(WId wid); 24 | explicit MacPlatformWindow(NSRunningApplication *runningApplication); 25 | 26 | virtual ~MacPlatformWindow(); 27 | 28 | /** 29 | * Return window title text of current window. 30 | * 31 | * On OS X, this gets the title of the application instead of the window. 32 | */ 33 | QString getTitle(); 34 | 35 | void raise(); 36 | void pasteClipboard(); 37 | void copy(); 38 | 39 | private: 40 | // Don't allow copies 41 | Q_DISABLE_COPY(MacPlatformWindow) 42 | 43 | long int m_windowNumber; 44 | NSWindow *m_window; 45 | NSRunningApplication *m_runningApplication; 46 | }; 47 | -------------------------------------------------------------------------------- /src/platform/mac/mactimer.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #pragma once 4 | 5 | 6 | #include 7 | 8 | #ifdef __OBJC__ 9 | @class NSTimer; 10 | #else 11 | using NSTimer = void; 12 | #endif 13 | 14 | /** 15 | * Class similar to a QTimer but allows setting a tolerance, which 16 | * makes timers more battery-friendly on OSX. 17 | */ 18 | class MacTimer final : public QObject 19 | { 20 | Q_OBJECT 21 | 22 | public: 23 | explicit MacTimer(QObject *parent = 0); 24 | virtual ~MacTimer(); 25 | 26 | void setInterval(int msec); 27 | int interval() const { return m_interval; } 28 | inline void setSingleShot(bool singleShot); 29 | 30 | /** 31 | * Set the tolerance for the timer. See NSTimer::setTolerance. 32 | * 33 | * Tolerance is ignored on OS X < 10.9. 34 | */ 35 | void setTolerance(int msec); 36 | int tolerance() const { return m_tolerance; } 37 | 38 | public Q_SLOTS: 39 | void start(); 40 | void stop(); 41 | inline bool isSingleShot() const { return m_singleShot; } 42 | 43 | Q_SIGNALS: 44 | void timeout(); 45 | 46 | private: 47 | Q_DISABLE_COPY(MacTimer) 48 | 49 | void restart(); 50 | 51 | int m_interval; 52 | int m_tolerance; 53 | bool m_singleShot; 54 | 55 | NSTimer *m_nsTimer; 56 | }; 57 | -------------------------------------------------------------------------------- /src/platform/mac/urlpasteboardmime.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | #pragma once 3 | 4 | #include 5 | 6 | #if QT_VERSION >= QT_VERSION_CHECK(6,0,0) 7 | # include 8 | using UrlPasteboardMimeBase = QUtiMimeConverter; 9 | #else 10 | # include 11 | using UrlPasteboardMimeBase = QMacPasteboardMime; 12 | #endif 13 | 14 | /** 15 | * Class for doing conversions of URLs between OS X UTIs and "normal" mimeTypes. 16 | */ 17 | class UrlPasteboardMime final : public UrlPasteboardMimeBase { 18 | public: 19 | //! Create an instance of UrlPasteboardMime which will try to convert to/from the given UTI. 20 | explicit UrlPasteboardMime(const QString &urlUti); 21 | 22 | #if QT_VERSION >= QT_VERSION_CHECK(6,0,0) 23 | QString mimeForUti(const QString &uti) const override; 24 | QString utiForMime(const QString &mime) const override; 25 | QVariant convertToMime(const QString &mime, const QList &data, const QString &uti) const override; 26 | QList convertFromMime(const QString &mime, const QVariant &data, const QString &uti) const override; 27 | #else 28 | QString convertorName() override; 29 | QString flavorFor(const QString &mime) override; 30 | QString mimeFor(QString uti) override; 31 | bool canConvert(const QString &mime, QString uti) override; 32 | QVariant convertToMime(const QString &mime, QList data, QString uti) override; 33 | QList convertFromMime(const QString &mime, QVariant data, QString uti) override; 34 | #endif 35 | private: 36 | QString m_urlUti; 37 | }; 38 | -------------------------------------------------------------------------------- /src/platform/platform.cmake: -------------------------------------------------------------------------------- 1 | # If window system is X11 then set X11_FOUND to TRUE. 2 | find_package(X11) 3 | 4 | file(GLOB copyq_SOURCES ${copyq_SOURCES} 5 | platform/platformclipboard.h 6 | ) 7 | 8 | if (UNIX) 9 | file(GLOB copyq_SOURCES ${copyq_SOURCES} platform/unix/*.cpp) 10 | endif() 11 | 12 | if (X11_FOUND AND NOT APPLE) 13 | include(platform/x11/x11platform.cmake) 14 | elseif (Q_WS_WIN OR WIN32) 15 | include(platform/win/winplatform.cmake) 16 | elseif (Q_OS_MAC OR APPLE) 17 | include(platform/mac/macplatform.cmake) 18 | else() 19 | message(WARNING "Building on unsupported platform!") 20 | file(GLOB copyq_SOURCES ${copyq_SOURCES} 21 | platform/dummy/*.cpp 22 | ) 23 | set(USE_QXT FALSE) 24 | endif() 25 | -------------------------------------------------------------------------------- /src/platform/platformclipboard.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #pragma once 4 | 5 | 6 | #include "common/clipboardmode.h" 7 | 8 | #include 9 | #include 10 | 11 | class QMimeData; 12 | 13 | /** 14 | * Interface for clipboard. 15 | */ 16 | class PlatformClipboard : public QObject 17 | { 18 | Q_OBJECT 19 | public: 20 | /** 21 | * Starts emitting changed. 22 | */ 23 | virtual void startMonitoring(const QStringList &formats) = 0; 24 | 25 | virtual void setMonitoringEnabled(ClipboardMode mode, bool enable) = 0; 26 | 27 | /** 28 | * Return clipboard data containing specified @a formats if available. 29 | */ 30 | virtual QVariantMap data(ClipboardMode mode, const QStringList &formats) const = 0; 31 | 32 | /** 33 | * Set data to clipboard. 34 | */ 35 | virtual void setData(ClipboardMode mode, const QVariantMap &dataMap) = 0; 36 | virtual void setRawData(ClipboardMode mode, QMimeData *mimeData) = 0; 37 | 38 | virtual const QMimeData *mimeData(ClipboardMode mode) const = 0; 39 | 40 | virtual bool isSelectionSupported() const = 0; 41 | 42 | virtual bool isHidden(const QMimeData &data) const = 0; 43 | 44 | virtual void setClipboardOwner(const QString &owner) = 0; 45 | 46 | signals: 47 | /// Notifies about clipboard changes. 48 | void changed(ClipboardMode mode); 49 | }; 50 | -------------------------------------------------------------------------------- /src/platform/platformcommon.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #pragma once 4 | 5 | class AppConfig; 6 | class PlatformWindow; 7 | 8 | bool pasteWithCtrlV(PlatformWindow &window, const AppConfig &config); 9 | 10 | void waitMs(int msec); 11 | -------------------------------------------------------------------------------- /src/platform/platformwindow.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #pragma once 4 | 5 | 6 | #include 7 | 8 | class QString; 9 | 10 | /** 11 | * Window storage class for platform. Used to raise/focus window and paste to window. 12 | */ 13 | class PlatformWindow 14 | { 15 | public: 16 | PlatformWindow() = default; 17 | 18 | virtual ~PlatformWindow() = default; 19 | 20 | /** 21 | * Return window title text. 22 | */ 23 | virtual QString getTitle() = 0; 24 | 25 | /** 26 | * Raise/focus window. 27 | */ 28 | virtual void raise() = 0; 29 | 30 | /** 31 | * Paste clipboard content to window. 32 | */ 33 | virtual void pasteClipboard() = 0; 34 | 35 | /** 36 | * Copy to clipboard from window. 37 | */ 38 | virtual void copy() = 0; 39 | 40 | PlatformWindow(const PlatformWindow &) = delete; 41 | PlatformWindow &operator=(const PlatformWindow &) = delete; 42 | }; 43 | -------------------------------------------------------------------------------- /src/platform/unix/unixsignalhandler.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #pragma once 4 | 5 | 6 | /** 7 | * Gracefully exit application on Unix signals SIGHUP, SIGINT and SIGTERM. 8 | * 9 | * More info at http://qt-project.org/doc/qt-4.8/unix-signals.html 10 | */ 11 | 12 | bool initUnixSignalHandler(); 13 | void startUnixSignalHandler(); 14 | -------------------------------------------------------------------------------- /src/platform/win/winplatform.cmake: -------------------------------------------------------------------------------- 1 | # File icon on Windows 2 | set(copyq_RC copyq.rc) 3 | 4 | file(GLOB copyq_SOURCES ${copyq_SOURCES} 5 | platform/win/winplatform.cpp 6 | platform/win/winplatformclipboard.cpp 7 | platform/win/winplatformwindow.cpp 8 | platform/dummy/dummyclipboard.cpp 9 | platform/platformcommon.cpp 10 | ../qxt/qxtglobalshortcut_win.cpp 11 | ) 12 | 13 | set(USE_QXT TRUE) 14 | 15 | # Omit opening extra console window on Windows. 16 | set(copyq_COMPILE 17 | WIN32 18 | ${copyq_COMPILE} 19 | ${copyq_RC} 20 | ) 21 | 22 | if (MSVC) 23 | set(copyq_LINK_FLAGS ${copyq_LINK_FLAGS} "/ENTRY:mainCRTStartup") 24 | endif() 25 | -------------------------------------------------------------------------------- /src/platform/win/winplatform.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #pragma once 4 | 5 | 6 | #include "platform/platformnativeinterface.h" 7 | 8 | class WinPlatform final : public PlatformNativeInterface 9 | { 10 | public: 11 | WinPlatform() {} 12 | 13 | PlatformWindowPtr getWindow(WId winId) override; 14 | 15 | PlatformWindowPtr getCurrentWindow() override; 16 | 17 | bool canGetWindowTitle() override { return true; } 18 | 19 | bool canAutostart() override { return true; } 20 | 21 | bool isAutostartEnabled() override; 22 | 23 | void setAutostartEnabled(bool enable) override; 24 | 25 | bool setPreventScreenCapture(WId winId, bool prevent) override; 26 | bool canPreventScreenCapture() override { return true; } 27 | 28 | QCoreApplication *createConsoleApplication(int &argc, char **argv) override; 29 | 30 | QApplication *createServerApplication(int &argc, char **argv) override; 31 | 32 | QGuiApplication *createClipboardProviderApplication(int &argc, char **argv) override; 33 | 34 | QCoreApplication *createClientApplication(int &argc, char **argv) override; 35 | 36 | QGuiApplication *createTestApplication(int &argc, char **argv) override; 37 | 38 | PlatformClipboardPtr clipboard() override; 39 | 40 | QStringList getCommandLineArguments(int, char**) override; 41 | 42 | bool findPluginDir(QDir *pluginsDir) override; 43 | 44 | QString defaultEditorCommand() override; 45 | 46 | QString translationPrefix() override; 47 | 48 | QString themePrefix() override; 49 | }; 50 | -------------------------------------------------------------------------------- /src/platform/win/winplatformclipboard.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #pragma once 4 | 5 | 6 | #include "platform/dummy/dummyclipboard.h" 7 | 8 | #include 9 | 10 | class WinPlatformClipboard final : public DummyClipboard 11 | { 12 | public: 13 | void startMonitoring(const QStringList &) override; 14 | 15 | bool isHidden(const QMimeData &data) const override; 16 | 17 | protected: 18 | void onChanged(int) override; 19 | const long int *clipboardSequenceNumber(ClipboardMode) const override { 20 | return &m_lastClipboardSequenceNumber; 21 | } 22 | 23 | private: 24 | long int m_lastClipboardSequenceNumber = 0; 25 | }; 26 | -------------------------------------------------------------------------------- /src/platform/win/winplatformwindow.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #pragma once 4 | 5 | 6 | #include "platform/platformwindow.h" 7 | 8 | #ifndef WINVER 9 | #define WINVER 0x0500 10 | #endif 11 | #include 12 | 13 | class AppConfig; 14 | 15 | class WinPlatformWindow final : public PlatformWindow 16 | { 17 | public: 18 | explicit WinPlatformWindow(HWND window); 19 | 20 | QString getTitle() override; 21 | 22 | void raise() override; 23 | 24 | void pasteClipboard() override; 25 | void copy() override; 26 | 27 | private: 28 | void sendKeyPress(WORD modifier, WORD key, const AppConfig &config); 29 | 30 | HWND m_window; 31 | }; 32 | -------------------------------------------------------------------------------- /src/platform/x11/systemclipboard/waylandclipboard.h: -------------------------------------------------------------------------------- 1 | /* 2 | SPDX-FileCopyrightText: 2020 David Edmundson 3 | 4 | SPDX-License-Identifier: LGPL-2.0-or-later 5 | */ 6 | 7 | #pragma once 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | class DataControlDevice; 14 | class DataControlDeviceManager; 15 | class KeyboardFocusWatcher; 16 | class QMimeData; 17 | 18 | class WaylandClipboard final : public QObject 19 | { 20 | Q_OBJECT 21 | 22 | public: 23 | static WaylandClipboard *instance(); 24 | 25 | ~WaylandClipboard(); 26 | 27 | void setMimeData(QMimeData *mime, QClipboard::Mode mode); 28 | const QMimeData *mimeData(QClipboard::Mode mode) const; 29 | bool waitForDevice(int timeoutMs = 5000) const; 30 | 31 | signals: 32 | void changed(QClipboard::Mode mode); 33 | 34 | private: 35 | explicit WaylandClipboard(QObject *parent); 36 | static WaylandClipboard *createInstance(); 37 | void gainedFocus(); 38 | std::shared_ptr m_keyboardFocusWatcher; 39 | 40 | std::unique_ptr m_manager; 41 | std::unique_ptr m_device; 42 | QElapsedTimer m_deviceRequestedTimer; 43 | }; 44 | -------------------------------------------------------------------------------- /src/platform/x11/x11info.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #include "x11info.h" 4 | 5 | #include 6 | 7 | #ifdef COPYQ_WITH_X11 8 | # if QT_VERSION < QT_VERSION_CHECK(6,0,0) 9 | # include 10 | # else 11 | # include 12 | # endif 13 | # include 14 | #else 15 | struct _XDisplay {}; 16 | #endif 17 | 18 | bool X11Info::isPlatformX11() 19 | { 20 | return QGuiApplication::platformName() == QStringLiteral("xcb"); 21 | } 22 | 23 | Display *X11Info::display() 24 | { 25 | #ifdef COPYQ_WITH_X11 26 | return QX11Info::display(); 27 | #else 28 | return nullptr; 29 | #endif 30 | } 31 | -------------------------------------------------------------------------------- /src/platform/x11/x11info.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #pragma once 4 | 5 | #ifdef __clang__ 6 | #pragma clang diagnostic push 7 | #pragma clang diagnostic ignored "-Wreserved-identifier" 8 | #endif 9 | 10 | typedef struct _XDisplay Display; 11 | 12 | #ifdef __clang__ 13 | #pragma clang diagnostic pop 14 | #endif 15 | 16 | class X11Info { 17 | public: 18 | static bool isPlatformX11(); 19 | static Display *display(); 20 | }; 21 | -------------------------------------------------------------------------------- /src/platform/x11/x11platformwindow.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #pragma once 4 | 5 | 6 | #include "platform/platformwindow.h" 7 | 8 | #include 9 | 10 | class AppConfig; 11 | class QWidget; 12 | 13 | class X11PlatformWindow final : public PlatformWindow 14 | { 15 | public: 16 | explicit X11PlatformWindow(); 17 | 18 | explicit X11PlatformWindow(quintptr winId); 19 | 20 | QString getTitle() override; 21 | 22 | void raise() override; 23 | 24 | void pasteClipboard() override; 25 | 26 | void copy() override; 27 | 28 | bool isValid() const; 29 | 30 | private: 31 | bool waitForFocus(int ms); 32 | 33 | void sendKeyPress(int modifier, int key, const AppConfig &config); 34 | 35 | quintptr m_window; 36 | }; 37 | -------------------------------------------------------------------------------- /src/scriptable/commandhelp.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #pragma once 4 | 5 | 6 | #include 7 | #include 8 | 9 | struct CommandHelp { 10 | CommandHelp(); 11 | 12 | CommandHelp(const char *command, const QString &description); 13 | 14 | CommandHelp &addArg(const QString &arg); 15 | 16 | QString toString() const; 17 | 18 | QString cmd; 19 | QString desc; 20 | QString args; 21 | }; 22 | 23 | QList commandHelp(); 24 | -------------------------------------------------------------------------------- /src/scriptable/scriptablefile.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #pragma once 4 | 5 | 6 | #include 7 | #include 8 | 9 | class QJSEngine; 10 | class QFile; 11 | 12 | class ScriptableFile : public QObject 13 | { 14 | Q_OBJECT 15 | 16 | public: 17 | Q_INVOKABLE explicit ScriptableFile(const QString &path = QString()); 18 | 19 | public slots: 20 | bool open(); 21 | bool openReadOnly(); 22 | bool openWriteOnly(); 23 | bool openAppend(); 24 | 25 | void close(); 26 | 27 | QJSValue read(qint64 maxSize); 28 | QJSValue readLine(qint64 maxSize = 0); 29 | QJSValue readAll(); 30 | 31 | qint64 write(const QJSValue &value); 32 | 33 | bool atEnd(); 34 | qint64 bytesAvailable(); 35 | qint64 bytesToWrite(); 36 | bool canReadLine(); 37 | QJSValue errorString(); 38 | bool isOpen(); 39 | bool isReadable(); 40 | bool isWritable(); 41 | QJSValue peek(qint64 maxSize); 42 | qint64 pos(); 43 | bool reset(); 44 | bool seek(qint64 pos); 45 | void setTextModeEnabled(bool enabled); 46 | qint64 size(); 47 | 48 | QJSValue fileName(); 49 | bool exists(); 50 | bool flush(); 51 | bool remove(); 52 | 53 | virtual QFile *self(); 54 | 55 | protected: 56 | void setFile(QFile *file); 57 | QJSEngine *engine() const; 58 | 59 | private: 60 | QJSValue newByteArray(const QByteArray &bytes); 61 | 62 | QFile *m_self = nullptr; 63 | QString m_path; 64 | }; 65 | -------------------------------------------------------------------------------- /src/scriptable/scriptablenetworkreply.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | #pragma once 3 | 4 | #include 5 | #include 6 | 7 | class QNetworkReply; 8 | 9 | class ScriptableNetworkReply final : public QObject { 10 | Q_OBJECT 11 | Q_PROPERTY(QJSValue data READ data CONSTANT) 12 | Q_PROPERTY(QJSValue error READ error CONSTANT) 13 | Q_PROPERTY(QJSValue status READ status CONSTANT) 14 | Q_PROPERTY(QJSValue redirect READ redirect CONSTANT) 15 | Q_PROPERTY(QJSValue headers READ headers CONSTANT) 16 | Q_PROPERTY(QJSValue finished READ finished CONSTANT) 17 | Q_PROPERTY(QJSValue url READ url CONSTANT) 18 | 19 | public: 20 | Q_INVOKABLE ScriptableNetworkReply() = default; 21 | 22 | ~ScriptableNetworkReply(); 23 | 24 | QJSValue data(); 25 | 26 | QJSValue error(); 27 | 28 | QJSValue status(); 29 | QJSValue redirect(); 30 | QJSValue headers(); 31 | 32 | QJSValue finished(); 33 | 34 | QJSValue url(); 35 | 36 | void setReply(QNetworkReply *reply); 37 | 38 | private: 39 | QJSEngine *engine() const; 40 | QJSValue newByteArray(const QByteArray &bytes) const; 41 | 42 | QNetworkReply *m_reply = nullptr; 43 | QJSValue m_data; 44 | QJSValue m_self; 45 | QByteArray m_rawData; 46 | }; 47 | -------------------------------------------------------------------------------- /src/scriptable/scriptablenetworkrequest.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | #pragma once 3 | 4 | #include 5 | #include 6 | 7 | class ScriptableNetworkReply; 8 | 9 | class ScriptableNetworkRequest final : public QObject 10 | { 11 | Q_OBJECT 12 | Q_PROPERTY(QJSValue headers READ headers WRITE setHeaders) 13 | Q_PROPERTY(QJSValue maxRedirects READ maxRedirects WRITE setMaxRedirects) 14 | 15 | public: 16 | Q_INVOKABLE ScriptableNetworkRequest() = default; 17 | 18 | QJSValue headers(); 19 | void setHeaders(const QJSValue &headers) { m_headers = headers; } 20 | 21 | QJSValue maxRedirects() const { return m_maxRedirects; } 22 | void setMaxRedirects(const QJSValue &redirect) { m_maxRedirects = redirect; } 23 | 24 | ScriptableNetworkReply *requestRaw( 25 | const QByteArray &method, const QString &url, const QByteArray &data) const; 26 | 27 | public slots: 28 | QJSValue request( 29 | const QJSValue &method, const QJSValue &url, const QJSValue &data = {}) const; 30 | 31 | private: 32 | QJSEngine *engine() const; 33 | QJSValue newByteArray(const QByteArray &bytes) const; 34 | 35 | QJSValue m_headers; 36 | QJSValue m_maxRedirects = 0; 37 | }; 38 | -------------------------------------------------------------------------------- /src/scriptable/scriptablesettings.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #include "scriptablesettings.h" 4 | 5 | ScriptableSettings::ScriptableSettings() 6 | : QObject() 7 | , m_settings() 8 | { 9 | } 10 | 11 | ScriptableSettings::ScriptableSettings(const QString &fileName) 12 | : QObject() 13 | , m_settings(fileName, QSettings::IniFormat) 14 | { 15 | } 16 | -------------------------------------------------------------------------------- /src/scriptable/scriptabletemporaryfile.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #include "scriptabletemporaryfile.h" 4 | 5 | #include 6 | 7 | Q_DECLARE_METATYPE(QTemporaryFile*) 8 | 9 | ScriptableTemporaryFile::ScriptableTemporaryFile(const QString &path) 10 | : ScriptableFile(path) 11 | { 12 | } 13 | 14 | bool ScriptableTemporaryFile::autoRemove() 15 | { 16 | return tmpFile()->autoRemove(); 17 | } 18 | 19 | QString ScriptableTemporaryFile::fileTemplate() 20 | { 21 | return tmpFile()->fileTemplate(); 22 | } 23 | 24 | void ScriptableTemporaryFile::setAutoRemove(bool autoRemove) 25 | { 26 | tmpFile()->setAutoRemove(autoRemove); 27 | } 28 | 29 | void ScriptableTemporaryFile::setFileTemplate(const QJSValue &name) 30 | { 31 | tmpFile()->setFileTemplate(name.toString()); 32 | } 33 | 34 | QFile *ScriptableTemporaryFile::self() 35 | { 36 | return tmpFile(); 37 | } 38 | 39 | QTemporaryFile *ScriptableTemporaryFile::tmpFile() 40 | { 41 | if (m_self) 42 | return m_self; 43 | 44 | m_self = new QTemporaryFile(this); 45 | setFile(m_self); 46 | return m_self; 47 | } 48 | -------------------------------------------------------------------------------- /src/scriptable/scriptabletemporaryfile.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #pragma once 4 | 5 | 6 | #include "scriptablefile.h" 7 | 8 | class QJSValue; 9 | class QTemporaryFile; 10 | 11 | class ScriptableTemporaryFile final : public ScriptableFile 12 | { 13 | Q_OBJECT 14 | public: 15 | Q_INVOKABLE explicit ScriptableTemporaryFile(const QString &path = QString()); 16 | 17 | public slots: 18 | bool autoRemove(); 19 | QString fileTemplate(); 20 | void setAutoRemove(bool autoRemove); 21 | void setFileTemplate(const QJSValue &name); 22 | 23 | QFile *self() override; 24 | 25 | private: 26 | QTemporaryFile *tmpFile(); 27 | 28 | QTemporaryFile *m_self = nullptr; 29 | }; 30 | -------------------------------------------------------------------------------- /src/scriptable/scriptoverrides.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | #pragma once 3 | 4 | namespace ScriptOverrides { 5 | enum ScriptOverrides { 6 | Paste = 0, 7 | OnItemsAdded = 1, 8 | OnItemsRemoved = 2, 9 | OnItemsChanged = 3, 10 | OnTabSelected = 4, 11 | OnItemsLoaded = 5, 12 | }; 13 | } 14 | -------------------------------------------------------------------------------- /src/tests/tests_common.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | #pragma once 4 | 5 | #include "tests/testinterface.h" 6 | 7 | #include 8 | #include 9 | 10 | class QByteArray; 11 | 12 | // Similar to QTemporaryFile but allows removing from other process. 13 | class TemporaryFile { 14 | public: 15 | TemporaryFile(); 16 | ~TemporaryFile(); 17 | QString fileName() const { return m_fileName; } 18 | 19 | private: 20 | QString m_fileName; 21 | }; 22 | 23 | int count(const QStringList &items, const QString &pattern); 24 | 25 | QStringList splitLines(const QByteArray &nativeText); 26 | 27 | bool testStderr( 28 | const QByteArray &stderrData, 29 | TestInterface::ReadStderrFlag flag = TestInterface::ReadErrors); 30 | 31 | /// Generate unique data. 32 | QByteArray generateData(); 33 | 34 | QString appWindowTitle(const QString &text); 35 | -------------------------------------------------------------------------------- /src/ui/configurationmanager.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | ConfigurationManager 4 | 5 | 6 | 7 | 0 8 | 0 9 | 679 10 | 621 11 | 12 | 13 | 14 | 15 | 320 16 | 240 17 | 18 | 19 | 20 | Preferences 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | Qt::Horizontal 30 | 31 | 32 | QDialogButtonBox::Apply|QDialogButtonBox::Cancel|QDialogButtonBox::Ok|QDialogButtonBox::Reset 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | ItemOrderList 41 | QWidget 42 |
gui/itemorderlist.h
43 | 1 44 |
45 |
46 | 47 | 48 |
49 | -------------------------------------------------------------------------------- /src/ui/pluginwidget.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | PluginWidget 4 | 5 | 6 | 7 | 0 8 | 0 9 | 400 10 | 300 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | true 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | true 31 | 32 | 33 | 34 | 35 | 36 | 37 | Qt::Vertical 38 | 39 | 40 | 41 | 20 42 | 1 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /src/version.cmake: -------------------------------------------------------------------------------- 1 | set(copyq_version "13.0.0") 2 | 3 | set(copyq_github_sha "$ENV{GITHUB_SHA}") 4 | if (copyq_github_sha) 5 | get_filename_component(copyq_github_ref "$ENV{GITHUB_REF}" NAME) 6 | string(SUBSTRING "${copyq_github_sha}" 0 8 copyq_github_sha) 7 | set(copyq_version "${copyq_version}-g${copyq_github_sha}-${copyq_github_ref}") 8 | else() 9 | find_package(Git) 10 | if(GIT_FOUND) 11 | execute_process(COMMAND 12 | "${GIT_EXECUTABLE}" describe --tags 13 | RESULT_VARIABLE copyq_git_describe_result 14 | OUTPUT_VARIABLE copyq_git_describe_output 15 | ERROR_QUIET 16 | OUTPUT_STRIP_TRAILING_WHITESPACE 17 | ) 18 | if(copyq_git_describe_result EQUAL 0) 19 | set(COPYQ_VERSION_TAG_REGEX "^v([0-9]+)") 20 | string(REGEX REPLACE "${COPYQ_VERSION_TAG_REGEX}" 21 | "\\1" copyq_git_describe_output 22 | "${copyq_git_describe_output}" 23 | ) 24 | set(copyq_version "${copyq_git_describe_output}") 25 | endif() 26 | endif() 27 | endif() 28 | -------------------------------------------------------------------------------- /src/version_file.cmake: -------------------------------------------------------------------------------- 1 | include(version.cmake) 2 | configure_file("${INPUT_FILE}" "${OUTPUT_FILE}") 3 | -------------------------------------------------------------------------------- /utils/appveyor/build_script.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/bash 2 | set -exo pipefail 3 | 4 | cmake --build build/ --config Release 5 | -------------------------------------------------------------------------------- /utils/appveyor/install.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/bash 2 | set -exo pipefail 3 | 4 | # shellcheck disable=SC1091 5 | source utils/appveyor/env.sh 6 | 7 | ls "$QTDIR/bin" 8 | ls "$QTDIR/lib/cmake" 9 | 10 | ls "$OPENSSL_PATH" 11 | ls "$OPENSSL_PATH/$LIBCRYPTO" 12 | ls "$OPENSSL_PATH/$LIBSSL" 13 | 14 | "$QTDIR/bin/qmake" --version 15 | -------------------------------------------------------------------------------- /utils/appveyor/test.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/bash 2 | set -exuo pipefail 3 | 4 | # shellcheck disable=SC1091 5 | source utils/appveyor/env.sh 6 | 7 | export PATH="$GPGPATH":$Destination:$PATH 8 | mkdir ~/.gnupg 9 | chmod go-rwx ~/.gnupg 10 | gpg --version 11 | 12 | "$Executable" tests 13 | 14 | gpgconf --kill all 15 | -------------------------------------------------------------------------------- /utils/appveyor/trigger_build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -exuo pipefail 3 | commit=$1 4 | branch=${2:-master} 5 | url=https://ci.appveyor.com/api/builds 6 | args=( 7 | # https://ci.appveyor.com/api-keys 8 | -H "Authorization: Bearer ${APPVEYOR_TOKEN}" 9 | -H "Content-Type: application/json" 10 | --data-binary 11 | '{"accountName": "hluk", "projectSlug": "copyq", "branch": "'"$branch"'", "commitId": "'"$commit"'"}' 12 | "$url" 13 | ) 14 | exec curl "${args[@]}" 15 | -------------------------------------------------------------------------------- /utils/copy_files.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Save whole files in CopyQ. 3 | # USAGE: 4 | # utils/copy_files.sh [FILES...] 5 | # EXAMPLE: 6 | # TAB=images utils/copy_files.sh ~/Pictures/*.jpg 7 | COPYQ=${COPYQ:-copyq} 8 | TAB=${TAB:-files} 9 | 10 | set -e 11 | 12 | i=0 13 | for x in "$@"; do 14 | # get MIME 15 | mime=$(file -b -L --mime-type "$x") 16 | # print info 17 | printf "%s: %s\n" "$mime" "$x" 18 | # write image with label 19 | "$COPYQ" -s "$SESSION" tab "$TAB" write $((++i)) \ 20 | "application/x-copyq-item-notes" "$x" \ 21 | "$mime" - < "$x" 22 | done 23 | -------------------------------------------------------------------------------- /utils/create_source_package.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | version=$1 3 | prefix=Copyq-$version 4 | out=${2:-"$prefix.tar.gz"} 5 | out=$(readlink -f "$out") 6 | 7 | script=$(readlink -f "$0") 8 | source="$(dirname "$(dirname "$script")")" 9 | 10 | set -e 11 | 12 | die () { 13 | echo "ERROR: $*" 14 | exit 1 15 | } 16 | 17 | git -C "$source" archive --format=tar.gz --prefix="$prefix/" --output="$out" "v$version" || 18 | die "First arguments must be existing version (tag v must exist in repository)" 19 | 20 | echo "Created source package for version $version: $out" 21 | 22 | size=$(stat --format="%s" "$out") 23 | hash=$(md5sum "$out" | cut -d' ' -f 1) 24 | echo " $hash $size $out" 25 | -------------------------------------------------------------------------------- /utils/debian/create_source_packages.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | distros=( 5 | jammy 6 | noble 7 | plucky 8 | ) 9 | 10 | sed -i 's/quilt/native/' 'debian/source/format' 11 | echo 9 > 'debian/compat' 12 | rm -f debian/watch 13 | 14 | for distro in "${distros[@]}"; do 15 | ./utils/debian/update_changelog.sh "$distro" 16 | debuild -S -d 17 | done 18 | -------------------------------------------------------------------------------- /utils/debian/update_changelog.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | distro=${1:-xenial} 5 | version="$(git describe|sed 's/^v//;s/-/./;s/-/~/')~$distro" 6 | 7 | sed -i "s/^set(copyq_version .*)$/set(copyq_version \"$version\")/" src/version.cmake 8 | grep -Fq "\"$version\"" src/version.cmake 9 | 10 | git checkout HEAD debian/control 11 | sed -i 's/debhelper .*,/debhelper (>= 9),/' 'debian/control' 12 | sed -i 's/Standards-Version:.*/Standards-Version: 3.9.7/' 'debian/control' 13 | 14 | git checkout HEAD debian/changelog 15 | 16 | dch \ 17 | -M \ 18 | -v "$version" \ 19 | -D "$distro" "from git commit $(git rev-parse HEAD)" 20 | 21 | git diff 22 | 23 | echo "To upload source code for $version run:" 24 | echo " debuild -S && dput ppa:hluk/copyq-beta ../copyq_${version}_source.changes" 25 | -------------------------------------------------------------------------------- /utils/download_window_builds.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euo pipefail 3 | version=$1 4 | base=https://ci.appveyor.com/api/projects/hluk/copyq/artifacts 5 | urls=( 6 | "$base/copyq-$version.zip?tag=v$version" 7 | "$base/copyq-$version-setup.exe?tag=v$version" 8 | ) 9 | for url in "${urls[@]}"; do 10 | echo "Downloading: $url" 11 | curl -LO --fail-with-body "$url" 12 | done 13 | echo "DONE" 14 | -------------------------------------------------------------------------------- /utils/fedora/build_sprm.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -ex 3 | 4 | dir=$(dirname "$(readlink -f "$0")") 5 | spec_template=$dir/copyq.spec 6 | repo=$USER/copyq 7 | 8 | revision=$(git rev-parse HEAD) 9 | rev=$(git rev-parse --short HEAD) 10 | branch=$(git rev-parse --abbrev-ref HEAD) 11 | last_version=$(git describe --tags --abbrev=0) 12 | date=$(date -u '+%Y%m%d') 13 | sed_script=$(cat < "$spec" 29 | ${EDITOR:-vi} "$spec" 30 | 31 | rpmlint "$spec" 32 | spectool -g --sourcedir "$spec" 33 | rpmbuild -bs "$spec" 34 | 35 | cat < 39 | 40 | Install the package using: 41 | 42 | sudo dnf install 'dnf-command(copr)' 43 | sudo dnf copr enable $repo 44 | sudo dnf install copyq 45 | EOF 46 | -------------------------------------------------------------------------------- /utils/fosshub.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """ 3 | Create new release and upload files to FossHUB. 4 | 5 | Get the API key from: https://devzone.fosshub.com/dashboard/profile 6 | 7 | USAGE: ./fosshub.py 8 | """ 9 | import requests 10 | import sys 11 | 12 | project_id = '5c1195728c9fe8186f80a14b' 13 | fosshub_new_release_url = 'https://api.fosshub.com/rest/projects/{project_id}/releases/'.format(project_id=project_id) 14 | github_release_url = 'https://github.com/hluk/CopyQ/releases/download/v{version}/{basename}' 15 | files = { 16 | 'copyq-{version}-setup.exe': 'Windows Installer', 17 | 'copyq-{version}.zip': 'Windows Portable', 18 | 'CopyQ-macos-10.dmg.zip': 'macOS', 19 | 'CopyQ-macos-12-m1.dmg.zip': 'macOS M1', 20 | } 21 | 22 | version = sys.argv[1] 23 | api_key = sys.argv[2] 24 | 25 | # https://devzone.fosshub.com/dashboard/restApi 26 | data = { 27 | 'version': version, 28 | 'files': [{ 29 | 'fileUrl': github_release_url.format(version=version, basename=basename.format(version=version)), 30 | 'type': filetype, 31 | 'version': version 32 | } for basename, filetype in files.items()], 33 | 'publish': True, 34 | } 35 | headers = { 36 | 'X-Auth-Key': api_key 37 | } 38 | 39 | response = requests.post(fosshub_new_release_url, json=data, headers=headers) 40 | if response.status_code != 200: 41 | raise RuntimeError('Unexpected response: ' + response.text) 42 | 43 | print('All OK: ' + response.text) 44 | -------------------------------------------------------------------------------- /utils/generata-big-data-tab.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euo pipefail 3 | 4 | COPYQ=${COPYQ:-copyq} 5 | session=test 6 | tab=BIG 7 | 8 | items=10000 9 | size=50000 10 | 11 | for x in $(seq $items); do 12 | echo $x 13 | head -c $size /dev/random | base64 | "$COPYQ" -s $session tab $tab insert -1 - 14 | done 15 | -------------------------------------------------------------------------------- /utils/github/homebrew/Formula/extra-cmake-modules.rb: -------------------------------------------------------------------------------- 1 | class ExtraCmakeModules < Formula 2 | desc "Extra modules and scripts for CMake" 3 | homepage "https://api.kde.org/frameworks/extra-cmake-modules/html/index.html" 4 | url "https://download.kde.org/stable/frameworks/6.7/extra-cmake-modules-6.7.0.tar.xz" 5 | sha256 "d81de82692d3d2bb77110332a65c8266252becc2c3f307ce814990ce5607b8dc" 6 | license all_of: ["BSD-2-Clause", "BSD-3-Clause", "MIT"] 7 | head "https://invent.kde.org/frameworks/extra-cmake-modules.git" 8 | 9 | depends_on "cmake" => [:build, :test] 10 | depends_on "ninja" => :build 11 | 12 | depends_on "qt" => :build 13 | 14 | def install 15 | args = std_cmake_args 16 | args << "-DBUILD_HTML_DOCS=OFF" 17 | args << "-DBUILD_MAN_DOCS=OFF" 18 | args << "-DBUILD_QTHELP_DOCS=OFF" 19 | args << "-DBUILD_TESTING=OFF" 20 | 21 | mkdir "build" do 22 | system "cmake", "-G", "Ninja", "..", *args 23 | system "ninja" 24 | system "ninja", "install" 25 | end 26 | end 27 | 28 | test do 29 | (testpath/"CMakeLists.txt").write("find_package(ECM REQUIRED)") 30 | system "cmake", ".", "-Wno-dev" 31 | 32 | expected="ECM_DIR:PATH=#{HOMEBREW_PREFIX}/share/ECM/cmake" 33 | assert_match expected, File.read(testpath/"CMakeCache.txt") 34 | end 35 | end 36 | -------------------------------------------------------------------------------- /utils/github/homebrew/Formula/kf6-kconfig.rb: -------------------------------------------------------------------------------- 1 | class Kf6Kconfig < Formula 2 | desc "Configuration system" 3 | homepage "https://www.kde.org" 4 | url "https://download.kde.org/stable/frameworks/6.7/kconfig-6.7.0.tar.xz" 5 | sha256 "be2d5ddb63e56703bc097e5d9912b39abc513ac51654de2e0d83a1aed2c54b1b" 6 | head "https://invent.kde.org/frameworks/kconfig.git" 7 | 8 | depends_on "cmake" => [:build, :test] 9 | depends_on "ninja" => :build 10 | 11 | depends_on "copyq/kde/extra-cmake-modules" => [:build, :test] 12 | 13 | depends_on "qt" 14 | 15 | def install 16 | args = std_cmake_args 17 | args << "-DBUILD_TESTING=OFF" 18 | args << "-DBUILD_QCH=OFF" 19 | args << "-DKDE_INSTALL_QMLDIR=lib/qt6/qml" 20 | args << "-DKDE_INSTALL_PLUGINDIR=lib/qt6/plugins" 21 | args << "-DKDE_INSTALL_QTPLUGINDIR=lib/qt6/plugins" 22 | 23 | args << "-DKCONFIG_USE_GUI=OFF" 24 | args << "-DKCONFIG_USE_DBUS=OFF" 25 | 26 | mkdir "build" do 27 | system "cmake", "-G", "Ninja", "..", *args 28 | system "ninja" 29 | system "ninja", "install" 30 | prefix.install "install_manifest.txt" 31 | end 32 | end 33 | 34 | test do 35 | (testpath/"CMakeLists.txt").write("find_package(KF6Config REQUIRED)") 36 | system "cmake", ".", "-Wno-dev" 37 | end 38 | end 39 | -------------------------------------------------------------------------------- /utils/github/homebrew/Formula/kf6-knotifications.rb: -------------------------------------------------------------------------------- 1 | class Kf6Knotifications < Formula 2 | desc "Abstraction for system notifications" 3 | homepage "https://www.kde.org" 4 | url "https://download.kde.org/stable/frameworks/6.7/knotifications-6.7.0.tar.xz" 5 | sha256 "9e972f015d9b31b3283bf842a32d270096224d127c13a6e79450f4f0452de5e7" 6 | head "https://invent.kde.org/frameworks/knotifications.git" 7 | 8 | depends_on "cmake" => [:build, :test] 9 | depends_on "ninja" => :build 10 | 11 | depends_on "copyq/kde/extra-cmake-modules" => [:build, :test] 12 | depends_on "copyq/kde/kf6-kconfig" 13 | 14 | def install 15 | args = std_cmake_args 16 | 17 | args << "-DEXCLUDE_DEPRECATED_BEFORE_AND_AT=5.90.0" 18 | 19 | args << "-DBUILD_TESTING=OFF" 20 | args << "-DBUILD_QCH=OFF" 21 | args << "-DKDE_INSTALL_QMLDIR=lib/qt6/qml" 22 | args << "-DKDE_INSTALL_PLUGINDIR=lib/qt6/plugins" 23 | args << "-DKDE_INSTALL_QTPLUGINDIR=lib/qt6/plugins" 24 | args << "-DUSE_DBUS=OFF" 25 | 26 | mkdir "build" do 27 | system "cmake", "-G", "Ninja", "..", *args 28 | system "ninja" 29 | system "ninja", "install" 30 | prefix.install "install_manifest.txt" 31 | end 32 | end 33 | 34 | test do 35 | (testpath/"CMakeLists.txt").write("find_package(KF6Notifications REQUIRED)") 36 | system "cmake", ".", "-Wno-dev" 37 | end 38 | end 39 | -------------------------------------------------------------------------------- /utils/github/homebrew/Formula/kf6-kstatusnotifieritem.rb: -------------------------------------------------------------------------------- 1 | class Kf6Kstatusnotifieritem < Formula 2 | desc "Abstraction for status/tray" 3 | homepage "https://www.kde.org" 4 | url "https://download.kde.org/stable/frameworks/6.7/kstatusnotifieritem-6.7.0.tar.xz" 5 | sha256 "80eae2693cdb5da669b4ed6a8228bddc39816aca0fde928f231e4894827d1de0" 6 | head "https://invent.kde.org/frameworks/kstatusnotifieritem.git" 7 | 8 | depends_on "cmake" => [:build, :test] 9 | depends_on "ninja" => :build 10 | 11 | depends_on "copyq/kde/extra-cmake-modules" => [:build, :test] 12 | depends_on "copyq/kde/kf6-kconfig" 13 | depends_on "copyq/kde/kf6-kwindowsystem" 14 | 15 | def install 16 | args = std_cmake_args 17 | 18 | args << "-DEXCLUDE_DEPRECATED_BEFORE_AND_AT=5.90.0" 19 | 20 | args << "-DBUILD_TESTING=OFF" 21 | args << "-DBUILD_QCH=OFF" 22 | args << "-DKDE_INSTALL_QMLDIR=lib/qt6/qml" 23 | args << "-DKDE_INSTALL_PLUGINDIR=lib/qt6/plugins" 24 | args << "-DKDE_INSTALL_QTPLUGINDIR=lib/qt6/plugins" 25 | args << "-DUSE_DBUS=OFF" 26 | 27 | mkdir "build" do 28 | system "cmake", "-G", "Ninja", "..", *args 29 | system "ninja" 30 | system "ninja", "install" 31 | prefix.install "install_manifest.txt" 32 | end 33 | end 34 | 35 | test do 36 | (testpath/"CMakeLists.txt").write("find_package(KF6Statusnotifieritem REQUIRED)") 37 | system "cmake", ".", "-Wno-dev" 38 | end 39 | end 40 | -------------------------------------------------------------------------------- /utils/github/homebrew/Formula/kf6-kwindowsystem.rb: -------------------------------------------------------------------------------- 1 | class Kf6Kwindowsystem < Formula 2 | desc "Access to the windowing system" 3 | homepage "https://www.kde.org" 4 | url "https://download.kde.org/stable/frameworks/6.7/kwindowsystem-6.7.0.tar.xz" 5 | sha256 "62c0f0b4a9507939d84aeeda55bbd4300b88c04e37953e5189b139003310a8f4" 6 | head "https://invent.kde.org/frameworks/kwindowsystem.git" 7 | 8 | depends_on "cmake" => [:build, :test] 9 | depends_on "ninja" => :build 10 | 11 | depends_on "copyq/kde/extra-cmake-modules" => [:build, :test] 12 | 13 | depends_on "qt" 14 | 15 | def install 16 | args = std_cmake_args 17 | args << "-DBUILD_TESTING=OFF" 18 | args << "-DBUILD_QCH=OFF" 19 | args << "-DKDE_INSTALL_QMLDIR=lib/qt6/qml" 20 | args << "-DKDE_INSTALL_PLUGINDIR=lib/qt6/plugins" 21 | args << "-DKDE_INSTALL_QTPLUGINDIR=lib/qt6/plugins" 22 | 23 | mkdir "build" do 24 | system "cmake", "-G", "Ninja", "..", *args 25 | system "ninja" 26 | system "ninja", "install" 27 | prefix.install "install_manifest.txt" 28 | end 29 | end 30 | 31 | test do 32 | (testpath/"CMakeLists.txt").write("find_package(KF6WindowSystem REQUIRED)") 33 | system "cmake", ".", "-Wno-dev" 34 | end 35 | end 36 | -------------------------------------------------------------------------------- /utils/github/install-macos.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Installs build dependencies. 3 | set -xeuo pipefail 4 | 5 | # Create repository for Homebrew. 6 | ( 7 | cd utils/github/homebrew/ 8 | git config --global user.email "noreply@github.com" 9 | git config --global user.name "GitHub Actions" 10 | git init . 11 | git add . 12 | git commit -m "Initial" 13 | ) 14 | 15 | # workaround for symlink issues 16 | rm -rf \ 17 | /usr/local/bin/2to3* \ 18 | /usr/local/bin/idle3* \ 19 | /usr/local/bin/pydoc3* \ 20 | /usr/local/bin/python3* \ 21 | /usr/local/bin/python3-config* 22 | 23 | brew uninstall cmake 24 | 25 | # Install Homebrew: https://brew.sh/ 26 | /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)" 27 | 28 | brew tap copyq/kde utils/github/homebrew/ 29 | 30 | brew install qt@6 31 | brew install --verbose \ 32 | copyq/kde/kf6-knotifications \ 33 | copyq/kde/kf6-kstatusnotifieritem 34 | -------------------------------------------------------------------------------- /utils/github/test-linux-global-shortcuts.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Tests global shortcuts on X11. 3 | set -xeuo pipefail 4 | 5 | export COPYQ_SESSION_NAME=__COPYQ_SHORTCUT 6 | 7 | source "$(dirname "$0")/test-start-server.sh" 8 | trap "kill $copyq_pid || true" QUIT TERM INT HUP EXIT 9 | 10 | ./copyq removeTab TEST || true 11 | 12 | # register Ctrl+Alt+T to exit CopyQ 13 | ./copyq - <> "$COPYQ_LOG_FILE" && 28 | scrot "$f" || 29 | break 30 | done 31 | ) & 32 | 33 | # Avoid following warning: 34 | # QtWarning: QStandardPaths: XDG_RUNTIME_DIR not set, defaulting to '/tmp/runtime-root' 35 | export XDG_RUNTIME_DIR='/tmp/runtime-root' 36 | mkdir -p "$XDG_RUNTIME_DIR" 37 | chmod 0700 "$XDG_RUNTIME_DIR" 38 | 39 | # Disable encryption tests because exporting GPG key asks for password. 40 | export COPYQ_TESTS_SKIP_ITEMENCRYPT=1 41 | 42 | export COPYQ_TESTS_SKIP_DRAG_AND_DROP=1 43 | 44 | export COPYQ_TESTS_RERUN_FAILED=1 45 | export COPYQ_TESTS_NO_NETWORK=1 46 | "$INSTALL_PREFIX/bin/copyq" tests 47 | -------------------------------------------------------------------------------- /utils/launchpad/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:24.04 2 | LABEL \ 3 | name="CopyQ Launchpad Environment" \ 4 | description="Environment for submitting CopyQ to Launchpad" \ 5 | vendor="Lukas Holecek " \ 6 | license="GPLv2+" 7 | 8 | RUN export DEBIAN_FRONTEND=noninteractive \ 9 | && apt-get update \ 10 | && apt install -y \ 11 | debhelper \ 12 | devscripts \ 13 | dpkg-dev \ 14 | dput \ 15 | git \ 16 | gnupg2 \ 17 | vim 18 | 19 | # gpg2 --export-secret-keys $EMAIL > launchpad.key 20 | COPY launchpad.key /tmp/gpg.key 21 | 22 | RUN git clone https://github.com/hluk/CopyQ.git /root/copyq 23 | 24 | WORKDIR /root/copyq 25 | 26 | COPY entrypoint.sh /root/entrypoint.sh 27 | ENTRYPOINT ["/root/entrypoint.sh"] 28 | -------------------------------------------------------------------------------- /utils/launchpad/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | email=$1 5 | context=$(dirname "$0") 6 | 7 | cd "$context" 8 | 9 | trap 'rm -f launchpad.key' QUIT TERM INT EXIT 10 | gpg2 --export-secret-keys "$email" > launchpad.key 11 | 12 | exec podman build -t launchpad . 13 | -------------------------------------------------------------------------------- /utils/launchpad/entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | gpg2 --import /tmp/gpg.key 5 | 6 | exec bash -i 7 | -------------------------------------------------------------------------------- /utils/launchpad/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | exec podman run -it --rm launchpad 3 | -------------------------------------------------------------------------------- /utils/linux_make_icons.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | make_icons() 5 | { 6 | input_icon=$1 7 | output_basename=$2 8 | 9 | for extent in 16 22 24 32 48 64 128 256 512 1024; do 10 | size="${extent}x${extent}" 11 | output="${output_basename}_$size.png" 12 | echo "Converting $input_icon -> $output" 13 | convert -background transparent -density 600 "$input_icon" \ 14 | -resize "$size" "$output" 15 | done 16 | } 17 | 18 | cd src/images 19 | make_icons icon.svg icon 20 | -------------------------------------------------------------------------------- /utils/lupdate.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | lupdate_args=( 3 | src/ 4 | plugins/*/*.{cpp,h,ui} 5 | -ts 6 | ${1:-translations/*.ts} 7 | ) 8 | exec "${LUPDATE:-lupdate-qt5}" "${lupdate_args[@]}" 9 | -------------------------------------------------------------------------------- /utils/make_icns.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -ex 3 | 4 | image_dir=src/images 5 | tmp_dir=icon.iconset 6 | 7 | out=${image_dir}/icon.icns 8 | 9 | rm -rf "${tmp_dir}" 10 | mkdir -p "${tmp_dir}" 11 | 12 | convert_img () { 13 | size=$1 14 | highdpi=$2 15 | 16 | target_img=${tmp_dir}/icon_${size}x${size} 17 | if [[ -n "$highdpi" ]]; then 18 | target_img="${target_img}@${highdpi}x" 19 | size=$(expr $size \* $highdpi) 20 | fi 21 | target_img="${target_img}.png" 22 | 23 | source_img=${image_dir}/icon_${size}x${size}.png 24 | 25 | cp "$source_img" "$target_img" 26 | } 27 | 28 | convert_img 16 29 | convert_img 16 2 30 | convert_img 32 31 | convert_img 32 2 32 | convert_img 128 33 | convert_img 128 2 34 | convert_img 256 35 | convert_img 256 2 36 | convert_img 512 37 | convert_img 512 2 38 | 39 | iconutil --convert icns --output $out "${tmp_dir}" 40 | rm -rf "${tmp_dir}" 41 | -------------------------------------------------------------------------------- /utils/make_ico.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | image_dir=src/images 3 | out=${1:-src/images/icon.ico} 4 | 5 | args=( 6 | -background transparent 7 | ${image_dir}/icon_16x16.png 8 | \( ${image_dir}/icon_22x22.png -resize 20x20 \) 9 | ${image_dir}/icon_24x24.png 10 | ${image_dir}/icon_32x32.png 11 | \( ${image_dir}/icon_48x48.png -resize 40x40 \) 12 | ${image_dir}/icon_48x48.png 13 | ${image_dir}/icon_64x64.png 14 | \( ${image_dir}/icon_128x128.png -resize 96x96 \) 15 | ${image_dir}/icon_128x128.png 16 | ${image_dir}/icon_256x256.png 17 | "$out" 18 | ) 19 | 20 | exec convert "${args[@]}" 21 | -------------------------------------------------------------------------------- /utils/sanitize.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | sanitizers="address,leak,bounds,bool,enum,null,undefined" 5 | export CXX_FLAGS="$CXX_FLAGS -fno-omit-frame-pointer -mllvm -asan-use-private-alias=1" 6 | 7 | build_dir=build-sanitize 8 | utils_dir=$(dirname "$(readlink -f "$0")") 9 | src_dir=$utils_dir/.. 10 | steps=( 11 | clean 12 | cmake 13 | ninja 14 | run 15 | ) 16 | 17 | if [ -n "$CLANG_ROOT" ]; then 18 | export PATH=$CLANG_ROOT:$PATH 19 | fi 20 | CXX=${CXX:-clang++} 21 | 22 | export ASAN_SYMBOLIZER_PATH=${ASAN_SYMBOLIZER_PATH:-$(which llvm-symbolizer)} 23 | export ASAN_OPTIONS=${ASAN_OPTIONS:-"detect_leaks=1 detect_stack_use_after_return=1 print_stats=1 use_odr_indicator=1"} 24 | 25 | echo "=== Using sanitizers (directory \"$build_dir\") ===" 26 | 27 | step=2 28 | if [ -d "$build_dir" ]; then 29 | echo "Select starting point:" 30 | select step in "${steps[@]}"; do step=$REPLY; break; done 31 | fi 32 | 33 | has_step () { 34 | [[ $step -le $1 ]] 35 | } 36 | 37 | has_step "${#steps[*]}" 38 | 39 | if has_step 1; then 40 | rm -r "$build_dir" || exit 1 41 | fi 42 | 43 | mkdir -p "$build_dir" 44 | cd "$build_dir" 45 | 46 | if has_step 2; then 47 | cmake \ 48 | -DCMAKE_INSTALL_PREFIX="$PWD/install" \ 49 | -DCMAKE_CXX_COMPILER="$CXX" \ 50 | -DCMAKE_CXX_FLAGS="$CXX_FLAGS -fsanitize=$sanitizers" \ 51 | -DCMAKE_BUILD_TYPE=Debug \ 52 | -DCMAKE_GENERATOR=Ninja \ 53 | "$src_dir" 54 | fi 55 | 56 | if has_step 3; then 57 | ninja install 58 | fi 59 | 60 | if has_step 4; then 61 | ./copyq -s test1 "$@" 62 | fi 63 | -------------------------------------------------------------------------------- /utils/sign_released_files.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euo pipefail 3 | 4 | sha512sum *.gz *.zip *.exe linux/*.deb linux/*.rpm | 5 | sed 's/ linux\// /' > checksums-sha512.txt 6 | 7 | # https://docs.sigstore.dev/quickstart/quickstart-cosign/ 8 | cosign sign-blob checksums-sha512.txt --bundle cosign.bundle 9 | 10 | cosign verify-blob checksums-sha512.txt --bundle cosign.bundle \ 11 | --certificate-identity=hluk@email.cz \ 12 | --certificate-oidc-issuer=https://github.com/login/oauth 13 | -------------------------------------------------------------------------------- /utils/test_window_build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Downloads and tests Windows build from Appveyor. 3 | # Usage: 4 | # utils/test_window_build.sh [BRANCH=master [VERSION=$(git describe origin/BRANCH)]] 5 | set -ex 6 | 7 | branch=${1:-master} 8 | version=${2:-$(git describe "origin/$branch")} 9 | project=hluk/copyq 10 | tmp_dir=/tmp/copyq-test 11 | archive="copyq-$version.zip" 12 | url="https://ci.appveyor.com/api/projects/$project/artifacts/$archive?branch=$branch" 13 | 14 | if [[ ! -f "$archive" ]]; then 15 | curl -o "$archive" "$url" 16 | fi 17 | 18 | unzip "$archive" -d "$tmp_dir" 19 | wine "$tmp_dir/copyq-$version/copyq.exe" 20 | -------------------------------------------------------------------------------- /utils/view_windows_screenshots.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euo pipefail 3 | 4 | image_viewer=${IMAGE_VIEWER:-eog} 5 | url="https://ci.appveyor.com/api/projects/hluk/copyq/artifacts/copyq-screenshots.zip?all=true&$*" 6 | 7 | if [[ $# == 0 ]]; then 8 | echo "Usage: $0 {tag=v8.0.0|branch=master|pr=true}" 9 | exit 1 10 | fi 11 | 12 | dir=$(mktemp --directory) 13 | clean() { 14 | rm -rf -- "$dir" 15 | } 16 | trap clean QUIT TERM INT HUP EXIT 17 | 18 | curl -LsSf --output "$dir/copyq-screenshots.zip" "$url" 19 | 7z e -o"$dir" "$dir/copyq-screenshots.zip" 20 | "$image_viewer" "$dir" 21 | -------------------------------------------------------------------------------- /utils/windows_copyq_update.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Script to update CopyQ installation on Windows. 3 | build=${1:-"../build-copyq-Qt_4_8_5-Release"} 4 | dst=${2:-"/c/dev/copyq"} 5 | src=${3:-$PWD} 6 | 7 | set -e 8 | 9 | update() { 10 | set -e 11 | mkdir -p "${@: -1}" 12 | cp -uv -- "$@" 13 | } 14 | 15 | update "$src"/{README.md,AUTHORS,HACKING,LICENSE} "$dst" 16 | update "$src"/shared/themes/*.{css,ini} "$dst/themes" 17 | update "$build"/copyq.exe "$dst" 18 | update "$build"/plugins/*.dll "$dst/plugins" 19 | update "$build"/src/*.qm "$dst/translations" 20 | --------------------------------------------------------------------------------