Compare commits
36 Commits
Author | SHA1 | Date |
---|---|---|
Niklas | befc5e5446 | |
Niklas | 4f9b25190b | |
Niklas | 11c944c122 | |
Niklas | df9a7cc096 | |
Niklas | 5f2de7de05 | |
Niklas | 613a51b812 | |
Niklas | 1121c3b8b1 | |
Niklas | e3645a682e | |
Niklas | 183abda31e | |
Niklas | 878c297f3f | |
Niklas | e1a9ae803d | |
Niklas | 9df10cc4c8 | |
Niklas | 317513d5ab | |
Niklas | b1e97de1e1 | |
Karol Czeryna | 44049914e5 | |
Niklas | e196e57a04 | |
Niklas | 2ed294ea4c | |
Niklas | 1d3e335f3f | |
Niklas | 692fa1eda2 | |
Niklas | ab6769c7f8 | |
Niklas | 245af995fb | |
Niklas | d80c6b8bc5 | |
Niklas | f8f034f641 | |
Niklas | 41d1bc41e9 | |
Niklas | 2587b2c0f2 | |
Niklas | aa77c14a51 | |
Niklas | d3d3f1e833 | |
Niklas | b63b82528f | |
Niklas | d75f993ef8 | |
Niklas | 6d5356f140 | |
Niklas | b740fbd0d3 | |
Niklas | fd76a8b187 | |
Niklas | 284e54303b | |
Niklas | 0f8e8901fb | |
Niklas | b9155dd401 | |
Niklas | e94a0d67cb |
|
@ -1,67 +0,0 @@
|
|||
workflows:
|
||||
version: 2
|
||||
build:
|
||||
jobs:
|
||||
- build
|
||||
|
||||
version: 2
|
||||
jobs:
|
||||
build:
|
||||
docker:
|
||||
- image: buildpack-deps:bionic
|
||||
steps:
|
||||
- run:
|
||||
name: Install pre deps
|
||||
command: |
|
||||
apt-get update -yqq \
|
||||
&& apt-get install -yqq \
|
||||
build-essential \
|
||||
cmake \
|
||||
gcc \
|
||||
g++ \
|
||||
qt5-default \
|
||||
qt5-qmake \
|
||||
qtmultimedia5-dev \
|
||||
libqt5svg5-dev \
|
||||
libx11-dev \
|
||||
libavformat-dev \
|
||||
libavcodec-dev \
|
||||
libavutil-dev \
|
||||
libswscale-dev \
|
||||
libqt5x11extras5-dev \
|
||||
libxcb-util-dev \
|
||||
libxcb-cursor-dev \
|
||||
libxcb1-dev \
|
||||
- run:
|
||||
name: QMake Version
|
||||
command: qmake --version
|
||||
- checkout
|
||||
- run: git submodule sync
|
||||
- run: git submodule update --init
|
||||
- run:
|
||||
name: LS
|
||||
command: ls -lahR ~/project
|
||||
- run:
|
||||
name: Create Build Env
|
||||
command: mkdir build && pwd && ls
|
||||
- run:
|
||||
name: Build
|
||||
command: |
|
||||
cd build && pwd && ls;
|
||||
qmake ..;
|
||||
make -j2;
|
||||
cd ..;
|
||||
- run:
|
||||
name: Create Artifact Path
|
||||
command: mkdir /kshare
|
||||
- run:
|
||||
name: Store Build
|
||||
command: cp build/src/kshare /kshare/
|
||||
- run:
|
||||
name: Build Debian Package
|
||||
command: |
|
||||
cd packages/;
|
||||
./makedeb.sh ci;
|
||||
cp *.deb /kshare/
|
||||
- store_artifacts:
|
||||
path: /kshare/
|
|
@ -0,0 +1,102 @@
|
|||
kind: pipeline
|
||||
type: docker
|
||||
name: build
|
||||
|
||||
platform:
|
||||
os: linux
|
||||
arch: amd64
|
||||
|
||||
steps:
|
||||
- name: submodules
|
||||
image: alpine/git
|
||||
commands:
|
||||
- git submodule update --init --recursive
|
||||
|
||||
- name: build-mxe
|
||||
image: ubuntu:bionic
|
||||
volumes:
|
||||
- name: cache
|
||||
path: /release
|
||||
commands:
|
||||
- rm -rf build/ || true
|
||||
- apt-get update && apt-get install -yqq wget gnupg2 curl rsync p7zip git
|
||||
- mkdir build && pwd && ls -lahR .
|
||||
- cd build
|
||||
- wget -qO - https://pkg.mxe.cc/repos/apt/client-conf/mxeapt.gpg | apt-key add -
|
||||
- echo 'deb https://pkg.mxe.cc/repos/apt/ bionic main' >> /etc/apt/sources.list
|
||||
- apt-get update && apt-get install -yqq mxe-x86-64-w64-mingw32.shared-qtbase mxe-x86-64-w64-mingw32.shared-qtmultimedia mxe-x86-64-w64-mingw32.shared-qttools mxe-x86-64-w64-mingw32.shared-qtwinextras
|
||||
- apt-get install -yqq mxe-x86-64-w64-mingw32.shared-ffmpeg
|
||||
- export PATH=/usr/lib/mxe/usr/x86_64-w64-mingw32.shared/qt5/bin:$PATH
|
||||
- export PATH=/usr/lib/mxe/usr/bin:$PATH
|
||||
- cp /usr/lib/mxe/usr/x86_64-w64-mingw32.shared/include/lmcons.h /usr/lib/mxe/usr/x86_64-w64-mingw32.shared/include/Lmcons.h
|
||||
- qmake --version
|
||||
- qmake CONFIG+=nopkg ../KShare.pro
|
||||
- make -j2
|
||||
- mkdir dist
|
||||
- cp src/release/kshare.exe dist/KShare.exe
|
||||
- /usr/lib/mxe/tools/copydlldeps.sh --infile dist/KShare.exe --destdir dist/ --recursivesrcdir /usr/lib/mxe/usr/x86_64-w64-mingw32.shared/ --srcdir ../src/ --copy --enforcedir /usr/lib/mxe/usr/x86_64-w64-mingw32.shared/qt5/plugins/platforms/ --objdump /usr/lib/mxe/usr/bin/x86_64-w64-mingw32.shared-objdump
|
||||
- mkdir dist/mediaservice; cp /usr/lib/mxe/usr/x86_64-w64-mingw32.shared/qt5/plugins/mediaservice/dsengine.dll dist/mediaservice
|
||||
- cd dist/; cp KShare.exe "/release/KShare_v${DRONE_COMMIT_SHA:0:9}.exe"; zip -r "/release/win_kshare_v${DRONE_COMMIT_SHA:0:9}_portable.zip" *
|
||||
- ls -lahR /release/
|
||||
|
||||
- name: build-ubuntu
|
||||
image: buildpack-deps:19.10
|
||||
volumes:
|
||||
- name: cache
|
||||
path: /release
|
||||
commands:
|
||||
- rm -rf build/ || true
|
||||
- apt-get update -yqq && apt-get install -yqq build-essential cmake \gcc g++ qt5-default qt5-qmake qtmultimedia5-dev libqt5svg5-dev libx11-dev libavformat-dev libavcodec-dev libavutil-dev libswscale-dev libqt5x11extras5-dev libxcb-util-dev libxcb-cursor-dev libxcb1-dev
|
||||
- qmake --version
|
||||
- mkdir build && pwd && ls -lahR .
|
||||
- cd build && pwd && ls; qmake ..; make -j2; cd ..
|
||||
- mkdir /release || true
|
||||
- cp build/src/kshare "/release/kshare_v${DRONE_COMMIT_SHA:0:9}"
|
||||
- cd packages/; ./makedeb.sh ci; cp *.deb /release/; cd ..
|
||||
|
||||
- name: build-arch
|
||||
image: archlinux/base:latest
|
||||
volumes:
|
||||
- name: cache
|
||||
path: /release
|
||||
commands:
|
||||
- rm -rf build/ || true
|
||||
- pacman -Sy && pacman -S --noconfirm base-devel git sudo wget
|
||||
- "echo 'Set disable_coredump false' >> /etc/sudo.conf"
|
||||
- "mkdir /home/build && useradd --home /home/build --shell=/bin/false build && usermod -L build && chown build:build /home/build && echo 'build ALL=(ALL) NOPASSWD: ALL' >> /etc/sudoers && echo 'root ALL=(ALL) NOPASSWD: ALL' >> /etc/sudoers"
|
||||
- cd /home/build && sudo -u build wget https://raw.githubusercontent.com/Gurkengewuerz/KShare/${DRONE_BRANCH}/packages/arch/${DRONE_BRANCH}-KShare/PKGBUILD
|
||||
- cd /home/build && pwd && ls -lah
|
||||
- cd /home/build && sudo -u build makepkg --syncdeps --noconfirm
|
||||
- mkdir /release || true
|
||||
- cp /home/build/*.pkg.tar.xz /release/
|
||||
|
||||
- name: artifacts
|
||||
image: alpine:latest
|
||||
volumes:
|
||||
- name: cache
|
||||
path: /release
|
||||
commands:
|
||||
- cat /etc/issue
|
||||
- apk add --no-cache openssh-client ca-certificates sshpass
|
||||
- mkdir -p ~/.ssh
|
||||
- chmod 700 ~/.ssh
|
||||
- echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config
|
||||
- export REMOTE_PATH=/data/${DRONE_REPO_OWNER}/${DRONE_REPO_NAME}/${DRONE_BRANCH}/$(date +'%Y%m%d-%H%M%S')-${DRONE_COMMIT_SHA:0:9}/
|
||||
- export SSHPASS=$${REMOTE_PASSWORD}
|
||||
- sshpass -e ssh $${REMOTE_USERNAME}@$${REMOTE_HOST} "mkdir -p $REMOTE_PATH"
|
||||
- "sshpass -e scp -r /release/* $${REMOTE_USERNAME}@$${REMOTE_HOST}:$REMOTE_PATH"
|
||||
environment:
|
||||
REMOTE_USERNAME:
|
||||
from_secret: remote_username
|
||||
REMOTE_PASSWORD:
|
||||
from_secret: remote_password
|
||||
REMOTE_HOST:
|
||||
from_secret: remote_host
|
||||
when:
|
||||
event:
|
||||
- push
|
||||
- tag
|
||||
|
||||
volumes:
|
||||
- name: cache
|
||||
temp: {}
|
|
@ -1,32 +0,0 @@
|
|||
environment:
|
||||
QTDIR: C:\Qt\5.9\mingw53_32
|
||||
platform: x86
|
||||
build_script:
|
||||
- dir
|
||||
- mkdir build
|
||||
- cd build
|
||||
- set PATH=%PATH%;%QTDIR%\bin;C:\Qt\Tools\mingw530_32\bin;C:\MinGW\msys\1.0\bin
|
||||
- git submodule update --init --recursive
|
||||
- curl -kLO https://ffmpeg.zeranoe.com/builds/win64/dev/ffmpeg-3.3.2-win64-dev.zip
|
||||
- 7z x ffmpeg-3.3.2-win64-dev.zip
|
||||
- set FFMPEG_DEV_PATH=%CD%\ffmpeg-3.3.2-win64-dev
|
||||
- curl -kLO https://ffmpeg.zeranoe.com/builds/win64/shared/ffmpeg-3.3.2-win64-shared.zip
|
||||
- 7z x ffmpeg-3.3.2-win64-shared.zip
|
||||
- set FFMPEG_SHARED_PATH=%cd%\ffmpeg-3.3.2-win64-shared
|
||||
- curl -v -L --http1.1 --tlsv1.2 "https://downloads.sourceforge.net/project/qtav/depends/QtAV-depends-windows-x86+x64.7z" -o av.7z
|
||||
- 7z x av.7z > NUL
|
||||
- xcopy ffmpeg-3.3.2-win64-shared\* %QTDIR% /e /i /Y
|
||||
- xcopy ffmpeg-3.3.2-win64-dev\* %QTDIR% /e /i /Y
|
||||
- xcopy QtAV-depends-windows-x86+x64\* %QTDIR% /e /i /Y
|
||||
- qmake CONFIG+=nopkg ../KShare.pro
|
||||
- mingw32-make.exe -j%NUMBER_OF_PROCESSORS%
|
||||
- copy src\release\kshare.exe ..\KShare.exe
|
||||
- cd ..
|
||||
- bash AppVeyor\make_installer.sh
|
||||
artifacts:
|
||||
- path: KShare.exe
|
||||
name: Shared link
|
||||
- path: installer.exe
|
||||
name: Installer
|
||||
- path: portable.zip
|
||||
name: Portable version
|
37
README.md
37
README.md
|
@ -2,17 +2,31 @@
|
|||
A [ShareX](https://getsharex.com/) inspired cross platform utility written with Qt.
|
||||
Originally written by [ArsenArsen](https://github.com/ArsenArsen) and here enhanced with [these](https://github.com/Gurkengewuerz/KShare/projects/1) features.
|
||||
|
||||
| | Linux | Windows |
|
||||
|--------|-------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| master | [![CircleCI](https://circleci.com/gh/Gurkengewuerz/KShare/tree/master.svg?style=svg)](https://circleci.com/gh/Gurkengewuerz/KShare/tree/master) | [![Build status](https://ci.appveyor.com/api/projects/status/ujxmg1dk7f5p8ijh/branch/master?svg=true)](https://ci.appveyor.com/project/Gurkengewuerz/kshare/branch/master) |
|
||||
| dev | [![CircleCI](https://circleci.com/gh/Gurkengewuerz/KShare/tree/dev.svg?style=svg)](https://circleci.com/gh/Gurkengewuerz/KShare/tree/dev) | [![Build status](https://ci.appveyor.com/api/projects/status/ujxmg1dk7f5p8ijh/branch/dev?svg=true)](https://ci.appveyor.com/project/Gurkengewuerz/kshare/branch/dev) |
|
||||
## Buildstatus (Arch, Ubuntu/Debian and Windows (MXE))
|
||||
**master**|**dev**
|
||||
:-----:|:-----:
|
||||
[![Build Status](https://giteaci.mc8051.de/api/badges/Gurkengewuerz/KShare/status.svg?ref=refs/heads/master)](https://giteaci.mc8051.de/Gurkengewuerz/KShare)| [![Build Status](https://giteaci.mc8051.de/api/badges/Gurkengewuerz/KShare/status.svg?ref=refs/heads/dev)](https://giteaci.mc8051.de/Gurkengewuerz/KShare)
|
||||
|
||||
[Artifacts](https://artifacts.mc8051.de/Gurkengewuerz/KShare)
|
||||
|
||||
## Screenshot
|
||||
Made with KShare itself, of course :)
|
||||
![](https://i.imgur.com/oJrCNkq.png)
|
||||
|
||||
## 🎉 Features
|
||||
* 💻 open source
|
||||
* 🪶 lightweight
|
||||
* 🖧 cross-platform
|
||||
* 🔍 magnifying lense for image capture
|
||||
* ⌨️ customizable keyboard shortcuts
|
||||
* ✒️ image annotation (_rectangle_, _ellipse_, _freehand_, _line_, _arrow_, _text_)
|
||||
* 📂 upload screenshots, files, clipboard or text
|
||||
* 🤏 color picker
|
||||
* 📤 multiple destinations implemented (_imgur_, _gdrive_, _clipboard_)
|
||||
* 🔧 custom uploader (_works perfectly with ![**php_filehost**](https://github.com/Gurkengewuerz/php_filehost)_)
|
||||
* 🖌️ themes (_dark_, ![_breeze dark_, _breeze light_](https://github.com/Alexhuszagh/BreezeStyleSheets), ![_qdarkstyle_](https://github.com/ColinDuquesnoy/QDarkStyleSheet))
|
||||
|
||||
## Usage
|
||||
See the [wiki](https://github.com/ArsenArsen/KShare/wiki).
|
||||
Please note that KShare is not compatiable with Wayland due to some permission issues. Please use X.Org instead.
|
||||
|
||||
## Dependencies
|
||||
|
@ -36,18 +50,13 @@ Additionally, on Linux, you require:
|
|||
Despite the name implying so, this project does not depend on the KDE API at all.
|
||||
|
||||
## Install
|
||||
|Distro|Link|
|
||||
|:----:|:--:|
|
||||
|Arch Linux (development)|[kshare-git](https://aur.archlinux.org/packages/kshare-git/)|
|
||||
|Ubuntu/Debian (development)|[.deb](https://nativeci.arsenarsen.com/job/KShare%20\(dev\)/main=linux/lastSuccessfulBuild/artifact/packages/simpleName.deb)|
|
||||
|Arch Linux |[kshare](https://aur.archlinux.org/packages/kshare/)|
|
||||
|Ubuntu/Debian |[.deb](https://nativeci.arsenarsen.com/job/KShare%20\(master\)/main=linux/lastSuccessfulBuild/artifact/packages/simpleName.deb)|
|
||||
Download the development versions for Arch Linux, Ubuntu/Debian and Windows [here](https://artifacts.mc8051.de/Gurkengewuerz/KShare/dev/). The stable/master branch is available [here](https://artifacts.mc8051.de/Gurkengewuerz/KShare/master/).
|
||||
|
||||
For other UNIX-like platforms, and MSYS2 (for Windows):
|
||||
|
||||
You have to obtain the dependencies though.
|
||||
```bash
|
||||
git clone --recursive https://github.com/ArsenArsen/KShare.git
|
||||
git clone --recursive https://github.com/Gurkengewuerz/KShare.git
|
||||
cd KShare
|
||||
qmake # Might be qmake-qt5 on your system
|
||||
make
|
||||
|
@ -55,8 +64,6 @@ make
|
|||
|
||||
On systems with FFMpeg pre-3.1 you need to apply `OlderSystemFix.patch` to `src/recording/encoders/encoder.cpp`.
|
||||
On systems with Qt pre-5.7 you need to install the Qt version from their website.
|
||||
You can attempt to `curl https://raw.githubusercontent.com/ArsenArsen/KShare/master/install.sh | bash`
|
||||
|
||||
You can find more details [here](https://blog.arsenarsen.com/posts/compiling-kshare-on-linux-mac-os-x-and-windows-final-revision)
|
||||
You can attempt to `curl https://raw.githubusercontent.com/Gurkengewuerz/KShare/master/install.sh | bash`
|
||||
|
||||
###### Started on 19th of April 2017 by [ArsenArsen](https://github.com/ArsenArsen) to bring some attention and improvement to Linux screenshotting.
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
kshare.arsenarsen.com
|
|
@ -1,3 +0,0 @@
|
|||
source 'https://rubygems.org'
|
||||
|
||||
gem "github-pages", group: :jekyll_plugins
|
|
@ -1,216 +0,0 @@
|
|||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
activesupport (4.2.8)
|
||||
i18n (~> 0.7)
|
||||
minitest (~> 5.1)
|
||||
thread_safe (~> 0.3, >= 0.3.4)
|
||||
tzinfo (~> 1.1)
|
||||
addressable (2.5.1)
|
||||
public_suffix (~> 2.0, >= 2.0.2)
|
||||
coffee-script (2.4.1)
|
||||
coffee-script-source
|
||||
execjs
|
||||
coffee-script-source (1.12.2)
|
||||
colorator (1.1.0)
|
||||
ethon (0.10.1)
|
||||
ffi (>= 1.3.0)
|
||||
execjs (2.7.0)
|
||||
faraday (0.13.0)
|
||||
multipart-post (>= 1.2, < 3)
|
||||
ffi (1.9.18)
|
||||
forwardable-extended (2.6.0)
|
||||
gemoji (3.0.0)
|
||||
github-pages (155)
|
||||
activesupport (= 4.2.8)
|
||||
github-pages-health-check (= 1.3.5)
|
||||
jekyll (= 3.5.2)
|
||||
jekyll-avatar (= 0.4.2)
|
||||
jekyll-coffeescript (= 1.0.1)
|
||||
jekyll-default-layout (= 0.1.4)
|
||||
jekyll-feed (= 0.9.2)
|
||||
jekyll-gist (= 1.4.1)
|
||||
jekyll-github-metadata (= 2.8.0)
|
||||
jekyll-mentions (= 1.2.0)
|
||||
jekyll-optional-front-matter (= 0.2.0)
|
||||
jekyll-paginate (= 1.1.0)
|
||||
jekyll-readme-index (= 0.1.0)
|
||||
jekyll-redirect-from (= 0.12.1)
|
||||
jekyll-relative-links (= 0.4.1)
|
||||
jekyll-sass-converter (= 1.5.0)
|
||||
jekyll-seo-tag (= 2.2.3)
|
||||
jekyll-sitemap (= 1.0.0)
|
||||
jekyll-swiss (= 0.4.0)
|
||||
jekyll-theme-architect (= 0.1.0)
|
||||
jekyll-theme-cayman (= 0.1.0)
|
||||
jekyll-theme-dinky (= 0.1.0)
|
||||
jekyll-theme-hacker (= 0.1.0)
|
||||
jekyll-theme-leap-day (= 0.1.0)
|
||||
jekyll-theme-merlot (= 0.1.0)
|
||||
jekyll-theme-midnight (= 0.1.0)
|
||||
jekyll-theme-minimal (= 0.1.0)
|
||||
jekyll-theme-modernist (= 0.1.0)
|
||||
jekyll-theme-primer (= 0.5.0)
|
||||
jekyll-theme-slate (= 0.1.0)
|
||||
jekyll-theme-tactile (= 0.1.0)
|
||||
jekyll-theme-time-machine (= 0.1.0)
|
||||
jekyll-titles-from-headings (= 0.4.0)
|
||||
jemoji (= 0.8.0)
|
||||
kramdown (= 1.13.2)
|
||||
liquid (= 4.0.0)
|
||||
listen (= 3.0.6)
|
||||
mercenary (~> 0.3)
|
||||
minima (= 2.1.1)
|
||||
rouge (= 1.11.1)
|
||||
terminal-table (~> 1.4)
|
||||
github-pages-health-check (1.3.5)
|
||||
addressable (~> 2.3)
|
||||
net-dns (~> 0.8)
|
||||
octokit (~> 4.0)
|
||||
public_suffix (~> 2.0)
|
||||
typhoeus (~> 0.7)
|
||||
html-pipeline (2.7.0)
|
||||
activesupport (>= 2)
|
||||
nokogiri (>= 1.4)
|
||||
i18n (0.8.6)
|
||||
jekyll (3.5.2)
|
||||
addressable (~> 2.4)
|
||||
colorator (~> 1.0)
|
||||
jekyll-sass-converter (~> 1.0)
|
||||
jekyll-watch (~> 1.1)
|
||||
kramdown (~> 1.3)
|
||||
liquid (~> 4.0)
|
||||
mercenary (~> 0.3.3)
|
||||
pathutil (~> 0.9)
|
||||
rouge (~> 1.7)
|
||||
safe_yaml (~> 1.0)
|
||||
jekyll-avatar (0.4.2)
|
||||
jekyll (~> 3.0)
|
||||
jekyll-coffeescript (1.0.1)
|
||||
coffee-script (~> 2.2)
|
||||
jekyll-default-layout (0.1.4)
|
||||
jekyll (~> 3.0)
|
||||
jekyll-feed (0.9.2)
|
||||
jekyll (~> 3.3)
|
||||
jekyll-gist (1.4.1)
|
||||
octokit (~> 4.2)
|
||||
jekyll-github-metadata (2.8.0)
|
||||
jekyll (~> 3.1)
|
||||
octokit (~> 4.0, != 4.4.0)
|
||||
jekyll-mentions (1.2.0)
|
||||
activesupport (~> 4.0)
|
||||
html-pipeline (~> 2.3)
|
||||
jekyll (~> 3.0)
|
||||
jekyll-optional-front-matter (0.2.0)
|
||||
jekyll (~> 3.0)
|
||||
jekyll-paginate (1.1.0)
|
||||
jekyll-readme-index (0.1.0)
|
||||
jekyll (~> 3.0)
|
||||
jekyll-redirect-from (0.12.1)
|
||||
jekyll (~> 3.3)
|
||||
jekyll-relative-links (0.4.1)
|
||||
jekyll (~> 3.3)
|
||||
jekyll-sass-converter (1.5.0)
|
||||
sass (~> 3.4)
|
||||
jekyll-seo-tag (2.2.3)
|
||||
jekyll (~> 3.3)
|
||||
jekyll-sitemap (1.0.0)
|
||||
jekyll (~> 3.3)
|
||||
jekyll-swiss (0.4.0)
|
||||
jekyll-theme-architect (0.1.0)
|
||||
jekyll (~> 3.5)
|
||||
jekyll-seo-tag (~> 2.0)
|
||||
jekyll-theme-cayman (0.1.0)
|
||||
jekyll (~> 3.5)
|
||||
jekyll-seo-tag (~> 2.0)
|
||||
jekyll-theme-dinky (0.1.0)
|
||||
jekyll (~> 3.5)
|
||||
jekyll-seo-tag (~> 2.0)
|
||||
jekyll-theme-hacker (0.1.0)
|
||||
jekyll (~> 3.5)
|
||||
jekyll-seo-tag (~> 2.0)
|
||||
jekyll-theme-leap-day (0.1.0)
|
||||
jekyll (~> 3.5)
|
||||
jekyll-seo-tag (~> 2.0)
|
||||
jekyll-theme-merlot (0.1.0)
|
||||
jekyll (~> 3.5)
|
||||
jekyll-seo-tag (~> 2.0)
|
||||
jekyll-theme-midnight (0.1.0)
|
||||
jekyll (~> 3.5)
|
||||
jekyll-seo-tag (~> 2.0)
|
||||
jekyll-theme-minimal (0.1.0)
|
||||
jekyll (~> 3.5)
|
||||
jekyll-seo-tag (~> 2.0)
|
||||
jekyll-theme-modernist (0.1.0)
|
||||
jekyll (~> 3.5)
|
||||
jekyll-seo-tag (~> 2.0)
|
||||
jekyll-theme-primer (0.5.0)
|
||||
jekyll (~> 3.5)
|
||||
jekyll-seo-tag (~> 2.2)
|
||||
jekyll-theme-slate (0.1.0)
|
||||
jekyll (~> 3.5)
|
||||
jekyll-seo-tag (~> 2.0)
|
||||
jekyll-theme-tactile (0.1.0)
|
||||
jekyll (~> 3.5)
|
||||
jekyll-seo-tag (~> 2.0)
|
||||
jekyll-theme-time-machine (0.1.0)
|
||||
jekyll (~> 3.5)
|
||||
jekyll-seo-tag (~> 2.0)
|
||||
jekyll-titles-from-headings (0.4.0)
|
||||
jekyll (~> 3.3)
|
||||
jekyll-watch (1.5.0)
|
||||
listen (~> 3.0, < 3.1)
|
||||
jemoji (0.8.0)
|
||||
activesupport (~> 4.0)
|
||||
gemoji (~> 3.0)
|
||||
html-pipeline (~> 2.2)
|
||||
jekyll (>= 3.0)
|
||||
kramdown (1.13.2)
|
||||
liquid (4.0.0)
|
||||
listen (3.0.6)
|
||||
rb-fsevent (>= 0.9.3)
|
||||
rb-inotify (>= 0.9.7)
|
||||
mercenary (0.3.6)
|
||||
mini_portile2 (2.2.0)
|
||||
minima (2.1.1)
|
||||
jekyll (~> 3.3)
|
||||
minitest (5.10.3)
|
||||
multipart-post (2.0.0)
|
||||
net-dns (0.8.0)
|
||||
nokogiri (1.8.0)
|
||||
mini_portile2 (~> 2.2.0)
|
||||
octokit (4.7.0)
|
||||
sawyer (~> 0.8.0, >= 0.5.3)
|
||||
pathutil (0.14.0)
|
||||
forwardable-extended (~> 2.6)
|
||||
public_suffix (2.0.5)
|
||||
rb-fsevent (0.10.2)
|
||||
rb-inotify (0.9.10)
|
||||
ffi (>= 0.5.0, < 2)
|
||||
rouge (1.11.1)
|
||||
safe_yaml (1.0.4)
|
||||
sass (3.5.1)
|
||||
sass-listen (~> 4.0.0)
|
||||
sass-listen (4.0.0)
|
||||
rb-fsevent (~> 0.9, >= 0.9.4)
|
||||
rb-inotify (~> 0.9, >= 0.9.7)
|
||||
sawyer (0.8.1)
|
||||
addressable (>= 2.3.5, < 2.6)
|
||||
faraday (~> 0.8, < 1.0)
|
||||
terminal-table (1.8.0)
|
||||
unicode-display_width (~> 1.1, >= 1.1.1)
|
||||
thread_safe (0.3.6)
|
||||
typhoeus (0.8.0)
|
||||
ethon (>= 0.8.0)
|
||||
tzinfo (1.2.3)
|
||||
thread_safe (~> 0.1)
|
||||
unicode-display_width (1.3.0)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
|
||||
DEPENDENCIES
|
||||
github-pages
|
||||
|
||||
BUNDLED WITH
|
||||
1.15.3
|
|
@ -1,2 +0,0 @@
|
|||
theme: jekyll-theme-minimal
|
||||
categories: [wiki]
|
|
@ -1,66 +0,0 @@
|
|||
<!doctype html>
|
||||
<html lang="{{ site.lang | default: "en-US" }}">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="chrome=1">
|
||||
|
||||
{% seo %}
|
||||
|
||||
<link rel="stylesheet" href="{{ '/assets/css/style.css?v=' | append: site.github.build_revision | relative_url }}">
|
||||
<meta name="viewport" content="width=device-width">
|
||||
<!--[if lt IE 9]>
|
||||
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
|
||||
<![endif]-->
|
||||
</head>
|
||||
<body>
|
||||
<div class="wrapper">
|
||||
<header>
|
||||
<h1>{{ site.title | default: site.github.repository_name }}</h1>
|
||||
<p>{{ site.description | default: site.github.project_tagline }}</p>
|
||||
<p><a href="/wiki">Click here to visit the wiki</a></p>
|
||||
|
||||
{% if site.github.is_project_page %}
|
||||
<p class="view"><a href="{{ site.github.repository_url }}">View the Project on GitHub <small>{{ github_name }}</small></a></p>
|
||||
{% endif %}
|
||||
|
||||
{% if site.github.is_user_page %}
|
||||
<p class="view"><a href="{{ site.github.owner_url }}">View My GitHub Profile</a></p>
|
||||
{% endif %}
|
||||
|
||||
{% if site.show_downloads %}
|
||||
<ul>
|
||||
<li><a href="{{ site.github.zip_url }}">Download <strong>ZIP File</strong></a></li>
|
||||
<li><a href="{{ site.github.tar_url }}">Download <strong>TAR Ball</strong></a></li>
|
||||
<li><a href="{{ site.github.repository_url }}">View On <strong>GitHub</strong></a></li>
|
||||
</ul>
|
||||
{% endif %}
|
||||
</header>
|
||||
<section>
|
||||
|
||||
{{ content }}
|
||||
|
||||
</section>
|
||||
<footer>
|
||||
<p>Copyright (c) ArsenArsen 2017</p>
|
||||
{% if site.github.is_project_page %}
|
||||
<p>This project is maintained by <a href="{{ site.github.owner_url }}">{{ site.github.owner_name }}</a></p>
|
||||
{% endif %}
|
||||
<p><small>Hosted on GitHub Pages — Theme by <a href="https://github.com/orderedlist">orderedlist</a></small></p>
|
||||
</footer>
|
||||
</div>
|
||||
<script src="{{ '/assets/js/scale.fix.js' | relative_url }}"></script>
|
||||
|
||||
|
||||
{% if site.google_analytics %}
|
||||
<script>
|
||||
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
||||
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
||||
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
||||
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
|
||||
|
||||
ga('create', '{{ site.google_analytics }}', 'auto');
|
||||
ga('send', 'pageview');
|
||||
</script>
|
||||
{% endif %}
|
||||
</body>
|
||||
</html>
|
|
@ -1,75 +0,0 @@
|
|||
<!doctype html>
|
||||
<html lang="{{ site.lang | default: "en-US" }}">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="chrome=1">
|
||||
|
||||
{% seo %}
|
||||
|
||||
<link rel="stylesheet" href="{{ '/assets/css/style.css?v=' | append: site.github.build_revision | relative_url }}">
|
||||
<meta name="viewport" content="width=device-width">
|
||||
<!--[if lt IE 9]>
|
||||
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
|
||||
<![endif]-->
|
||||
</head>
|
||||
<body>
|
||||
<div class="wrapper">
|
||||
<header>
|
||||
<h1>{{ site.title | default: site.github.repository_name }}</h1>
|
||||
<p>{{ site.description | default: site.github.project_tagline }}</p>
|
||||
<p><a href="/">Click here to go back to the homepage</a></p>
|
||||
|
||||
{% for page in site.pages %}
|
||||
{% if page.categories contains 'wiki' %}
|
||||
<a href="{{ page.url }}">{{ page.title }}</a><br />
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
|
||||
<br />
|
||||
<br />
|
||||
{% if site.github.is_project_page %}
|
||||
<p class="view"><a href="{{ site.github.repository_url }}">View the Project on GitHub <small>{{ github_name }}</small></a></p>
|
||||
{% endif %}
|
||||
|
||||
{% if site.github.is_user_page %}
|
||||
<p class="view"><a href="{{ site.github.owner_url }}">View My GitHub Profile</a></p>
|
||||
{% endif %}
|
||||
|
||||
{% if site.show_downloads %}
|
||||
<ul>
|
||||
<li><a href="{{ site.github.zip_url }}">Download <strong>ZIP File</strong></a></li>
|
||||
<li><a href="{{ site.github.tar_url }}">Download <strong>TAR Ball</strong></a></li>
|
||||
<li><a href="{{ site.github.repository_url }}">View On <strong>GitHub</strong></a></li>
|
||||
</ul>
|
||||
{% endif %}
|
||||
</header>
|
||||
<section>
|
||||
|
||||
{{ content }}
|
||||
|
||||
</section>
|
||||
<footer>
|
||||
<p>Copyright (c) ArsenArsen 2017</p>
|
||||
{% if site.github.is_project_page %}
|
||||
<p>This project is maintained by <a href="{{ site.github.owner_url }}">{{ site.github.owner_name }}</a></p>
|
||||
{% endif %}
|
||||
<p><small>Hosted on GitHub Pages — Theme by <a href="https://github.com/orderedlist">orderedlist</a></small></p>
|
||||
</footer>
|
||||
</div>
|
||||
<script src="{{ '/assets/js/scale.fix.js' | relative_url }}"></script>
|
||||
|
||||
|
||||
{% if site.google_analytics %}
|
||||
<script>
|
||||
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
||||
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
||||
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
||||
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
|
||||
|
||||
ga('create', '{{ site.google_analytics }}', 'auto');
|
||||
ga('send', 'pageview');
|
||||
</script>
|
||||
{% endif %}
|
||||
</body>
|
||||
</html>
|
|
@ -1,13 +0,0 @@
|
|||
---
|
||||
---
|
||||
|
||||
@import "{{ site.theme }}";
|
||||
|
||||
/* stupid css killed the cat */
|
||||
header ul {
|
||||
background: none;
|
||||
border-radius: 0px;
|
||||
border: 0px solid #e0e0e0;
|
||||
|
||||
|
||||
}
|
|
@ -1,54 +0,0 @@
|
|||
---
|
||||
layout: layout
|
||||
---
|
||||
|
||||
|
||||
# **KShare**
|
||||
## The free open source and cross platform screen sharing software
|
||||
|
||||
KShare is a screenshotting utility built using Qt and written in C++.
|
||||
It has many features, including:
|
||||
* Area capture,
|
||||
* Fullscreen capture,
|
||||
* Active window capture,
|
||||
* Magnifier, to make those aligments,
|
||||
* Drawing on screenshots (blur, shapes, text, ...),
|
||||
* Recording,
|
||||
* Highly customizable video codecs,
|
||||
* Automatic upload/clipboard copying,
|
||||
* Hotkeys,
|
||||
* Color picker, and last but not least,
|
||||
* Custom upload destinations,
|
||||
* Upload from clipboard,
|
||||
* Upload History,
|
||||
* Crossplatform,
|
||||
* Windows 10 Darkmode
|
||||
|
||||
## Enough talking, show us how it looks
|
||||
The main window is rather simple, with only a log, and a button in it:
|
||||
![image1](https://i.imgur.com/Tnrj90b.png)
|
||||
|
||||
The settings have quite a bit more going on:
|
||||
![image2](https://i.imgur.com/GFN2jCU.png)
|
||||
|
||||
The area selection editor is simple:
|
||||
![image3](https://i.imgur.com/Cbi8YsL.png)
|
||||
|
||||
And the color picker is the simplest thing ever:
|
||||
![image4](http://i.imgur.com/VIeGbdQ.jpg)
|
||||
|
||||
The way you select the area to record is by resizing this simple widget:
|
||||
![image5](http://i.imgur.com/0iXFHnm.png)
|
||||
|
||||
And when you start recording there is a simple preview shown:
|
||||
![image6](http://i.imgur.com/6fu33TR.png)
|
||||
|
||||
## Download
|
||||
Currently, the only good download I provide is for Arch Linux and Ubuntu 17.04
|
||||
The Arch download is on the AUR as `kshare` and `kshare-git`,
|
||||
The OS X and Debian/Ubuntu builds can be found here: [CI](https://nativeci.arsenarsen.com/job/KShare%20(master\))
|
||||
There is a windows build on [AppVeyor]()
|
||||
|
||||
## Wait.. how do I actually use this?
|
||||
|
||||
Here is the wiki: [`ding`](https://github.com/ArsenArsen/KShare/wiki)
|
|
@ -1,42 +0,0 @@
|
|||
---
|
||||
title: Basic Usage
|
||||
categories: [wiki]
|
||||
layout: wikipage
|
||||
---
|
||||
# Basic usage
|
||||
When you start the app (with no arguments, discussed later) a window is popped up, and a tray icon is made.
|
||||
|
||||
## The window
|
||||
![](http://i.imgur.com/QOebwEM.png)
|
||||
|
||||
The main window is a log window with a settings button.
|
||||
|
||||
The menu bar has a `File` menu. It has two options, `Quit`, which exits ~~no need to press it :^)~~, and `About`, which contains licensing information:
|
||||
![](http://i.imgur.com/4fVJb1w.png)
|
||||
|
||||
There is a second menu, namely `Screenshot`. It has two options, area, and fullscreen capture. See below.
|
||||
|
||||
The third, `Utility`, menu has the color picker in it.
|
||||
|
||||
The fourth and final menu, `Recording`, has a start and stop recording button.
|
||||
|
||||
## The tray
|
||||
![](http://i.imgur.com/quVDzRN.png)
|
||||
|
||||
The tray consists of a small, but nice, icon made by @BriannaFoxwell. Upon right clicking it you get the context menu shown above. The menu is rather simple, containing basic controls, and screenshotting options.
|
||||
These options will be explained below.
|
||||
|
||||
## Screenshotting options
|
||||
### Area capture
|
||||
Area capture takes a snapshot of the screen, and shows you a fullscreen editor for you to select a region in. This editor is explained in a section below.
|
||||
|
||||
### Fullscreen capture
|
||||
Fullscreen capture takes a snapshot of the entire screen and skips the editor part. Straight to the destination (explained later as well).
|
||||
|
||||
### Active window capture
|
||||
Takes the active window and uploads it straight to your destination of choice
|
||||
|
||||
## Crop Editor
|
||||
Crop Editor is a window you can use to select the area of the screen to upload. It consists of a grey overlay and a re-sizable rectangle. The rectangle is resized by holding the mouse buttons. When you let go of the button, a new selection will start replacing the old one. On the first press the same thing happens.
|
||||
Press `Escape` to cancel, and `Return`, or `Enter` to submit.
|
||||
Oh. And you can draw with the bar that appears on the top.
|
|
@ -1,45 +0,0 @@
|
|||
---
|
||||
title: Destinations
|
||||
categories: [wiki]
|
||||
layout: wikipage
|
||||
---
|
||||
# Destinations
|
||||
Destinations determine where your image goes
|
||||
|
||||
There is a set of default uploaders, two, to be exact.
|
||||
## Default uploaders:
|
||||
### imgur
|
||||
Uploads your image to imgur.
|
||||
### clipboard
|
||||
Copies your image to clipboard.
|
||||
|
||||
## Custom uploaders
|
||||
Placed into `CONFIG PATH/KShare/uploaders`
|
||||
Eg: `$HOME/.config/KShare/uploaders`
|
||||
All uploaders have to be `.uploader` files!
|
||||
Custom uploaders can be added, and are made with JSON, and follow this template:
|
||||
```js
|
||||
{
|
||||
"name": "", // String, required
|
||||
"desc": "", // String, optional
|
||||
"method": "", // String, default: "POST", for now, just POST. Request more if you need them
|
||||
"target": "", // URL, required
|
||||
"format": "", // String, default: "json", can be `x-www-form-urlencoded` or `json` or `multipart-form-data`. Setting to `PLAIN` will make the body ignored and only the image sent.
|
||||
"base64": false, // Optional, makes the data base64
|
||||
"body": {}, // A JSON object, where one of the nodes can be a string in the format `/ANYTHING/`. In `ANYTHING`, `%contenttype` is replaced with the image type and `%imagedata` is replaced with the image encoded with `imageformat`. Unless you use multipart, see below
|
||||
"return": "" // Return pathspec. `|` copies the entire body, `.path.to.node` copies the value of the node. The dot IS IMPORTANT. Without it, nothing happens. If one of the nodes is not a string, the string is copied, if one is an object, recursion continues, if one is null, nothing is copied, otherwise the node is JSON stringified. Only supports JSON for now.
|
||||
}
|
||||
```
|
||||
Note that QJson does not support comments.
|
||||
### Multipart
|
||||
Multipart is obviously made out of multiple parts. The way you define a multipart body is:
|
||||
```js
|
||||
[
|
||||
{
|
||||
"__HeaderName": "HeaderValue", // No limit here. Must start with __, which is removed later.
|
||||
"body": { /* same way you define it for anything json */ }, // Can be string. Strings matching `/.../` are processed same way as in a json field.
|
||||
"name": "files[]" // Info to add to Content-Disposition (eg part name, filename, ...)
|
||||
}
|
||||
]
|
||||
```
|
||||
This would go in the `body` field of the above JSON.
|
|
@ -1,29 +0,0 @@
|
|||
---
|
||||
title: Encoder Settings
|
||||
categories: [wiki]
|
||||
layout: wikipage
|
||||
---
|
||||
# Encoder settings
|
||||
The encoders used can be customized to a high degree. Every encoder besides GIF has some settings.
|
||||
![](http://i.imgur.com/O8nfeos.png)
|
||||
|
||||
## Image encoder settings
|
||||
The only option here is quality, by default it uses the default for the format you use. You can change it by unticking format default. [More info](http://doc.qt.io/qt-5/qpixmap.html#save)
|
||||
|
||||
## Video encoder settings
|
||||
The common settings are bitrate and GOP size.
|
||||
|
||||
GOP Size is the size of a group of pictures.
|
||||
Bitrate is the target bitrate.
|
||||
|
||||
### h264/h265
|
||||
The H.26[45] MP4 codec has a few presets to choose. The recommended is to choose the slowest one you can cope with.
|
||||
I recommend medium.
|
||||
|
||||
CRF is the constant rate factor of this video stream, and again I recommend leaving the default value, `23`.
|
||||
|
||||
### VP9
|
||||
VP9 is the WebP codec. Only option it has is lossless encoding, and you want it off, trust me.
|
||||
|
||||
### GIF
|
||||
GIF has no options. It's terrible whatever you do to it.
|
|
@ -1,23 +0,0 @@
|
|||
---
|
||||
title: Hotkeys
|
||||
categories: [wiki]
|
||||
layout: wikipage
|
||||
---
|
||||
# Hotkeys
|
||||
Hotkeys are configured in the settings UI.
|
||||
![](http://i.imgur.com/esYoMWo.png)
|
||||
Currently available hotkeys are:
|
||||
## Fullscreen image
|
||||
This bind lets you take a fullscreen image and upload it instantly.
|
||||
## Area image
|
||||
Equivalent to `Take area shot` and `Screenshot -> Area`. Takes a snapshot and opens the crop editor.
|
||||
## Active window
|
||||
Equivalent to `Active window` and `Screenshot -> Active window`. Takes a snapshot of the active window and sends it.
|
||||
## Color picker
|
||||
Opens the color picker
|
||||
## Recording start/stop
|
||||
Starts and stops recording
|
||||
|
||||
## Editing hotkeys
|
||||
All binds can be modified using by double clicking the hotkey name.
|
||||
You can either type the hotkey in or press record and press the key combination you want on your keyboard
|
|
@ -1,23 +0,0 @@
|
|||
---
|
||||
title: Settings
|
||||
categories: [wiki]
|
||||
layout: wikipage
|
||||
---
|
||||
# Settings
|
||||
## Destination
|
||||
![](http://i.imgur.com/540REFK.png)
|
||||
Select the active destination. Adding more is possible and explained it Custom Uploaders
|
||||
**Default:** `imgur`
|
||||
## Filename scheme
|
||||
![](http://i.imgur.com/RHHEO3K.png)
|
||||
Used to generate filenames. Extensions are placed in place of `%ext`. `%(DATE FORMAT)date` can be used to replace the date format with a format as specified by [this documentation page](http://doc.qt.io/qt-5/qdatetime.html#toString)
|
||||
**Default:** `Screenshot %(yyyy-MM-dd HH-mm-ss)date.%ext`
|
||||
## Delay before taking a screenshot
|
||||
![](http://i.imgur.com/j0D7OqI.png)
|
||||
Applies only to the buttons in menus. Hotkeys do not follow this rule. In seconds. Mostly used to let animations fade.
|
||||
Min: `0.00`
|
||||
Max: `99.99`
|
||||
**Default:** `0.25`
|
||||
|
||||
## Hotkeys
|
||||
**Explained on a separate page.**
|
|
@ -1,34 +0,0 @@
|
|||
---
|
||||
title: Tools
|
||||
categories: [wiki]
|
||||
layout: wikipage
|
||||
---
|
||||
# Drawing
|
||||
![](http://i.imgur.com/5nWhpqw.png)
|
||||
On-screen drawing is pretty simple. Right click in the crop editor to show a pen selection tool. When you click on a pen it will stay selected until you press `Reset`.
|
||||
|
||||
You can move drawings around by Ctrl+Dragging them
|
||||
|
||||
## Available pens:
|
||||
### Free draw (pen icon)
|
||||
Makes a path where your mouse went.
|
||||
### Blur (badly made blurred rectangle icon)
|
||||
Allows you to set a rectangle to blur out.
|
||||
### Straight line
|
||||
A line between where you start and end dragging
|
||||
### Text
|
||||
Asks you to insert some text.
|
||||
**WARNING:** Avoid pressing esc
|
||||
### Rectangle
|
||||
Drag to draw a rectangle
|
||||
### Ellipse
|
||||
Drag to draw an ellipse
|
||||
### Arrow
|
||||
Draws an arrow from start to end of your drag
|
||||
### Eraser[](https://www.youtube.com/watch?v=OjGrcJ4lZCc)
|
||||
Removes all items you drag your mouse over
|
||||
|
||||
### Clear all drawings
|
||||
Removes all drawings
|
||||
### Reset
|
||||
Allows you to choose a region to cut for the final result.
|
|
@ -1,11 +0,0 @@
|
|||
---
|
||||
title: Index
|
||||
categories: [wiki]
|
||||
layout: wikipage
|
||||
---
|
||||
|
||||
# Welcome to the KShare wiki!
|
||||
The cross platform screenshotting utility
|
||||
|
||||
# Usage
|
||||
See the [`Basic usage`](/wiki/Basic-Usage.html) page
|
|
@ -1,6 +1,6 @@
|
|||
# Maintainer: Gurkengewuerz <niklas@mc8051.de>
|
||||
pkgname=kshare-git
|
||||
pkgver=v4.1.r196.gc38161b
|
||||
pkgver=v5.0.4+dev
|
||||
pkgrel=1
|
||||
pkgdesc="The free and open source and cross platform screen sharing software."
|
||||
arch=('i686' 'x86_64')
|
||||
|
@ -8,14 +8,14 @@ url="https://github.com/Gurkengewuerz/KShare"
|
|||
license=('MIT')
|
||||
provides=(kshare)
|
||||
conflicts=(kshare)
|
||||
depends=(qt5-base qt5-x11extras qt5-svg xcb-util-cursor ffmpeg libxfixes)
|
||||
depends=(qt5-base qt5-x11extras qt5-svg qt5-multimedia xcb-util-cursor ffmpeg libxfixes)
|
||||
makedepends=(git pkg-config)
|
||||
source=(git+https://github.com/Gurkengewuerz/KShare.git#branch=dev)
|
||||
sha1sums=('SKIP')
|
||||
|
||||
pkgver() {
|
||||
cd KShare
|
||||
echo "v4.1.r196.gc38161b"
|
||||
echo "v5.0.4+dev"
|
||||
}
|
||||
|
||||
prepare() {
|
|
@ -1,6 +1,6 @@
|
|||
# Maintainer: Gurkengewuerz <niklas@mc8051.de>
|
||||
pkgname=kshare
|
||||
pkgver=v5.0.0
|
||||
pkgver=v5.0.4
|
||||
pkgrel=1
|
||||
conflicts=("kshare-git")
|
||||
pkgdesc="The free and open source and cross platform screen sharing software."
|
||||
|
@ -8,7 +8,7 @@ arch=('i686' 'x86_64')
|
|||
url="https://github.com/Gurkengewuerz/KShare"
|
||||
license=('MIT')
|
||||
provides=('kshare=$pkgver')
|
||||
depends=(qt5-base qt5-x11extras qt5-svg xcb-util-cursor ffmpeg libxfixes)
|
||||
depends=(qt5-base qt5-x11extras qt5-svg qt5-multimedia xcb-util-cursor ffmpeg libxfixes)
|
||||
makedepends=(git pkg-config)
|
||||
source=(git+https://github.com/Gurkengewuerz/KShare.git)
|
||||
sha1sums=('SKIP')
|
|
@ -2,7 +2,8 @@
|
|||
VERSION=$(grep setApplicationVersion ../src/main.cpp | head -n1 | cut -d \" -f2)
|
||||
echo "Make Debian package for v$VERSION" >&2
|
||||
|
||||
cp deb work -r
|
||||
mkdir work/ || true
|
||||
cp deb/* work -r
|
||||
sed "s/%ver/$VERSION/g" deb/DEBIAN/control > work/DEBIAN/control
|
||||
mkdir -p work/usr/bin
|
||||
|
||||
|
@ -29,8 +30,10 @@ else
|
|||
fi
|
||||
|
||||
cd work
|
||||
echo "md5sum" >&2
|
||||
md5sum usr/bin/kshare usr/share/applications/KShare.desktop > DEBIAN/md5sums
|
||||
cd ..
|
||||
echo "dpkg-deb" >&2
|
||||
dpkg-deb -b work/
|
||||
mv work.deb kshare_v${VERSION}.deb
|
||||
rm -rf work
|
||||
|
|
|
@ -55,5 +55,6 @@ echo -----------------
|
|||
|
||||
cat installer.iss.pattern.bottom >> installer.iss
|
||||
"C:\Program Files (x86)\Inno Setup 5\ISCC.exe" installer.iss
|
||||
cp Output/setup.exe ../../installer.exe || exit 1
|
||||
cp portable.zip ../../ || exit 2
|
||||
cp Output/setup.exe ../../win_kshare_v${ver}_installer.exe || exit 1
|
||||
cp ../../KShare.exe ../../KShare_v${ver}.exe || exit 1
|
||||
cp portable.zip ../../win_kshare_v${ver}_portable.zip || exit 2
|
|
@ -41,6 +41,14 @@ void hotkeying::load(QString seqName, std::function<void()> func, QString def) {
|
|||
;
|
||||
}
|
||||
|
||||
void hotkeying::clearAll() {
|
||||
for(QString e : hotkeys.keys()) {
|
||||
QHotkey *hk = hotkeys.value(e);
|
||||
hk->setRegistered(false);
|
||||
delete hk;
|
||||
}
|
||||
}
|
||||
|
||||
bool hotkeying::valid(QString seq) {
|
||||
return seq.isEmpty() || !QKeySequence(seq).toString().isEmpty();
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ namespace hotkeying {
|
|||
void hotkey(QString seqName, QKeySequence seq, std::function<void()> func);
|
||||
bool valid(QString seq);
|
||||
void load(QString seqName, std::function<void()> func, QString def = QString());
|
||||
void clearAll();
|
||||
QString sequence(QString seqName);
|
||||
} // namespace hotkeying
|
||||
|
||||
|
|
|
@ -3,11 +3,10 @@
|
|||
#include <QNetworkAccessManager>
|
||||
#include <QNetworkReply>
|
||||
#include <QNetworkRequest>
|
||||
#include <thread>
|
||||
#include <logs/requestlogging.hpp>
|
||||
#include <logs/screenshotfile.h>
|
||||
|
||||
QNetworkAccessManager ioutils::networkManager;
|
||||
QNetworkAccessManager* ioutils::networkManager= new QNetworkAccessManager();
|
||||
|
||||
void ioutils::addLogEntry(QNetworkReply* reply, QByteArray data, QString result, ScreenshotFile sf) {
|
||||
requestlogging::RequestContext ctx;
|
||||
|
@ -38,13 +37,13 @@ void ioutils::postMultipart(QUrl target,
|
|||
for (auto header : headers) {
|
||||
if (header.first.toLower() != "content-type") req.setRawHeader(header.first.toUtf8(), header.second.toUtf8());
|
||||
}
|
||||
QNetworkReply *reply = networkManager.post(req, body);
|
||||
QNetworkReply *reply = networkManager->post(req, body);
|
||||
addTask();
|
||||
QObject::connect(reply, &QNetworkReply::finished, [reply, callback] {
|
||||
removeTask();
|
||||
QByteArray data = reply->readAll();
|
||||
callback(QJsonDocument::fromJson(data), data, reply);
|
||||
delete reply;
|
||||
reply->deleteLater();
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -56,13 +55,13 @@ void ioutils::postMultipartData(QUrl target,
|
|||
for (auto header : headers) {
|
||||
if (header.first.toLower() != "content-type") req.setRawHeader(header.first.toUtf8(), header.second.toUtf8());
|
||||
}
|
||||
QNetworkReply *reply = networkManager.post(req, body);
|
||||
QNetworkReply *reply = networkManager->post(req, body);
|
||||
addTask();
|
||||
QObject::connect(reply, &QNetworkReply::finished, [reply, callback] {
|
||||
removeTask();
|
||||
QByteArray data = reply->readAll();
|
||||
callback(data, reply);
|
||||
delete reply;
|
||||
reply->deleteLater();
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -73,7 +72,7 @@ void ioutils::getJson(QUrl target,
|
|||
for (auto header : headers) {
|
||||
req.setRawHeader(header.first.toUtf8(), header.second.toUtf8());
|
||||
}
|
||||
QNetworkReply *reply = networkManager.get(req);
|
||||
QNetworkReply *reply = networkManager->get(req);
|
||||
addTask();
|
||||
QObject::connect(reply, &QNetworkReply::finished, [reply, callback] {
|
||||
removeTask();
|
||||
|
@ -91,13 +90,13 @@ void ioutils::postJson(QUrl target,
|
|||
for (auto header : headers) {
|
||||
req.setRawHeader(header.first.toUtf8(), header.second.toUtf8());
|
||||
}
|
||||
QNetworkReply *reply = networkManager.post(req, body);
|
||||
QNetworkReply *reply = networkManager->post(req, body);
|
||||
addTask();
|
||||
QObject::connect(reply, &QNetworkReply::finished, [reply, callback] {
|
||||
removeTask();
|
||||
QByteArray data = reply->readAll();
|
||||
callback(QJsonDocument::fromJson(data), data, reply);
|
||||
delete reply;
|
||||
reply->deleteLater();
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -106,13 +105,13 @@ void ioutils::getData(QUrl target, QList<QPair<QString, QString>> headers, std::
|
|||
for (auto header : headers) {
|
||||
req.setRawHeader(header.first.toUtf8(), header.second.toUtf8());
|
||||
}
|
||||
QNetworkReply *reply = networkManager.get(req);
|
||||
QNetworkReply *reply = networkManager->get(req);
|
||||
addTask();
|
||||
QObject::connect(reply, &QNetworkReply::finished, [reply, callback] {
|
||||
removeTask();
|
||||
QByteArray data = reply->readAll();
|
||||
callback(data, reply);
|
||||
delete reply;
|
||||
reply->deleteLater();
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -124,16 +123,19 @@ void ioutils::postData(QUrl target,
|
|||
for (auto header : headers) {
|
||||
req.setRawHeader(header.first.toUtf8(), header.second.toUtf8());
|
||||
}
|
||||
QNetworkReply *reply = networkManager.post(req, body);
|
||||
QNetworkReply *reply = networkManager->post(req, body);
|
||||
addTask();
|
||||
QObject::connect(reply, &QNetworkReply::finished, [reply, callback] {
|
||||
removeTask();
|
||||
QByteArray data = reply->readAll();
|
||||
callback(data, reply);
|
||||
delete reply;
|
||||
reply->deleteLater();
|
||||
});
|
||||
}
|
||||
|
||||
void ioutils::deleteNetworkManger() {
|
||||
delete networkManager;
|
||||
}
|
||||
|
||||
QString ioutils::methodString(QNetworkAccessManager::Operation operation) {
|
||||
switch (operation) {
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
#include <logs/screenshotfile.h>
|
||||
|
||||
namespace ioutils {
|
||||
extern QNetworkAccessManager networkManager;
|
||||
extern QNetworkAccessManager* networkManager;
|
||||
void addLogEntry(QNetworkReply* reply, QByteArray data, QString result, ScreenshotFile sf);
|
||||
void getJson(QUrl target,
|
||||
QList<QPair<QString, QString>> headers,
|
||||
|
@ -28,6 +28,7 @@ namespace ioutils {
|
|||
QList<QPair<QString, QString>> headers,
|
||||
QHttpMultiPart *body,
|
||||
std::function<void(QByteArray, QNetworkReply *)> callback);
|
||||
void deleteNetworkManger();
|
||||
QString methodString(QNetworkAccessManager::Operation operation);
|
||||
QString httpString(int responseCode);
|
||||
} // namespace ioutils
|
||||
|
|
|
@ -74,7 +74,7 @@ int main(int argc, char *argv[]) {
|
|||
a.setQuitOnLastWindowClosed(false);
|
||||
a.setApplicationName("KShare");
|
||||
a.setOrganizationName("ArsenArsen");
|
||||
a.setApplicationVersion("5.0.0");
|
||||
a.setApplicationVersion("5.0.4");
|
||||
|
||||
QString locale = QLocale::system().name();
|
||||
if (locale != "en_US") loadTranslation(locale);
|
||||
|
|
|
@ -205,6 +205,8 @@ void MainWindow::closeEvent(QCloseEvent *event) {
|
|||
}
|
||||
|
||||
void MainWindow::quit() {
|
||||
ioutils::deleteNetworkManger();
|
||||
hotkeying::clearAll();
|
||||
QApplication::quit();
|
||||
}
|
||||
|
||||
|
|
|
@ -3,9 +3,12 @@
|
|||
#include "systemnotification.h"
|
||||
#include "mainwindow.hpp"
|
||||
#include "ui_mainwindow.h"
|
||||
#include <settings.hpp>
|
||||
#include <QApplication>
|
||||
#include <QMediaPlayer>
|
||||
|
||||
QMediaPlayer *mediaPlayer = nullptr;
|
||||
|
||||
void notifications::notify(QString title, QString body, QSystemTrayIcon::MessageIcon icon) {
|
||||
if (!MainWindow::inst() || !MainWindow::inst()->valid()) return;
|
||||
notifyNolog(title, body, icon);
|
||||
|
@ -24,29 +27,36 @@ void notifications::notifyNolog(QString title, QString body, QSystemTrayIcon::Me
|
|||
}
|
||||
|
||||
void notifications::playSound(notifications::Sound soundType) {
|
||||
QMediaPlayer*mediaPlayer = new QMediaPlayer(MainWindow::inst());
|
||||
if(!settings::settings().value("playSound", true).toBool()) return;
|
||||
|
||||
switch (soundType) {
|
||||
case notifications::Sound::CAPTURE:
|
||||
mediaPlayer->setMedia(QUrl("qrc:/capturesound.wav"));
|
||||
break;
|
||||
try {
|
||||
if (mediaPlayer == nullptr) {
|
||||
mediaPlayer = new QMediaPlayer(MainWindow::inst());
|
||||
}
|
||||
|
||||
case notifications::Sound::SUCCESS:
|
||||
mediaPlayer->setMedia(QUrl("qrc:/successsound.wav"));
|
||||
break;
|
||||
switch (soundType) {
|
||||
case notifications::Sound::CAPTURE:
|
||||
mediaPlayer->setMedia(QUrl("qrc:/capturesound.wav"));
|
||||
break;
|
||||
|
||||
case notifications::Sound::ERROR:
|
||||
mediaPlayer->setMedia(QUrl("qrc:/errorsound.wav"));
|
||||
break;
|
||||
case notifications::Sound::SUCCESS:
|
||||
mediaPlayer->setMedia(QUrl("qrc:/successsound.wav"));
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
case notifications::Sound::ERROR:
|
||||
mediaPlayer->setMedia(QUrl("qrc:/errorsound.wav"));
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
mediaPlayer->setVolume(25);
|
||||
mediaPlayer->play();
|
||||
|
||||
if(mediaPlayer->error() != QMediaPlayer::NoError && mediaPlayer->error() != QMediaPlayer::ServiceMissingError)
|
||||
notifications::notify(QString::number(mediaPlayer->error()), mediaPlayer->errorString(), QSystemTrayIcon::Warning);
|
||||
} catch (...) {
|
||||
notifications::notifyNolog(QObject::tr("KShare: No sound driver"), "No sound driver found. Install libqt5multimedia5-plugins for notifcation sound support.", QSystemTrayIcon::Warning);
|
||||
}
|
||||
|
||||
mediaPlayer->setVolume(25);
|
||||
mediaPlayer->play();
|
||||
|
||||
if(mediaPlayer->error() != QMediaPlayer::NoError && mediaPlayer->error() != QMediaPlayer::ServiceMissingError)
|
||||
notifications::notify(QString::number(mediaPlayer->error()), mediaPlayer->errorString(), QSystemTrayIcon::Warning);
|
||||
|
||||
}
|
||||
|
|
|
@ -68,6 +68,7 @@ SettingsDialog::SettingsDialog(QWidget *parent) : QDialog(parent), ui(new Ui::Se
|
|||
ui->quickMode->setChecked(settings::settings().value("quickMode", false).toBool());
|
||||
ui->hideToTray->setChecked(settings::settings().value("hideOnClose", true).toBool());
|
||||
ui->captureCursor->setChecked(settings::settings().value("captureCursor", true).toBool());
|
||||
ui->playSound->setChecked(settings::settings().value("playSound", true).toBool());
|
||||
ui->saveLocation->setCurrentIndex(settings::settings().value("saveLocation", 1).toInt());
|
||||
ui->themeSelection->setCurrentIndex(settings::settings().value("theme", 0).toInt());
|
||||
for (int i = 0; i < (int)formats::Recording::None; i++) {
|
||||
|
@ -158,6 +159,10 @@ void SettingsDialog::on_captureCursor_clicked(bool checked) {
|
|||
settings::settings().setValue("captureCursor", checked);
|
||||
}
|
||||
|
||||
void SettingsDialog::on_playSound_clicked(bool checked) {
|
||||
settings::settings().setValue("playSound", checked);
|
||||
}
|
||||
|
||||
void SettingsDialog::on_formatBox_currentIndexChanged(int index) {
|
||||
if (isVisible()) settings::settings().setValue("recording/format", index);
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@ private slots:
|
|||
void on_quickMode_clicked(bool checked);
|
||||
void on_hideToTray_clicked(bool checked);
|
||||
void on_captureCursor_clicked(bool checked);
|
||||
void on_playSound_clicked(bool checked);
|
||||
void on_formatBox_currentIndexChanged(int index);
|
||||
void on_imageFormatBox_currentIndexChanged(int index);
|
||||
void on_pushButton_clicked();
|
||||
|
|
|
@ -6,195 +6,14 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>650</width>
|
||||
<height>759</height>
|
||||
<width>753</width>
|
||||
<height>326</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Crop editor settings</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="19" column="1" colspan="2">
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>Advanced</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="3" column="0">
|
||||
<widget class="QSpinBox" name="cropX">
|
||||
<property name="suffix">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="prefix">
|
||||
<string notr="true">x: </string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>-999999</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>999999</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QSpinBox" name="cropY">
|
||||
<property name="prefix">
|
||||
<string notr="true">y: </string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>-999999</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>999999</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="2">
|
||||
<widget class="QLabel" name="label_8">
|
||||
<property name="text">
|
||||
<string>Editor Position (tweak if the editor does not cover the entire screen)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="QPushButton" name="pushButton">
|
||||
<property name="text">
|
||||
<string>Encoder settings</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="15" column="2">
|
||||
<widget class="QSpinBox" name="fpsMax">
|
||||
<property name="suffix">
|
||||
<string>FPS</string>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>255</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="15" column="1">
|
||||
<widget class="QLabel" name="label_9">
|
||||
<property name="text">
|
||||
<string>Frames Per Second For Recording</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="1">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Delay before taking a screenshot</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="13" column="1">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Recording format</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="11" column="1" colspan="2">
|
||||
<widget class="QCheckBox" name="captureCursor">
|
||||
<property name="text">
|
||||
<string>Capture cursor</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QLineEdit" name="nameScheme">
|
||||
<property name="toolTip">
|
||||
<string>%(date format)date and %ext are supported</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">Screenshot %(yyyy-MM-dd HH-mm-ss)date.%ext</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="13" column="2">
|
||||
<widget class="QComboBox" name="formatBox">
|
||||
<property name="currentIndex">
|
||||
<number>-1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>File name scheme:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="17" column="2">
|
||||
<widget class="QLineEdit" name="fullscreenCapture"/>
|
||||
</item>
|
||||
<item row="18" column="1">
|
||||
<widget class="QLabel" name="label_11">
|
||||
<property name="text">
|
||||
<string>Focused capture command (save to %FILE_PATH or print to stdout)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="18" column="2">
|
||||
<widget class="QLineEdit" name="focusedCapture"/>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QLineEdit" name="folderFormat">
|
||||
<property name="text">
|
||||
<string>%(yyyy-MM)date</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QLabel" name="label_12">
|
||||
<property name="text">
|
||||
<string>Screenshot Subfolder</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="12" column="1" colspan="2">
|
||||
<widget class="QCheckBox" name="hideToTray">
|
||||
<property name="text">
|
||||
<string>Pressing <X> hides to tray</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="1">
|
||||
<widget class="QComboBox" name="saveLocation">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Pictures folder</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Screenshots folder (In your user folder)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Do not save</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="2">
|
||||
<widget class="QPushButton" name="settingsButton">
|
||||
<property name="text">
|
||||
<string>Open settings directory</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Destination:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="20" column="1" colspan="2">
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
|
@ -205,92 +24,355 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>File save location</string>
|
||||
<item row="0" column="1" colspan="2">
|
||||
<widget class="QTabWidget" name="tabWidget">
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QListWidget" name="uploaderList"/>
|
||||
</item>
|
||||
<item row="14" column="2">
|
||||
<widget class="QComboBox" name="imageFormatBox"/>
|
||||
</item>
|
||||
<item row="9" column="1">
|
||||
<widget class="QDoubleSpinBox" name="delay">
|
||||
<property name="toolTip">
|
||||
<string>In seconds</string>
|
||||
</property>
|
||||
<property name="whatsThis">
|
||||
<string>A delay before taking a screenshot, in seconds</string>
|
||||
</property>
|
||||
<property name="suffix">
|
||||
<string notr="true">s</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="1">
|
||||
<widget class="QCheckBox" name="quickMode">
|
||||
<property name="text">
|
||||
<string>Quick mode (mouse release screenshots)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="17" column="1">
|
||||
<widget class="QLabel" name="label_10">
|
||||
<property name="text">
|
||||
<string>Fullscreen capture command (save to %FILE_PATH or print to stdout)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Hotkeys</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="14" column="1">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>Still image format</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2" rowspan="7">
|
||||
<widget class="QListWidget" name="hotkeys"/>
|
||||
</item>
|
||||
<item row="8" column="2">
|
||||
<widget class="QLabel" name="label_13">
|
||||
<property name="text">
|
||||
<string>Theme</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="2">
|
||||
<widget class="QComboBox" name="themeSelection">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>System Default</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>QDarkStyle</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Breeze Light</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Breeze Dark</string>
|
||||
</property>
|
||||
</item>
|
||||
<widget class="QWidget" name="tab_4">
|
||||
<attribute name="title">
|
||||
<string>General</string>
|
||||
</attribute>
|
||||
<layout class="QGridLayout" name="gridLayout_8">
|
||||
<item row="0" column="0">
|
||||
<layout class="QFormLayout" name="formLayout_3">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_13">
|
||||
<property name="text">
|
||||
<string>Theme</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="themeSelection">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>System Default</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>QDarkStyle</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Breeze Light</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Breeze Dark</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QCheckBox" name="quickMode">
|
||||
<property name="text">
|
||||
<string>Quick mode (mouse release screenshots)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QCheckBox" name="hideToTray">
|
||||
<property name="text">
|
||||
<string>Pressing <X> hides to tray</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QCheckBox" name="captureCursor">
|
||||
<property name="text">
|
||||
<string>Capture cursor</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Delay before taking a screenshot</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="1">
|
||||
<widget class="QDoubleSpinBox" name="delay">
|
||||
<property name="toolTip">
|
||||
<string>In seconds</string>
|
||||
</property>
|
||||
<property name="whatsThis">
|
||||
<string>A delay before taking a screenshot, in seconds</string>
|
||||
</property>
|
||||
<property name="suffix">
|
||||
<string notr="true">s</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QCheckBox" name="playSound">
|
||||
<property name="text">
|
||||
<string>Play notification Sound</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QPushButton" name="settingsButton">
|
||||
<property name="text">
|
||||
<string>Open settings directory</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab">
|
||||
<attribute name="title">
|
||||
<string>Hoster</string>
|
||||
</attribute>
|
||||
<layout class="QGridLayout" name="gridLayout_6">
|
||||
<item row="0" column="0">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QListWidget" name="uploaderList"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab_2">
|
||||
<attribute name="title">
|
||||
<string>Hotkeys</string>
|
||||
</attribute>
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<item row="0" column="0">
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QListWidget" name="hotkeys"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab_3">
|
||||
<attribute name="title">
|
||||
<string>Paths</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||
<item>
|
||||
<layout class="QFormLayout" name="formLayout_4">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>File name scheme</string>
|
||||
</property>
|
||||
<property name="margin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="nameScheme">
|
||||
<property name="toolTip">
|
||||
<string>%(date format)date and %ext are supported</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">Screenshot %(yyyy-MM-dd HH-mm-ss)date.%ext</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_12">
|
||||
<property name="text">
|
||||
<string>Screenshot Subfolder</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="folderFormat">
|
||||
<property name="text">
|
||||
<string>%(yyyy-MM)date</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>File save location</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QComboBox" name="saveLocation">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Pictures folder</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Screenshots folder (In your user folder)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Do not save</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab_5">
|
||||
<attribute name="title">
|
||||
<string>Recording</string>
|
||||
</attribute>
|
||||
<layout class="QGridLayout" name="gridLayout_10">
|
||||
<item row="2" column="0">
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>Advanced</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="3" column="0">
|
||||
<widget class="QSpinBox" name="cropX">
|
||||
<property name="suffix">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="prefix">
|
||||
<string notr="true">x: </string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>-999999</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>999999</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QSpinBox" name="cropY">
|
||||
<property name="prefix">
|
||||
<string notr="true">y: </string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>-999999</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>999999</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="2">
|
||||
<widget class="QLabel" name="label_8">
|
||||
<property name="text">
|
||||
<string>Editor Position (tweak if the editor does not cover the entire screen)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="QPushButton" name="pushButton">
|
||||
<property name="text">
|
||||
<string>Encoder settings</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<layout class="QGridLayout" name="gridLayout_9">
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="formatBox">
|
||||
<property name="currentIndex">
|
||||
<number>-1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Recording format</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>Still image format</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QComboBox" name="imageFormatBox"/>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_9">
|
||||
<property name="text">
|
||||
<string>Frames Per Second For Recording</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QSpinBox" name="fpsMax">
|
||||
<property name="suffix">
|
||||
<string>FPS</string>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>255</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab_6">
|
||||
<attribute name="title">
|
||||
<string>Advanced</string>
|
||||
</attribute>
|
||||
<layout class="QGridLayout" name="gridLayout_11">
|
||||
<item row="0" column="0">
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_10">
|
||||
<property name="text">
|
||||
<string>Fullscreen capture command (save to %FILE_PATH or print to stdout)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_11">
|
||||
<property name="text">
|
||||
<string>Focused capture command (save to %FILE_PATH or print to stdout)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="fullscreenCapture"/>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="focusedCapture"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
|
|
|
@ -34,6 +34,7 @@ SOURCES += main.cpp\
|
|||
screenshotter.cpp \
|
||||
utils.cpp \
|
||||
uploaders/default/imguruploader.cpp \
|
||||
uploaders/default/gdriveuploader.cpp \
|
||||
io/ioutils.cpp \
|
||||
settings.cpp \
|
||||
uploaders/default/clipboarduploader.cpp \
|
||||
|
@ -65,6 +66,7 @@ SOURCES += main.cpp\
|
|||
hotkeyinputdialog.cpp \
|
||||
cropeditor/drawing/arrowitem.cpp \
|
||||
uploaders/default/imgursettingsdialog.cpp \
|
||||
uploaders/default/gdrivesettingsdialog.cpp \
|
||||
filenamevalidator.cpp \
|
||||
logs/requestlogging.cpp \
|
||||
monospacetextdialog.cpp \
|
||||
|
@ -85,6 +87,7 @@ HEADERS += mainwindow.hpp \
|
|||
screenshotter.hpp \
|
||||
utils.hpp \
|
||||
uploaders/default/imguruploader.hpp \
|
||||
uploaders/default/gdriveuploader.hpp \
|
||||
io/ioutils.hpp \
|
||||
settings.hpp \
|
||||
uploaders/default/clipboarduploader.hpp \
|
||||
|
@ -118,6 +121,7 @@ HEADERS += mainwindow.hpp \
|
|||
hotkeyinputdialog.hpp \
|
||||
cropeditor/drawing/arrowitem.hpp \
|
||||
uploaders/default/imgursettingsdialog.hpp \
|
||||
uploaders/default/gdrivesettingsdialog.hpp \
|
||||
filenamevalidator.hpp \
|
||||
logs/requestlogging.hpp \
|
||||
monospacetextdialog.hpp \
|
||||
|
@ -189,6 +193,7 @@ FORMS += mainwindow.ui \
|
|||
aboutbox.ui \
|
||||
hotkeyinputdialog.ui \
|
||||
uploaders/default/imgursettingsdialog.ui \
|
||||
uploaders/default/gdrivesettingsdialog.ui \
|
||||
monospacetextdialog.ui \
|
||||
screenoverlay/screenoverlaysettings.ui
|
||||
|
||||
|
|
|
@ -0,0 +1,177 @@
|
|||
#include "gdrivesettingsdialog.hpp"
|
||||
#include "ui_gdrivesettingsdialog.h"
|
||||
|
||||
#include <QDesktopServices>
|
||||
#include <QDialogButtonBox>
|
||||
#include <QLabel>
|
||||
#include <QLineEdit>
|
||||
#include <QNetworkReply>
|
||||
#include <QPushButton>
|
||||
#include <QUrl>
|
||||
#include <io/ioutils.hpp>
|
||||
#include <settings.hpp>
|
||||
|
||||
GDriveSettingsDialog::GDriveSettingsDialog(QWidget *parent) : QDialog(parent), ui(new Ui::GDriveSettingsDialog) {
|
||||
ui->setupUi(this);
|
||||
connect(this, &GDriveSettingsDialog::accepted, this, &GDriveSettingsDialog::deleteLater);
|
||||
ui->clientId->setText(settings::settings().value("google/cid").toString());
|
||||
ui->clientSecret->setText(settings::settings().value("google/csecret").toString());
|
||||
ui->folderId->setText(settings::settings().value("google/folder").toString().toUtf8());
|
||||
|
||||
ui->isPublic->setChecked(settings::settings().value("google/public").toBool());
|
||||
}
|
||||
|
||||
GDriveSettingsDialog::~GDriveSettingsDialog() {
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void GDriveSettingsDialog::on_addApp_clicked() {
|
||||
QDesktopServices::openUrl(
|
||||
QUrl(QString("https://accounts.google.com/o/oauth2/auth?client_id=%1&redirect_uri=urn:ietf:wg:oauth:2.0:oob&response_type=code&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fdrive").arg(ui->clientId->text())));
|
||||
}
|
||||
|
||||
void GDriveSettingsDialog::on_isPublic_clicked(bool checked) {
|
||||
settings::settings().setValue("google/public", checked);
|
||||
}
|
||||
|
||||
void GDriveSettingsDialog::on_folderId_textChanged(QString arg1) {
|
||||
settings::settings().setValue("google/folder", arg1);
|
||||
}
|
||||
|
||||
bool GDriveSettingsDialog::checkAuthorization () {
|
||||
if (ui->folderId->text().isEmpty()) return false;
|
||||
settings::settings().setValue("google/folder", ui->folderId->text());
|
||||
|
||||
if (settings::settings().contains("google/expire") //
|
||||
&& settings::settings().contains("google/refresh") //
|
||||
&& settings::settings().contains("google/access")) {
|
||||
QDateTime expireTime = settings::settings().value("google/expire").toDateTime();
|
||||
if (QDateTime::currentDateTimeUtc() > expireTime) {
|
||||
// Token expired
|
||||
ui->status->setText(tr("Token expired"));
|
||||
} else {
|
||||
ui->buttonBox->setEnabled(false);
|
||||
ui->testButton->setEnabled(false);
|
||||
ioutils::getData(QUrl(QString("https://www.googleapis.com/drive/v3/files?q='%1'+in+parents&fields=files(md5Checksum,+originalFilename)").arg(ui->folderId->text())),
|
||||
QList<QPair<QString, QString>>({ QPair<QString, QString>("Authorization", settings::settings().value("google/access").toString().prepend("Bearer ")) }),
|
||||
[&](QByteArray a, QNetworkReply *r) {
|
||||
|
||||
QVariant statusCode = r->attribute(QNetworkRequest::HttpStatusCodeAttribute);
|
||||
if (!statusCode.isValid()) return;
|
||||
|
||||
ui->testButton->setEnabled(true);
|
||||
|
||||
int status = statusCode.toInt();
|
||||
if (status != 200 && status != 400)
|
||||
{
|
||||
QString reason = r->attribute( QNetworkRequest::HttpReasonPhraseAttribute ).toString();
|
||||
qDebug() << reason;
|
||||
|
||||
ui->buttonBox->setEnabled(true);
|
||||
ui->status->setText(reason);
|
||||
return;
|
||||
}
|
||||
|
||||
QJsonDocument response = QJsonDocument::fromJson(a);
|
||||
if (!response.isObject()) {
|
||||
ui->buttonBox->setEnabled(true);
|
||||
ui->status->setText("Invalid JSON");
|
||||
return;
|
||||
}
|
||||
QJsonObject res = response.object();
|
||||
|
||||
if (res.contains("error")) {
|
||||
ui->buttonBox->setEnabled(true);
|
||||
|
||||
ui->status->setText(res.value("error_description").toString().toUtf8());
|
||||
ui->status->setStyleSheet("* { color: red; }");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
ui->buttonBox->setEnabled(true);
|
||||
ui->testButton->hide();
|
||||
|
||||
ui->status->setText(tr("It works!"));
|
||||
ui->status->setStyleSheet("* { color: green; }");
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// No Token set
|
||||
ui->status->setText(tr("Login with Google needed"));
|
||||
}
|
||||
}
|
||||
|
||||
void GDriveSettingsDialog::on_testButton_clicked() {
|
||||
GDriveSettingsDialog::checkAuthorization();
|
||||
}
|
||||
|
||||
void GDriveSettingsDialog::on_authorize_clicked() {
|
||||
if (ui->pin->text().isEmpty() || ui->folderId->text().isEmpty()) return;
|
||||
ui->buttonBox->setEnabled(false);
|
||||
QJsonObject object;
|
||||
object.insert("client_id", ui->clientId->text());
|
||||
object.insert("client_secret", ui->clientSecret->text());
|
||||
object.insert("grant_type", "authorization_code");
|
||||
object.insert("code", ui->pin->text());
|
||||
object.insert("redirect_uri", "urn:ietf:wg:oauth:2.0:oob");
|
||||
settings::settings().setValue("google/cid", ui->clientId->text());
|
||||
settings::settings().setValue("google/csecret", ui->clientSecret->text());
|
||||
settings::settings().setValue("google/folder", ui->folderId->text());
|
||||
settings::settings().setValue("google/public", ui->isPublic->isChecked());
|
||||
|
||||
ioutils::postJson(QUrl("https://accounts.google.com/o/oauth2/token"),
|
||||
QList<QPair<QString, QString>>({ QPair<QString, QString>("Content-Type", "applicaton/json") }),
|
||||
QJsonDocument::fromVariant(object.toVariantMap()).toJson(),
|
||||
[&](QJsonDocument response, QByteArray, QNetworkReply *r) {
|
||||
QVariant statusCode = r->attribute(QNetworkRequest::HttpStatusCodeAttribute);
|
||||
if (!statusCode.isValid()) return;
|
||||
|
||||
int status = statusCode.toInt();
|
||||
if (status != 200 && status != 400)
|
||||
{
|
||||
QString reason = r->attribute( QNetworkRequest::HttpReasonPhraseAttribute ).toString();
|
||||
qDebug() << reason;
|
||||
|
||||
ui->buttonBox->setEnabled(true);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (!response.isObject()) {
|
||||
ui->buttonBox->setEnabled(true);
|
||||
return;
|
||||
}
|
||||
QJsonObject res = response.object();
|
||||
|
||||
if (res.contains("error")) {
|
||||
ui->buttonBox->setEnabled(true);
|
||||
|
||||
ui->status->setText(res.value("error_description").toString().toUtf8());
|
||||
ui->status->setStyleSheet("* { color: red; }");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (res.value("success").toBool()) {
|
||||
ui->buttonBox->setEnabled(true);
|
||||
return;
|
||||
}
|
||||
|
||||
settings::settings().setValue("google/expire",
|
||||
QDateTime::currentDateTimeUtc().addSecs(res["expires_in"].toInt()));
|
||||
settings::settings().setValue("google/refresh", res["refresh_token"].toString().toUtf8());
|
||||
settings::settings().setValue("google/access", res["access_token"].toString().toUtf8());
|
||||
ui->status->setText(tr("It works!"));
|
||||
ui->status->setStyleSheet("* { color: green; }");
|
||||
|
||||
ui->authorize->setEnabled(false);
|
||||
ui->addApp->setEnabled(false);
|
||||
ui->clientSecret->setEnabled(false);
|
||||
ui->clientId->setEnabled(false);
|
||||
|
||||
ui->buttonBox->setEnabled(true);
|
||||
|
||||
ui->testButton->hide();
|
||||
});
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
#ifndef GDRIVESETTINGSDIALOG_HPP
|
||||
#define GDRIVESETTINGSDIALOG_HPP
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
namespace Ui {
|
||||
class GDriveSettingsDialog;
|
||||
}
|
||||
|
||||
class GDriveSettingsDialog : public QDialog {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit GDriveSettingsDialog(QWidget *parent = 0);
|
||||
~GDriveSettingsDialog();
|
||||
|
||||
private slots:
|
||||
void on_addApp_clicked();
|
||||
void on_authorize_clicked();
|
||||
void on_testButton_clicked();
|
||||
bool checkAuthorization();
|
||||
void on_isPublic_clicked(bool);
|
||||
void on_folderId_textChanged(QString);
|
||||
|
||||
private:
|
||||
Ui::GDriveSettingsDialog *ui;
|
||||
};
|
||||
|
||||
#endif // GRDIVESETTINGSDIALOG_HPP
|
|
@ -0,0 +1,174 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>GDriveSettingsDialog</class>
|
||||
<widget class="QDialog" name="GDriveSettingsDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>287</width>
|
||||
<height>389</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>GDrive auth</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="1" column="1">
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>OAuth2</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="4" column="0" colspan="2">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
||||
p, li { white-space: pre-wrap; }
|
||||
</style></head><body style=" font-family:'Noto Sans'; font-size:9pt; font-weight:400; font-style:normal;">
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">Authentication needed</span></p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0" colspan="2">
|
||||
<widget class="QPushButton" name="addApp">
|
||||
<property name="text">
|
||||
<string>Login with Google</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0" colspan="2">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string><html><head/><body><p>Enter verification code</p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0" colspan="2">
|
||||
<widget class="QLineEdit" name="pin">
|
||||
<property name="placeholderText">
|
||||
<string>Authorization code</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="0" colspan="2">
|
||||
<widget class="QPushButton" name="authorize">
|
||||
<property name="text">
|
||||
<string>Authorize</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="14" column="0" colspan="2">
|
||||
<widget class="QLabel" name="status">
|
||||
<property name="styleSheet">
|
||||
<string notr="true">* { color: red; }</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Not working</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Client ID/Client Secret</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="clientSecret">
|
||||
<property name="placeholderText">
|
||||
<string>Client Secret</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLineEdit" name="clientId">
|
||||
<property name="placeholderText">
|
||||
<string>Client ID</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Upload Public</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Folder ID</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="15" column="0" colspan="2">
|
||||
<widget class="QPushButton" name="testButton">
|
||||
<property name="text">
|
||||
<string>Check Authorization</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLineEdit" name="folderId"/>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QCheckBox" name="isPublic">
|
||||
<property name="text">
|
||||
<string>Is Public</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>GDriveSettingsDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>GDriveSettingsDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
|
@ -0,0 +1,162 @@
|
|||
#include "gdriveuploader.hpp"
|
||||
|
||||
#include <QBuffer>
|
||||
#include <QJsonObject>
|
||||
#include <QJsonValue>
|
||||
#include <QNetworkReply>
|
||||
#include <QHttpMultiPart>
|
||||
#include <QHttpPart>
|
||||
#include <QString>
|
||||
#include <formats.hpp>
|
||||
#include <io/ioutils.hpp>
|
||||
#include <notifications.hpp>
|
||||
#include <settings.hpp>
|
||||
#include <utils.hpp>
|
||||
#include <logs/screenshotfile.h>
|
||||
#include <uploaders/default/gdrivesettingsdialog.hpp>
|
||||
|
||||
struct SegfaultWorkaround { // I'm a scrub for doing this
|
||||
SegfaultWorkaround(QByteArray a, GDriveUploader *u, QString m, bool ip, ScreenshotFile f) : byteArray(), dis(u), mime(m), isPublic(ip), sf(f) {
|
||||
a.swap(byteArray);
|
||||
QJsonObject object;
|
||||
object.insert("client_id", settings::settings().value("google/cid").toString());
|
||||
object.insert("client_secret", settings::settings().value("google/csecret").toString());
|
||||
object.insert("grant_type", "refresh_token");
|
||||
object.insert("refresh_token", settings::settings().value("google/refresh").toString());
|
||||
|
||||
ioutils::postJson(
|
||||
QUrl("https://accounts.google.com/o/oauth2/token"),
|
||||
QList<QPair<QString, QString>>({ QPair<QString, QString>("Content-Type", "applicaton/json") }),
|
||||
QJsonDocument::fromVariant(object.toVariantMap()).toJson(), [&](QJsonDocument response, QByteArray, QNetworkReply *r) {
|
||||
qDebug() << response;
|
||||
if (r->error() != QNetworkReply::NoError || !response.isObject()) {
|
||||
notifications::notify(QObject::tr("KShare Google Uploader"),
|
||||
QString(QObject::tr("Failed upload! Error in refresh token")));
|
||||
notifications::playSound(notifications::Sound::ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
QJsonObject res = response.object();
|
||||
QString token = res["access_token"].toString();
|
||||
settings::settings().setValue("google/expire", QDateTime::currentDateTimeUtc().addSecs(res["expires_in"].toInt()));
|
||||
settings::settings().setValue("google/refresh", res["refresh_token"].toString());
|
||||
settings::settings().setValue("google/access", token);
|
||||
|
||||
dis->handleSend(token.prepend("Bearer "), isPublic, mime, byteArray, sf);
|
||||
|
||||
QScopedPointer<SegfaultWorkaround>(this);
|
||||
});
|
||||
}
|
||||
|
||||
private:
|
||||
QByteArray byteArray;
|
||||
GDriveUploader *dis;
|
||||
QString mime;
|
||||
bool isPublic;
|
||||
ScreenshotFile sf;
|
||||
}; // I feel terrible for making this. I am sorry, reader
|
||||
|
||||
void GDriveUploader::doUpload(QByteArray byteArray, QString format, ScreenshotFile sf) {
|
||||
if (byteArray.size() > 1e+7) {
|
||||
notifications::notify(tr("KShare imgur Uploader"), tr("Failed upload! Image too big"));
|
||||
return;
|
||||
}
|
||||
QString mime;
|
||||
if (formats::normalFormatFromName(format) != formats::Normal::None)
|
||||
mime = formats::normalFormatMIME(formats::normalFormatFromName(format));
|
||||
else
|
||||
mime = formats::recordingFormatMIME(formats::recordingFormatFromName(format));
|
||||
|
||||
if (settings::settings().contains("google/expire") //
|
||||
&& settings::settings().contains("google/refresh") //
|
||||
&& settings::settings().contains("google/access")) {
|
||||
QDateTime expireTime = settings::settings().value("google/expire").toDateTime();
|
||||
bool isPublic = settings::settings().value("google/public", false).toBool();
|
||||
if (QDateTime::currentDateTimeUtc() > expireTime) {
|
||||
qDebug() << "Need to refresh Google Access Token";
|
||||
new SegfaultWorkaround(byteArray, this, mime, isPublic, sf);
|
||||
} else handleSend("Bearer " + settings::settings().value("google/access", "").toString().toUtf8(), isPublic, mime, byteArray, sf);
|
||||
}
|
||||
}
|
||||
|
||||
void GDriveUploader::showSettings() {
|
||||
(new GDriveSettingsDialog())->show();
|
||||
}
|
||||
|
||||
void GDriveUploader::setPermission(QString fileID, QString auth, QString role, QString type, bool allowFileDiscovery) {
|
||||
QJsonObject object;
|
||||
object.insert("role", role);
|
||||
object.insert("type", type);
|
||||
object.insert("allowFileDiscovery", QString(allowFileDiscovery));
|
||||
QJsonDocument doc(object);
|
||||
|
||||
ioutils::postData(QUrl(QString("https://www.googleapis.com/drive/v3/files/%1/permissions").arg(fileID)),
|
||||
QList<QPair<QString, QString>>({ QPair<QString, QString>("Content-Type", "application/json"), QPair<QString, QString>("Authorization", auth) }),
|
||||
QString(doc.toJson(QJsonDocument::Compact)).toUtf8(),
|
||||
[&](QByteArray , QNetworkReply *) {
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
void GDriveUploader::handleSend(QString auth, bool isPublic, QString mime, QByteArray byteArray, ScreenshotFile sf) {
|
||||
QHttpMultiPart *multipart = new QHttpMultiPart(QHttpMultiPart::RelatedType);
|
||||
|
||||
QHttpPart metaPart;
|
||||
metaPart.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("application/json"));
|
||||
metaPart.setHeader(
|
||||
QNetworkRequest::ContentDispositionHeader,
|
||||
QVariant("form-data; name=\"metadata\"")
|
||||
);
|
||||
QString data("{name: '"+sf.getFilename()+"', parents: ['"+settings::settings().value("google/folder").toString().toUtf8()+"']}");
|
||||
metaPart.setBody(data.toUtf8());
|
||||
multipart->append(metaPart);
|
||||
|
||||
QHttpPart imagePart;
|
||||
imagePart.setHeader(QNetworkRequest::ContentTypeHeader, QVariant(mime.toUtf8()));
|
||||
imagePart.setHeader(
|
||||
QNetworkRequest::ContentDispositionHeader,
|
||||
QVariant("form-data; name=\"file\"; filename=\""+sf.getFilename()+"\"")
|
||||
);
|
||||
|
||||
imagePart.setBody(byteArray);
|
||||
multipart->append(imagePart);
|
||||
|
||||
ioutils::postMultipartData(QUrl("https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart&fields=id,webViewLink,webContentLink"),
|
||||
QList<QPair<QString, QString>>() << QPair<QString, QString>("Authorization", auth),
|
||||
multipart, [byteArray, this, mime, sf, auth, isPublic](QByteArray res, QNetworkReply *r) {
|
||||
qDebug() << QString(res).toUtf8();
|
||||
if (r->error() == QNetworkReply::ContentAccessDenied) {
|
||||
(new GDriveSettingsDialog())->show();
|
||||
return;
|
||||
}
|
||||
|
||||
QString result = QString(res).toUtf8();
|
||||
if (!result.isEmpty()) {
|
||||
QJsonDocument doc = QJsonDocument::fromJson(result.toUtf8());
|
||||
if(!doc.isObject()) {
|
||||
notifications::notify(tr("KShare Google Uploader "),
|
||||
QString(tr("Failed upload! Invalid JSON")));
|
||||
notifications::playSound(notifications::Sound::ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
if(isPublic) {
|
||||
setPermission(doc.object()["id"].toString(), auth);
|
||||
}
|
||||
result = doc.object()["webViewLink"].toString();
|
||||
ioutils::addLogEntry(r, res, result, sf);
|
||||
|
||||
notifications::notify(tr("KShare Google Uploader"), tr("Uploaded to Google!"));
|
||||
notifications::playSound(notifications::Sound::SUCCESS);
|
||||
utils::toClipboard(result);
|
||||
} else {
|
||||
|
||||
ioutils::addLogEntry(r, res, result, sf);
|
||||
notifications::notify(tr("KShare Google Uploader "),
|
||||
QString(tr("Failed upload! Google said: HTTP %1: %2"))
|
||||
.arg(r->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt())
|
||||
.arg(r->errorString()));
|
||||
notifications::playSound(notifications::Sound::ERROR);
|
||||
}
|
||||
});
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
#ifndef GDRIVEUPLOADER_HPP
|
||||
#define GRIVEUPLOADER_HPP
|
||||
|
||||
#include "../uploader.hpp"
|
||||
#include <QApplication>
|
||||
#include <logs/screenshotfile.h>
|
||||
|
||||
class GDriveUploader : public Uploader {
|
||||
Q_DECLARE_TR_FUNCTIONS(GDriveUploader)
|
||||
friend struct SegfaultWorkaround;
|
||||
|
||||
public:
|
||||
QString name() override {
|
||||
return "Google Drive";
|
||||
}
|
||||
QString description() override {
|
||||
return "drive.google.com uploader";
|
||||
}
|
||||
void doUpload(QByteArray byteArray, QString, ScreenshotFile sf) override;
|
||||
void showSettings() override;
|
||||
void setPermission(QString, QString, QString = "reader", QString = "anyone", bool = false);
|
||||
|
||||
private:
|
||||
void handleSend(QString auth, bool isPublic, QString mime, QByteArray byteArray, ScreenshotFile sf);
|
||||
};
|
||||
|
||||
#endif // GDRIVEUPLOADER_HPP
|
|
@ -14,7 +14,7 @@
|
|||
#include <logs/screenshotfile.h>
|
||||
|
||||
struct SegfaultWorkaround { // I'm a scrub for doing this
|
||||
SegfaultWorkaround(QByteArray a, ImgurUploader *u, QString m) : byteArray(), dis(u), mime(m) {
|
||||
SegfaultWorkaround(QByteArray a, ImgurUploader *u, QString m, ScreenshotFile f) : byteArray(), dis(u), mime(m), sf(f) {
|
||||
a.swap(byteArray);
|
||||
QJsonObject object;
|
||||
object.insert("client_id", settings::settings().value("imgur/cid").toString());
|
||||
|
@ -26,7 +26,6 @@ struct SegfaultWorkaround { // I'm a scrub for doing this
|
|||
QUrl("https://api.imgur.com/oauth2/token"),
|
||||
QList<QPair<QString, QString>>({ QPair<QString, QString>("Content-Type", "applicaton/json") }),
|
||||
QJsonDocument::fromVariant(object.toVariantMap()).toJson(), [&](QJsonDocument response, QByteArray, QNetworkReply *r) {
|
||||
ScreenshotFile sf;
|
||||
qDebug() << response;
|
||||
if (r->error() != QNetworkReply::NoError || !response.isObject()) {
|
||||
dis->handleSend(QStringLiteral("Client-ID 8a98f183fc895da"), mime, byteArray, sf);
|
||||
|
@ -52,6 +51,7 @@ private:
|
|||
QByteArray byteArray;
|
||||
ImgurUploader *dis;
|
||||
QString mime;
|
||||
ScreenshotFile sf;
|
||||
}; // I feel terrible for making this. I am sorry, reader
|
||||
|
||||
void ImgurUploader::doUpload(QByteArray byteArray, QString format, ScreenshotFile sf) {
|
||||
|
@ -69,7 +69,7 @@ void ImgurUploader::doUpload(QByteArray byteArray, QString format, ScreenshotFil
|
|||
&& settings::settings().contains("imgur/access")) {
|
||||
QDateTime expireTime = settings::settings().value("imgur/expire").toDateTime();
|
||||
if (QDateTime::currentDateTimeUtc() > expireTime) {
|
||||
new SegfaultWorkaround(byteArray, this, mime);
|
||||
new SegfaultWorkaround(byteArray, this, mime, sf);
|
||||
} else
|
||||
handleSend("Bearer " + settings::settings().value("imgur/access").toString(), mime, byteArray, sf);
|
||||
} else
|
||||
|
@ -87,14 +87,14 @@ void ImgurUploader::handleSend(QString auth, QString mime, QByteArray byteArray,
|
|||
byteArray, [byteArray, this, mime, sf](QJsonDocument res, QByteArray data, QNetworkReply *r) {
|
||||
QString result = res.object()["data"].toObject()["link"].toString();
|
||||
if (r->error() == QNetworkReply::ContentAccessDenied) {
|
||||
new SegfaultWorkaround(byteArray, this, mime);
|
||||
new SegfaultWorkaround(byteArray, this, mime, sf);
|
||||
return;
|
||||
}
|
||||
if (!result.isEmpty()) {
|
||||
ioutils::addLogEntry(r, data, result, sf);
|
||||
utils::toClipboard(result);
|
||||
notifications::notify(tr("KShare imgur Uploader"), tr("Uploaded to imgur!"));
|
||||
notifications::playSound(notifications::Sound::SUCCESS);
|
||||
utils::toClipboard(result);
|
||||
} else {
|
||||
ioutils::addLogEntry(r, data, result, sf);
|
||||
notifications::notify(tr("KShare imgur Uploader "),
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#include "customuploader.hpp"
|
||||
#include "default/clipboarduploader.hpp"
|
||||
#include "default/imguruploader.hpp"
|
||||
#include "default/gdriveuploader.hpp"
|
||||
#include <QBuffer>
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
|
@ -33,6 +34,7 @@ UploaderSingleton::UploaderSingleton() : QObject() {
|
|||
|
||||
// UPLOADERS
|
||||
registerUploader(new ImgurUploader);
|
||||
registerUploader(new GDriveUploader);
|
||||
registerUploader(new ClipboardUploader);
|
||||
// ---------
|
||||
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
__pycache__
|
||||
*.pyc
|
Binary file not shown.
Before Width: | Height: | Size: 7.7 MiB |
File diff suppressed because it is too large
Load Diff
|
@ -1,94 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
# The MIT License (MIT)
|
||||
#
|
||||
# Copyright (c) <2013-2014> <Colin Duquesnoy>
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
# THE SOFTWARE.
|
||||
#
|
||||
"""
|
||||
A simple example of use.
|
||||
|
||||
Load an ui made in QtDesigner and apply the DarkStyleSheet.
|
||||
|
||||
|
||||
Requirements:
|
||||
- Python 2 or Python 3
|
||||
- PyQt4
|
||||
|
||||
.. note.. :: qdarkstyle does not have to be installed to run
|
||||
the example
|
||||
|
||||
"""
|
||||
import logging
|
||||
import sys
|
||||
from PyQt5 import QtWidgets, QtCore
|
||||
from PyQt5.QtCore import QFile, QTextStream
|
||||
# make the example runnable without the need to install
|
||||
|
||||
import example
|
||||
import breeze_resources
|
||||
|
||||
def main():
|
||||
"""
|
||||
Application entry point
|
||||
"""
|
||||
logging.basicConfig(level=logging.DEBUG)
|
||||
# create the application and the main window
|
||||
app = QtWidgets.QApplication(sys.argv)
|
||||
#app.setStyle(QtWidgets.QStyleFactory.create("fusion"))
|
||||
window = QtWidgets.QMainWindow()
|
||||
|
||||
# setup ui
|
||||
ui = example.Ui_MainWindow()
|
||||
ui.setupUi(window)
|
||||
ui.bt_delay_popup.addActions([
|
||||
ui.actionAction,
|
||||
ui.actionAction_C
|
||||
])
|
||||
ui.bt_instant_popup.addActions([
|
||||
ui.actionAction,
|
||||
ui.actionAction_C
|
||||
])
|
||||
ui.bt_menu_button_popup.addActions([
|
||||
ui.actionAction,
|
||||
ui.actionAction_C
|
||||
])
|
||||
window.setWindowTitle("BreezeDark example")
|
||||
|
||||
# tabify dock widgets to show bug #6
|
||||
window.tabifyDockWidget(ui.dockWidget1, ui.dockWidget2)
|
||||
|
||||
# setup stylesheet
|
||||
file = QFile(":/dark.qss")
|
||||
file.open(QFile.ReadOnly | QFile.Text)
|
||||
stream = QTextStream(file)
|
||||
app.setStyleSheet(stream.readAll())
|
||||
|
||||
# auto quit after 2s when testing on travis-ci
|
||||
if "--travis" in sys.argv:
|
||||
QtCore.QTimer.singleShot(2000, app.exit)
|
||||
|
||||
# run
|
||||
window.show()
|
||||
app.exec_()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
|
@ -1,359 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Form implementation generated from reading ui file 'example.ui'
|
||||
#
|
||||
# Created by: PyQt5 UI code generator 5.4.2
|
||||
#
|
||||
# WARNING! All changes made in this file will be lost!
|
||||
|
||||
from PyQt5 import QtCore, QtGui, QtWidgets
|
||||
|
||||
class Ui_MainWindow(object):
|
||||
def setupUi(self, MainWindow):
|
||||
MainWindow.setObjectName("MainWindow")
|
||||
MainWindow.resize(1068, 824)
|
||||
self.centralwidget = QtWidgets.QWidget(MainWindow)
|
||||
self.centralwidget.setObjectName("centralwidget")
|
||||
self.verticalLayout_5 = QtWidgets.QVBoxLayout(self.centralwidget)
|
||||
self.verticalLayout_5.setObjectName("verticalLayout_5")
|
||||
self.tabWidget = QtWidgets.QTabWidget(self.centralwidget)
|
||||
self.tabWidget.setTabPosition(QtWidgets.QTabWidget.East)
|
||||
self.tabWidget.setTabsClosable(True)
|
||||
self.tabWidget.setObjectName("tabWidget")
|
||||
self.tab = QtWidgets.QWidget()
|
||||
self.tab.setObjectName("tab")
|
||||
self.gridLayout = QtWidgets.QGridLayout(self.tab)
|
||||
self.gridLayout.setObjectName("gridLayout")
|
||||
self.groupBox = QtWidgets.QGroupBox(self.tab)
|
||||
self.groupBox.setObjectName("groupBox")
|
||||
self.verticalLayout_3 = QtWidgets.QVBoxLayout(self.groupBox)
|
||||
self.verticalLayout_3.setObjectName("verticalLayout_3")
|
||||
self.toolBox = QtWidgets.QToolBox(self.groupBox)
|
||||
self.toolBox.setObjectName("toolBox")
|
||||
self.page = QtWidgets.QWidget()
|
||||
self.page.setGeometry(QtCore.QRect(0, 0, 718, 227))
|
||||
self.page.setObjectName("page")
|
||||
self.gridLayout_4 = QtWidgets.QGridLayout(self.page)
|
||||
self.gridLayout_4.setObjectName("gridLayout_4")
|
||||
self.lineEdit = QtWidgets.QLineEdit(self.page)
|
||||
self.lineEdit.setObjectName("lineEdit")
|
||||
self.gridLayout_4.addWidget(self.lineEdit, 0, 0, 1, 1)
|
||||
self.toolBox.addItem(self.page, "")
|
||||
self.page_2 = QtWidgets.QWidget()
|
||||
self.page_2.setGeometry(QtCore.QRect(0, 0, 718, 227))
|
||||
self.page_2.setObjectName("page_2")
|
||||
self.gridLayout_5 = QtWidgets.QGridLayout(self.page_2)
|
||||
self.gridLayout_5.setObjectName("gridLayout_5")
|
||||
self.listWidget = QtWidgets.QListWidget(self.page_2)
|
||||
self.listWidget.setObjectName("listWidget")
|
||||
item = QtWidgets.QListWidgetItem()
|
||||
self.listWidget.addItem(item)
|
||||
item = QtWidgets.QListWidgetItem()
|
||||
self.listWidget.addItem(item)
|
||||
item = QtWidgets.QListWidgetItem()
|
||||
self.listWidget.addItem(item)
|
||||
item = QtWidgets.QListWidgetItem()
|
||||
self.listWidget.addItem(item)
|
||||
item = QtWidgets.QListWidgetItem()
|
||||
self.listWidget.addItem(item)
|
||||
item = QtWidgets.QListWidgetItem()
|
||||
self.listWidget.addItem(item)
|
||||
item = QtWidgets.QListWidgetItem()
|
||||
self.listWidget.addItem(item)
|
||||
item = QtWidgets.QListWidgetItem()
|
||||
self.listWidget.addItem(item)
|
||||
self.gridLayout_5.addWidget(self.listWidget, 0, 0, 1, 1)
|
||||
self.toolBox.addItem(self.page_2, "")
|
||||
self.verticalLayout_3.addWidget(self.toolBox)
|
||||
self.gridLayout.addWidget(self.groupBox, 1, 0, 1, 1)
|
||||
self.tabWidget_2 = QtWidgets.QTabWidget(self.tab)
|
||||
self.tabWidget_2.setObjectName("tabWidget_2")
|
||||
self.tab_3 = QtWidgets.QWidget()
|
||||
self.tab_3.setObjectName("tab_3")
|
||||
self.gridLayout_6 = QtWidgets.QGridLayout(self.tab_3)
|
||||
self.gridLayout_6.setObjectName("gridLayout_6")
|
||||
self.checkableButton = QtWidgets.QPushButton(self.tab_3)
|
||||
self.checkableButton.setCheckable(True)
|
||||
self.checkableButton.setChecked(True)
|
||||
self.checkableButton.setObjectName("checkableButton")
|
||||
self.gridLayout_6.addWidget(self.checkableButton, 1, 0, 1, 1)
|
||||
self.pushButton = QtWidgets.QPushButton(self.tab_3)
|
||||
self.pushButton.setObjectName("pushButton")
|
||||
self.gridLayout_6.addWidget(self.pushButton, 0, 0, 1, 1)
|
||||
self.pushButton_5 = QtWidgets.QPushButton(self.tab_3)
|
||||
self.pushButton_5.setObjectName("pushButton_5")
|
||||
self.gridLayout_6.addWidget(self.pushButton_5, 2, 0, 1, 1)
|
||||
self.tabWidget_2.addTab(self.tab_3, "")
|
||||
self.tab_5 = QtWidgets.QWidget()
|
||||
self.tab_5.setObjectName("tab_5")
|
||||
self.gridLayout_7 = QtWidgets.QGridLayout(self.tab_5)
|
||||
self.gridLayout_7.setObjectName("gridLayout_7")
|
||||
self.tableWidget = QtWidgets.QTableWidget(self.tab_5)
|
||||
self.tableWidget.setObjectName("tableWidget")
|
||||
self.tableWidget.setColumnCount(2)
|
||||
self.tableWidget.setRowCount(4)
|
||||
item = QtWidgets.QTableWidgetItem()
|
||||
self.tableWidget.setVerticalHeaderItem(0, item)
|
||||
item = QtWidgets.QTableWidgetItem()
|
||||
self.tableWidget.setVerticalHeaderItem(1, item)
|
||||
item = QtWidgets.QTableWidgetItem()
|
||||
self.tableWidget.setVerticalHeaderItem(2, item)
|
||||
item = QtWidgets.QTableWidgetItem()
|
||||
self.tableWidget.setVerticalHeaderItem(3, item)
|
||||
item = QtWidgets.QTableWidgetItem()
|
||||
self.tableWidget.setHorizontalHeaderItem(0, item)
|
||||
item = QtWidgets.QTableWidgetItem()
|
||||
self.tableWidget.setHorizontalHeaderItem(1, item)
|
||||
self.gridLayout_7.addWidget(self.tableWidget, 0, 0, 1, 1)
|
||||
self.tabWidget_2.addTab(self.tab_5, "")
|
||||
self.tab_4 = QtWidgets.QWidget()
|
||||
self.tab_4.setObjectName("tab_4")
|
||||
self.tabWidget_2.addTab(self.tab_4, "")
|
||||
self.gridLayout.addWidget(self.tabWidget_2, 0, 0, 1, 1)
|
||||
self.tabWidget.addTab(self.tab, "")
|
||||
self.tab_2 = QtWidgets.QWidget()
|
||||
self.tab_2.setObjectName("tab_2")
|
||||
self.gridLayout_2 = QtWidgets.QGridLayout(self.tab_2)
|
||||
self.gridLayout_2.setObjectName("gridLayout_2")
|
||||
self.groupBox_2 = QtWidgets.QGroupBox(self.tab_2)
|
||||
self.groupBox_2.setObjectName("groupBox_2")
|
||||
self.verticalLayout_4 = QtWidgets.QVBoxLayout(self.groupBox_2)
|
||||
self.verticalLayout_4.setObjectName("verticalLayout_4")
|
||||
self.label = QtWidgets.QLabel(self.groupBox_2)
|
||||
self.label.setObjectName("label")
|
||||
self.verticalLayout_4.addWidget(self.label)
|
||||
self.radioButton = QtWidgets.QRadioButton(self.groupBox_2)
|
||||
self.radioButton.setObjectName("radioButton")
|
||||
self.verticalLayout_4.addWidget(self.radioButton)
|
||||
self.checkBox = QtWidgets.QCheckBox(self.groupBox_2)
|
||||
self.checkBox.setObjectName("checkBox")
|
||||
self.verticalLayout_4.addWidget(self.checkBox)
|
||||
self.checkBox_2 = QtWidgets.QCheckBox(self.groupBox_2)
|
||||
self.checkBox_2.setTristate(True)
|
||||
self.checkBox_2.setObjectName("checkBox_2")
|
||||
self.verticalLayout_4.addWidget(self.checkBox_2)
|
||||
self.treeWidget = QtWidgets.QTreeWidget(self.groupBox_2)
|
||||
self.treeWidget.setObjectName("treeWidget")
|
||||
item_0 = QtWidgets.QTreeWidgetItem(self.treeWidget)
|
||||
item_1 = QtWidgets.QTreeWidgetItem(self.treeWidget)
|
||||
item_2 = QtWidgets.QTreeWidgetItem(item_1)
|
||||
item_2.setText(0, "subitem")
|
||||
self.verticalLayout_4.addWidget(self.treeWidget)
|
||||
self.gridLayout_2.addWidget(self.groupBox_2, 0, 0, 1, 1)
|
||||
self.tabWidget.addTab(self.tab_2, "")
|
||||
self.verticalLayout_5.addWidget(self.tabWidget)
|
||||
self.horizontalLayout = QtWidgets.QHBoxLayout()
|
||||
self.horizontalLayout.setObjectName("horizontalLayout")
|
||||
self.pushButton_2 = QtWidgets.QPushButton(self.centralwidget)
|
||||
self.pushButton_2.setObjectName("pushButton_2")
|
||||
self.horizontalLayout.addWidget(self.pushButton_2)
|
||||
self.bt_delay_popup = QtWidgets.QToolButton(self.centralwidget)
|
||||
self.bt_delay_popup.setObjectName("bt_delay_popup")
|
||||
self.horizontalLayout.addWidget(self.bt_delay_popup)
|
||||
self.bt_instant_popup = QtWidgets.QToolButton(self.centralwidget)
|
||||
self.bt_instant_popup.setPopupMode(QtWidgets.QToolButton.InstantPopup)
|
||||
self.bt_instant_popup.setObjectName("bt_instant_popup")
|
||||
self.horizontalLayout.addWidget(self.bt_instant_popup)
|
||||
self.bt_menu_button_popup = QtWidgets.QToolButton(self.centralwidget)
|
||||
self.bt_menu_button_popup.setPopupMode(QtWidgets.QToolButton.MenuButtonPopup)
|
||||
self.bt_menu_button_popup.setObjectName("bt_menu_button_popup")
|
||||
self.horizontalLayout.addWidget(self.bt_menu_button_popup)
|
||||
self.line_2 = QtWidgets.QFrame(self.centralwidget)
|
||||
self.line_2.setFrameShape(QtWidgets.QFrame.VLine)
|
||||
self.line_2.setFrameShadow(QtWidgets.QFrame.Sunken)
|
||||
self.line_2.setObjectName("line_2")
|
||||
self.horizontalLayout.addWidget(self.line_2)
|
||||
self.pushButton_3 = QtWidgets.QPushButton(self.centralwidget)
|
||||
self.pushButton_3.setEnabled(False)
|
||||
self.pushButton_3.setObjectName("pushButton_3")
|
||||
self.horizontalLayout.addWidget(self.pushButton_3)
|
||||
self.doubleSpinBox = QtWidgets.QDoubleSpinBox(self.centralwidget)
|
||||
self.doubleSpinBox.setObjectName("doubleSpinBox")
|
||||
self.horizontalLayout.addWidget(self.doubleSpinBox)
|
||||
self.toolButton = QtWidgets.QToolButton(self.centralwidget)
|
||||
self.toolButton.setPopupMode(QtWidgets.QToolButton.InstantPopup)
|
||||
self.toolButton.setObjectName("toolButton")
|
||||
self.horizontalLayout.addWidget(self.toolButton)
|
||||
self.verticalLayout_5.addLayout(self.horizontalLayout)
|
||||
MainWindow.setCentralWidget(self.centralwidget)
|
||||
self.menubar = QtWidgets.QMenuBar(MainWindow)
|
||||
self.menubar.setGeometry(QtCore.QRect(0, 0, 1068, 29))
|
||||
self.menubar.setObjectName("menubar")
|
||||
self.menuMenu = QtWidgets.QMenu(self.menubar)
|
||||
self.menuMenu.setObjectName("menuMenu")
|
||||
self.menuSubmenu_2 = QtWidgets.QMenu(self.menuMenu)
|
||||
self.menuSubmenu_2.setObjectName("menuSubmenu_2")
|
||||
MainWindow.setMenuBar(self.menubar)
|
||||
self.statusbar = QtWidgets.QStatusBar(MainWindow)
|
||||
self.statusbar.setObjectName("statusbar")
|
||||
MainWindow.setStatusBar(self.statusbar)
|
||||
self.dockWidget1 = QtWidgets.QDockWidget(MainWindow)
|
||||
self.dockWidget1.setObjectName("dockWidget1")
|
||||
self.dockWidgetContents = QtWidgets.QWidget()
|
||||
self.dockWidgetContents.setObjectName("dockWidgetContents")
|
||||
self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.dockWidgetContents)
|
||||
self.verticalLayout_2.setObjectName("verticalLayout_2")
|
||||
self.verticalLayout = QtWidgets.QVBoxLayout()
|
||||
self.verticalLayout.setObjectName("verticalLayout")
|
||||
self.comboBox = QtWidgets.QComboBox(self.dockWidgetContents)
|
||||
self.comboBox.setObjectName("comboBox")
|
||||
self.comboBox.addItem("")
|
||||
self.comboBox.addItem("")
|
||||
self.verticalLayout.addWidget(self.comboBox)
|
||||
self.horizontalSlider = QtWidgets.QSlider(self.dockWidgetContents)
|
||||
self.horizontalSlider.setOrientation(QtCore.Qt.Horizontal)
|
||||
self.horizontalSlider.setObjectName("horizontalSlider")
|
||||
self.verticalLayout.addWidget(self.horizontalSlider)
|
||||
self.textEdit = QtWidgets.QTextEdit(self.dockWidgetContents)
|
||||
self.textEdit.setObjectName("textEdit")
|
||||
self.verticalLayout.addWidget(self.textEdit)
|
||||
self.line = QtWidgets.QFrame(self.dockWidgetContents)
|
||||
self.line.setFrameShape(QtWidgets.QFrame.HLine)
|
||||
self.line.setFrameShadow(QtWidgets.QFrame.Sunken)
|
||||
self.line.setObjectName("line")
|
||||
self.verticalLayout.addWidget(self.line)
|
||||
self.progressBar = QtWidgets.QProgressBar(self.dockWidgetContents)
|
||||
self.progressBar.setProperty("value", 24)
|
||||
self.progressBar.setObjectName("progressBar")
|
||||
self.verticalLayout.addWidget(self.progressBar)
|
||||
self.verticalLayout_2.addLayout(self.verticalLayout)
|
||||
self.frame = QtWidgets.QFrame(self.dockWidgetContents)
|
||||
self.frame.setMinimumSize(QtCore.QSize(0, 100))
|
||||
self.frame.setFrameShape(QtWidgets.QFrame.StyledPanel)
|
||||
self.frame.setFrameShadow(QtWidgets.QFrame.Raised)
|
||||
self.frame.setLineWidth(3)
|
||||
self.frame.setObjectName("frame")
|
||||
self.verticalLayout_2.addWidget(self.frame)
|
||||
self.dockWidget1.setWidget(self.dockWidgetContents)
|
||||
MainWindow.addDockWidget(QtCore.Qt.DockWidgetArea(1), self.dockWidget1)
|
||||
self.toolBar = QtWidgets.QToolBar(MainWindow)
|
||||
self.toolBar.setObjectName("toolBar")
|
||||
MainWindow.addToolBar(QtCore.Qt.TopToolBarArea, self.toolBar)
|
||||
self.dockWidget2 = QtWidgets.QDockWidget(MainWindow)
|
||||
self.dockWidget2.setObjectName("dockWidget2")
|
||||
self.dockWidgetContents_2 = QtWidgets.QWidget()
|
||||
self.dockWidgetContents_2.setObjectName("dockWidgetContents_2")
|
||||
self.gridLayout_3 = QtWidgets.QGridLayout(self.dockWidgetContents_2)
|
||||
self.gridLayout_3.setObjectName("gridLayout_3")
|
||||
self.verticalSlider = QtWidgets.QSlider(self.dockWidgetContents_2)
|
||||
self.verticalSlider.setOrientation(QtCore.Qt.Vertical)
|
||||
self.verticalSlider.setObjectName("verticalSlider")
|
||||
self.gridLayout_3.addWidget(self.verticalSlider, 0, 0, 1, 1)
|
||||
self.dockWidget2.setWidget(self.dockWidgetContents_2)
|
||||
MainWindow.addDockWidget(QtCore.Qt.DockWidgetArea(1), self.dockWidget2)
|
||||
self.actionAction = QtWidgets.QAction(MainWindow)
|
||||
self.actionAction.setObjectName("actionAction")
|
||||
self.actionSub_menu = QtWidgets.QAction(MainWindow)
|
||||
self.actionSub_menu.setObjectName("actionSub_menu")
|
||||
self.actionAction_C = QtWidgets.QAction(MainWindow)
|
||||
self.actionAction_C.setObjectName("actionAction_C")
|
||||
self.menuSubmenu_2.addAction(self.actionSub_menu)
|
||||
self.menuSubmenu_2.addAction(self.actionAction_C)
|
||||
self.menuMenu.addAction(self.actionAction)
|
||||
self.menuMenu.addAction(self.menuSubmenu_2.menuAction())
|
||||
self.menubar.addAction(self.menuMenu.menuAction())
|
||||
self.toolBar.addAction(self.actionAction)
|
||||
self.toolBar.addAction(self.actionSub_menu)
|
||||
|
||||
self.retranslateUi(MainWindow)
|
||||
self.tabWidget.setCurrentIndex(0)
|
||||
self.toolBox.setCurrentIndex(1)
|
||||
self.tabWidget_2.setCurrentIndex(0)
|
||||
QtCore.QMetaObject.connectSlotsByName(MainWindow)
|
||||
MainWindow.setTabOrder(self.pushButton, self.checkableButton)
|
||||
MainWindow.setTabOrder(self.checkableButton, self.pushButton_5)
|
||||
MainWindow.setTabOrder(self.pushButton_5, self.tabWidget_2)
|
||||
MainWindow.setTabOrder(self.tabWidget_2, self.tableWidget)
|
||||
MainWindow.setTabOrder(self.tableWidget, self.radioButton)
|
||||
MainWindow.setTabOrder(self.radioButton, self.checkBox)
|
||||
MainWindow.setTabOrder(self.checkBox, self.checkBox_2)
|
||||
MainWindow.setTabOrder(self.checkBox_2, self.treeWidget)
|
||||
MainWindow.setTabOrder(self.treeWidget, self.pushButton_2)
|
||||
MainWindow.setTabOrder(self.pushButton_2, self.bt_delay_popup)
|
||||
MainWindow.setTabOrder(self.bt_delay_popup, self.bt_instant_popup)
|
||||
MainWindow.setTabOrder(self.bt_instant_popup, self.bt_menu_button_popup)
|
||||
MainWindow.setTabOrder(self.bt_menu_button_popup, self.pushButton_3)
|
||||
MainWindow.setTabOrder(self.pushButton_3, self.doubleSpinBox)
|
||||
MainWindow.setTabOrder(self.doubleSpinBox, self.toolButton)
|
||||
MainWindow.setTabOrder(self.toolButton, self.comboBox)
|
||||
MainWindow.setTabOrder(self.comboBox, self.horizontalSlider)
|
||||
MainWindow.setTabOrder(self.horizontalSlider, self.textEdit)
|
||||
MainWindow.setTabOrder(self.textEdit, self.verticalSlider)
|
||||
MainWindow.setTabOrder(self.verticalSlider, self.tabWidget)
|
||||
MainWindow.setTabOrder(self.tabWidget, self.lineEdit)
|
||||
MainWindow.setTabOrder(self.lineEdit, self.listWidget)
|
||||
|
||||
def retranslateUi(self, MainWindow):
|
||||
_translate = QtCore.QCoreApplication.translate
|
||||
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
|
||||
self.groupBox.setTitle(_translate("MainWindow", "ToolBox"))
|
||||
self.toolBox.setItemText(self.toolBox.indexOf(self.page), _translate("MainWindow", "Page 1"))
|
||||
__sortingEnabled = self.listWidget.isSortingEnabled()
|
||||
self.listWidget.setSortingEnabled(False)
|
||||
item = self.listWidget.item(0)
|
||||
item.setText(_translate("MainWindow", "New Item"))
|
||||
item = self.listWidget.item(1)
|
||||
item.setText(_translate("MainWindow", "New Item"))
|
||||
item = self.listWidget.item(2)
|
||||
item.setText(_translate("MainWindow", "New Item"))
|
||||
item = self.listWidget.item(3)
|
||||
item.setText(_translate("MainWindow", "New Item"))
|
||||
item = self.listWidget.item(4)
|
||||
item.setText(_translate("MainWindow", "New Item"))
|
||||
item = self.listWidget.item(5)
|
||||
item.setText(_translate("MainWindow", "New Item"))
|
||||
item = self.listWidget.item(6)
|
||||
item.setText(_translate("MainWindow", "New Item"))
|
||||
item = self.listWidget.item(7)
|
||||
item.setText(_translate("MainWindow", "New Item"))
|
||||
self.listWidget.setSortingEnabled(__sortingEnabled)
|
||||
self.toolBox.setItemText(self.toolBox.indexOf(self.page_2), _translate("MainWindow", "Page 2"))
|
||||
self.checkableButton.setText(_translate("MainWindow", "Checkable button"))
|
||||
self.pushButton.setText(_translate("MainWindow", "PushButton"))
|
||||
self.pushButton_5.setText(_translate("MainWindow", "PushButton"))
|
||||
self.tabWidget_2.setTabText(self.tabWidget_2.indexOf(self.tab_3), _translate("MainWindow", "Tab 1"))
|
||||
item = self.tableWidget.verticalHeaderItem(0)
|
||||
item.setText(_translate("MainWindow", "New Row"))
|
||||
item = self.tableWidget.verticalHeaderItem(1)
|
||||
item.setText(_translate("MainWindow", "New Row"))
|
||||
item = self.tableWidget.verticalHeaderItem(2)
|
||||
item.setText(_translate("MainWindow", "New Row"))
|
||||
item = self.tableWidget.verticalHeaderItem(3)
|
||||
item.setText(_translate("MainWindow", "New Row"))
|
||||
item = self.tableWidget.horizontalHeaderItem(0)
|
||||
item.setText(_translate("MainWindow", "New Column"))
|
||||
item = self.tableWidget.horizontalHeaderItem(1)
|
||||
item.setText(_translate("MainWindow", "New Column 2"))
|
||||
self.tabWidget_2.setTabText(self.tabWidget_2.indexOf(self.tab_5), _translate("MainWindow", "Page"))
|
||||
self.tabWidget_2.setTabText(self.tabWidget_2.indexOf(self.tab_4), _translate("MainWindow", "Tab 2"))
|
||||
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab), _translate("MainWindow", "Tab 1"))
|
||||
self.groupBox_2.setTitle(_translate("MainWindow", "GroupBox"))
|
||||
self.label.setText(_translate("MainWindow", "TextLabel"))
|
||||
self.radioButton.setText(_translate("MainWindow", "RadioB&utton"))
|
||||
self.checkBox.setText(_translate("MainWindow", "CheckBox"))
|
||||
self.checkBox_2.setText(_translate("MainWindow", "CheckBox Tristate"))
|
||||
self.treeWidget.headerItem().setText(0, _translate("MainWindow", "qdz"))
|
||||
__sortingEnabled = self.treeWidget.isSortingEnabled()
|
||||
self.treeWidget.setSortingEnabled(False)
|
||||
self.treeWidget.topLevelItem(0).setText(0, _translate("MainWindow", "qzd"))
|
||||
self.treeWidget.topLevelItem(1).setText(0, _translate("MainWindow", "effefe"))
|
||||
self.treeWidget.setSortingEnabled(__sortingEnabled)
|
||||
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_2), _translate("MainWindow", "Tab 2"))
|
||||
self.pushButton_2.setText(_translate("MainWindow", "PushButton"))
|
||||
self.bt_delay_popup.setText(_translate("MainWindow", "Delayed popup "))
|
||||
self.bt_instant_popup.setText(_translate("MainWindow", "Instant popup"))
|
||||
self.bt_menu_button_popup.setText(_translate("MainWindow", "MenuButtonPopup"))
|
||||
self.pushButton_3.setText(_translate("MainWindow", "Disabled"))
|
||||
self.toolButton.setText(_translate("MainWindow", "..."))
|
||||
self.menuMenu.setTitle(_translate("MainWindow", "&Menu"))
|
||||
self.menuSubmenu_2.setTitle(_translate("MainWindow", "&Submenu 2"))
|
||||
self.dockWidget1.setWindowTitle(_translate("MainWindow", "&Dock widget 1"))
|
||||
self.comboBox.setItemText(0, _translate("MainWindow", "Item 0"))
|
||||
self.comboBox.setItemText(1, _translate("MainWindow", "Item 2"))
|
||||
self.toolBar.setWindowTitle(_translate("MainWindow", "toolBar"))
|
||||
self.dockWidget2.setWindowTitle(_translate("MainWindow", "Dock widget &2"))
|
||||
self.actionAction.setText(_translate("MainWindow", "&Action"))
|
||||
self.actionSub_menu.setText(_translate("MainWindow", "&Action B"))
|
||||
self.actionSub_menu.setToolTip(_translate("MainWindow", "submenu"))
|
||||
self.actionAction_C.setText(_translate("MainWindow", "Action &C"))
|
||||
|
|
@ -1,94 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
# The MIT License (MIT)
|
||||
#
|
||||
# Copyright (c) <2013-2014> <Colin Duquesnoy>
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
# THE SOFTWARE.
|
||||
#
|
||||
"""
|
||||
A simple example of use.
|
||||
|
||||
Load an ui made in QtDesigner and apply the DarkStyleSheet.
|
||||
|
||||
|
||||
Requirements:
|
||||
- Python 2 or Python 3
|
||||
- PyQt4
|
||||
|
||||
.. note.. :: qdarkstyle does not have to be installed to run
|
||||
the example
|
||||
|
||||
"""
|
||||
import logging
|
||||
import sys
|
||||
from PyQt5 import QtWidgets, QtCore
|
||||
from PyQt5.QtCore import QFile, QTextStream
|
||||
# make the example runnable without the need to install
|
||||
|
||||
import example
|
||||
import breeze_resources
|
||||
|
||||
def main():
|
||||
"""
|
||||
Application entry point
|
||||
"""
|
||||
logging.basicConfig(level=logging.DEBUG)
|
||||
# create the application and the main window
|
||||
app = QtWidgets.QApplication(sys.argv)
|
||||
#app.setStyle(QtWidgets.QStyleFactory.create("fusion"))
|
||||
window = QtWidgets.QMainWindow()
|
||||
|
||||
# setup ui
|
||||
ui = example.Ui_MainWindow()
|
||||
ui.setupUi(window)
|
||||
ui.bt_delay_popup.addActions([
|
||||
ui.actionAction,
|
||||
ui.actionAction_C
|
||||
])
|
||||
ui.bt_instant_popup.addActions([
|
||||
ui.actionAction,
|
||||
ui.actionAction_C
|
||||
])
|
||||
ui.bt_menu_button_popup.addActions([
|
||||
ui.actionAction,
|
||||
ui.actionAction_C
|
||||
])
|
||||
window.setWindowTitle("Breeze example")
|
||||
|
||||
# tabify dock widgets to show bug #6
|
||||
window.tabifyDockWidget(ui.dockWidget1, ui.dockWidget2)
|
||||
|
||||
# setup stylesheet
|
||||
file = QFile(":/light.qss")
|
||||
file.open(QFile.ReadOnly | QFile.Text)
|
||||
stream = QTextStream(file)
|
||||
app.setStyleSheet(stream.readAll())
|
||||
|
||||
# auto quit after 2s when testing on travis-ci
|
||||
if "--travis" in sys.argv:
|
||||
QtCore.QTimer.singleShot(2000, app.exit)
|
||||
|
||||
# run
|
||||
window.show()
|
||||
app.exec_()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
|
@ -1,87 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
# The MIT License (MIT)
|
||||
#
|
||||
# Copyright (c) <2013-2014> <Colin Duquesnoy>
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
# THE SOFTWARE.
|
||||
#
|
||||
"""
|
||||
A simple example of use.
|
||||
|
||||
Load an ui made in QtDesigner and apply the DarkStyleSheet.
|
||||
|
||||
|
||||
Requirements:
|
||||
- Python 2 or Python 3
|
||||
- PyQt4
|
||||
|
||||
.. note.. :: qdarkstyle does not have to be installed to run
|
||||
the example
|
||||
|
||||
"""
|
||||
import logging
|
||||
import sys
|
||||
from PyQt5 import QtWidgets, QtCore
|
||||
# make the example runnable without the need to install
|
||||
|
||||
import example
|
||||
|
||||
|
||||
def main():
|
||||
"""
|
||||
Application entry point
|
||||
"""
|
||||
logging.basicConfig(level=logging.DEBUG)
|
||||
# create the application and the main window
|
||||
app = QtWidgets.QApplication(sys.argv)
|
||||
#app.setStyle(QtWidgets.QStyleFactory.create("fusion"))
|
||||
window = QtWidgets.QMainWindow()
|
||||
|
||||
# setup ui
|
||||
ui = example.Ui_MainWindow()
|
||||
ui.setupUi(window)
|
||||
ui.bt_delay_popup.addActions([
|
||||
ui.actionAction,
|
||||
ui.actionAction_C
|
||||
])
|
||||
ui.bt_instant_popup.addActions([
|
||||
ui.actionAction,
|
||||
ui.actionAction_C
|
||||
])
|
||||
ui.bt_menu_button_popup.addActions([
|
||||
ui.actionAction,
|
||||
ui.actionAction_C
|
||||
])
|
||||
window.setWindowTitle("Native example")
|
||||
|
||||
# tabify dock widgets to show bug #6
|
||||
window.tabifyDockWidget(ui.dockWidget1, ui.dockWidget2)
|
||||
|
||||
# auto quit after 2s when testing on travis-ci
|
||||
if "--travis" in sys.argv:
|
||||
QtCore.QTimer.singleShot(2000, app.exit)
|
||||
|
||||
# run
|
||||
window.show()
|
||||
app.exec_()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
|
@ -1,473 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""QDarkStyle is a dark stylesheet for Python and Qt applications.
|
||||
|
||||
This module provides a function to transparently load the stylesheets
|
||||
with the correct rc file.
|
||||
|
||||
First, start importing our module
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import qdarkstyle
|
||||
|
||||
Then you can get stylesheet provided by QDarkStyle for various Qt wrappers
|
||||
as shown bellow
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# PySide
|
||||
dark_stylesheet = qdarkstyle.load_stylesheet_pyside()
|
||||
# PySide 2
|
||||
dark_stylesheet = qdarkstyle.load_stylesheet_pyside2()
|
||||
# PyQt4
|
||||
dark_stylesheet = qdarkstyle.load_stylesheet_pyqt()
|
||||
# PyQt5
|
||||
dark_stylesheet = qdarkstyle.load_stylesheet_pyqt5()
|
||||
|
||||
Or from environment variables provided for QtPy or PyQtGraph, see
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# QtPy
|
||||
dark_stylesheet = qdarkstyle.load_stylesheet_from_environment()
|
||||
# PyQtGraph
|
||||
dark_stylesheet = qdarkstyle.load_stylesheet_from_environment(is_pyqtgraph)
|
||||
|
||||
Finally, set your QApplication with it
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
app.setStyleSheet(dark_stylesheet)
|
||||
|
||||
Enjoy!
|
||||
|
||||
"""
|
||||
|
||||
import logging
|
||||
import os
|
||||
import platform
|
||||
import sys
|
||||
import warnings
|
||||
import copy
|
||||
|
||||
if sys.version_info >= (3, 4):
|
||||
import importlib
|
||||
|
||||
__version__ = "2.6.8"
|
||||
|
||||
|
||||
QT_BINDINGS = ['PyQt4', 'PyQt5', 'PySide', 'PySide2']
|
||||
"""list: values of all Qt bindings to import."""
|
||||
|
||||
QT_ABSTRACTIONS = ['qtpy', 'pyqtgraph', 'Qt']
|
||||
"""list: values of all Qt abstraction layers to import."""
|
||||
|
||||
QT4_IMPORT_API = ['QtCore', 'QtGui']
|
||||
"""list: which subpackage to import for Qt4 API."""
|
||||
|
||||
QT5_IMPORT_API = ['QtCore', 'QtGui', 'QtWidgets']
|
||||
"""list: which subpackage to import for Qt5 API."""
|
||||
|
||||
QT_API_VALUES = ['pyqt', 'pyqt5', 'pyside', 'pyside2']
|
||||
"""list: values for QT_API environment variable used by QtPy."""
|
||||
|
||||
QT_LIB_VALUES = ['PyQt', 'PyQt5', 'PySide', 'PySide2']
|
||||
"""list: values for PYQTGRAPH_QT_LIB environment variable used by PyQtGraph."""
|
||||
|
||||
QT_BINDING = 'Not set or nonexistent'
|
||||
"""str: Qt binding in use."""
|
||||
|
||||
QT_ABSTRACTION = 'Not set or nonexistent'
|
||||
"""str: Qt abstraction layer in use."""
|
||||
|
||||
|
||||
def _logger():
|
||||
return logging.getLogger('qdarkstyle')
|
||||
|
||||
|
||||
def _qt_wrapper_import(qt_api):
|
||||
"""
|
||||
Check if Qt API defined can be imported.
|
||||
|
||||
:param qt_api: Qt API string to test import
|
||||
|
||||
:return load function fot given qt_api, otherwise empty string
|
||||
|
||||
"""
|
||||
qt_wrapper = ''
|
||||
loader = ""
|
||||
|
||||
try:
|
||||
if qt_api == 'PyQt' or qt_api == 'pyqt':
|
||||
import PyQt4
|
||||
qt_wrapper = 'PyQt4'
|
||||
loader = load_stylesheet_pyqt()
|
||||
elif qt_api == 'PyQt5' or qt_api == 'pyqt5':
|
||||
import PyQt5
|
||||
qt_wrapper = 'PyQt5'
|
||||
loader = load_stylesheet_pyqt5()
|
||||
elif qt_api == 'PySide' or qt_api == 'pyside':
|
||||
import PySide
|
||||
qt_wrapper = 'PySide'
|
||||
loader = load_stylesheet_pyside()
|
||||
elif qt_api == 'PySide2' or qt_api == 'pyside2':
|
||||
import PySide2
|
||||
qt_wrapper = 'PySide2'
|
||||
loader = load_stylesheet_pyside2()
|
||||
except ImportError as err:
|
||||
_logger().error("Impossible import Qt wrapper.\n %s", str(err))
|
||||
else:
|
||||
_logger().info("Using Qt wrapper = %s ", qt_wrapper)
|
||||
QT_BINDING = qt_wrapper
|
||||
finally:
|
||||
return loader
|
||||
|
||||
|
||||
def load_stylesheet_from_environment(is_pyqtgraph=False):
|
||||
"""
|
||||
Load the stylesheet from QT_API (or PYQTGRAPH_QT_LIB) environment variable.
|
||||
|
||||
:param is_pyqtgraph: True if it is to be set using PYQTGRAPH_QT_LIB
|
||||
|
||||
:raise KeyError: if QT_API/PYQTGRAPH_QT_LIB does not exist
|
||||
|
||||
:return the stylesheet string
|
||||
"""
|
||||
warnings.warn(
|
||||
"load_stylesheet_from_environment() will be deprecated in version 3,"
|
||||
"use load_stylesheet()",
|
||||
PendingDeprecationWarning
|
||||
)
|
||||
qt_api = ''
|
||||
pyqtgraph_qt_lib = ''
|
||||
|
||||
loader = ""
|
||||
|
||||
# Get values from QT_API
|
||||
try:
|
||||
qt_api = os.environ['QT_API']
|
||||
except KeyError as err:
|
||||
# Log this error just if using QT_API
|
||||
if not is_pyqtgraph:
|
||||
_logger().error("QT_API does not exist, do os.environ['QT_API']= "
|
||||
"and choose one option from %s", QT_API_VALUES)
|
||||
else:
|
||||
if not is_pyqtgraph:
|
||||
if qt_api in QT_API_VALUES:
|
||||
QT_ABSTRACTION = "qtpy"
|
||||
_logger().info("Found QT_API='%s'", qt_api)
|
||||
loader = _qt_wrapper_import(qt_api)
|
||||
else:
|
||||
# Raise this error because the function need this key/value
|
||||
raise KeyError("QT_API=%s is unknown, please use a value "
|
||||
"from %s",
|
||||
(qt_api, QT_API_VALUES))
|
||||
|
||||
# Get values from PYQTGRAPH_QT_LIB
|
||||
try:
|
||||
pyqtgraph_qt_lib = os.environ['PYQTGRAPH_QT_LIB']
|
||||
except KeyError as err:
|
||||
# Log this error just if using PYQTGRAPH_QT_LIB
|
||||
if is_pyqtgraph:
|
||||
_logger().error("PYQTGRAP_QT_API does not exist, do "
|
||||
"os.environ['PYQTGRAPH_QT_LIB']= "
|
||||
"and choose one option from %s",
|
||||
QT_LIB_VALUES)
|
||||
else:
|
||||
|
||||
if is_pyqtgraph:
|
||||
if pyqtgraph_qt_lib in QT_LIB_VALUES:
|
||||
QT_ABSTRACTION = "pyqtgraph"
|
||||
_logger().info("Found PYQTGRAPH_QT_LIB='%s'", pyqtgraph_qt_lib)
|
||||
loader = _qt_wrapper_import(pyqtgraph_qt_lib)
|
||||
else:
|
||||
# Raise this error because the function need this key/value
|
||||
raise KeyError("PYQTGRAPH_QT_LIB=%s is unknown, please use a "
|
||||
"value from %s", (
|
||||
pyqtgraph_qt_lib,
|
||||
QT_LIB_VALUES))
|
||||
|
||||
# Just a warning if both are set but differs each other
|
||||
if qt_api and pyqtgraph_qt_lib:
|
||||
if qt_api != pyqtgraph_qt_lib.lower():
|
||||
_logger().warning("Both QT_API=%s and PYQTGRAPH_QT_LIB=%s are set, "
|
||||
"but with different values, this could cause "
|
||||
"some issues if using them in the same project!",
|
||||
qt_api, pyqtgraph_qt_lib)
|
||||
|
||||
return loader
|
||||
|
||||
|
||||
def load_stylesheet(pyside=True):
|
||||
"""
|
||||
Load the stylesheet. Takes care of importing the rc module.
|
||||
|
||||
:param pyside: True to load the pyside rc file, False to load the PyQt rc file
|
||||
|
||||
:return the stylesheet string
|
||||
"""
|
||||
warnings.warn(
|
||||
"load_stylesheet() will not receive pyside parameter in version 3. "
|
||||
"Set QtPy environment variable to specify the Qt binding insteady.",
|
||||
PendingDeprecationWarning
|
||||
)
|
||||
# Smart import of the rc file
|
||||
|
||||
pyside_ver = None
|
||||
|
||||
if pyside:
|
||||
|
||||
# Detect the PySide version available
|
||||
try:
|
||||
import PySide
|
||||
except ImportError: # Compatible with py27
|
||||
import PySide2
|
||||
pyside_ver = 2
|
||||
else:
|
||||
pyside_ver = 1
|
||||
|
||||
if pyside_ver == 1:
|
||||
import qdarkstyle.pyside_style_rc
|
||||
else:
|
||||
import qdarkstyle.pyside2_style_rc
|
||||
else:
|
||||
import qdarkstyle.pyqt_style_rc
|
||||
|
||||
# Load the stylesheet content from resources
|
||||
if not pyside:
|
||||
from PyQt4.QtCore import QFile, QTextStream
|
||||
else:
|
||||
if pyside_ver == 1:
|
||||
from PySide.QtCore import QFile, QTextStream
|
||||
else:
|
||||
from PySide2.QtCore import QFile, QTextStream
|
||||
|
||||
f = QFile(":qdarkstyle/style.qss")
|
||||
if not f.exists():
|
||||
_logger().error("Unable to load stylesheet, file not found in "
|
||||
"resources")
|
||||
return ""
|
||||
else:
|
||||
f.open(QFile.ReadOnly | QFile.Text)
|
||||
ts = QTextStream(f)
|
||||
stylesheet = ts.readAll()
|
||||
if platform.system().lower() == 'darwin': # see issue #12 on github
|
||||
mac_fix = '''
|
||||
QDockWidget::title
|
||||
{
|
||||
background-color: #32414B;
|
||||
text-align: center;
|
||||
height: 12px;
|
||||
}
|
||||
'''
|
||||
stylesheet += mac_fix
|
||||
return stylesheet
|
||||
|
||||
|
||||
def load_stylesheet_pyside():
|
||||
"""
|
||||
Load the stylesheet for use in a pyside application.
|
||||
|
||||
:return the stylesheet string
|
||||
"""
|
||||
warnings.warn(
|
||||
"load_stylesheet_pyside() will be deprecated in version 3,"
|
||||
"set QtPy environment variable to specify the Qt binding and "
|
||||
"use load_stylesheet()",
|
||||
PendingDeprecationWarning
|
||||
)
|
||||
return load_stylesheet(pyside=True)
|
||||
|
||||
|
||||
def load_stylesheet_pyside2():
|
||||
"""
|
||||
Load the stylesheet for use in a pyside2 application.
|
||||
|
||||
:raise NotImplementedError: Because it is not supported yet
|
||||
"""
|
||||
warnings.warn(
|
||||
"load_stylesheet_pyside2() will be deprecated in version 3,"
|
||||
"set QtPy environment variable to specify the Qt binding and "
|
||||
"use load_stylesheet()",
|
||||
PendingDeprecationWarning
|
||||
)
|
||||
return load_stylesheet(pyside=True)
|
||||
|
||||
|
||||
def load_stylesheet_pyqt():
|
||||
"""
|
||||
Load the stylesheet for use in a pyqt4 application.
|
||||
|
||||
:return the stylesheet string
|
||||
"""
|
||||
warnings.warn(
|
||||
"load_stylesheet_pyqt() will be deprecated in version 3,"
|
||||
"set QtPy environment variable to specify the Qt binding and "
|
||||
"use load_stylesheet()",
|
||||
PendingDeprecationWarning
|
||||
)
|
||||
return load_stylesheet(pyside=False)
|
||||
|
||||
|
||||
def load_stylesheet_pyqt5():
|
||||
"""
|
||||
Load the stylesheet for use in a pyqt5 application.
|
||||
|
||||
:param pyside: True to load the pyside rc file, False to load the PyQt rc file
|
||||
|
||||
:return the stylesheet string
|
||||
"""
|
||||
warnings.warn(
|
||||
"load_stylesheet_pyqt5() will be deprecated in version 3,"
|
||||
"set QtPy environment variable to specify the Qt binding and "
|
||||
"use load_stylesheet()",
|
||||
PendingDeprecationWarning
|
||||
)
|
||||
# Smart import of the rc file
|
||||
import qdarkstyle.pyqt5_style_rc
|
||||
|
||||
# Load the stylesheet content from resources
|
||||
from PyQt5.QtCore import QFile, QTextStream
|
||||
|
||||
f = QFile(":qdarkstyle/style.qss")
|
||||
if not f.exists():
|
||||
_logger().error("Unable to load stylesheet, file not found in "
|
||||
"resources")
|
||||
return ""
|
||||
else:
|
||||
f.open(QFile.ReadOnly | QFile.Text)
|
||||
ts = QTextStream(f)
|
||||
stylesheet = ts.readAll()
|
||||
if platform.system().lower() == 'darwin': # see issue #12 on github
|
||||
mac_fix = '''
|
||||
QDockWidget::title
|
||||
{
|
||||
background-color: #32414B;
|
||||
text-align: center;
|
||||
height: 12px;
|
||||
}
|
||||
'''
|
||||
stylesheet += mac_fix
|
||||
return stylesheet
|
||||
|
||||
|
||||
def information():
|
||||
"""Get system and runtime information."""
|
||||
info = []
|
||||
qt_api = ''
|
||||
qt_lib = ''
|
||||
qt_bin = ''
|
||||
|
||||
try:
|
||||
qt_api = os.environ['QT_API']
|
||||
except KeyError:
|
||||
qt_api = 'Not set or nonexistent'
|
||||
|
||||
try:
|
||||
from Qt import __binding__
|
||||
except Exception:
|
||||
# It should be (KeyError, ModuleNotFoundError, ImportError)
|
||||
# but each python version have a different one, and not define others
|
||||
qt_lib = 'Not set or nonexistent'
|
||||
else:
|
||||
qt_lib = __binding__
|
||||
|
||||
try:
|
||||
qt_bin = os.environ['PYQTGRAPH_QT_LIB']
|
||||
except KeyError:
|
||||
qt_bin = 'Not set or nonexistent'
|
||||
|
||||
info.append('QDarkStyle: %s' % __version__)
|
||||
info.append('OS: %s %s %s' % (platform.system(), platform.release(), platform.machine()))
|
||||
info.append('Platform: %s' % sys.platform)
|
||||
info.append('Python: %s' % '.'.join(str(e) for e in sys.version_info[:]))
|
||||
info.append('Python API: %s' % sys.api_version)
|
||||
|
||||
info.append('Binding in use: %s' % QT_BINDING)
|
||||
info.append('Abstraction in use: %s' % QT_ABSTRACTION)
|
||||
|
||||
info.append('qtpy (QT_API): %s' % qt_api)
|
||||
info.append('pyqtgraph (PYQTGRAPH_QT_LIB): %s' % qt_lib)
|
||||
info.append('Qt.py (__binding__): %s' % qt_bin)
|
||||
|
||||
return info
|
||||
|
||||
|
||||
def qt_bindings():
|
||||
"""Return a list of qt bindings available."""
|
||||
return _check_imports(import_list=QT_BINDINGS)
|
||||
|
||||
|
||||
def qt_abstractions():
|
||||
"""Return a list of qt abstraction layers available."""
|
||||
return _check_imports(import_list=QT_ABSTRACTIONS)
|
||||
|
||||
|
||||
def _check_imports(import_list):
|
||||
"""Return a list of imports available."""
|
||||
|
||||
# Disable warnings here
|
||||
warnings.filterwarnings("ignore")
|
||||
|
||||
import_list_return = copy.deepcopy(import_list)
|
||||
# Using import_list_return var in for, does not work in py2.7
|
||||
# when removing the element, it reflects on for list
|
||||
# so it skips next element
|
||||
for current_import in import_list:
|
||||
|
||||
spec = True
|
||||
# Copy the sys path to make sure to not insert anything
|
||||
sys_path = sys.path
|
||||
|
||||
# Check import
|
||||
if sys.version_info >= (3, 4):
|
||||
spec = importlib.util.find_spec(current_import)
|
||||
else:
|
||||
try:
|
||||
__import__(current_import)
|
||||
except RuntimeWarning:
|
||||
spec = True
|
||||
except Exception:
|
||||
spec = None
|
||||
else:
|
||||
spec = True
|
||||
|
||||
if spec is None:
|
||||
# Remove if not available
|
||||
import_list_return.remove(current_import)
|
||||
|
||||
# Restore sys path
|
||||
sys.path = sys_path
|
||||
|
||||
# Restore warnings
|
||||
warnings.resetwarnings()
|
||||
|
||||
return import_list_return
|
||||
|
||||
|
||||
def _import_qt_modules_from(use_binding='pyqt5', use_abstraction='qtpy'):
|
||||
"""New approach to import modules using importlib."""
|
||||
|
||||
if not sys.version_info >= (3, 4):
|
||||
print('Function not available for Python < 3.4')
|
||||
|
||||
spec_binding = importlib.util.find_spec(use_binding)
|
||||
spec_abstraction = importlib.util.find_spec(use_abstraction)
|
||||
|
||||
if spec_binding is None:
|
||||
print("Cannot find Qt binding: ", use_binding)
|
||||
else:
|
||||
module = importlib.util.module_from_spec(spec_binding)
|
||||
spec.loader.exec_module(module)
|
||||
# Adding the module to sys.modules is optional.
|
||||
sys.modules[name] = module
|
||||
|
||||
if spec_abstraction is None:
|
||||
print("Cannot find Qt abstraction layer: ", use_abstraction)
|
||||
else:
|
||||
module = importlib.util.module_from_spec(spec)
|
||||
spec.loader.exec_module(module)
|
||||
# Adding the module to sys.modules is optional.
|
||||
sys.modules[name] = module
|
|
@ -1,65 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from qdarkstyle import qt_bindings, qt_abstractions, information, __version__
|
||||
import qdarkstyle
|
||||
import argparse
|
||||
import sys
|
||||
|
||||
from os.path import abspath, dirname
|
||||
sys.path.insert(0, abspath(dirname(abspath(__file__)) + '/..'))
|
||||
|
||||
|
||||
def print_list_md(info):
|
||||
"""Print a list of information, line by line."""
|
||||
for item in info:
|
||||
print(' - ' + item)
|
||||
|
||||
|
||||
def main():
|
||||
"""Execute QDarkStyle example."""
|
||||
parser = argparse.ArgumentParser(description=__doc__,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter)
|
||||
parser.add_argument('-i', '--information', action='store_true',
|
||||
help="Show information about environment (important for bug report)")
|
||||
parser.add_argument('-b', '--bindings', action='store_true',
|
||||
help="Show available bindings for Qt")
|
||||
parser.add_argument('-a', '--abstractions', action='store_true',
|
||||
help="Show available abstraction layers for Qt bindings")
|
||||
# parser.add_argument('-e', '--example', action='store_true',
|
||||
# help="Show qdarkstyle example, subcommand.")
|
||||
parser.add_argument('-v', '--version', action='store_true',
|
||||
help="Show qdarkstyle version")
|
||||
parser.add_argument('--all', action='store_true',
|
||||
help="Show all information options at once")
|
||||
|
||||
# parsing arguments from command line
|
||||
args = parser.parse_args()
|
||||
|
||||
parser.print_help()
|
||||
|
||||
if args.information or args.all:
|
||||
info = information()
|
||||
print('\nInformation about your current environment setup:')
|
||||
print_list_md(info)
|
||||
|
||||
if args.bindings or args.all:
|
||||
info = qt_bindings()
|
||||
print('\nQt bindings available:')
|
||||
print_list_md(info)
|
||||
|
||||
if args.abstractions or args.all:
|
||||
info = qt_abstractions()
|
||||
print('\nQt abstraction layers available:')
|
||||
print_list_md(info)
|
||||
|
||||
if args.version:
|
||||
info = __version__
|
||||
print('\nVersion: %s' % info)
|
||||
|
||||
# if args.example:
|
||||
# example.main()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
Binary file not shown.
|
@ -211,7 +211,7 @@
|
|||
<context>
|
||||
<name>ClipboardUploader</name>
|
||||
<message>
|
||||
<location filename="../src/uploaders/default/clipboarduploader.cpp" line="18"/>
|
||||
<location filename="../src/uploaders/default/clipboarduploader.cpp" line="19"/>
|
||||
<source>Copied to clipboard!</source>
|
||||
<translation>In die Zwischenablage kopiert!</translation>
|
||||
</message>
|
||||
|
@ -340,150 +340,150 @@
|
|||
<context>
|
||||
<name>CustomUploader</name>
|
||||
<message>
|
||||
<location filename="../src/uploaders/customuploader.cpp" line="34"/>
|
||||
<location filename="../src/uploaders/customuploader.cpp" line="33"/>
|
||||
<source>Root not an object</source>
|
||||
<translation>Root (Wurzel) ist kein JSON Objekt</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/uploaders/customuploader.cpp" line="38"/>
|
||||
<location filename="../src/uploaders/customuploader.cpp" line="37"/>
|
||||
<source>name is not a string</source>
|
||||
<translation>"name" ist keine Zeichenkette</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/uploaders/customuploader.cpp" line="43"/>
|
||||
<location filename="../src/uploaders/customuploader.cpp" line="42"/>
|
||||
<source>desc not a string</source>
|
||||
<translation>"desc" ist keine Zeichenkette</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/uploaders/customuploader.cpp" line="51"/>
|
||||
<location filename="../src/uploaders/customuploader.cpp" line="50"/>
|
||||
<source>method not a string</source>
|
||||
<translation>"method" ist keine Zeichenkette</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/uploaders/customuploader.cpp" line="56"/>
|
||||
<location filename="../src/uploaders/customuploader.cpp" line="55"/>
|
||||
<source>method invalid</source>
|
||||
<translation>"method" ist ungültig</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/uploaders/customuploader.cpp" line="60"/>
|
||||
<location filename="../src/uploaders/customuploader.cpp" line="59"/>
|
||||
<source>target missing</source>
|
||||
<translation>Das Ziel fehlt</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/uploaders/customuploader.cpp" line="63"/>
|
||||
<location filename="../src/uploaders/customuploader.cpp" line="62"/>
|
||||
<source>target not URL</source>
|
||||
<translation>Das Ziel ist keine URL</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/uploaders/customuploader.cpp" line="78"/>
|
||||
<location filename="../src/uploaders/customuploader.cpp" line="77"/>
|
||||
<source>format invalid</source>
|
||||
<translation>"format" ist ungültig</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/uploaders/customuploader.cpp" line="81"/>
|
||||
<location filename="../src/uploaders/customuploader.cpp" line="80"/>
|
||||
<source>format provided but not string</source>
|
||||
<translation>"format" ist keine Zeichenkette</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/uploaders/customuploader.cpp" line="84"/>
|
||||
<location filename="../src/uploaders/customuploader.cpp" line="83"/>
|
||||
<source>body not set</source>
|
||||
<translation>Die Antwort hatte keinen "body"</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/uploaders/customuploader.cpp" line="88"/>
|
||||
<location filename="../src/uploaders/customuploader.cpp" line="87"/>
|
||||
<source>all elements of body must be objects</source>
|
||||
<translation>Alle Teile des "body"s müssen Objekte sein</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/uploaders/customuploader.cpp" line="90"/>
|
||||
<location filename="../src/uploaders/customuploader.cpp" line="89"/>
|
||||
<source>all parts must have a body which is object or string!</source>
|
||||
<translation>Alle Teile müssen einen "body" haben, welcher eine Zeichenkette oder ein Objekt ist!</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/uploaders/customuploader.cpp" line="94"/>
|
||||
<location filename="../src/uploaders/customuploader.cpp" line="93"/>
|
||||
<source>all parts of body must be string or object</source>
|
||||
<translation>Alle Teile des "body"s müssen eine Zeichenkette oder ein Objekt sein</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/uploaders/customuploader.cpp" line="98"/>
|
||||
<location filename="../src/uploaders/customuploader.cpp" line="97"/>
|
||||
<source>all __headers must be strings</source>
|
||||
<translation>Alle mit "__" beginnenden Kopfzeilen müssen Zeichenketten sein</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/uploaders/customuploader.cpp" line="102"/>
|
||||
<location filename="../src/uploaders/customuploader.cpp" line="101"/>
|
||||
<source>body not array (needed for multipart)</source>
|
||||
<translation>Der "body"ist kein Array (für "multipart" benötigt)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/uploaders/customuploader.cpp" line="107"/>
|
||||
<location filename="../src/uploaders/customuploader.cpp" line="106"/>
|
||||
<source>body not object</source>
|
||||
<translation>Der "body" ist kein Objekt</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/uploaders/customuploader.cpp" line="114"/>
|
||||
<location filename="../src/uploaders/customuploader.cpp" line="113"/>
|
||||
<source>body not string (reason: format: PLAIN)</source>
|
||||
<extracomment>`format: PLAIN` should stay the same</extracomment>
|
||||
<translation>Antwort "body" ist keine Zeichenkette (Grund: "format: PLAIN")</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/uploaders/customuploader.cpp" line="118"/>
|
||||
<location filename="../src/uploaders/customuploader.cpp" line="117"/>
|
||||
<source>headers must be object</source>
|
||||
<translation>"headers" ist kein JSON Objekt</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/uploaders/customuploader.cpp" line="126"/>
|
||||
<location filename="../src/uploaders/customuploader.cpp" line="125"/>
|
||||
<source>return invalid</source>
|
||||
<translation>Antwort ungültig</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/uploaders/customuploader.cpp" line="130"/>
|
||||
<location filename="../src/uploaders/customuploader.cpp" line="129"/>
|
||||
<source>fileLimit not decimal</source>
|
||||
<extracomment>fileLimit stays English</extracomment>
|
||||
<translation>"fileLimit" ist keine Dezimalzahl</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/uploaders/customuploader.cpp" line="135"/>
|
||||
<location filename="../src/uploaders/customuploader.cpp" line="134"/>
|
||||
<source>base64 must be boolean</source>
|
||||
<translation>Base64 muss ein Wahrheitswert sein</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/uploaders/customuploader.cpp" line="137"/>
|
||||
<location filename="../src/uploaders/customuploader.cpp" line="136"/>
|
||||
<source>base64 required with json</source>
|
||||
<translation>Base64 für JSON benötigt</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/uploaders/customuploader.cpp" line="220"/>
|
||||
<location filename="../src/uploaders/customuploader.cpp" line="223"/>
|
||||
<location filename="../src/uploaders/customuploader.cpp" line="229"/>
|
||||
<location filename="../src/uploaders/customuploader.cpp" line="353"/>
|
||||
<location filename="../src/uploaders/customuploader.cpp" line="371"/>
|
||||
<location filename="../src/uploaders/customuploader.cpp" line="381"/>
|
||||
<location filename="../src/uploaders/customuploader.cpp" line="219"/>
|
||||
<location filename="../src/uploaders/customuploader.cpp" line="222"/>
|
||||
<location filename="../src/uploaders/customuploader.cpp" line="228"/>
|
||||
<location filename="../src/uploaders/customuploader.cpp" line="352"/>
|
||||
<location filename="../src/uploaders/customuploader.cpp" line="370"/>
|
||||
<location filename="../src/uploaders/customuploader.cpp" line="380"/>
|
||||
<source>KShare Custom Uploader </source>
|
||||
<translation>KShare benutzerdefinierter Uploader </translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/uploaders/customuploader.cpp" line="220"/>
|
||||
<location filename="../src/uploaders/customuploader.cpp" line="219"/>
|
||||
<source>Copied upload link to clipboard!</source>
|
||||
<translation>Link in die Zwischenablage kopiert!</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/uploaders/customuploader.cpp" line="223"/>
|
||||
<location filename="../src/uploaders/customuploader.cpp" line="222"/>
|
||||
<source>Upload done, but result empty!</source>
|
||||
<translation>Hochgeladen, aber eine leere Antwort erhalten!</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/uploaders/customuploader.cpp" line="230"/>
|
||||
<location filename="../src/uploaders/customuploader.cpp" line="229"/>
|
||||
<source>Upload done, but result is not JSON Object! Result in clipboard.</source>
|
||||
<translation>Hochgeladen, aber die Antwort war kein JSON-Objekt! Die Antwort wurde in die Zwischenablage kopiert.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/uploaders/customuploader.cpp" line="354"/>
|
||||
<location filename="../src/uploaders/customuploader.cpp" line="381"/>
|
||||
<location filename="../src/uploaders/customuploader.cpp" line="353"/>
|
||||
<location filename="../src/uploaders/customuploader.cpp" line="380"/>
|
||||
<source>Copied upload result to clipboard!</source>
|
||||
<translation>Ergebnis in die Zwischenablage kopiert!</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/uploaders/customuploader.cpp" line="371"/>
|
||||
<location filename="../src/uploaders/customuploader.cpp" line="370"/>
|
||||
<source>File limit exceeded!</source>
|
||||
<translation>Dateigröße überschritten!</translation>
|
||||
</message>
|
||||
|
@ -657,7 +657,7 @@ p, li { white-space: pre-wrap; }
|
|||
<name>ImgurUploader</name>
|
||||
<message>
|
||||
<location filename="../src/uploaders/default/imguruploader.cpp" line="59"/>
|
||||
<location filename="../src/uploaders/default/imguruploader.cpp" line="96"/>
|
||||
<location filename="../src/uploaders/default/imguruploader.cpp" line="95"/>
|
||||
<source>KShare imgur Uploader</source>
|
||||
<translation>KShare imgur Uploader</translation>
|
||||
</message>
|
||||
|
@ -667,17 +667,17 @@ p, li { white-space: pre-wrap; }
|
|||
<translation>Hochladen fehlgeschlagen! Das Bild überschreitet die maximale Größe</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/uploaders/default/imguruploader.cpp" line="96"/>
|
||||
<location filename="../src/uploaders/default/imguruploader.cpp" line="95"/>
|
||||
<source>Uploaded to imgur!</source>
|
||||
<translation>Auf imgur hochgeladen!</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/uploaders/default/imguruploader.cpp" line="99"/>
|
||||
<location filename="../src/uploaders/default/imguruploader.cpp" line="100"/>
|
||||
<source>KShare imgur Uploader </source>
|
||||
<translation>KShare imgur Uploader </translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/uploaders/default/imguruploader.cpp" line="100"/>
|
||||
<location filename="../src/uploaders/default/imguruploader.cpp" line="101"/>
|
||||
<source>Failed upload! imgur said: HTTP %1: %2</source>
|
||||
<translation>Hochladen fehlgeschlagen! Imgur hat hiermit geantwortet: "HTTP %1:%2"</translation>
|
||||
</message>
|
||||
|
@ -746,7 +746,7 @@ p, li { white-space: pre-wrap; }
|
|||
</message>
|
||||
<message>
|
||||
<location filename="../src/mainwindow.ui" line="85"/>
|
||||
<location filename="../src/mainwindow.cpp" line="94"/>
|
||||
<location filename="../src/mainwindow.cpp" line="99"/>
|
||||
<source>About</source>
|
||||
<translation type="unfinished">Über</translation>
|
||||
</message>
|
||||
|
@ -836,75 +836,75 @@ p, li { white-space: pre-wrap; }
|
|||
<translation type="unfinished">&Breche Aufnahme ab</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mainwindow.cpp" line="39"/>
|
||||
<location filename="../src/mainwindow.cpp" line="44"/>
|
||||
<source>Recording format not set in settings. Aborting.</source>
|
||||
<translation>Das Format für die Aufnahmen wurde nicht in den Einstellungen definiert. Aufnahme wird abgebrochen.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mainwindow.cpp" line="93"/>
|
||||
<location filename="../src/mainwindow.cpp" line="98"/>
|
||||
<source>Quit</source>
|
||||
<translation>Beenden</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mainwindow.cpp" line="71"/>
|
||||
<location filename="../src/mainwindow.cpp" line="76"/>
|
||||
<source>Show/Hide</source>
|
||||
<translation>Zeigen / Verstecken</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mainwindow.cpp" line="72"/>
|
||||
<location filename="../src/mainwindow.cpp" line="77"/>
|
||||
<source>Take fullscreen shot</source>
|
||||
<translation>Screenshot des ganzen Bildschirms</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mainwindow.cpp" line="73"/>
|
||||
<location filename="../src/mainwindow.cpp" line="78"/>
|
||||
<source>Take area shot</source>
|
||||
<translation>Screenshot eines Gebietes</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mainwindow.cpp" line="76"/>
|
||||
<location filename="../src/mainwindow.cpp" line="81"/>
|
||||
<source>Screenshot active window</source>
|
||||
<translation>Screenshot des aktiven Fensters</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mainwindow.cpp" line="79"/>
|
||||
<location filename="../src/mainwindow.cpp" line="84"/>
|
||||
<source>Copy from Clipbaord</source>
|
||||
<translation type="unfinished">Zwischenablage hochladen</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mainwindow.cpp" line="80"/>
|
||||
<location filename="../src/mainwindow.cpp" line="85"/>
|
||||
<source>Show color picker</source>
|
||||
<translation>Zeige die Farbpipette</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mainwindow.cpp" line="81"/>
|
||||
<location filename="../src/mainwindow.cpp" line="86"/>
|
||||
<source>Record screen</source>
|
||||
<translation>Bildschirm aufnehmen</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mainwindow.cpp" line="82"/>
|
||||
<location filename="../src/mainwindow.cpp" line="87"/>
|
||||
<source>Stop recording</source>
|
||||
<translation>Stoppe Aufnahme</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mainwindow.cpp" line="83"/>
|
||||
<location filename="../src/mainwindow.cpp" line="88"/>
|
||||
<source>Abort recording</source>
|
||||
<translation>Breche Aufnahme ab</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mainwindow.cpp" line="238"/>
|
||||
<location filename="../src/mainwindow.cpp" line="272"/>
|
||||
<location filename="../src/mainwindow.cpp" line="275"/>
|
||||
<location filename="../src/mainwindow.cpp" line="309"/>
|
||||
<source>Cannot determine location for pictures</source>
|
||||
<translation type="unfinished">Die Position des Ordners für Bilder kann nicht bestimmt werden</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mainwindow.cpp" line="243"/>
|
||||
<location filename="../src/mainwindow.cpp" line="277"/>
|
||||
<location filename="../src/mainwindow.cpp" line="280"/>
|
||||
<location filename="../src/mainwindow.cpp" line="314"/>
|
||||
<source>Cannot determine location of your home directory</source>
|
||||
<translation type="unfinished">Die Position des Benutzerverzeichnisses kann nicht bestimmt werden</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/mainwindow.cpp" line="248"/>
|
||||
<location filename="../src/mainwindow.cpp" line="282"/>
|
||||
<location filename="../src/mainwindow.cpp" line="285"/>
|
||||
<location filename="../src/mainwindow.cpp" line="319"/>
|
||||
<source>Invalid config [saveLocation not int or is not in range]</source>
|
||||
<translation type="unfinished">Ungültige Config (Speicherziel ist keine natürliche Zahl oder nicht in einem gültigen Bereich)</translation>
|
||||
</message>
|
||||
|
@ -923,7 +923,7 @@ p, li { white-space: pre-wrap; }
|
|||
<translation>Konnte den Ordner für die Konfigurationsdateien nicht erstellen</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/uploaders/customuploader.cpp" line="25"/>
|
||||
<location filename="../src/uploaders/customuploader.cpp" line="24"/>
|
||||
<source>Invalid file: </source>
|
||||
<translation>Ungültige Datei: </translation>
|
||||
</message>
|
||||
|
@ -971,6 +971,11 @@ p, li { white-space: pre-wrap; }
|
|||
</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/notifications.cpp" line="56"/>
|
||||
<source>KShare: No sound driver</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>RecordingFormats</name>
|
||||
|
@ -1098,166 +1103,236 @@ Stopptaste: %3</translation>
|
|||
<translation>Zuschneideeditor Einstellungen</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/settingsdialog.ui" line="39"/>
|
||||
<location filename="../src/settingsdialog.ui" line="34"/>
|
||||
<source>General</source>
|
||||
<translatorcomment>Allgemein</translatorcomment>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/settingsdialog.ui" line="42"/>
|
||||
<source>Theme</source>
|
||||
<translatorcomment>Erscheinungsbild</translatorcomment>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/settingsdialog.ui" line="50"/>
|
||||
<source>System Default</source>
|
||||
<translation type="unfinished">System</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/settingsdialog.ui" line="55"/>
|
||||
<source>QDarkStyle</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/settingsdialog.ui" line="60"/>
|
||||
<source>Breeze Light</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/settingsdialog.ui" line="65"/>
|
||||
<source>Breeze Dark</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/settingsdialog.ui" line="73"/>
|
||||
<source>Quick mode (mouse release screenshots)</source>
|
||||
<translation>Schneller Modus (Maus loslassen reicht)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/settingsdialog.ui" line="70"/>
|
||||
<location filename="../src/settingsdialog.ui" line="94"/>
|
||||
<source>Delay before taking a screenshot</source>
|
||||
<translation>Verzögerung vor einem Screenshot</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/settingsdialog.ui" line="26"/>
|
||||
<location filename="../src/settingsdialog.ui" line="101"/>
|
||||
<source>In seconds</source>
|
||||
<translation>In Sekunden</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/settingsdialog.ui" line="29"/>
|
||||
<location filename="../src/settingsdialog.ui" line="104"/>
|
||||
<source>A delay before taking a screenshot, in seconds</source>
|
||||
<translation>Verzögerung vor einem Screenshot in Sekunden</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/settingsdialog.ui" line="46"/>
|
||||
<location filename="../src/settingsdialog.ui" line="124"/>
|
||||
<source>Hoster</source>
|
||||
<translation type="unfinished">Hoster</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/settingsdialog.ui" line="152"/>
|
||||
<source>Paths</source>
|
||||
<translation type="unfinished">Pfade</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/settingsdialog.ui" line="160"/>
|
||||
<source>File name scheme</source>
|
||||
<translation type="unfinished">Dateibennenung</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/settingsdialog.ui" line="180"/>
|
||||
<source>Screenshot Subfolder</source>
|
||||
<translation type="unfinished">Unterordnermuster</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/settingsdialog.ui" line="187"/>
|
||||
<source>%(yyyy-MM)date</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/settingsdialog.ui" line="223"/>
|
||||
<source>Recording</source>
|
||||
<translatorcomment>Aufzeichnung</translatorcomment>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/settingsdialog.ui" line="348"/>
|
||||
<source>Fullscreen capture command (save to %FILE_PATH or print to stdout)</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/settingsdialog.ui" line="53"/>
|
||||
<location filename="../src/settingsdialog.ui" line="138"/>
|
||||
<source>Hotkeys</source>
|
||||
<translation>Hotkeys</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/settingsdialog.ui" line="60"/>
|
||||
<location filename="../src/settingsdialog.ui" line="297"/>
|
||||
<source>Still image format</source>
|
||||
<translation>Format für Bilder</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/settingsdialog.ui" line="77"/>
|
||||
<location filename="../src/settingsdialog.ui" line="290"/>
|
||||
<source>Recording format</source>
|
||||
<translation>Aufnahmeformate</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/settingsdialog.ui" line="84"/>
|
||||
<location filename="../src/settingsdialog.ui" line="87"/>
|
||||
<source>Capture cursor</source>
|
||||
<translation>Mauszeiger aufnehmen</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/settingsdialog.ui" line="91"/>
|
||||
<location filename="../src/settingsdialog.ui" line="170"/>
|
||||
<source>%(date format)date and %ext are supported</source>
|
||||
<translation>%(Datumsformat)Datum ujnd %ext werden unterstützt</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/settingsdialog.ui" line="108"/>
|
||||
<source>File name scheme:</source>
|
||||
<translation>Benennungsschema:</translation>
|
||||
<translation type="vanished">Benennungsschema:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/settingsdialog.ui" line="115"/>
|
||||
<location filename="../src/settingsdialog.ui" line="80"/>
|
||||
<source>Pressing <X> hides to tray</source>
|
||||
<translation>Drücke <X> um dieses Fenster in die Taskleiste zu minimieren</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/settingsdialog.ui" line="133"/>
|
||||
<location filename="../src/settingsdialog.ui" line="212"/>
|
||||
<source>Do not save</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Nicht speichern</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/settingsdialog.ui" line="141"/>
|
||||
<location filename="../src/settingsdialog.ui" line="116"/>
|
||||
<source>Open settings directory</source>
|
||||
<translation>Öffne Konfigurationsordner</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/settingsdialog.ui" line="148"/>
|
||||
<source>Destination:</source>
|
||||
<translation>Speicherziel:</translation>
|
||||
<translation type="vanished">Speicherziel:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/settingsdialog.ui" line="244"/>
|
||||
<location filename="../src/settingsdialog.ui" line="355"/>
|
||||
<source>Focused capture command (save to %FILE_PATH or print to stdout)</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/settingsdialog.ui" line="123"/>
|
||||
<location filename="../src/settingsdialog.ui" line="202"/>
|
||||
<source>Pictures folder</source>
|
||||
<translation>Ordner für Bilder</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/settingsdialog.ui" line="128"/>
|
||||
<location filename="../src/settingsdialog.ui" line="207"/>
|
||||
<source>Screenshots folder (In your user folder)</source>
|
||||
<translation>Screenshot ordner (In deinem Benutzerordner)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/settingsdialog.ui" line="165"/>
|
||||
<location filename="../src/settingsdialog.ui" line="194"/>
|
||||
<source>File save location</source>
|
||||
<translation>Speicherort für Bilder</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/settingsdialog.ui" line="172"/>
|
||||
<location filename="../src/settingsdialog.ui" line="229"/>
|
||||
<location filename="../src/settingsdialog.ui" line="340"/>
|
||||
<source>Advanced</source>
|
||||
<translation>Erweiterte Einstellungen</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/settingsdialog.ui" line="207"/>
|
||||
<location filename="../src/settingsdialog.ui" line="264"/>
|
||||
<source>Editor Position (tweak if the editor does not cover the entire screen)</source>
|
||||
<translation>Editor Position (Ändern, wenn nicht der ganzen Bildschirm ausgefüllt ist)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/settingsdialog.ui" line="214"/>
|
||||
<location filename="../src/settingsdialog.ui" line="271"/>
|
||||
<source>Encoder settings</source>
|
||||
<translation>Kodierer Einstellungen</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/settingsdialog.ui" line="224"/>
|
||||
<location filename="../src/settingsdialog.ui" line="314"/>
|
||||
<source>FPS</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>FPS</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/settingsdialog.ui" line="234"/>
|
||||
<location filename="../src/settingsdialog.ui" line="307"/>
|
||||
<source>Frames Per Second For Recording</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>FPS für Aufnahmen</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/settingsdialog.cpp" line="56"/>
|
||||
<location filename="../src/settingsdialog.cpp" line="58"/>
|
||||
<source>Fullscreen image</source>
|
||||
<translation>Screenshot des ganzen Bildschirms</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/settingsdialog.cpp" line="57"/>
|
||||
<location filename="../src/settingsdialog.cpp" line="59"/>
|
||||
<source>Area image</source>
|
||||
<translation>Screenshot eines Gebietes</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/settingsdialog.cpp" line="59"/>
|
||||
<location filename="../src/settingsdialog.cpp" line="61"/>
|
||||
<source>Active window</source>
|
||||
<translation>Screenshot des aktiven Fensters</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/settingsdialog.cpp" line="61"/>
|
||||
<location filename="../src/settingsdialog.cpp" line="63"/>
|
||||
<source>Copy from Clipboard</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/settingsdialog.cpp" line="62"/>
|
||||
<location filename="../src/settingsdialog.cpp" line="64"/>
|
||||
<source>Color picker</source>
|
||||
<translation>Farbpipette</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/settingsdialog.cpp" line="63"/>
|
||||
<location filename="../src/settingsdialog.cpp" line="65"/>
|
||||
<source>Stop Recording</source>
|
||||
<translation>Stoppe Aufnahme</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/settingsdialog.cpp" line="64"/>
|
||||
<location filename="../src/settingsdialog.cpp" line="66"/>
|
||||
<source>Start Recording</source>
|
||||
<translation>Starte Aufnahme</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/settingsdialog.cpp" line="86"/>
|
||||
<location filename="../src/settingsdialog.cpp" line="89"/>
|
||||
<source>Capture cursor (disabled: implementation missing)</source>
|
||||
<translation>Mauszeiger aufnehmen (Deaktiviert: Implementierung fehlt)</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>SystemNotification</name>
|
||||
<message>
|
||||
<location filename="../src/systemnotification.cpp" line="29"/>
|
||||
<source>KShare Info</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>TextItem</name>
|
||||
<message>
|
||||
|
@ -1274,39 +1349,39 @@ Stopptaste: %3</translation>
|
|||
<context>
|
||||
<name>UploaderSingleton</name>
|
||||
<message>
|
||||
<location filename="../src/uploaders/uploadersingleton.cpp" line="127"/>
|
||||
<location filename="../src/uploaders/uploadersingleton.cpp" line="128"/>
|
||||
<source>KShare - Failed to open File</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/uploaders/uploadersingleton.cpp" line="167"/>
|
||||
<location filename="../src/uploaders/uploadersingleton.cpp" line="180"/>
|
||||
<source>Cannot determine location for pictures</source>
|
||||
<translation>Die Position des Ordners für Bilder kann nicht bestimmt werden</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/uploaders/uploadersingleton.cpp" line="172"/>
|
||||
<location filename="../src/uploaders/uploadersingleton.cpp" line="185"/>
|
||||
<source>Cannot determine location of your home directory</source>
|
||||
<translation>Die Position des Benutzerverzeichnisses kann nicht bestimmt werden</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/uploaders/uploadersingleton.cpp" line="177"/>
|
||||
<location filename="../src/uploaders/uploadersingleton.cpp" line="190"/>
|
||||
<source>Invalid config [saveLocation not int or is not in range]</source>
|
||||
<translation>Ungültige Config (Speicherziel ist keine natürliche Zahl oder nicht in einem gültigen Bereich)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/uploaders/uploadersingleton.cpp" line="50"/>
|
||||
<location filename="../src/uploaders/uploadersingleton.cpp" line="51"/>
|
||||
<source>Ambigious uploader </source>
|
||||
<translation>Unklarer Uploadername </translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/uploaders/uploadersingleton.cpp" line="61"/>
|
||||
<location filename="../src/uploaders/uploadersingleton.cpp" line="62"/>
|
||||
<source>Currently selected uploader is not set up properly! Falling back to imgur</source>
|
||||
<translation>Ausgewählter Uploader ist nicht korrekt eingestellt! Nutze imgur als Ersatz</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/uploaders/uploadersingleton.cpp" line="79"/>
|
||||
<location filename="../src/uploaders/uploadersingleton.cpp" line="115"/>
|
||||
<location filename="../src/uploaders/uploadersingleton.cpp" line="117"/>
|
||||
<location filename="../src/uploaders/uploadersingleton.cpp" line="119"/>
|
||||
<source>KShare - Failed to save picture</source>
|
||||
<translation>KShare - Speichern des Bildes fehlgeschlagen</translation>
|
||||
</message>
|
||||
|
|
Loading…
Reference in New Issue